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

This commit is contained in:
Léo Gaspard
2024-02-23 09:06:00 +01:00
committed by GitHub
parent b5a74c8578
commit 557e2e6518
3 changed files with 53 additions and 1 deletions

View File

@@ -11,6 +11,9 @@
* Add bindings for `CanvasState.reset()`, affecting `CanvasRenderingContext2D` and `OffscreenCanvasRenderingContext2D`.
[#3844](https://github.com/rustwasm/wasm-bindgen/pull/3844)
* Add `TryFrom` implementations for `Number`, that allow losslessly converting from 64- and 128-bits numbers.
[#3847](https://github.com/rustwasm/wasm-bindgen/pull/3847)
### Fixed
* Make .wasm output deterministic when using `--reference-types`.

View File

@@ -2793,6 +2793,37 @@ macro_rules! number_from {
}
number_from!(i8 u8 i16 u16 i32 u32 f32 f64);
/// The error type returned when a checked integral type conversion fails.
#[derive(Debug, Copy, Clone, PartialEq, Eq)]
pub struct TryFromIntError(());
impl fmt::Display for TryFromIntError {
fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result {
fmt.write_str("out of range integral type conversion attempted")
}
}
impl std::error::Error for TryFromIntError {}
macro_rules! number_try_from {
($($x:ident)*) => ($(
impl TryFrom<$x> for Number {
type Error = TryFromIntError;
#[inline]
fn try_from(x: $x) -> Result<Number, Self::Error> {
let x_f64 = x as f64;
if x_f64 >= Number::MIN_SAFE_INTEGER && x_f64 <= Number::MAX_SAFE_INTEGER {
Ok(Number::from(x_f64))
} else {
Err(TryFromIntError(()))
}
}
}
)*)
}
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 {

View File

@@ -1,4 +1,7 @@
use std::f64::{INFINITY, NAN};
use std::{
convert::TryFrom,
f64::{INFINITY, NAN},
};
use js_sys::*;
use wasm_bindgen::prelude::*;
@@ -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.);