mirror of
https://github.com/denoland/rusty_v8.git
synced 2025-02-02 20:55:00 -05:00
136 lines
3.7 KiB
Rust
136 lines
3.7 KiB
Rust
|
use crate::support::int;
|
||
|
use crate::BigInt;
|
||
|
use crate::Context;
|
||
|
use crate::HandleScope;
|
||
|
use crate::Isolate;
|
||
|
use crate::Local;
|
||
|
|
||
|
use std::mem::MaybeUninit;
|
||
|
|
||
|
extern "C" {
|
||
|
fn v8__BigInt__New(isolate: *mut Isolate, value: i64) -> *const BigInt;
|
||
|
fn v8__BigInt__NewFromUnsigned(
|
||
|
isolate: *mut Isolate,
|
||
|
value: u64,
|
||
|
) -> *const BigInt;
|
||
|
fn v8__BigInt__NewFromWords(
|
||
|
context: *const Context,
|
||
|
sign_bit: int,
|
||
|
word_count: int,
|
||
|
words: *const u64,
|
||
|
) -> *const BigInt;
|
||
|
fn v8__BigInt__Uint64Value(this: *const BigInt, lossless: *mut bool) -> u64;
|
||
|
fn v8__BigInt__Int64Value(this: *const BigInt, lossless: *mut bool) -> i64;
|
||
|
fn v8__BigInt__WordCount(this: *const BigInt) -> int;
|
||
|
fn v8__BigInt__ToWordsArray(
|
||
|
this: *const BigInt,
|
||
|
sign_bit: *mut int,
|
||
|
word_count: *mut int,
|
||
|
words: *mut u64,
|
||
|
);
|
||
|
}
|
||
|
|
||
|
impl BigInt {
|
||
|
pub fn new_from_i64<'s>(
|
||
|
scope: &mut HandleScope<'s>,
|
||
|
value: i64,
|
||
|
) -> Local<'s, BigInt> {
|
||
|
unsafe {
|
||
|
scope.cast_local(|sd| v8__BigInt__New(sd.get_isolate_ptr(), value))
|
||
|
}
|
||
|
.unwrap()
|
||
|
}
|
||
|
|
||
|
pub fn new_from_u64<'s>(
|
||
|
scope: &mut HandleScope<'s>,
|
||
|
value: u64,
|
||
|
) -> Local<'s, BigInt> {
|
||
|
unsafe {
|
||
|
scope.cast_local(|sd| {
|
||
|
v8__BigInt__NewFromUnsigned(sd.get_isolate_ptr(), value)
|
||
|
})
|
||
|
}
|
||
|
.unwrap()
|
||
|
}
|
||
|
|
||
|
/// Creates a new BigInt object using a specified sign bit and a
|
||
|
/// specified list of digits/words.
|
||
|
/// The resulting number is calculated as:
|
||
|
///
|
||
|
/// (-1)^sign_bit * (words[0] * (2^64)^0 + words[1] * (2^64)^1 + ...)
|
||
|
pub fn new_from_words<'s>(
|
||
|
scope: &mut HandleScope<'s>,
|
||
|
sign_bit: bool,
|
||
|
words: &[u64],
|
||
|
) -> Option<Local<'s, BigInt>> {
|
||
|
unsafe {
|
||
|
scope.cast_local(|sd| {
|
||
|
v8__BigInt__NewFromWords(
|
||
|
sd.get_current_context(),
|
||
|
sign_bit as int,
|
||
|
words.len() as int,
|
||
|
words.as_ptr(),
|
||
|
)
|
||
|
})
|
||
|
}
|
||
|
}
|
||
|
|
||
|
/// Returns the value of this BigInt as an unsigned 64-bit integer, and a
|
||
|
/// `bool` indicating whether the return value was truncated was truncated or
|
||
|
/// wrapped around. In particular, it will be `false` if this BigInt is
|
||
|
/// negative.
|
||
|
pub fn u64_value(&self) -> (u64, bool) {
|
||
|
let mut lossless = MaybeUninit::uninit();
|
||
|
let v = unsafe { v8__BigInt__Uint64Value(&*self, lossless.as_mut_ptr()) };
|
||
|
let lossless = unsafe { lossless.assume_init() };
|
||
|
(v, lossless)
|
||
|
}
|
||
|
|
||
|
/// Returns the value of this BigInt as a signed 64-bit integer, and a `bool`
|
||
|
/// indicating whether this BigInt was truncated or not.
|
||
|
pub fn i64_value(&self) -> (i64, bool) {
|
||
|
let mut lossless = MaybeUninit::uninit();
|
||
|
let v = unsafe { v8__BigInt__Int64Value(&*self, lossless.as_mut_ptr()) };
|
||
|
let lossless = unsafe { lossless.assume_init() };
|
||
|
(v, lossless)
|
||
|
}
|
||
|
|
||
|
/// Returns the number of 64-bit words needed to store the result of
|
||
|
/// `to_words_array`.
|
||
|
pub fn word_count(&self) -> usize {
|
||
|
unsafe { v8__BigInt__WordCount(&*self) as usize }
|
||
|
}
|
||
|
|
||
|
/// Converts this BigInt to a (sign_bit, words) pair. `sign_bit` will be true
|
||
|
/// if this BigInt is negative. If `words` has too few elements, the result will
|
||
|
/// be truncated to fit.
|
||
|
pub fn to_words_array<'a>(
|
||
|
&self,
|
||
|
words: &'a mut [u64],
|
||
|
) -> (bool, &'a mut [u64]) {
|
||
|
let mut sign_bit = MaybeUninit::uninit();
|
||
|
let mut word_count = words.len() as int;
|
||
|
unsafe {
|
||
|
v8__BigInt__ToWordsArray(
|
||
|
&*self,
|
||
|
sign_bit.as_mut_ptr(),
|
||
|
&mut word_count,
|
||
|
words.as_mut_ptr(),
|
||
|
)
|
||
|
}
|
||
|
|
||
|
let sign_bit = unsafe { sign_bit.assume_init() };
|
||
|
debug_assert!(sign_bit == 0 || sign_bit == 1);
|
||
|
let word_count = word_count as usize;
|
||
|
|
||
|
(
|
||
|
sign_bit == 1,
|
||
|
if word_count < words.len() {
|
||
|
&mut words[..word_count]
|
||
|
} else {
|
||
|
words
|
||
|
},
|
||
|
)
|
||
|
}
|
||
|
}
|