math.big: add from_bytes function (#11213)

pull/11220/head
Miccah 2021-08-17 01:12:39 -05:00 committed by GitHub
parent 90b25e7a4b
commit 19abe8c750
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
2 changed files with 36 additions and 0 deletions

View File

@ -118,6 +118,28 @@ pub fn from_string(input string) Number {
return n return n
} }
// from_bytes converts an array of bytes (little-endian) to a big.Number.
// Higher precedence bytes are expected at lower indices in the array.
pub fn from_bytes(input []byte) ?Number {
if input.len > 128 {
return error('input array too large. big.Number can only hold up to 1024 bit numbers')
}
// pad input
mut padded_input := []byte{len: ((input.len + 3) & ~0x3) - input.len, cap: (input.len + 3) & ~0x3, init: 0x0}
padded_input << input
// combine every 4 bytes into a u32 and insert into n.array
mut n := Number{}
for i := 0; i < padded_input.len; i += 4 {
x3 := u32(padded_input[i])
x2 := u32(padded_input[i + 1])
x1 := u32(padded_input[i + 2])
x0 := u32(padded_input[i + 3])
val := (x3 << 24) | (x2 << 16) | (x1 << 8) | x0
n.array[(padded_input.len - i) / 4 - 1] = val
}
return n
}
// .int() converts (a small) big.Number `n` to an ordinary integer. // .int() converts (a small) big.Number `n` to an ordinary integer.
pub fn (n &Number) int() int { pub fn (n &Number) int() int {
r := C.bignum_to_int(n) r := C.bignum_to_int(n)

View File

@ -165,3 +165,17 @@ fn test_bytes_trimmed() {
assert big.from_int(1024).bytes_trimmed() == [byte(0x00), 0x04] assert big.from_int(1024).bytes_trimmed() == [byte(0x00), 0x04]
assert big.from_int(1048576).bytes_trimmed() == [byte(0x00), 0x00, 0x10] assert big.from_int(1048576).bytes_trimmed() == [byte(0x00), 0x00, 0x10]
} }
fn test_from_bytes() ? {
assert big.from_bytes([]) ?.hexstr() == '0'
assert big.from_bytes([byte(0x13)]) ?.hexstr() == '13'
assert big.from_bytes([byte(0x13), 0x37]) ?.hexstr() == '1337'
assert big.from_bytes([byte(0x13), 0x37, 0xca]) ?.hexstr() == '1337ca'
assert big.from_bytes([byte(0x13), 0x37, 0xca, 0xfe]) ?.hexstr() == '1337cafe'
assert big.from_bytes([byte(0x13), 0x37, 0xca, 0xfe, 0xba]) ?.hexstr() == '1337cafeba'
assert big.from_bytes([byte(0x13), 0x37, 0xca, 0xfe, 0xba, 0xbe]) ?.hexstr() == '1337cafebabe'
assert big.from_bytes([]byte{len: 128, init: 0x0}) ?.hexstr() == '0'
if x := big.from_bytes([]byte{len: 129, init: 0x0}) {
return error('expected error, got $x')
}
}