171 lines
5.8 KiB
Plaintext
171 lines
5.8 KiB
Plaintext
use core::integer::u128_byte_reverse;
|
|
|
|
pub const ONE_SHIFT_160: u256 = 0x10000000000000000000000000000000000000000;
|
|
pub const ONE_SHIFT_96: u256 = 0x1000000000000000000000000;
|
|
|
|
pub const ONE_SHIFT_64: u128 = 0x10000000000000000;
|
|
|
|
pub const UNEXPECTED_OVERFLOW: felt252 = 'unexpected overflow';
|
|
pub const UNEXPECTED_ZERO: felt252 = 'unexpected zero';
|
|
|
|
// Returns 1 << (8 * `n_bytes`) as u256.
|
|
//
|
|
// Panics if `n_bytes >= 32`.
|
|
pub fn one_shift_left_bytes_u256(n_bytes: u8) -> u256 {
|
|
match n_bytes {
|
|
0 => 0x1,
|
|
1 => 0x100,
|
|
2 => 0x10000,
|
|
3 => 0x1000000,
|
|
4 => 0x100000000,
|
|
5 => 0x10000000000,
|
|
6 => 0x1000000000000,
|
|
7 => 0x100000000000000,
|
|
8 => 0x10000000000000000,
|
|
9 => 0x1000000000000000000,
|
|
10 => 0x100000000000000000000,
|
|
11 => 0x10000000000000000000000,
|
|
12 => 0x1000000000000000000000000,
|
|
13 => 0x100000000000000000000000000,
|
|
14 => 0x10000000000000000000000000000,
|
|
15 => 0x1000000000000000000000000000000,
|
|
16 => 0x100000000000000000000000000000000,
|
|
17 => 0x10000000000000000000000000000000000,
|
|
18 => 0x1000000000000000000000000000000000000,
|
|
19 => 0x100000000000000000000000000000000000000,
|
|
20 => 0x10000000000000000000000000000000000000000,
|
|
21 => 0x1000000000000000000000000000000000000000000,
|
|
22 => 0x100000000000000000000000000000000000000000000,
|
|
23 => 0x10000000000000000000000000000000000000000000000,
|
|
24 => 0x1000000000000000000000000000000000000000000000000,
|
|
25 => 0x100000000000000000000000000000000000000000000000000,
|
|
26 => 0x10000000000000000000000000000000000000000000000000000,
|
|
27 => 0x1000000000000000000000000000000000000000000000000000000,
|
|
28 => 0x100000000000000000000000000000000000000000000000000000000,
|
|
29 => 0x10000000000000000000000000000000000000000000000000000000000,
|
|
30 => 0x1000000000000000000000000000000000000000000000000000000000000,
|
|
31 => 0x100000000000000000000000000000000000000000000000000000000000000,
|
|
_ => core::panic_with_felt252('n_bytes too big'),
|
|
}
|
|
}
|
|
|
|
|
|
// Returns 1 << (8 * `n_bytes`) as u128.
|
|
//
|
|
// Panics if `n_bytes >= 16`.
|
|
pub fn one_shift_left_bytes_u128(n_bytes: u8) -> u128 {
|
|
match n_bytes {
|
|
0 => 0x1,
|
|
1 => 0x100,
|
|
2 => 0x10000,
|
|
3 => 0x1000000,
|
|
4 => 0x100000000,
|
|
5 => 0x10000000000,
|
|
6 => 0x1000000000000,
|
|
7 => 0x100000000000000,
|
|
8 => 0x10000000000000000,
|
|
9 => 0x1000000000000000000,
|
|
10 => 0x100000000000000000000,
|
|
11 => 0x10000000000000000000000,
|
|
12 => 0x1000000000000000000000000,
|
|
13 => 0x100000000000000000000000000,
|
|
14 => 0x10000000000000000000000000000,
|
|
15 => 0x1000000000000000000000000000000,
|
|
_ => core::panic_with_felt252('n_bytes too big'),
|
|
}
|
|
}
|
|
|
|
// Returns 1 << (8 * `n_bytes`) as u64.
|
|
//
|
|
// Panics if `n_bytes >= 8`.
|
|
pub fn one_shift_left_bytes_u64(n_bytes: u8) -> u64 {
|
|
match n_bytes {
|
|
0 => 0x1,
|
|
1 => 0x100,
|
|
2 => 0x10000,
|
|
3 => 0x1000000,
|
|
4 => 0x100000000,
|
|
5 => 0x10000000000,
|
|
6 => 0x1000000000000,
|
|
7 => 0x100000000000000,
|
|
_ => core::panic_with_felt252('n_bytes too big'),
|
|
}
|
|
}
|
|
|
|
pub fn u64_byte_reverse(value: u64) -> u64 {
|
|
let reversed = u128_byte_reverse(value.into()) / ONE_SHIFT_64.try_into().expect('not zero');
|
|
reversed.try_into().unwrap()
|
|
}
|
|
|
|
/// If `self` is an error, panics with a `felt252` value
|
|
/// corresponding to the error. Otherwise, returns the success value.
|
|
/// This differs from `Result::unwrap` which always panics with
|
|
/// the same message and doesn't include information about the error.
|
|
pub trait UnwrapWithFelt252<T, E> {
|
|
fn unwrap_with_felt252(self: Result<T, E>) -> T;
|
|
}
|
|
|
|
/// Reinterpret `u64` as `i64` as if it was a two's complement binary representation.
|
|
pub fn u64_as_i64(value: u64) -> i64 {
|
|
if value < 0x8000000000000000 {
|
|
value.try_into().unwrap()
|
|
} else {
|
|
let value: i128 = value.into();
|
|
(value - 0x10000000000000000).try_into().unwrap()
|
|
}
|
|
}
|
|
|
|
/// Reinterpret `u32` as `i32` as if it was a two's complement binary representation.
|
|
pub fn u32_as_i32(value: u32) -> i32 {
|
|
if value < 0x80000000 {
|
|
value.try_into().unwrap()
|
|
} else {
|
|
let value: i64 = value.into();
|
|
(value - 0x100000000).try_into().unwrap()
|
|
}
|
|
}
|
|
|
|
pub fn array_felt252_to_bytes31(mut input: Array<felt252>) -> Array<bytes31> {
|
|
let mut output = array![];
|
|
loop {
|
|
match input.pop_front() {
|
|
Option::Some(v) => { output.append(v.try_into().unwrap()); },
|
|
Option::None => { break; },
|
|
}
|
|
};
|
|
output
|
|
}
|
|
|
|
#[cfg(test)]
|
|
mod tests {
|
|
use super::{u64_as_i64, u32_as_i32};
|
|
|
|
#[test]
|
|
fn test_u64_as_i64() {
|
|
assert!(u64_as_i64(0) == 0);
|
|
assert!(u64_as_i64(1) == 1);
|
|
assert!(u64_as_i64(2) == 2);
|
|
assert!(u64_as_i64(3) == 3);
|
|
assert!(u64_as_i64(9223372036854775806) == 9223372036854775806);
|
|
assert!(u64_as_i64(9223372036854775807) == 9223372036854775807);
|
|
assert!(u64_as_i64(9223372036854775808) == -9223372036854775808);
|
|
assert!(u64_as_i64(9223372036854775809) == -9223372036854775807);
|
|
assert!(u64_as_i64(18446744073709551614) == -2);
|
|
assert!(u64_as_i64(18446744073709551615) == -1);
|
|
}
|
|
|
|
#[test]
|
|
fn test_u32_as_i32() {
|
|
assert!(u32_as_i32(0) == 0);
|
|
assert!(u32_as_i32(1) == 1);
|
|
assert!(u32_as_i32(2) == 2);
|
|
assert!(u32_as_i32(3) == 3);
|
|
assert!(u32_as_i32(2147483646) == 2147483646);
|
|
assert!(u32_as_i32(2147483647) == 2147483647);
|
|
assert!(u32_as_i32(2147483648) == -2147483648);
|
|
assert!(u32_as_i32(2147483649) == -2147483647);
|
|
assert!(u32_as_i32(4294967294) == -2);
|
|
assert!(u32_as_i32(4294967295) == -1);
|
|
}
|
|
}
|