Add byteutils.hexToByteArrayStrict (#120)

This commit is contained in:
zah 2022-06-17 11:37:06 +03:00 committed by GitHub
parent b3ea2c6b46
commit 9fe9cb7002
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
2 changed files with 67 additions and 3 deletions

View File

@ -31,14 +31,14 @@ proc readHexChar*(c: char): byte
else:
raise newException(ValueError, $c & " is not a hexadecimal character")
template skip0xPrefix(hexStr: string): int =
template skip0xPrefix(hexStr: openArray[char]): int =
## Returns the index of the first meaningful char in `hexStr` by skipping
## "0x" prefix
if hexStr.len > 1 and hexStr[0] == '0' and hexStr[1] in {'x', 'X'}: 2
else: 0
func hexToByteArray*(hexStr: string, output: var openArray[byte], fromIdx, toIdx: int)
{.raises: [ValueError, Defect].} =
func hexToByteArrayImpl(hexStr: openArray[char], output: var openArray[byte], fromIdx, toIdx: int): int
{.raises: [ValueError, Defect].} =
## Read a hex string and store it in a byte array `output`. No "endianness" reordering is done.
## Allows specifying the byte range to process into the array
var sIdx = skip0xPrefix(hexStr)
@ -53,21 +53,58 @@ func hexToByteArray*(hexStr: string, output: var openArray[byte], fromIdx, toIdx
output[bIdx] = hexStr[sIdx].readHexChar shl 4 or hexStr[sIdx + 1].readHexChar
inc(sIdx, 2)
sIdx
func hexToByteArray*(hexStr: string, output: var openArray[byte], fromIdx, toIdx: int)
{.raises: [ValueError, Defect].} =
## Read a hex string and store it in a byte array `output`. No "endianness" reordering is done.
## Allows specifying the byte range to process into the array.
## The hex input may be longer than strictly necessary.
discard hexToByteArrayImpl(hexStr, output, fromIdx, toIdx)
func hexToByteArray*(hexStr: string, output: var openArray[byte])
{.raises: [ValueError, Defect], inline.} =
## Read a hex string and store it in a byte array `output`. No "endianness" reordering is done.
## The hex input may be longer than strictly necessary.
hexToByteArray(hexStr, output, 0, output.high)
func hexToByteArray*[N: static[int]](hexStr: string): array[N, byte]
{.raises: [ValueError, Defect], noinit, inline.}=
## Read an hex string and store it in a byte array. No "endianness" reordering is done.
## The hex input may be longer than strictly necessary.
hexToByteArray(hexStr, result)
func hexToByteArray*(hexStr: string, N: static int): array[N, byte]
{.raises: [ValueError, Defect], noinit, inline.}=
## Read an hex string and store it in a byte array. No "endianness" reordering is done.
## The hex input may be longer than strictly necessary.
hexToByteArray(hexStr, result)
func hexToByteArrayStrict*(hexStr: openArray[char], output: var openArray[byte], fromIdx, toIdx: int)
{.raises: [ValueError, Defect].} =
## Read a hex string and store it in a byte array `output`. No "endianness" reordering is done.
## Allows specifying the byte range to process into the array. The entire input must be consumed.
if hexToByteArrayImpl(hexStr, output, fromIdx, toIdx) != hexStr.len:
raise (ref ValueError)(msg: "hex string too long")
func hexToByteArrayStrict*(hexStr: openArray[char], output: var openArray[byte])
{.raises: [ValueError, Defect], inline.} =
## Read a hex string and store it in a byte array `output`. No "endianness" reordering is done.
## The entire input must be consumed.
hexToByteArrayStrict(hexStr, output, 0, output.high)
func hexToByteArrayStrict*[N: static[int]](hexStr: openArray[char]): array[N, byte]
{.raises: [ValueError, Defect], noinit, inline.}=
## Read an hex string and store it in a byte array. No "endianness" reordering is done.
## The entire input must be consumed.
hexToByteArrayStrict(hexStr, result)
func hexToByteArrayStrict*(hexStr: openArray[char], N: static int): array[N, byte]
{.raises: [ValueError, Defect], noinit, inline.}=
## Read an hex string and store it in a byte array. No "endianness" reordering is done.
## The entire input must be consumed.
hexToByteArrayStrict(hexStr, result)
func fromHex*[N](A: type array[N, byte], hexStr: string): A
{.raises: [ValueError, Defect], noinit, inline.}=
## Read an hex string and store it in a byte array. No "endianness" reordering is done.

View File

@ -28,6 +28,32 @@ suite "Byte utils":
hexToByteArray(s, a)
check a == [255.byte, 255, 255, 255]
test "hexToByteArrayStrict":
let
short0 = ""
short1 = "0x"
short2 = "0x00"
short3 = "0xffffff"
short4 = "0xfffffff"
correct = "0xffffffff"
long1 = "0xfffffffff"
long2 = "0xffffffffff"
var a: array[4, byte]
hexToByteArrayStrict(correct, a)
check a == [255.byte, 255, 255, 255]
template reject(val: string) =
expect ValueError: hexToByteArrayStrict(val, a)
reject short0
reject short1
reject short2
reject short3
reject short4
reject long1
reject long2
test "hexToByteArray: Return array":
let
s = "0x12345678"
@ -115,6 +141,7 @@ suite "Byte utils":
string.fromBytes([]) == ""
@[byte(ord('a'))] == static("a".toBytes())
"a" == static(string.fromBytes([byte(ord('a'))]))
test "slices":
var a: array[4, byte]
a[0..<2] = [2'u8, 3]