From 7d90055bc6f0048431c4285f3af5d3b705bde3fb Mon Sep 17 00:00:00 2001 From: Christian Ivicevic Date: Fri, 13 Oct 2023 17:35:30 +0200 Subject: [PATCH 1/2] Introduce wasm_bindgen support and expose a toNumber method for use in JavaScript --- Cargo.toml | 2 ++ README.md | 6 ++++++ src/decimal.rs | 3 +++ src/lib.rs | 2 ++ src/wasm.rs | 14 ++++++++++++++ 5 files changed, 27 insertions(+) create mode 100644 src/wasm.rs diff --git a/Cargo.toml b/Cargo.toml index 5373244a..499fc8c2 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -34,6 +34,7 @@ rocket = { default-features = false, optional = true, version = "0.5.0-rc.3" } serde = { default-features = false, optional = true, version = "1.0" } serde_json = { default-features = false, optional = true, version = "1.0" } tokio-postgres = { default-features = false, optional = true, version = "0.7" } +wasm-bindgen = { default-features = false, optional = true, version = "0.2" } [dev-dependencies] bincode = { default-features = false, version = "1.0" } @@ -81,6 +82,7 @@ serde-with-float = ["serde"] serde-with-str = ["serde"] std = ["arrayvec/std", "borsh?/std", "bytes?/std", "rand?/std", "rkyv?/std", "serde?/std", "serde_json?/std"] tokio-pg = ["db-tokio-postgres"] # Backwards compatability +wasm-bindgen = ["dep:wasm-bindgen"] [[bench]] harness = false diff --git a/README.md b/README.md index aa4c39fa..29a14bb7 100644 --- a/README.md +++ b/README.md @@ -106,6 +106,7 @@ assert_eq!(total, dec!(27.26)); * [rocket-traits](#rocket-traits) * [rust-fuzz](#rust-fuzz) * [std](#std) +* [wasm-bindgen](#wasm-bindgen) **Database** @@ -297,6 +298,11 @@ pub struct OptionArbitraryExample { Enable `std` library support. This is enabled by default, however in the future will be opt in. For now, to support `no_std` libraries, this crate can be compiled with `--no-default-features`. +### `wasm-bindgen` + +Enable [`wasm-bindgen`](https://github.com/rustwasm/wasm-bindgen) support which makes `Decimal` compatible with the +`wasm_bindgen` attribute macro and exposes a `toNumber()` method for use in JavaScript. + ## Building Please refer to the [Build document](BUILD.md) for more information on building and testing Rust Decimal. diff --git a/src/decimal.rs b/src/decimal.rs index e057d4f7..519029a6 100644 --- a/src/decimal.rs +++ b/src/decimal.rs @@ -27,6 +27,8 @@ use num_traits::float::FloatCore; use num_traits::{FromPrimitive, Num, One, Signed, ToPrimitive, Zero}; #[cfg(feature = "rkyv")] use rkyv::{Archive, Deserialize, Serialize}; +#[cfg(feature = "wasm-bindgen")] +use wasm_bindgen::prelude::wasm_bindgen; /// The smallest value that can be represented by this decimal type. const MIN: Decimal = Decimal { @@ -121,6 +123,7 @@ pub struct UnpackedDecimal { archive_attr(derive(Clone, Copy, Debug)) )] #[cfg_attr(feature = "rkyv-safe", archive(check_bytes))] +#[cfg_attr(feature = "wasm-bindgen", wasm_bindgen)] pub struct Decimal { // Bits 0-15: unused // Bits 16-23: Contains "e", a value between 0-28 that indicates the scale diff --git a/src/lib.rs b/src/lib.rs index 59900e65..7e54bde5 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -51,6 +51,8 @@ mod serde; ) ))] pub mod serde; +#[cfg(feature = "wasm-bindgen")] +pub mod wasm; pub use decimal::{Decimal, RoundingStrategy}; pub use error::Error; diff --git a/src/wasm.rs b/src/wasm.rs new file mode 100644 index 00000000..cc6f2515 --- /dev/null +++ b/src/wasm.rs @@ -0,0 +1,14 @@ +use num_traits::ToPrimitive; +use wasm_bindgen::prelude::wasm_bindgen; + +use crate::Decimal; + +#[wasm_bindgen] +impl Decimal { + /// Returns the value of this `Decimal` converted to a primitive number. + #[wasm_bindgen(js_name = toNumber)] + #[must_use] + pub fn to_number(&self) -> f64 { + self.to_f64().unwrap_or(f64::NAN) + } +} From 2b7e9d97db5c399c3ca1ee636750fc0a248a4115 Mon Sep 17 00:00:00 2001 From: Christian Ivicevic Date: Sat, 14 Oct 2023 11:40:04 +0200 Subject: [PATCH 2/2] Introduce a static fromNumber function to enable JavaScript sending Decimal objects across the boundary --- README.md | 3 ++- src/wasm.rs | 9 ++++++++- 2 files changed, 10 insertions(+), 2 deletions(-) diff --git a/README.md b/README.md index 29a14bb7..fe6675a2 100644 --- a/README.md +++ b/README.md @@ -301,7 +301,8 @@ libraries, this crate can be compiled with `--no-default-features`. ### `wasm-bindgen` Enable [`wasm-bindgen`](https://github.com/rustwasm/wasm-bindgen) support which makes `Decimal` compatible with the -`wasm_bindgen` attribute macro and exposes a `toNumber()` method for use in JavaScript. +`wasm_bindgen` attribute macro and exposes `fromNumber()` and `toNumber()` methods to convert between `Decimal` and +the primitive `number` type across boundaries. ## Building diff --git a/src/wasm.rs b/src/wasm.rs index cc6f2515..2308354e 100644 --- a/src/wasm.rs +++ b/src/wasm.rs @@ -1,10 +1,17 @@ -use num_traits::ToPrimitive; +use num_traits::{FromPrimitive, ToPrimitive}; use wasm_bindgen::prelude::wasm_bindgen; use crate::Decimal; #[wasm_bindgen] impl Decimal { + /// Returns a new `Decimal` object instance by converting a primitive number. + #[wasm_bindgen(js_name = fromNumber)] + #[must_use] + pub fn from_number(value: f64) -> Option { + Decimal::from_f64(value) + } + /// Returns the value of this `Decimal` converted to a primitive number. #[wasm_bindgen(js_name = toNumber)] #[must_use]