Bigint fixes
* Native and big integer comparison * Refuse to serialize negative big ints for now
This commit is contained in:
parent
d63dfad954
commit
bfb0825721
|
@ -55,7 +55,12 @@ proc `<`(x, y: string | seq[byte]): bool =
|
|||
|
||||
proc `<`*[T](x, y: Preserve[T]): bool =
|
||||
if x.kind != y.kind:
|
||||
result = x.kind < y.kind
|
||||
if x.kind == pkSignedInteger and y.kind == pkBigInteger:
|
||||
result = x.int < y.bigint
|
||||
elif x.kind == pkBigInteger and y.kind == pkSignedInteger:
|
||||
result = x.bigint < y.int
|
||||
else:
|
||||
result = x.kind < y.kind
|
||||
else:
|
||||
case x.kind
|
||||
of pkBoolean:
|
||||
|
@ -126,6 +131,7 @@ proc hash*[T](prs: Preserve[T]): Hash =
|
|||
of pkSignedInteger:
|
||||
h = h !& hash(prs.int)
|
||||
of pkBigInteger:
|
||||
h = h !& hash(prs.bigint.flags)
|
||||
h = h !& hash(prs.bigint)
|
||||
of pkString:
|
||||
h = h !& hash(prs.string)
|
||||
|
@ -265,12 +271,13 @@ proc write*[T](str: Stream; prs: Preserve[T]) =
|
|||
inc(bitCount)
|
||||
var byteCount = (bitCount + 8) div 8
|
||||
str.write(0xa0'u8 or (byteCount - 1))
|
||||
proc write(n: uint8, i: BiggestInt) =
|
||||
proc write(n: uint8; i: BiggestInt) =
|
||||
if n > 0:
|
||||
write(n.pred, i shr 8)
|
||||
str.write(i.uint8)
|
||||
write(byteCount, prs.int)
|
||||
of pkBigInteger:
|
||||
doAssert(Negative notin prs.bigint.flags, "negative big integers not implemented")
|
||||
var bytes = newSeqOfCap[uint8](prs.bigint.limbs.len * 4)
|
||||
var begun = false
|
||||
for i in countdown(prs.bigint.limbs.high, 0):
|
||||
|
@ -285,8 +292,6 @@ proc write*[T](str: Stream; prs: Preserve[T]) =
|
|||
else:
|
||||
str.write(0xb0'u8)
|
||||
str.writeVarint(bytes.len)
|
||||
if Negative in prs.bigint.flags:
|
||||
bytes[0] = uint8(- bytes[0].int8)
|
||||
str.write(cast[string](bytes))
|
||||
of pkString:
|
||||
str.write(0xb1'u8)
|
||||
|
@ -364,7 +369,7 @@ proc parsePreserve*(s: Stream): Preserve[void] =
|
|||
let len = s.readVarint()
|
||||
result.symbol = s.readStr(len)
|
||||
of 0xb4:
|
||||
result = Preserve[void](kind: pkRecord #[, label: s.parsePreserve()]#)
|
||||
result = Preserve[void](kind: pkRecord)
|
||||
while s.peekUint8() != endMarker:
|
||||
result.record.add(s.parsePreserve())
|
||||
discard s.readUint8()
|
||||
|
@ -389,12 +394,9 @@ proc parsePreserve*(s: Stream): Preserve[void] =
|
|||
discard s.readUint8()
|
||||
of 0xb0:
|
||||
let len = s.readVarint()
|
||||
let initial = s.readInt8()
|
||||
result = Preserve[void](kind: pkBigInteger, bigint: initBigInt(initial))
|
||||
for _ in 2..len:
|
||||
result = Preserve[void](kind: pkBigInteger)
|
||||
for _ in 1..len:
|
||||
result.bigint = (result.bigint shl 8) + s.readUint8().int32
|
||||
if initial < 0:
|
||||
result.bigint.flags = {Negative}
|
||||
else:
|
||||
case 0xf0 and tag
|
||||
of 0x90:
|
||||
|
@ -422,7 +424,15 @@ proc toPreserve*(n: SomeInteger): Preserve[void] =
|
|||
Preserve[void](kind: pkSignedInteger, int: n.BiggestInt)
|
||||
|
||||
proc toPreserve*(n: BigInt): Preserve[void] =
|
||||
Preserve[void](kind: pkBigInteger, bigint: n)
|
||||
if initBigInt(low(BiggestInt)) < n and n < initBigInt(high(BiggestInt)):
|
||||
var tmp: BiggestUint
|
||||
for limb in n.limbs:
|
||||
tmp = (tmp shl 32) or limb
|
||||
if Negative in n.flags:
|
||||
tmp = (not tmp) + 1
|
||||
result = Preserve[void](kind: pkSignedInteger, int: cast[BiggestInt](tmp))
|
||||
else:
|
||||
result = Preserve[void](kind: pkBigInteger, bigint: n)
|
||||
|
||||
proc toPreserve*(s: string): Preserve[void] =
|
||||
Preserve[void](kind: pkString, string: s)
|
||||
|
|
|
@ -50,8 +50,8 @@ suite "native":
|
|||
|
||||
suite "big":
|
||||
let testVectors = @[
|
||||
("87112285931760246646623899502532662132736", "B012010000000000000000000000000000000000"),
|
||||
("-87112285931760246646623899502532662132736", "B012FF0000000000000000000000000000000000"),
|
||||
("87112285931760246646623899502532662132736",
|
||||
"B012010000000000000000000000000000000000"),
|
||||
]
|
||||
|
||||
for (decimals, hex) in testVectors:
|
||||
|
|
Loading…
Reference in New Issue