Skip to content

Commit

Permalink
Add wasm support to rust-decimal
Browse files Browse the repository at this point in the history
A new optional feature 'wasm' has been introduced in the codebase. This enables `wasm-bindgen` support, making `Decimal` compatible with the `wasm_bindgen` attribute macro, and exposes `fromNumber()` and `toNumber()` methods to convert between `Decimal` and the primitive `number` type.
  • Loading branch information
ChristianIvicevic committed Mar 6, 2024
1 parent c5d4afe commit 587addd
Show file tree
Hide file tree
Showing 5 changed files with 40 additions and 0 deletions.
2 changes: 2 additions & 0 deletions Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,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" }
Expand Down Expand Up @@ -85,6 +86,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 = ["dep:wasm-bindgen"]

[[bench]]
harness = false
Expand Down
7 changes: 7 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -104,6 +104,7 @@ assert_eq!(total, dec!(27.26));
* [rocket-traits](#rocket-traits)
* [rust-fuzz](#rust-fuzz)
* [std](#std)
* [wasm](#wasm)

**Database**

Expand Down Expand Up @@ -331,6 +332,12 @@ Please see the `examples` directory for more information regarding `serde_json`
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`

Enable [`wasm-bindgen`](https://github.com/rustwasm/wasm-bindgen) support which makes `Decimal` compatible with the
`wasm_bindgen` attribute macro and exposes `fromNumber()` and `toNumber()` methods to convert between `Decimal` and
the primitive `number` type across boundaries.

## Building

Please refer to the [Build document](BUILD.md) for more information on building and testing Rust Decimal.
Expand Down
3 changes: 3 additions & 0 deletions src/decimal.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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")]
use wasm_bindgen::prelude::wasm_bindgen;

/// The smallest value that can be represented by this decimal type.
const MIN: Decimal = Decimal {
Expand Down Expand Up @@ -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", wasm_bindgen)]
pub struct Decimal {
// Bits 0-15: unused
// Bits 16-23: Contains "e", a value between 0-28 that indicates the scale
Expand Down
2 changes: 2 additions & 0 deletions src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -52,6 +52,8 @@ mod serde;
)
))]
pub mod serde;
#[cfg(feature = "wasm")]
pub mod wasm;

pub use decimal::{Decimal, RoundingStrategy};
pub use error::Error;
Expand Down
26 changes: 26 additions & 0 deletions src/wasm.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
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> {
Decimal::from_f64(value)
}

/// Returns the value of this `Decimal` converted to a primitive number.
///
/// # Caution
/// At the time of writing this implementation the conversion from `Decimal` to `f64` cannot
/// fail. To prevent undefined behavior in case the underlying implementation changes `f64::NAN`
/// is returned as a stable fallback value.
#[wasm_bindgen(js_name = toNumber)]
#[must_use]
pub fn to_number(&self) -> f64 {
self.to_f64().unwrap_or(f64::NAN)
}
}

0 comments on commit 587addd

Please sign in to comment.