fix little-endian parsing

This commit is contained in:
mratsim 2018-12-03 21:01:29 +01:00
parent 2856378427
commit 059439b2c3
2 changed files with 43 additions and 22 deletions

View File

@ -75,12 +75,11 @@ func readDecChar(c: range['0'..'9']): int {.inline.}=
#
# ############################################################
func parseRawUint*(
func parseRawUintLE(
src: openarray[byte],
bits: static int,
endian: static Endianness): BigInt[bits] =
bits: static int): BigInt[bits] {.inline.}=
## Parse an unsigned integer from its canonical
## big-endian or little-endian unsigned representation
## little-endian unsigned representation
## And store it into a BigInt of size bits
##
## CT:
@ -91,28 +90,39 @@ func parseRawUint*(
acc = Word(0)
acc_len = 0
template body(){.dirty.} =
for src_idx in 0 ..< src.len:
let src_byte = Word(src[src_idx])
acc = acc and (src_byte shl acc_len)
# buffer reads
acc = acc or (src_byte shl acc_len)
acc_len += 8 # We count bit by bit
# if full, dump
if acc_len >= WordBitSize:
result[dst_idx] = acc and MaxWord
inc dst_idx
acc_len -= WordBitSize
acc = src_byte shr (8 - acc_len)
when endian == bigEndian:
for src_idx in countdown(src.high, 0):
body()
else:
for src_idx in 0 ..< src.len:
body()
if acc_len != 0:
result[dst_idx] = acc
func parseRawUint*(
src: openarray[byte],
bits: static int,
order: static Endianness): BigInt[bits] =
## Parse an unsigned integer from its canonical
## big-endian or little-endian unsigned representation
## And store it into a BigInt of size bits
##
## CT:
## - no leaks
when order == littleEndian:
parseRawUintLE(src, bits)
else:
{.error: "Not implemented at the moment".}
# ############################################################
#
# Serialising from internal representation to canonical format

View File

@ -31,8 +31,9 @@ suite "IO":
T(big[0]) == 0
T(big[1]) == 1
test "Parsing and dumping round-trip":
block: # "Little-endian"
test "Parsing and dumping round-trip on uint64":
block:
# "Little-endian" - 2^63
let x = 1'u64 shl 63
let x_bytes = cast[array[8, byte]](x)
let big = parseRawUint(x_bytes, 64, littleEndian) # It's fine even on big-endian platform. We only want the byte-pattern
@ -41,11 +42,21 @@ suite "IO":
dumpRawUint(r_bytes, big, littleEndian)
check: x_bytes == r_bytes
# block: # "Little-endian"
# let x = uint64 rand(0..high(int))
# let x_bytes = cast[array[8, byte]](x)
# let big = parseRawUint(x_bytes, 64, littleEndian) # It's fine even on big-endian platform. We only want the byte-pattern
block: # "Little-endian" - single random
let x = uint64 rand(0..high(int))
let x_bytes = cast[array[8, byte]](x)
let big = parseRawUint(x_bytes, 64, littleEndian) # It's fine even on big-endian platform. We only want the byte-pattern
# var r_bytes: array[8, byte]
# dumpRawUint(r_bytes, big, littleEndian)
# check: x_bytes == r_bytes
var r_bytes: array[8, byte]
dumpRawUint(r_bytes, big, littleEndian)
check: x_bytes == r_bytes
block: # "Little-endian" - 10 random cases
for _ in 0 ..< 10:
let x = uint64 rand(0..high(int))
let x_bytes = cast[array[8, byte]](x)
let big = parseRawUint(x_bytes, 64, littleEndian) # It's fine even on big-endian platform. We only want the byte-pattern
var r_bytes: array[8, byte]
dumpRawUint(r_bytes, big, littleEndian)
check: x_bytes == r_bytes