1use crate::error::{RangeError, SyntaxError};
2use crate::utils::bind;
3use alloc::format;
4use alloc::str::FromStr;
5use alloc::string::String;
6
7#[derive(Clone, Debug)]
12#[repr(transparent)]
13pub struct BigInt {
14 inner: emlite::Val,
15}
16
17bind!(BigInt);
18
19impl FromStr for BigInt {
20 type Err = SyntaxError;
21
22 fn from_str(s: &str) -> Result<Self, Self::Err> {
23 let ctor = emlite::Val::global("BigInt");
24 let result = ctor.invoke(&[s.into()]);
25 result.as_::<Result<Self, SyntaxError>>()
26 }
27}
28
29impl BigInt {
30 pub fn from_i64(value: i64) -> Self {
42 let ctor = emlite::Val::global("BigInt");
43 let val = ctor.invoke(&[value.into()]);
44 Self { inner: val }
45 }
46
47 pub fn from_u64(value: u64) -> Self {
59 let ctor = emlite::Val::global("BigInt");
60 let val = ctor.invoke(&[value.into()]);
61 Self { inner: val }
62 }
63
64 pub fn to_string_with_radix(&self, radix: Option<u32>) -> String {
81 match radix {
82 Some(r) => self
83 .inner
84 .call("toString", &[r.into()])
85 .as_::<Option<String>>()
86 .unwrap_or_default(),
87 None => self
88 .inner
89 .call("toString", &[])
90 .as_::<Option<String>>()
91 .unwrap_or_default(),
92 }
93 }
94
95 pub fn to_string_repr(&self) -> String {
105 self.to_string_with_radix(None)
106 }
107
108 pub fn value_of(&self) -> Self {
118 let val = self.inner.call("valueOf", &[]);
119 Self { inner: val }
120 }
121
122 pub fn to_i64(&self) -> Result<i64, RangeError> {
138 let max_check = emlite::Val::global("eval").invoke(&[format!(
140 "({}) <= {}n",
141 self.to_string_repr(),
142 i64::MAX
143 )
144 .into()]);
145 let min_check = emlite::Val::global("eval").invoke(&[format!(
146 "({}) >= {}n",
147 self.to_string_repr(),
148 i64::MIN
149 )
150 .into()]);
151
152 if max_check.as_::<bool>() && min_check.as_::<bool>() {
153 Ok(emlite::Val::global("Number")
154 .invoke(&[self.inner.clone()])
155 .as_::<i64>())
156 } else {
157 Err(RangeError::new(&format!(
158 "BigInt value {} is out of i64 range",
159 self.to_string_repr()
160 )))
161 }
162 }
163
164 pub fn to_u64(&self) -> Result<u64, RangeError> {
180 let pos_check =
182 emlite::Val::global("eval")
183 .invoke(&[format!("({}) >= 0n", self.to_string_repr()).into()]);
184 let max_check = emlite::Val::global("eval").invoke(&[format!(
185 "({}) <= {}n",
186 self.to_string_repr(),
187 u64::MAX
188 )
189 .into()]);
190
191 if pos_check.as_::<bool>() && max_check.as_::<bool>() {
192 Ok(emlite::Val::global("Number")
193 .invoke(&[self.inner.clone()])
194 .as_::<u64>())
195 } else if !pos_check.as_::<bool>() {
196 Err(RangeError::new(&format!(
197 "BigInt value {} is negative and cannot be converted to u64",
198 self.to_string_repr()
199 )))
200 } else {
201 Err(RangeError::new(&format!(
202 "BigInt value {} is too large for u64",
203 self.to_string_repr()
204 )))
205 }
206 }
207
208 pub fn pow(&self, other: &BigInt) -> BigInt {
210 let result = emlite::Val::global("eval").invoke(&[format!(
211 "({}) ** ({})",
212 self.to_string_repr(),
213 other.to_string_repr()
214 )
215 .into()]);
216 Self { inner: result }
217 }
218
219 pub fn get_hash(&self) -> u64 {
221 use emlite::FromVal;
222 self.inner.as_handle() as u64
224 }
225
226 pub fn is_zero(&self) -> bool {
228 self == &Self::zero()
229 }
230
231 pub fn is_positive(&self) -> bool {
233 self > &Self::zero()
234 }
235
236 pub fn is_negative(&self) -> bool {
238 self < &Self::zero()
239 }
240
241 pub fn abs(&self) -> BigInt {
243 if self.is_negative() {
244 -self
245 } else {
246 self.clone()
247 }
248 }
249
250 pub fn zero() -> BigInt {
252 Self::from_i64(0)
253 }
254
255 pub fn one() -> BigInt {
257 Self::from_i64(1)
258 }
259
260 pub fn minus_one() -> BigInt {
262 Self::from_i64(-1)
263 }
264
265 pub fn as_int_n(width: u32, bigint: &BigInt) -> BigInt {
267 let result =
268 emlite::Val::global("BigInt").call("asIntN", &[width.into(), bigint.inner.clone()]);
269 Self { inner: result }
270 }
271
272 pub fn as_uint_n(width: u32, bigint: &BigInt) -> BigInt {
274 let result =
275 emlite::Val::global("BigInt").call("asUintN", &[width.into(), bigint.inner.clone()]);
276 Self { inner: result }
277 }
278
279 pub fn to_locale_string(&self) -> String {
281 self.inner
282 .call("toLocaleString", &[])
283 .as_::<Option<String>>()
284 .unwrap_or_default()
285 }
286
287 pub fn parse(s: &str) -> Result<BigInt, SyntaxError> {
289 Self::from_str(s)
290 }
291}
292
293impl crate::prelude::DynCast for BigInt {
294 fn instanceof(val: &emlite::Val) -> bool {
295 val.type_of() == "bigint"
296 }
297
298 fn unchecked_from_val(v: emlite::Val) -> Self {
299 Self { inner: v }
300 }
301
302 fn unchecked_from_val_ref(v: &emlite::Val) -> &Self {
303 unsafe { &*(v as *const emlite::Val as *const Self) }
304 }
305
306 fn unchecked_from_val_mut(v: &mut emlite::Val) -> &mut Self {
307 unsafe { &mut *(v as *mut emlite::Val as *mut Self) }
308 }
309}
310
311impl core::fmt::Display for BigInt {
312 fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
313 write!(f, "{}", self.to_string_repr())
314 }
315}
316
317impl core::ops::Add for BigInt {
319 type Output = BigInt;
320 fn add(self, rhs: BigInt) -> Self::Output {
321 let result = emlite::Val::global("eval").invoke(&[format!(
322 "({}) + ({})",
323 self.to_string_repr(),
324 rhs.to_string_repr()
325 )
326 .into()]);
327 BigInt { inner: result }
328 }
329}
330
331impl core::ops::Add for &BigInt {
332 type Output = BigInt;
333 fn add(self, rhs: &BigInt) -> Self::Output {
334 let result = emlite::Val::global("eval").invoke(&[format!(
335 "({}) + ({})",
336 self.to_string_repr(),
337 rhs.to_string_repr()
338 )
339 .into()]);
340 BigInt { inner: result }
341 }
342}
343
344impl core::ops::Sub for BigInt {
345 type Output = BigInt;
346 fn sub(self, rhs: BigInt) -> Self::Output {
347 let result = emlite::Val::global("eval").invoke(&[format!(
348 "({}) - ({})",
349 self.to_string_repr(),
350 rhs.to_string_repr()
351 )
352 .into()]);
353 BigInt { inner: result }
354 }
355}
356
357impl core::ops::Sub for &BigInt {
358 type Output = BigInt;
359 fn sub(self, rhs: &BigInt) -> Self::Output {
360 let result = emlite::Val::global("eval").invoke(&[format!(
361 "({}) - ({})",
362 self.to_string_repr(),
363 rhs.to_string_repr()
364 )
365 .into()]);
366 BigInt { inner: result }
367 }
368}
369
370impl core::ops::Mul for BigInt {
371 type Output = BigInt;
372 fn mul(self, rhs: BigInt) -> Self::Output {
373 let result = emlite::Val::global("eval").invoke(&[format!(
374 "({}) * ({})",
375 self.to_string_repr(),
376 rhs.to_string_repr()
377 )
378 .into()]);
379 BigInt { inner: result }
380 }
381}
382
383impl core::ops::Mul for &BigInt {
384 type Output = BigInt;
385 fn mul(self, rhs: &BigInt) -> Self::Output {
386 let result = emlite::Val::global("eval").invoke(&[format!(
387 "({}) * ({})",
388 self.to_string_repr(),
389 rhs.to_string_repr()
390 )
391 .into()]);
392 BigInt { inner: result }
393 }
394}
395
396impl core::ops::Div for BigInt {
397 type Output = BigInt;
398 fn div(self, rhs: BigInt) -> Self::Output {
399 let result = emlite::Val::global("eval").invoke(&[format!(
400 "({}) / ({})",
401 self.to_string_repr(),
402 rhs.to_string_repr()
403 )
404 .into()]);
405 BigInt { inner: result }
406 }
407}
408
409impl core::ops::Div for &BigInt {
410 type Output = BigInt;
411 fn div(self, rhs: &BigInt) -> Self::Output {
412 let result = emlite::Val::global("eval").invoke(&[format!(
413 "({}) / ({})",
414 self.to_string_repr(),
415 rhs.to_string_repr()
416 )
417 .into()]);
418 BigInt { inner: result }
419 }
420}
421
422impl core::ops::Rem for BigInt {
423 type Output = BigInt;
424 fn rem(self, rhs: BigInt) -> Self::Output {
425 let result = emlite::Val::global("eval").invoke(&[format!(
426 "({}) % ({})",
427 self.to_string_repr(),
428 rhs.to_string_repr()
429 )
430 .into()]);
431 BigInt { inner: result }
432 }
433}
434
435impl core::ops::Rem for &BigInt {
436 type Output = BigInt;
437 fn rem(self, rhs: &BigInt) -> Self::Output {
438 let result = emlite::Val::global("eval").invoke(&[format!(
439 "({}) % ({})",
440 self.to_string_repr(),
441 rhs.to_string_repr()
442 )
443 .into()]);
444 BigInt { inner: result }
445 }
446}
447
448impl core::ops::Neg for BigInt {
449 type Output = BigInt;
450 fn neg(self) -> Self::Output {
451 let result =
452 emlite::Val::global("eval").invoke(&[format!("-({})", self.to_string_repr()).into()]);
453 BigInt { inner: result }
454 }
455}
456
457impl core::ops::Neg for &BigInt {
458 type Output = BigInt;
459 fn neg(self) -> Self::Output {
460 let result =
461 emlite::Val::global("eval").invoke(&[format!("-({})", self.to_string_repr()).into()]);
462 BigInt { inner: result }
463 }
464}
465
466impl core::ops::BitAnd for BigInt {
468 type Output = BigInt;
469 fn bitand(self, rhs: BigInt) -> Self::Output {
470 let result = emlite::Val::global("eval").invoke(&[format!(
471 "({}) & ({})",
472 self.to_string_repr(),
473 rhs.to_string_repr()
474 )
475 .into()]);
476 BigInt { inner: result }
477 }
478}
479
480impl core::ops::BitAnd for &BigInt {
481 type Output = BigInt;
482 fn bitand(self, rhs: &BigInt) -> Self::Output {
483 let result = emlite::Val::global("eval").invoke(&[format!(
484 "({}) & ({})",
485 self.to_string_repr(),
486 rhs.to_string_repr()
487 )
488 .into()]);
489 BigInt { inner: result }
490 }
491}
492
493impl core::ops::BitOr for BigInt {
494 type Output = BigInt;
495 fn bitor(self, rhs: BigInt) -> Self::Output {
496 let result = emlite::Val::global("eval").invoke(&[format!(
497 "({}) | ({})",
498 self.to_string_repr(),
499 rhs.to_string_repr()
500 )
501 .into()]);
502 BigInt { inner: result }
503 }
504}
505
506impl core::ops::BitOr for &BigInt {
507 type Output = BigInt;
508 fn bitor(self, rhs: &BigInt) -> Self::Output {
509 let result = emlite::Val::global("eval").invoke(&[format!(
510 "({}) | ({})",
511 self.to_string_repr(),
512 rhs.to_string_repr()
513 )
514 .into()]);
515 BigInt { inner: result }
516 }
517}
518
519impl core::ops::BitXor for BigInt {
520 type Output = BigInt;
521 fn bitxor(self, rhs: BigInt) -> Self::Output {
522 let result = emlite::Val::global("eval").invoke(&[format!(
523 "({}) ^ ({})",
524 self.to_string_repr(),
525 rhs.to_string_repr()
526 )
527 .into()]);
528 BigInt { inner: result }
529 }
530}
531
532impl core::ops::BitXor for &BigInt {
533 type Output = BigInt;
534 fn bitxor(self, rhs: &BigInt) -> Self::Output {
535 let result = emlite::Val::global("eval").invoke(&[format!(
536 "({}) ^ ({})",
537 self.to_string_repr(),
538 rhs.to_string_repr()
539 )
540 .into()]);
541 BigInt { inner: result }
542 }
543}
544
545impl core::ops::Not for BigInt {
546 type Output = BigInt;
547 fn not(self) -> Self::Output {
548 let result =
549 emlite::Val::global("eval").invoke(&[format!("~({})", self.to_string_repr()).into()]);
550 BigInt { inner: result }
551 }
552}
553
554impl core::ops::Not for &BigInt {
555 type Output = BigInt;
556 fn not(self) -> Self::Output {
557 let result =
558 emlite::Val::global("eval").invoke(&[format!("~({})", self.to_string_repr()).into()]);
559 BigInt { inner: result }
560 }
561}
562
563impl core::ops::Shl<BigInt> for BigInt {
564 type Output = BigInt;
565 fn shl(self, rhs: BigInt) -> Self::Output {
566 let result = emlite::Val::global("eval").invoke(&[format!(
567 "({}) << ({})",
568 self.to_string_repr(),
569 rhs.to_string_repr()
570 )
571 .into()]);
572 BigInt { inner: result }
573 }
574}
575
576impl core::ops::Shl<&BigInt> for &BigInt {
577 type Output = BigInt;
578 fn shl(self, rhs: &BigInt) -> Self::Output {
579 let result = emlite::Val::global("eval").invoke(&[format!(
580 "({}) << ({})",
581 self.to_string_repr(),
582 rhs.to_string_repr()
583 )
584 .into()]);
585 BigInt { inner: result }
586 }
587}
588
589impl core::ops::Shr<BigInt> for BigInt {
590 type Output = BigInt;
591 fn shr(self, rhs: BigInt) -> Self::Output {
592 let result = emlite::Val::global("eval").invoke(&[format!(
593 "({}) >> ({})",
594 self.to_string_repr(),
595 rhs.to_string_repr()
596 )
597 .into()]);
598 BigInt { inner: result }
599 }
600}
601
602impl core::ops::Shr<&BigInt> for &BigInt {
603 type Output = BigInt;
604 fn shr(self, rhs: &BigInt) -> Self::Output {
605 let result = emlite::Val::global("eval").invoke(&[format!(
606 "({}) >> ({})",
607 self.to_string_repr(),
608 rhs.to_string_repr()
609 )
610 .into()]);
611 BigInt { inner: result }
612 }
613}
614
615impl PartialEq for BigInt {
617 fn eq(&self, other: &Self) -> bool {
618 emlite::Val::global("eval")
619 .invoke(&[format!(
620 "({}) === ({})",
621 self.to_string_repr(),
622 other.to_string_repr()
623 )
624 .into()])
625 .as_::<bool>()
626 }
627}
628
629impl Eq for BigInt {}
630
631impl PartialOrd for BigInt {
632 fn partial_cmp(&self, other: &Self) -> Option<core::cmp::Ordering> {
633 Some(self.cmp(other))
634 }
635}
636
637impl Ord for BigInt {
638 fn cmp(&self, other: &Self) -> core::cmp::Ordering {
639 let lt = emlite::Val::global("eval")
640 .invoke(&[format!("({}) < ({})", self.to_string_repr(), other.to_string_repr()).into()])
641 .as_::<bool>();
642 let gt = emlite::Val::global("eval")
643 .invoke(&[format!("({}) > ({})", self.to_string_repr(), other.to_string_repr()).into()])
644 .as_::<bool>();
645
646 if lt {
647 core::cmp::Ordering::Less
648 } else if gt {
649 core::cmp::Ordering::Greater
650 } else {
651 core::cmp::Ordering::Equal
652 }
653 }
654}
655
656impl core::hash::Hash for BigInt {
657 fn hash<H: core::hash::Hasher>(&self, state: &mut H) {
658 use emlite::FromVal;
659 self.inner.as_handle().hash(state);
660 }
661}
662
663impl core::ops::AddAssign for BigInt {
665 fn add_assign(&mut self, rhs: BigInt) {
666 *self = core::mem::take(self) + rhs;
667 }
668}
669
670impl core::ops::AddAssign<&BigInt> for BigInt {
671 fn add_assign(&mut self, rhs: &BigInt) {
672 *self = &*self + rhs;
673 }
674}
675
676impl core::ops::SubAssign for BigInt {
677 fn sub_assign(&mut self, rhs: BigInt) {
678 *self = core::mem::take(self) - rhs;
679 }
680}
681
682impl core::ops::SubAssign<&BigInt> for BigInt {
683 fn sub_assign(&mut self, rhs: &BigInt) {
684 *self = &*self - rhs;
685 }
686}
687
688impl core::ops::MulAssign for BigInt {
689 fn mul_assign(&mut self, rhs: BigInt) {
690 *self = core::mem::take(self) * rhs;
691 }
692}
693
694impl core::ops::MulAssign<&BigInt> for BigInt {
695 fn mul_assign(&mut self, rhs: &BigInt) {
696 *self = &*self * rhs;
697 }
698}
699
700impl core::ops::DivAssign for BigInt {
701 fn div_assign(&mut self, rhs: BigInt) {
702 *self = core::mem::take(self) / rhs;
703 }
704}
705
706impl core::ops::DivAssign<&BigInt> for BigInt {
707 fn div_assign(&mut self, rhs: &BigInt) {
708 *self = &*self / rhs;
709 }
710}
711
712impl core::ops::RemAssign for BigInt {
713 fn rem_assign(&mut self, rhs: BigInt) {
714 *self = core::mem::take(self) % rhs;
715 }
716}
717
718impl core::ops::RemAssign<&BigInt> for BigInt {
719 fn rem_assign(&mut self, rhs: &BigInt) {
720 *self = &*self % rhs;
721 }
722}
723
724impl core::ops::BitAndAssign for BigInt {
725 fn bitand_assign(&mut self, rhs: BigInt) {
726 *self = core::mem::take(self) & rhs;
727 }
728}
729
730impl core::ops::BitAndAssign<&BigInt> for BigInt {
731 fn bitand_assign(&mut self, rhs: &BigInt) {
732 *self = &*self & rhs;
733 }
734}
735
736impl core::ops::BitOrAssign for BigInt {
737 fn bitor_assign(&mut self, rhs: BigInt) {
738 *self = core::mem::take(self) | rhs;
739 }
740}
741
742impl core::ops::BitOrAssign<&BigInt> for BigInt {
743 fn bitor_assign(&mut self, rhs: &BigInt) {
744 *self = &*self | rhs;
745 }
746}
747
748impl core::ops::BitXorAssign for BigInt {
749 fn bitxor_assign(&mut self, rhs: BigInt) {
750 *self = core::mem::take(self) ^ rhs;
751 }
752}
753
754impl core::ops::BitXorAssign<&BigInt> for BigInt {
755 fn bitxor_assign(&mut self, rhs: &BigInt) {
756 *self = &*self ^ rhs;
757 }
758}
759
760impl core::ops::ShlAssign<BigInt> for BigInt {
761 fn shl_assign(&mut self, rhs: BigInt) {
762 *self = core::mem::take(self) << rhs;
763 }
764}
765
766impl core::ops::ShlAssign<&BigInt> for BigInt {
767 fn shl_assign(&mut self, rhs: &BigInt) {
768 *self = &*self << rhs;
769 }
770}
771
772impl core::ops::ShrAssign<BigInt> for BigInt {
773 fn shr_assign(&mut self, rhs: BigInt) {
774 *self = core::mem::take(self) >> rhs;
775 }
776}
777
778impl core::ops::ShrAssign<&BigInt> for BigInt {
779 fn shr_assign(&mut self, rhs: &BigInt) {
780 *self = &*self >> rhs;
781 }
782}
783
784impl Default for BigInt {
785 fn default() -> Self {
786 Self::zero()
787 }
788}