Skip to main content

v8/
bigint.rs

1use crate::BigInt;
2use crate::Context;
3use crate::Local;
4use crate::isolate::RealIsolate;
5use crate::scope::PinScope;
6use crate::support::int;
7
8use std::mem::MaybeUninit;
9
10unsafe extern "C" {
11  fn v8__BigInt__New(isolate: *mut RealIsolate, value: i64) -> *const BigInt;
12  fn v8__BigInt__NewFromUnsigned(
13    isolate: *mut RealIsolate,
14    value: u64,
15  ) -> *const BigInt;
16  fn v8__BigInt__NewFromWords(
17    context: *const Context,
18    sign_bit: int,
19    word_count: int,
20    words: *const u64,
21  ) -> *const BigInt;
22  fn v8__BigInt__Uint64Value(this: *const BigInt, lossless: *mut bool) -> u64;
23  fn v8__BigInt__Int64Value(this: *const BigInt, lossless: *mut bool) -> i64;
24  fn v8__BigInt__WordCount(this: *const BigInt) -> int;
25  fn v8__BigInt__ToWordsArray(
26    this: *const BigInt,
27    sign_bit: *mut int,
28    word_count: *mut int,
29    words: *mut u64,
30  );
31}
32
33impl BigInt {
34  #[inline(always)]
35  pub fn new_from_i64<'s>(
36    scope: &PinScope<'s, '_, ()>,
37    value: i64,
38  ) -> Local<'s, BigInt> {
39    unsafe {
40      scope.cast_local(|sd| v8__BigInt__New(sd.get_isolate_ptr(), value))
41    }
42    .unwrap()
43  }
44
45  #[inline(always)]
46  pub fn new_from_u64<'s>(
47    scope: &PinScope<'s, '_, ()>,
48    value: u64,
49  ) -> Local<'s, BigInt> {
50    unsafe {
51      scope.cast_local(|sd| {
52        v8__BigInt__NewFromUnsigned(sd.get_isolate_ptr(), value)
53      })
54    }
55    .unwrap()
56  }
57
58  /// Creates a new BigInt object using a specified sign bit and a
59  /// specified list of digits/words.
60  /// The resulting number is calculated as:
61  ///
62  /// (-1)^sign_bit * (words[0] * (2^64)^0 + words[1] * (2^64)^1 + ...)
63  #[inline(always)]
64  pub fn new_from_words<'s>(
65    scope: &PinScope<'s, '_, ()>,
66    sign_bit: bool,
67    words: &[u64],
68  ) -> Option<Local<'s, BigInt>> {
69    unsafe {
70      scope.cast_local(|sd| {
71        v8__BigInt__NewFromWords(
72          sd.get_current_context(),
73          sign_bit as int,
74          words.len() as int,
75          words.as_ptr(),
76        )
77      })
78    }
79  }
80
81  /// Returns the value of this BigInt as an unsigned 64-bit integer, and a
82  /// `bool` indicating that the conversion was lossless when `true`.
83  /// The boolean value will be `false` if the return value was truncated or wrapped around,
84  /// in particular if the BigInt is negative.
85  #[inline(always)]
86  pub fn u64_value(&self) -> (u64, bool) {
87    let mut lossless = MaybeUninit::uninit();
88    let v = unsafe { v8__BigInt__Uint64Value(self, lossless.as_mut_ptr()) };
89    let lossless = unsafe { lossless.assume_init() };
90    (v, lossless)
91  }
92
93  /// Returns the value of this BigInt as a signed 64-bit integer, and a `bool`
94  /// indicating that the conversion was lossless when `true`.
95  /// The boolean value will be `false` if the return value was truncated or wrapped around.
96  #[inline(always)]
97  pub fn i64_value(&self) -> (i64, bool) {
98    let mut lossless = MaybeUninit::uninit();
99    let v = unsafe { v8__BigInt__Int64Value(self, lossless.as_mut_ptr()) };
100    let lossless = unsafe { lossless.assume_init() };
101    (v, lossless)
102  }
103
104  /// Returns the number of 64-bit words needed to store the result of
105  /// `to_words_array`.
106  #[inline(always)]
107  pub fn word_count(&self) -> usize {
108    unsafe { v8__BigInt__WordCount(self) as usize }
109  }
110
111  /// Converts this BigInt to a (sign_bit, words) pair. `sign_bit` will be true
112  /// if this BigInt is negative. If `words` has too few elements, the result will
113  /// be truncated to fit.
114  #[inline]
115  pub fn to_words_array<'a>(
116    &self,
117    words: &'a mut [u64],
118  ) -> (bool, &'a mut [u64]) {
119    let mut sign_bit = MaybeUninit::uninit();
120    let mut word_count = words.len() as int;
121    unsafe {
122      v8__BigInt__ToWordsArray(
123        self,
124        sign_bit.as_mut_ptr(),
125        &mut word_count,
126        words.as_mut_ptr(),
127      );
128    }
129
130    let sign_bit = unsafe { sign_bit.assume_init() };
131    debug_assert!(sign_bit == 0 || sign_bit == 1);
132    let word_count = word_count as usize;
133
134    (
135      sign_bit == 1,
136      if word_count < words.len() {
137        &mut words[..word_count]
138      } else {
139        words
140      },
141    )
142  }
143}