2019-07-06 18:07:41 +00:00
|
|
|
# byteutils
|
2022-07-18 11:02:40 +00:00
|
|
|
# Copyright (c) 2018-2022 Status Research & Development GmbH
|
2019-07-06 18:07:41 +00:00
|
|
|
# Licensed and distributed under either of
|
|
|
|
# * MIT license (license terms in the root directory or at http://opensource.org/licenses/MIT).
|
|
|
|
# * Apache v2 license (license terms in the root directory or at http://www.apache.org/licenses/LICENSE-2.0).
|
|
|
|
# at your option. This file may not be copied, modified, or distributed except according to those terms.
|
|
|
|
|
2022-07-18 11:02:40 +00:00
|
|
|
{.used.}
|
|
|
|
|
2020-12-10 11:05:22 +00:00
|
|
|
import
|
2022-07-08 09:34:21 +00:00
|
|
|
unittest2,
|
2020-12-10 11:05:22 +00:00
|
|
|
../stew/byteutils
|
2019-10-02 10:54:13 +00:00
|
|
|
|
|
|
|
proc compilationTest {.exportc: "compilationTest".} =
|
|
|
|
var bytes = @[1.byte, 2, 3, 4]
|
|
|
|
writeFile("test", bytes)
|
2019-07-06 18:07:41 +00:00
|
|
|
|
|
|
|
suite "Byte utils":
|
2023-11-14 10:53:47 +00:00
|
|
|
const simpleBArray = [0x12.byte, 0x34, 0x56, 0x78]
|
2019-07-06 18:07:41 +00:00
|
|
|
|
2023-11-14 10:53:47 +00:00
|
|
|
dualTest "hexToByteArray: Inplace partial string":
|
2019-07-06 18:07:41 +00:00
|
|
|
let s = "0x1234567890"
|
|
|
|
var a: array[5, byte]
|
|
|
|
hexToByteArray(s, a, 1, 3)
|
|
|
|
check a == [0.byte, 0x34, 0x56, 0x78, 0]
|
|
|
|
|
2023-11-14 10:53:47 +00:00
|
|
|
dualTest "hexToByteArray: Inplace full string":
|
2019-07-06 18:07:41 +00:00
|
|
|
let s = "0xffffffff"
|
|
|
|
var a: array[4, byte]
|
|
|
|
hexToByteArray(s, a)
|
|
|
|
check a == [255.byte, 255, 255, 255]
|
|
|
|
|
2023-11-14 10:53:47 +00:00
|
|
|
dualTest "hexToByteArrayStrict":
|
2022-06-17 08:37:06 +00:00
|
|
|
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
|
|
|
|
|
2023-11-14 10:53:47 +00:00
|
|
|
dualTest "hexToByteArray: Return array":
|
2019-07-06 18:07:41 +00:00
|
|
|
let
|
|
|
|
s = "0x12345678"
|
|
|
|
a = hexToByteArray[4](s)
|
|
|
|
check a == simpleBArray
|
|
|
|
|
2020-04-09 09:20:21 +00:00
|
|
|
expect(ValueError): discard hexToByteArray[1]("")
|
|
|
|
expect(ValueError): discard hexToByteArray[1]("1")
|
|
|
|
|
2023-11-14 10:53:47 +00:00
|
|
|
dualTest "hexToByteArray: missing bytes":
|
2023-01-19 07:19:26 +00:00
|
|
|
var buffer: array[1, byte]
|
|
|
|
expect(ValueError):
|
|
|
|
hexToByteArray("0x", buffer)
|
|
|
|
expect(ValueError):
|
|
|
|
hexToByteArray("", buffer)
|
|
|
|
expect(ValueError):
|
|
|
|
hexToByteArray("0", buffer)
|
|
|
|
|
2023-11-14 10:53:47 +00:00
|
|
|
dualTest "valid hex with empty array":
|
2023-01-19 07:19:26 +00:00
|
|
|
var buffer: seq[byte]
|
|
|
|
hexToByteArray("0x123", openArray[byte](buffer))
|
|
|
|
check(buffer == seq[byte](@[]))
|
|
|
|
|
2023-11-14 10:53:47 +00:00
|
|
|
dualTest "valid hex with empty array of size":
|
2023-01-19 07:19:26 +00:00
|
|
|
var buffer: seq[byte] = newSeq[byte](4)
|
|
|
|
hexToByteArray("00000123", openArray[byte](buffer))
|
|
|
|
check(buffer == @[0.byte, 0.byte, 1.byte, 35.byte])
|
|
|
|
check buffer.toHex == "00000123"
|
|
|
|
|
2023-11-14 10:53:47 +00:00
|
|
|
dualTest "empty output array is ok":
|
2023-01-19 07:19:26 +00:00
|
|
|
var output: array[0, byte]
|
|
|
|
|
|
|
|
hexToByteArray("", output)
|
|
|
|
hexToByteArray("0x", output)
|
|
|
|
hexToByteArray("0x32", output)
|
|
|
|
|
2023-11-14 10:53:47 +00:00
|
|
|
dualTest "array.fromHex":
|
2020-07-02 15:00:39 +00:00
|
|
|
let
|
|
|
|
s = "0x12345678"
|
|
|
|
a2 = array[2, byte].fromHex(s)
|
|
|
|
a4 = array[4, byte].fromHex(s)
|
|
|
|
|
|
|
|
check:
|
|
|
|
a2.toHex == "1234"
|
|
|
|
a4.toHex == "12345678"
|
|
|
|
|
|
|
|
expect(ValueError): echo array[5, byte].fromHex(s)
|
|
|
|
|
2023-11-14 10:53:47 +00:00
|
|
|
dualTest "toHex":
|
2019-07-06 18:07:41 +00:00
|
|
|
check simpleBArray.toHex == "12345678"
|
2020-04-09 09:20:21 +00:00
|
|
|
check hexToSeqByte("12345678") == simpleBArray
|
|
|
|
check hexToSeqByte("00") == [byte 0]
|
|
|
|
check hexToSeqByte("0x") == []
|
|
|
|
expect(ValueError): discard hexToSeqByte("1234567")
|
|
|
|
expect(ValueError): discard hexToSeqByte("X")
|
|
|
|
expect(ValueError): discard hexToSeqByte("0")
|
2022-01-06 16:05:47 +00:00
|
|
|
check simpleBArray.to0xHex == "0x12345678"
|
2019-07-06 18:07:41 +00:00
|
|
|
|
|
|
|
test "Array concatenation":
|
|
|
|
check simpleBArray & simpleBArray ==
|
|
|
|
[0x12.byte, 0x34, 0x56, 0x78, 0x12, 0x34, 0x56, 0x78]
|
|
|
|
|
2023-11-14 10:53:47 +00:00
|
|
|
dualTest "hexToPaddedByteArray":
|
2019-07-06 18:07:41 +00:00
|
|
|
block:
|
|
|
|
let a = hexToPaddedByteArray[4]("0x123")
|
|
|
|
check a.toHex == "00000123"
|
|
|
|
block:
|
|
|
|
let a = hexToPaddedByteArray[4]("0x1234")
|
|
|
|
check a.toHex == "00001234"
|
|
|
|
block:
|
|
|
|
let a = hexToPaddedByteArray[4]("0x1234567")
|
|
|
|
check a.toHex == "01234567"
|
|
|
|
block:
|
|
|
|
let a = hexToPaddedByteArray[4]("0x12345678")
|
|
|
|
check a.toHex == "12345678"
|
|
|
|
block:
|
|
|
|
let a = hexToPaddedByteArray[32]("0x68656c6c6f20776f726c64")
|
|
|
|
check a.toHex == "00000000000000000000000000000000000000000068656c6c6f20776f726c64"
|
|
|
|
block:
|
2020-04-09 09:20:21 +00:00
|
|
|
expect ValueError:
|
2019-12-20 12:23:30 +00:00
|
|
|
discard hexToPaddedByteArray[2]("0x12345")
|
2019-12-19 12:29:38 +00:00
|
|
|
|
2023-11-14 10:53:47 +00:00
|
|
|
dualTest "lessThan":
|
2019-12-19 12:29:38 +00:00
|
|
|
let
|
|
|
|
a = [0'u8, 1, 2]
|
|
|
|
b = [2'u8, 1, 0]
|
|
|
|
c = [0'u8, 1, 2, 3]
|
|
|
|
d = [0'u8, 1, 3, 3]
|
|
|
|
|
|
|
|
check:
|
|
|
|
not (a < a)
|
|
|
|
|
|
|
|
a < b
|
|
|
|
not (b < a)
|
|
|
|
|
|
|
|
c < b
|
|
|
|
not (b < c)
|
|
|
|
|
|
|
|
a < c
|
|
|
|
not (c < a)
|
|
|
|
|
|
|
|
c < d
|
|
|
|
not (d < c)
|
2020-03-04 22:09:42 +00:00
|
|
|
|
2023-11-14 10:53:47 +00:00
|
|
|
proc copyView(v: openArray[char]): seq[byte] =
|
|
|
|
v.toBytes()
|
|
|
|
|
|
|
|
dualTest "strings":
|
2020-03-04 22:09:42 +00:00
|
|
|
check:
|
|
|
|
"a".toBytes() == @[byte(ord('a'))]
|
2023-11-14 10:53:47 +00:00
|
|
|
copyView("a") == @[byte(ord('a'))]
|
|
|
|
|
2020-03-04 22:09:42 +00:00
|
|
|
string.fromBytes([byte(ord('a'))]) == "a"
|
2020-03-04 23:42:04 +00:00
|
|
|
|
2020-03-07 22:29:46 +00:00
|
|
|
"".toBytes().len() == 0
|
|
|
|
string.fromBytes([]) == ""
|
2020-05-06 13:51:07 +00:00
|
|
|
@[byte(ord('a'))] == static("a".toBytes())
|
|
|
|
"a" == static(string.fromBytes([byte(ord('a'))]))
|
2022-06-17 08:37:06 +00:00
|
|
|
|
2023-11-14 10:53:47 +00:00
|
|
|
test "strings cast":
|
|
|
|
check:
|
|
|
|
cast[ptr UncheckedArray[byte]](cstring(string.fromBytes([byte(ord('a'))])))[1] == byte(0)
|
|
|
|
|
2020-03-04 23:42:04 +00:00
|
|
|
test "slices":
|
|
|
|
var a: array[4, byte]
|
|
|
|
a[0..<2] = [2'u8, 3]
|
|
|
|
check:
|
|
|
|
a[1] == 3
|
|
|
|
|
|
|
|
a.toOpenArray(0, 3)[0..<2] = [4'u8, 5]
|
|
|
|
check:
|
|
|
|
a[1] == 5
|