Allow any integer type to use CT.isEqual(). (#51)

* Allow any integer type to use CT.isEqual().
* Add tests for different integer types.
This commit is contained in:
Eugene Kabanov 2020-07-30 20:09:49 +03:00 committed by GitHub
parent a5560c1ea6
commit 4c695e5933
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
2 changed files with 66 additions and 6 deletions

View File

@ -11,9 +11,15 @@
type
CT* = object
AnyByte* = byte | char
proc isEqual*[A: AnyByte, B: AnyByte](c: typedesc[CT], a: openArray[A],
when sizeof(int) == 8:
type
AnyItem* = byte|char|int8|uint16|int16|uint32|int32|uint64|int64|uint|int
elif sizeof(int) == 4:
type
AnyItem* = byte|char|int8|uint16|int16|uint32|int32|uint|int
proc isEqual*[A: AnyItem, B: AnyItem](c: typedesc[CT], a: openArray[A],
b: openArray[B]): bool {.
raises: [Defect] .} =
## Perform constant time comparison of two arrays ``a`` and ``b``.
@ -25,11 +31,15 @@ proc isEqual*[A: AnyByte, B: AnyByte](c: typedesc[CT], a: openArray[A],
## part of array's content is equal to another array's content if arrays
## lengths are different.
##
## Beware that arrays ``a`` and ``b`` MUST NOT BE empty.
## Beware that arrays ``a`` and ``b`` MUST NOT BE empty. Types ``A`` and
## ``B`` should be equal in size, e.g. ``(sizeof(A) == sizeof(B))``
doAssert(len(a) > 0 and len(b) > 0)
doAssert(sizeof(A) == sizeof(B))
var count = min(len(a), len(b))
var res = 0
var res = 0'u
while count > 0:
dec(count)
res = res or int(int(a[count]) xor int(b[count]))
(res == 0)
let av = when A is uint: a[count] else: uint(a[count])
let bv = when B is uint: b[count] else: uint(b[count])
res = res or (av xor bv)
(res == 0'u)

View File

@ -28,6 +28,26 @@ suite "Constant-time operations test suite":
seq4 = @byteArr4
seq5 = @byteArr5
int8Arr = [1'i8, 2'i8, 3'i8]
int16Arr = [1'i16, 2'i16, 3'i16]
int32Arr = [1'i32, 2'i32, 3'i32]
intArr = [1, 2, 3]
uint8Arr = [1'u8, 2'u8, 3'u8]
uint16Arr = [1'u16, 2'u16, 3'u16]
uint32Arr = [1'u32, 2'u32, 3'u32]
uintArr = [1'u, 2'u, 3'u]
var
emptyArray: array[0, byte]
emptyString = ""
emptySeq = newSeq[byte]()
when sizeof(int) == 8:
let
int64Arr = [1'i64, 2'i64, 3'i64]
uint64Arr = [1'u64, 2'u64, 3'u64]
check:
CT.isEqual(charArr1, charArr1) == true
CT.isEqual(charArr1, byteArr1) == true
@ -53,3 +73,33 @@ suite "Constant-time operations test suite":
CT.isEqual(str1, byteArr5) == false
CT.isEqual(seq1, str5) == false
CT.isEqual(charArr1, seq5) == false
CT.isEqual(int8Arr, int8Arr) == true
CT.isEqual(int8Arr, uint8Arr) == true
CT.isEqual(int16Arr, int16Arr) == true
CT.isEqual(int16Arr, uint16Arr) == true
CT.isEqual(int32Arr, int32Arr) == true
CT.isEqual(int32Arr, uint32Arr) == true
CT.isEqual(intArr, intArr) == true
CT.isEqual(intArr, uintArr) == true
when sizeof(int) == 8:
check:
CT.isEqual(int64Arr, int64Arr) == true
CT.isEqual(int64Arr, uint64Arr) == true
# Empty arrays
expect(AssertionError):
discard CT.isEqual(emptyArray, emptyArray)
expect(AssertionError):
discard CT.isEqual(emptyArray, emptyString)
expect(AssertionError):
discard CT.isEqual(emptyArray, emptySeq)
# Arrays, where T is different type size
expect(AssertionError):
discard CT.isEqual(int8Arr, int16Arr)
expect(AssertionError):
discard CT.isEqual(int16Arr, int32Arr)
expect(AssertionError):
discard CT.isEqual(int8Arr, intArr)