Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Introduce impl TryFrom for Number that succeeds iff the value is within the safe range #3847

Merged
merged 14 commits into from
Feb 23, 2024
18 changes: 18 additions & 0 deletions crates/js-sys/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2793,6 +2793,24 @@ macro_rules! number_from {
}
number_from!(i8 u8 i16 u16 i32 u32 f32 f64);

macro_rules! number_try_from {
($($x:ident)*) => ($(
impl TryFrom<$x> for Number {
type Error = $x;
Ekleog marked this conversation as resolved.
Show resolved Hide resolved

#[inline]
fn try_from(x: $x) -> Result<Number, Self::Error> {
if x as f64 >= Number::MIN_SAFE_INTEGER && x as f64 <= Number::MAX_SAFE_INTEGER {
Ok(Number::unchecked_from_js(JsValue::from(x as f64)))
Ekleog marked this conversation as resolved.
Show resolved Hide resolved
} else {
Err(x)
}
}
}
)*)
}
number_try_from!(i64 u64 i128 u128);

// TODO: add this on the next major version, when blanket impl is removed
/*
impl convert::TryFrom<JsValue> for Number {
Expand Down
20 changes: 19 additions & 1 deletion crates/js-sys/tests/wasm/Number.rs
Original file line number Diff line number Diff line change
@@ -1,4 +1,7 @@
use std::f64::{INFINITY, NAN};
use std::{
convert::TryFrom,
f64::{INFINITY, NAN},
daxpedda marked this conversation as resolved.
Show resolved Hide resolved
};

use js_sys::*;
use wasm_bindgen::prelude::*;
Expand Down Expand Up @@ -71,6 +74,21 @@ fn new() {
assert_eq!(Number::from(v).value_of(), 42.);
}

#[wasm_bindgen_test]
fn try_from() {
assert_eq!(Number::try_from(42u128).unwrap(), 42.);
assert_eq!(
Number::try_from(Number::MAX_SAFE_INTEGER as u64).unwrap(),
Number::MAX_SAFE_INTEGER
);
assert_eq!(
Number::try_from(Number::MIN_SAFE_INTEGER as i128).unwrap(),
Number::MIN_SAFE_INTEGER
);
assert!(Number::try_from(Number::MAX_SAFE_INTEGER as u128 + 1).is_err());
assert!(Number::try_from(Number::MIN_SAFE_INTEGER as i64 - 1).is_err());
}

#[wasm_bindgen_test]
fn parse_int_float() {
assert_eq!(Number::parse_int("42", 10), 42.);
Expand Down