Add byteutils.hexToByteArrayStrict (#120)
This commit is contained in:
parent
b3ea2c6b46
commit
9fe9cb7002
|
@ -31,14 +31,14 @@ proc readHexChar*(c: char): byte
|
||||||
else:
|
else:
|
||||||
raise newException(ValueError, $c & " is not a hexadecimal character")
|
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
|
## Returns the index of the first meaningful char in `hexStr` by skipping
|
||||||
## "0x" prefix
|
## "0x" prefix
|
||||||
if hexStr.len > 1 and hexStr[0] == '0' and hexStr[1] in {'x', 'X'}: 2
|
if hexStr.len > 1 and hexStr[0] == '0' and hexStr[1] in {'x', 'X'}: 2
|
||||||
else: 0
|
else: 0
|
||||||
|
|
||||||
func hexToByteArray*(hexStr: string, output: var openArray[byte], fromIdx, toIdx: int)
|
func hexToByteArrayImpl(hexStr: openArray[char], output: var openArray[byte], fromIdx, toIdx: int): int
|
||||||
{.raises: [ValueError, Defect].} =
|
{.raises: [ValueError, Defect].} =
|
||||||
## Read a hex string and store it in a byte array `output`. No "endianness" reordering is done.
|
## 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
|
## Allows specifying the byte range to process into the array
|
||||||
var sIdx = skip0xPrefix(hexStr)
|
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
|
output[bIdx] = hexStr[sIdx].readHexChar shl 4 or hexStr[sIdx + 1].readHexChar
|
||||||
inc(sIdx, 2)
|
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])
|
func hexToByteArray*(hexStr: string, output: var openArray[byte])
|
||||||
{.raises: [ValueError, Defect], inline.} =
|
{.raises: [ValueError, Defect], inline.} =
|
||||||
## Read a hex string and store it in a byte array `output`. No "endianness" reordering is done.
|
## 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)
|
hexToByteArray(hexStr, output, 0, output.high)
|
||||||
|
|
||||||
func hexToByteArray*[N: static[int]](hexStr: string): array[N, byte]
|
func hexToByteArray*[N: static[int]](hexStr: string): array[N, byte]
|
||||||
{.raises: [ValueError, Defect], noinit, inline.}=
|
{.raises: [ValueError, Defect], noinit, inline.}=
|
||||||
## Read an hex string and store it in a byte array. No "endianness" reordering is done.
|
## 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)
|
hexToByteArray(hexStr, result)
|
||||||
|
|
||||||
func hexToByteArray*(hexStr: string, N: static int): array[N, byte]
|
func hexToByteArray*(hexStr: string, N: static int): array[N, byte]
|
||||||
{.raises: [ValueError, Defect], noinit, inline.}=
|
{.raises: [ValueError, Defect], noinit, inline.}=
|
||||||
## Read an hex string and store it in a byte array. No "endianness" reordering is done.
|
## 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)
|
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
|
func fromHex*[N](A: type array[N, byte], hexStr: string): A
|
||||||
{.raises: [ValueError, Defect], noinit, inline.}=
|
{.raises: [ValueError, Defect], noinit, inline.}=
|
||||||
## Read an hex string and store it in a byte array. No "endianness" reordering is done.
|
## Read an hex string and store it in a byte array. No "endianness" reordering is done.
|
||||||
|
|
|
@ -28,6 +28,32 @@ suite "Byte utils":
|
||||||
hexToByteArray(s, a)
|
hexToByteArray(s, a)
|
||||||
check a == [255.byte, 255, 255, 255]
|
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":
|
test "hexToByteArray: Return array":
|
||||||
let
|
let
|
||||||
s = "0x12345678"
|
s = "0x12345678"
|
||||||
|
@ -115,6 +141,7 @@ suite "Byte utils":
|
||||||
string.fromBytes([]) == ""
|
string.fromBytes([]) == ""
|
||||||
@[byte(ord('a'))] == static("a".toBytes())
|
@[byte(ord('a'))] == static("a".toBytes())
|
||||||
"a" == static(string.fromBytes([byte(ord('a'))]))
|
"a" == static(string.fromBytes([byte(ord('a'))]))
|
||||||
|
|
||||||
test "slices":
|
test "slices":
|
||||||
var a: array[4, byte]
|
var a: array[4, byte]
|
||||||
a[0..<2] = [2'u8, 3]
|
a[0..<2] = [2'u8, 3]
|
||||||
|
|
Loading…
Reference in New Issue