Skip to content

Commit 6d77ea7

Browse files
committed
Add fromBytes proc
1 parent de8b594 commit 6d77ea7

File tree

3 files changed

+61
-0
lines changed

3 files changed

+61
-0
lines changed

src/bigints.nim

Lines changed: 46 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1331,3 +1331,49 @@ proc toBytes*(a: BigInt; endianness = system.cpuEndian): seq[byte] =
13311331
while result[pred i] == 0x00:
13321332
dec i
13331333
result.setLen(i)
1334+
1335+
proc fromBytes*(result: var BigInt; buf: openarray[uint8]; endianness = system.cpuEndian) =
1336+
## Convert a byte-sequence to `BigInt` value.
1337+
## The input `buf` is only interpreted as a natural (positive) number.
1338+
runnableExamples:
1339+
var n: BigInt
1340+
n.fromBytes([0x1'u8,0x2,0x3,0x4,0x5,0x6,0x7,0x8,0xA], bigEndian)
1341+
n = -n
1342+
doAssert n == initBigInt("-18591708106338011146")
1343+
result.limbs.setLen((buf.len + 3) shr 2)
1344+
case endianness
1345+
of bigEndian:
1346+
var
1347+
li = result.limbs.high
1348+
bi = buf.low
1349+
block:
1350+
var
1351+
limb: uint32
1352+
j = 4 - (buf.len and 3)
1353+
while j < 4:
1354+
limb = (limb shl 8) or buf[bi].uint32
1355+
inc(bi)
1356+
inc(j)
1357+
if bi > 0:
1358+
result.limbs[li] = limb
1359+
dec(li)
1360+
while li >= 0:
1361+
bigEndian32(addr result.limbs[li], unsafeAddr buf[bi])
1362+
inc(bi, 4)
1363+
dec(li)
1364+
of littleEndian:
1365+
var
1366+
li = result.limbs.low
1367+
bi = buf.low
1368+
while (bi + 4) < buf.len:
1369+
littleEndian32(addr result.limbs[li], unsafeAddr buf[bi])
1370+
inc(bi, 4)
1371+
inc(li)
1372+
if bi < buf.len:
1373+
var
1374+
limb: uint32
1375+
ji = buf.high
1376+
while ji >= bi:
1377+
limb = (limb shl 8) or buf[ji]
1378+
dec(ji)
1379+
result.limbs[li] = limb

tests/tbigints.nim

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -886,9 +886,15 @@ proc main() =
886886
block:
887887
let buf = n.toBytes(bigEndian)
888888
doAssert buf == @[ 0x1'u8, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7, 0x8, 0xA]
889+
var res: Bigint
890+
res.fromBytes(buf, bigEndian)
891+
doAssert res == n
889892
block:
890893
let buf = n.toBytes(littleEndian)
891894
doAssert buf == @[ 0xA'u8, 0x8, 0x7, 0x6, 0x5, 0x4, 0x3, 0x2, 0x1 ]
895+
var res: Bigint
896+
res.fromBytes(buf, littleEndian)
897+
doAssert res == n
892898

893899

894900
static: main()

tests/trandom.nim

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -20,3 +20,12 @@ block: # check uniformity
2020
doAssert(trials/nbuckets*0.5 < float(x))
2121
doAssert(float(x) < trials/nbuckets*1.5)
2222

23+
block: # check serialization roundtrip
24+
const
25+
trials = 1024
26+
var a, b: Bigint
27+
for x in 0..trials:
28+
a = rand(0.initBigInt..pow(2.initBigInt, x))
29+
for endian in [bigEndian, littleEndian]:
30+
b.fromBytes(a.toBytes(endian), endian)
31+
doAssert a == b

0 commit comments

Comments
 (0)