-
Notifications
You must be signed in to change notification settings - Fork 24
/
VarUInteger.kt
127 lines (111 loc) · 4.23 KB
/
VarUInteger.kt
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
package org.ton.block
import kotlinx.serialization.SerialName
import kotlinx.serialization.Serializable
import org.ton.bigint.*
import org.ton.cell.CellBuilder
import org.ton.cell.CellSlice
import org.ton.cell.invoke
import org.ton.tlb.TlbCodec
import org.ton.tlb.TlbConstructor
import org.ton.tlb.TlbObject
import org.ton.tlb.TlbPrettyPrinter
import kotlin.jvm.JvmName
import kotlin.jvm.JvmStatic
@SerialName("var_uint")
@Serializable
public data class VarUInteger(
@get:JvmName("len")
val len: Int,
@Serializable(BigIntSerializer::class)
@get:JvmName("value")
val value: BigInt
) : TlbObject {
constructor(int: Int) : this(int.toBigInt())
constructor(long: Long) : this(long.toBigInt())
constructor(value: BigInt) : this(
len = value.bitLength / Byte.SIZE_BITS + if (value.bitLength % Byte.SIZE_BITS == 0) 0 else 1,
value = value
)
fun toByte(): Byte = value.toByte()
fun toChar(): Char = value.toChar()
fun toDouble(): Double = throw UnsupportedOperationException()
fun toFloat(): Float = throw UnsupportedOperationException()
fun toInt(): Int = value.toInt()
fun toLong(): Long = value.toLong()
fun toShort(): Short = value.toShort()
operator fun plus(other: VarUInteger): VarUInteger {
val result = value + other.value
val maxLen = maxOf(len, other.len)
val actualLen = result.bitLength
val length = if (actualLen <= maxLen) maxLen else throw NumberFormatException("Integer overflow")
return VarUInteger(length, result)
}
operator fun minus(other: VarUInteger): VarUInteger {
val result = value - other.value
if (result < 0L) throw NumberFormatException("Integer underflow")
val len = maxOf(len, other.len)
return VarUInteger(len, result)
}
operator fun times(other: VarUInteger): VarUInteger {
val result = value * other.value
val maxLen = maxOf(len, other.len)
val actualLen = result.bitLength
val len = if (actualLen <= maxLen) maxLen else throw NumberFormatException("Integer overflow")
return VarUInteger(len, result)
}
operator fun div(other: VarUInteger): VarUInteger {
val result = value / other.value
val maxLen = maxOf(len, other.len)
val actualLen = result.bitLength
val len = if (actualLen <= maxLen) maxLen else throw NumberFormatException("Integer overflow")
return VarUInteger(len, result)
}
operator fun rem(other: VarUInteger): VarUInteger {
val result = value % other.value
val maxLen = maxOf(len, other.len)
val actualLen = result.bitLength
val len = if (actualLen <= maxLen) maxLen else throw NumberFormatException("Integer overflow")
return VarUInteger(len, result)
}
operator fun inc(): VarUInteger {
val result = value + 1.toBigInt()
val actualLen = result.bitLength
val length = if (actualLen < len) len else throw NumberFormatException("Integer overflow")
return VarUInteger(length, result)
}
operator fun dec(): VarUInteger {
val result = value - 1.toBigInt()
if (result < 0.toBigInt()) throw NumberFormatException("Integer overflow")
return VarUInteger(len, result)
}
override fun print(printer: TlbPrettyPrinter): TlbPrettyPrinter {
return printer.type("var_uint") {
field("len", len)
field("value", value)
}
}
override fun toString(): String = value.toString()
companion object {
@JvmStatic
fun tlbCodec(n: Int): TlbCodec<VarUInteger> = VarUIntegerTlbConstructor(n)
}
private class VarUIntegerTlbConstructor(
val n: Int
) : TlbConstructor<VarUInteger>(
schema = "var_uint\$_ {n:#} len:(#< n) value:(uint (len * 8)) = VarUInteger n;"
) {
override fun storeTlb(
cellBuilder: CellBuilder, value: VarUInteger
) = cellBuilder {
storeUIntLes(value.len, n)
storeUInt(value.value, value.len * 8)
}
override fun loadTlb(
cellSlice: CellSlice
): VarUInteger = cellSlice {
val len = loadUIntLes(n).toInt()
val value = loadUInt(len * 8)
VarUInteger(len, value)
}
}
}