Support automatic padding when constructing values from byte arrays

This commit is contained in:
Zahary Karadjov 2018-07-04 17:23:13 +03:00
parent 6ae8de932d
commit f00f525352
1 changed files with 39 additions and 13 deletions

View File

@ -300,6 +300,44 @@ func dumpHex*(x: Stint or StUint): string {.inline.}=
# TODO: Have a default static argument in the previous proc. Currently we get
# "Cannot evaluate at compile-time".
proc initFromBytesBE*[bits: static[int]](val: var Stuint[bits], ba: openarray[byte], allowPadding: static[bool] = true) =
## Initializes a UInt[bits] value from a byte buffer storing a big-endian
## representation of a number.
##
## If `allowPadding` is set to false, the input array must be exactly
## (bits div 8) bytes long. Otherwise, it may be shorter and the remaining
## bytes will be assumed to be zero.
const N = bits div 8
when not allowPadding:
assert(ba.len == N)
else:
assert ba.len <= N
{.pragma: restrict, codegenDecl: "$# __restrict $#".}
let r_ptr {.restrict.} = cast[ptr array[N, byte]](val.addr)
when system.cpuEndian == bigEndian:
# TODO: due to https://github.com/status-im/nim-stint/issues/38
# We can't cast a stack byte array to stuint with a convenient proc signature.
when allowPadding:
let baseIdx = N - val.len
for i, b in ba: r_ptr[baseIdx + i] = b
else:
for i, b in ba: r_ptr[i] = b
else:
when allowPadding:
let baseIdx = ba.len - 1
for i, b in ba: r_ptr[baseIdx - i] = b
else:
for i, b in ba: r_ptr[N-1 - i] = b
func fromBytesBE*(T: type Stuint, ba: openarray[byte],
allowPadding: static[bool] = true): T =
## This function provides a convenience wrapper around `initFromBytesBE`.
result.initFromBytesBE(ba, allowPadding)
func readUintBE*[bits: static[int]](ba: openarray[byte]): Stuint[bits] =
## Convert a big-endian array of (bits div 8) Bytes to an UInt[bits] (in native host endianness)
## Input:
@ -308,19 +346,7 @@ func readUintBE*[bits: static[int]](ba: openarray[byte]): Stuint[bits] =
## - A unsigned integer of the same size with `bits` bits
##
## ⚠ If the openarray length is bigger than bits div 8, part converted is undefined behaviour.
const N = bits div 8
assert(ba.len == N)
{.pragma: restrict, codegenDecl: "$# __restrict $#".}
let r_ptr {.restrict.} = cast[ptr array[N, byte]](result.addr)
for i, val in ba:
when system.cpuEndian == bigEndian:
# TODO: due to https://github.com/status-im/nim-stint/issues/38
# We can't cast a stack byte array to stuint with a convenient proc signature.
r_ptr[i] = val
else:
r_ptr[N-1 - i] = val
result.initFromBytesBE(ba, false)
func toByteArrayBE*[bits: static[int]](n: StUint[bits]): array[bits div 8, byte] =
## Convert a uint[bits] to to a big-endian array of bits div 8 bytes