numbat_wasm_debug/
big_uint_mock.rs

1use alloc::vec::Vec;
2use core::ops::{Add, Div, Mul, Rem, Sub};
3use core::ops::{AddAssign, DivAssign, MulAssign, RemAssign, SubAssign};
4use core::ops::{BitAnd, BitOr, BitXor, Shl, Shr};
5use core::ops::{BitAndAssign, BitOrAssign, BitXorAssign, ShlAssign, ShrAssign};
6use numbat_wasm::BigUintApi;
7
8use core::cmp::Ordering;
9use num_bigint::{BigInt, BigUint, Sign};
10
11#[derive(Debug)]
12pub struct RustBigUint(pub num_bigint::BigInt);
13
14impl RustBigUint {
15	pub fn value(&self) -> BigUint {
16		self.0.to_biguint().unwrap()
17	}
18}
19
20impl From<u64> for RustBigUint {
21	fn from(item: u64) -> Self {
22		RustBigUint(BigUint::from(item).into())
23	}
24}
25
26impl From<u32> for RustBigUint {
27	fn from(item: u32) -> Self {
28		RustBigUint(BigUint::from(item).into())
29	}
30}
31
32impl From<usize> for RustBigUint {
33	fn from(item: usize) -> Self {
34		RustBigUint(BigUint::from(item).into())
35	}
36}
37
38impl From<BigInt> for RustBigUint {
39	fn from(item: BigInt) -> Self {
40		RustBigUint(item)
41	}
42}
43
44impl From<BigUint> for RustBigUint {
45	fn from(item: BigUint) -> Self {
46		RustBigUint(BigInt::from_biguint(Sign::Plus, item))
47	}
48}
49
50impl Clone for RustBigUint {
51	fn clone(&self) -> Self {
52		RustBigUint(self.0.clone())
53	}
54}
55
56macro_rules! binary_operator {
57	($trait:ident, $method:ident) => {
58		impl $trait for RustBigUint {
59			type Output = RustBigUint;
60
61			fn $method(self, other: RustBigUint) -> RustBigUint {
62				RustBigUint((self.0).$method(other.0))
63			}
64		}
65
66		impl<'a, 'b> $trait<&'b RustBigUint> for &'a RustBigUint {
67			type Output = RustBigUint;
68
69			fn $method(self, other: &RustBigUint) -> RustBigUint {
70				RustBigUint(self.0.clone().$method(other.0.clone()))
71			}
72		}
73	};
74}
75
76binary_operator! {Add, add}
77binary_operator! {Mul, mul}
78binary_operator! {Div, div}
79binary_operator! {Rem, rem}
80
81binary_operator! {BitAnd, bitand}
82binary_operator! {BitOr, bitor}
83binary_operator! {BitXor, bitxor}
84
85fn check_sub_result(result: &BigInt) {
86	if result.sign() == num_bigint::Sign::Minus {
87		panic!(b"Cannot subtract because result would be negative")
88	}
89}
90
91impl Sub for RustBigUint {
92	type Output = RustBigUint;
93
94	fn sub(self, other: RustBigUint) -> RustBigUint {
95		let result = self.0 - other.0;
96		check_sub_result(&result);
97		RustBigUint(result)
98	}
99}
100
101impl<'a, 'b> Sub<&'b RustBigUint> for &'a RustBigUint {
102	type Output = RustBigUint;
103
104	fn sub(self, other: &RustBigUint) -> RustBigUint {
105		let result = self.0.clone().sub(other.0.clone());
106		check_sub_result(&result);
107		RustBigUint(result)
108	}
109}
110
111macro_rules! binary_assign_operator {
112	($trait:ident, $method:ident) => {
113		impl $trait<RustBigUint> for RustBigUint {
114			fn $method(&mut self, other: Self) {
115				BigInt::$method(&mut self.0, other.0);
116			}
117		}
118
119		impl $trait<&RustBigUint> for RustBigUint {
120			fn $method(&mut self, other: &RustBigUint) {
121				BigInt::$method(&mut self.0, &other.0);
122			}
123		}
124	};
125}
126
127binary_assign_operator! {AddAssign, add_assign}
128binary_assign_operator! {MulAssign, mul_assign}
129binary_assign_operator! {DivAssign, div_assign}
130binary_assign_operator! {RemAssign, rem_assign}
131
132binary_assign_operator! {BitAndAssign, bitand_assign}
133binary_assign_operator! {BitOrAssign,  bitor_assign}
134binary_assign_operator! {BitXorAssign, bitxor_assign}
135
136impl SubAssign<RustBigUint> for RustBigUint {
137	fn sub_assign(&mut self, other: Self) {
138		BigInt::sub_assign(&mut self.0, other.0);
139		check_sub_result(&self.0);
140	}
141}
142
143impl SubAssign<&RustBigUint> for RustBigUint {
144	fn sub_assign(&mut self, other: &RustBigUint) {
145		BigInt::sub_assign(&mut self.0, &other.0);
146		check_sub_result(&self.0);
147	}
148}
149
150macro_rules! shift_traits {
151	($shift_trait:ident, $method:ident) => {
152		impl $shift_trait<usize> for RustBigUint {
153			type Output = RustBigUint;
154
155			fn $method(self, rhs: usize) -> RustBigUint {
156				let result = $shift_trait::$method(self.0, rhs);
157				RustBigUint(result)
158			}
159		}
160
161		impl<'a> $shift_trait<usize> for &'a RustBigUint {
162			type Output = RustBigUint;
163
164			fn $method(self, rhs: usize) -> RustBigUint {
165				let result = $shift_trait::$method(&self.0, rhs);
166				RustBigUint(result)
167			}
168		}
169	};
170}
171
172shift_traits! {Shl, shl}
173shift_traits! {Shr, shr}
174
175macro_rules! shift_assign_traits {
176	($shift_assign_trait:ident, $method:ident) => {
177		impl $shift_assign_trait<usize> for RustBigUint {
178			fn $method(&mut self, rhs: usize) {
179				$shift_assign_trait::$method(&mut self.0, rhs);
180			}
181		}
182	};
183}
184
185shift_assign_traits! {ShlAssign, shl_assign}
186shift_assign_traits! {ShrAssign, shr_assign}
187
188impl PartialEq<Self> for RustBigUint {
189	#[inline]
190	fn eq(&self, other: &Self) -> bool {
191		PartialEq::eq(&self.0, &other.0)
192	}
193}
194
195impl Eq for RustBigUint {}
196
197impl PartialOrd<Self> for RustBigUint {
198	#[inline]
199	fn partial_cmp(&self, other: &Self) -> Option<Ordering> {
200		PartialOrd::partial_cmp(&self.0, &other.0)
201	}
202}
203
204impl Ord for RustBigUint {
205	#[inline]
206	fn cmp(&self, other: &Self) -> Ordering {
207		Ord::cmp(&self.0, &other.0)
208	}
209}
210
211impl PartialEq<u64> for RustBigUint {
212	#[inline]
213	fn eq(&self, other: &u64) -> bool {
214		PartialEq::eq(&self.0, &BigInt::from(*other as i64))
215	}
216}
217
218impl PartialOrd<u64> for RustBigUint {
219	#[inline]
220	fn partial_cmp(&self, other: &u64) -> Option<Ordering> {
221		PartialOrd::partial_cmp(&self.0, &BigInt::from(*other as i64))
222	}
223}
224
225use numbat_wasm::numbat_codec::*;
226
227impl NestedEncode for RustBigUint {
228	const TYPE_INFO: TypeInfo = TypeInfo::BigUint;
229
230	fn dep_encode<O: NestedEncodeOutput>(&self, dest: &mut O) -> Result<(), EncodeError> {
231		self.to_bytes_be().as_slice().dep_encode(dest)
232	}
233
234	fn dep_encode_or_exit<O: NestedEncodeOutput, ExitCtx: Clone>(
235		&self,
236		dest: &mut O,
237		c: ExitCtx,
238		exit: fn(ExitCtx, EncodeError) -> !,
239	) {
240		self.to_bytes_be()
241			.as_slice()
242			.dep_encode_or_exit(dest, c, exit);
243	}
244}
245
246impl TopEncode for RustBigUint {
247	const TYPE_INFO: TypeInfo = TypeInfo::BigUint;
248
249	fn top_encode<O: TopEncodeOutput>(&self, output: O) -> Result<(), EncodeError> {
250		self.to_bytes_be().top_encode(output)
251	}
252
253	fn top_encode_or_exit<O: TopEncodeOutput, ExitCtx: Clone>(
254		&self,
255		output: O,
256		c: ExitCtx,
257		exit: fn(ExitCtx, EncodeError) -> !,
258	) {
259		self.to_bytes_be().top_encode_or_exit(output, c, exit)
260	}
261}
262
263impl NestedDecode for RustBigUint {
264	const TYPE_INFO: TypeInfo = TypeInfo::BigUint;
265
266	fn dep_decode<I: NestedDecodeInput>(input: &mut I) -> Result<Self, DecodeError> {
267		let size = usize::dep_decode(input)?;
268		let bytes = input.read_slice(size)?;
269		Ok(RustBigUint::from_bytes_be(bytes))
270	}
271
272	fn dep_decode_or_exit<I: NestedDecodeInput, ExitCtx: Clone>(
273		input: &mut I,
274		c: ExitCtx,
275		exit: fn(ExitCtx, DecodeError) -> !,
276	) -> Self {
277		let size = usize::dep_decode_or_exit(input, c.clone(), exit);
278		let bytes = input.read_slice_or_exit(size, c, exit);
279		RustBigUint::from_bytes_be(bytes)
280	}
281}
282
283impl TopDecode for RustBigUint {
284	const TYPE_INFO: TypeInfo = TypeInfo::BigUint;
285
286	fn top_decode<I: TopDecodeInput>(input: I) -> Result<Self, DecodeError> {
287		Ok(RustBigUint::from_bytes_be(&*input.into_boxed_slice_u8()))
288	}
289
290	fn top_decode_or_exit<I: TopDecodeInput, ExitCtx: Clone>(
291		input: I,
292		_: ExitCtx,
293		_: fn(ExitCtx, DecodeError) -> !,
294	) -> Self {
295		RustBigUint::from_bytes_be(&*input.into_boxed_slice_u8())
296	}
297}
298
299impl numbat_wasm::abi::TypeAbi for RustBigUint {
300	fn type_name() -> String {
301		String::from("BigUint")
302	}
303}
304
305impl numbat_wasm::BigUintApi for RustBigUint {
306	fn byte_length(&self) -> i32 {
307		panic!("byte_length not yet implemented")
308	}
309
310	fn copy_to_slice_big_endian(&self, _slice: &mut [u8]) -> i32 {
311		panic!("copy_to_slice not yet implemented")
312	}
313
314	fn copy_to_array_big_endian_pad_right(&self, target: &mut [u8; 32]) {
315		if self.0.sign() == Sign::Plus {
316			let (_, bytes) = self.0.to_bytes_be();
317			let offset = 32 - bytes.len();
318			target[offset..].clone_from_slice(&bytes[..]);
319		}
320	}
321
322	fn to_bytes_be(&self) -> Vec<u8> {
323		if self.0.sign() == Sign::NoSign {
324			Vec::new()
325		} else {
326			let (_, be) = self.0.to_bytes_be();
327			be
328		}
329	}
330
331	fn to_bytes_be_pad_right(&self, nr_bytes: usize) -> Option<Vec<u8>> {
332		let (_, bytes_be) = self.0.to_bytes_be();
333		match bytes_be.len().cmp(&nr_bytes) {
334			Ordering::Greater => None,
335			Ordering::Equal => Some(bytes_be),
336			Ordering::Less => {
337				let mut res = vec![0u8; nr_bytes];
338				let offset = nr_bytes - bytes_be.len();
339				res[offset..].clone_from_slice(&bytes_be[..]);
340				Some(res)
341			},
342		}
343	}
344
345	fn from_bytes_be(bytes: &[u8]) -> Self {
346		let bi = BigInt::from_bytes_be(num_bigint::Sign::Plus, bytes);
347		bi.into()
348	}
349}