Skip to content

Commit 0f0284f

Browse files
committed
Add fromBytes proc
1 parent c132edd commit 0f0284f

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