1extern crate alloc;
2
3use alloc::{string::String, vec::Vec};
4use ark_ff::{BigInt, BigInteger as ark_BigInteger, BigInteger256};
5use ark_serialize::{CanonicalDeserialize, CanonicalSerialize};
6
7use core::{
8 cmp::Ordering::{Equal, Greater, Less},
9 convert::TryInto,
10};
11use num_bigint::BigUint;
12use wasm_bindgen::{
13 convert::{FromWasmAbi, IntoWasmAbi},
14 prelude::*,
15};
16
17const BIGINT256_NUM_BITS: i32 = 256;
22const BIGINT256_LIMB_BITS: i32 = 64;
23const BIGINT256_LIMB_BYTES: i32 = BIGINT256_LIMB_BITS / 8;
24const BIGINT256_NUM_LIMBS: i32 =
25 (BIGINT256_NUM_BITS + BIGINT256_LIMB_BITS - 1) / BIGINT256_LIMB_BITS;
26const BIGINT256_NUM_BYTES: usize = (BIGINT256_NUM_LIMBS as usize) * 8;
27
28pub struct WasmBigInteger256(pub BigInteger256);
29
30impl wasm_bindgen::describe::WasmDescribe for WasmBigInteger256 {
31 fn describe() {
32 <Vec<u8> as wasm_bindgen::describe::WasmDescribe>::describe();
33 }
34}
35
36impl FromWasmAbi for WasmBigInteger256 {
37 type Abi = <Vec<u8> as FromWasmAbi>::Abi;
38 unsafe fn from_abi(js: Self::Abi) -> Self {
39 let bytes: Vec<u8> = FromWasmAbi::from_abi(js);
40 WasmBigInteger256(BigInteger256::deserialize_compressed(bytes.as_slice()).unwrap())
42 }
43}
44
45impl IntoWasmAbi for WasmBigInteger256 {
46 type Abi = <Vec<u8> as FromWasmAbi>::Abi;
47
48 fn into_abi(self) -> Self::Abi {
49 self.0.to_bytes_le().into_abi()
50 }
51}
52
53pub fn to_biguint(x: &BigInteger256) -> BigUint {
54 let x_ = x.0.as_ptr().cast::<u8>();
55 let x_ = unsafe { core::slice::from_raw_parts(x_, BIGINT256_NUM_BYTES) };
56 num_bigint::BigUint::from_bytes_le(x_)
57}
58
59pub fn of_biguint(x: &BigUint) -> BigInteger256 {
60 let mut bytes = x.to_bytes_le();
61 bytes.resize(BIGINT256_NUM_BYTES, 0);
62 let limbs = bytes.as_ptr();
63 let limbs = limbs.cast::<[u64; BIGINT256_NUM_LIMBS as usize]>();
64 let limbs = unsafe { &(*limbs) };
65 BigInt(*limbs)
66}
67
68#[wasm_bindgen]
69pub fn caml_bigint_256_of_numeral(s: String, _len: u32, base: u32) -> WasmBigInteger256 {
70 match BigUint::parse_bytes(&s.into_bytes(), base) {
71 Some(data) => WasmBigInteger256(of_biguint(&data)),
72 None => panic!("caml_bigint_256_of_numeral"),
73 }
74}
75
76#[wasm_bindgen]
77pub fn caml_bigint_256_of_decimal_string(s: String) -> WasmBigInteger256 {
78 match BigUint::parse_bytes(&s.into_bytes(), 10) {
79 Some(data) => WasmBigInteger256(of_biguint(&data)),
80 None => panic!("caml_bigint_256_of_decimal_string"),
81 }
82}
83
84#[wasm_bindgen]
85pub fn caml_bigint_256_num_limbs() -> i32 {
86 BIGINT256_NUM_LIMBS
87}
88
89#[wasm_bindgen]
90pub fn caml_bigint_256_bytes_per_limb() -> i32 {
91 BIGINT256_LIMB_BYTES
92}
93
94#[wasm_bindgen]
95pub fn caml_bigint_256_div(x: WasmBigInteger256, y: WasmBigInteger256) -> WasmBigInteger256 {
96 let res: BigUint = to_biguint(&x.0) / to_biguint(&y.0);
97 WasmBigInteger256(of_biguint(&res))
98}
99
100#[wasm_bindgen]
101pub fn caml_bigint_256_compare(x: WasmBigInteger256, y: WasmBigInteger256) -> i8 {
102 match x.0.cmp(&y.0) {
103 Less => -1,
104 Equal => 0,
105 Greater => 1,
106 }
107}
108
109#[cfg_attr(feature = "std", wasm_bindgen)]
111#[cfg(feature = "std")]
112pub fn caml_bigint_256_print(x: WasmBigInteger256) {
113 println!("{}", to_biguint(&x.0));
114}
115
116#[cfg_attr(feature = "std", wasm_bindgen)]
118#[cfg(feature = "std")]
119pub fn caml_bigint_256_to_string(x: WasmBigInteger256) -> String {
120 to_biguint(&x.0).to_string()
121}
122
123#[wasm_bindgen]
124pub fn caml_bigint_256_test_bit(x: WasmBigInteger256, i: i32) -> bool {
125 match i.try_into() {
126 Ok(i) => x.0.get_bit(i),
127 Err(_) => panic!("caml_bigint_256_test_bit"),
128 }
129}
130
131#[wasm_bindgen]
132pub fn caml_bigint_256_to_bytes(x: WasmBigInteger256) -> Vec<u8> {
133 let mut serialized_bytes = Vec::with_capacity(core::mem::size_of::<WasmBigInteger256>());
136 x.0.serialize_compressed(&mut serialized_bytes)
137 .expect("serialize failed");
138 serialized_bytes
139}
140
141#[wasm_bindgen]
142pub fn caml_bigint_256_of_bytes(x: &[u8]) -> WasmBigInteger256 {
143 let len = core::mem::size_of::<WasmBigInteger256>();
144 assert!(x.len() == len, "caml_bigint_256_of_bytes");
145 WasmBigInteger256(
147 BigInteger256::deserialize_compressed(&mut &x[..]).expect("deserialization error"),
148 )
149}
150
151#[wasm_bindgen]
152pub fn caml_bigint_256_deep_copy(x: WasmBigInteger256) -> WasmBigInteger256 {
153 x
154}