From 732d8101e07326c93a6010fdaa3490809ce3b5fb Mon Sep 17 00:00:00 2001 From: Delyan Angelov Date: Mon, 19 Jul 2021 16:42:37 +0300 Subject: [PATCH] math.big: add .bytes() and .bytes_trimmed() methods, `big.from_int(1024).bytes_trimmed() == [byte(0x00), 0x04]` --- vlib/math/big/big.v | 34 ++++++++++++++++++++++++++++++++++ vlib/math/big/big_test.v | 22 ++++++++++++++++++++++ 2 files changed, 56 insertions(+) diff --git a/vlib/math/big/big.v b/vlib/math/big/big.v index 0bbb5717d9..00658c799c 100644 --- a/vlib/math/big/big.v +++ b/vlib/math/big/big.v @@ -282,3 +282,37 @@ pub fn factorial(nn Number) Number { pub fn fact(n int) Number { return factorial(from_int(n)) } + +// bytes returns an array of the bytes for the number `n`, +// in little endian format, where .bytes()[0] is the least +// significant byte. The result is NOT trimmed, and will contain 0s, even +// after the significant bytes. +// This method is faster than .bytes_trimmed(), but may be less convenient. +// Example: assert big.from_int(1).bytes()[0] == byte(0x01) +// Example: assert big.from_int(1024).bytes()[1] == byte(0x04) +// Example: assert big.from_int(1048576).bytes()[2] == byte(0x10) +pub fn (n &Number) bytes() []byte { + mut res := []byte{len: 128, init: 0} + unsafe { C.memcpy(res.data, n, 128) } + return res +} + +// bytes_trimmed returns an array of the bytes for the number `n`, +// in little endian format, where .bytes_trimmed()[0] is the least +// significant byte. The result is trimmed, so that *the last* byte +// of the result is also the the last meaningfull byte, != 0 . +// Example: assert big.from_int(1).bytes_trimmed() == [byte(0x01)] +// Example: assert big.from_int(1024).bytes_trimmed() == [byte(0x00), 0x04] +// Example: assert big.from_int(1048576).bytes_trimmed() == [byte(0x00), 0x00, 0x10] +pub fn (n &Number) bytes_trimmed() []byte { + mut res := []byte{len: 128, init: 0} + unsafe { C.memcpy(res.data, n, 128) } + mut non_zero_idx := 127 + for ; non_zero_idx >= 0; non_zero_idx-- { + if res[non_zero_idx] != 0 { + break + } + } + res.trim(non_zero_idx + 1) + return res +} diff --git a/vlib/math/big/big_test.v b/vlib/math/big/big_test.v index 6ba78686ed..63982cadcc 100644 --- a/vlib/math/big/big_test.v +++ b/vlib/math/big/big_test.v @@ -126,3 +126,25 @@ fn test_factorial() { f100 := big.factorial(big.from_u64(100)) assert f100.hexstr() == '1b30964ec395dc24069528d54bbda40d16e966ef9a70eb21b5b2943a321cdf10391745570cca9420c6ecb3b72ed2ee8b02ea2735c61a000000000000000000000000' } + +fn trimbytes(n int, x []byte) []byte { + mut res := x.clone() + res.trim(n) + return res +} + +fn test_bytes() { + assert big.from_int(0).bytes().len == 128 + assert big.from_hex_string('e'.repeat(100)).bytes().len == 128 + assert trimbytes(3, big.from_int(1).bytes()) == [byte(0x01), 0x00, 0x00] + assert trimbytes(3, big.from_int(1024).bytes()) == [byte(0x00), 0x04, 0x00] + assert trimbytes(3, big.from_int(1048576).bytes()) == [byte(0x00), 0x00, 0x10] +} + +fn test_bytes_trimmed() { + assert big.from_int(0).bytes_trimmed().len == 0 + assert big.from_hex_string('AB'.repeat(50)).bytes_trimmed().len == 50 + assert big.from_int(1).bytes_trimmed() == [byte(0x01)] + assert big.from_int(1024).bytes_trimmed() == [byte(0x00), 0x04] + assert big.from_int(1048576).bytes_trimmed() == [byte(0x00), 0x00, 0x10] +}