diff --git a/Cargo.toml b/Cargo.toml index 0e733d1..2cec4a7 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -43,6 +43,7 @@ criterion = { default-features = false, version = "0.5" } csv = "1" futures = { default-features = false, version = "0.3" } rand = { default-features = false, features = ["getrandom"], version = "0.8" } +rkyv-0_8 = { version = "0.8", package = "rkyv" } rust_decimal_macros = { default-features = false, version = "1.33" } serde = { default-features = false, features = ["derive"], version = "1.0" } serde_json = "1.0" @@ -72,7 +73,7 @@ proptest = ["dep:proptest"] rand = ["dep:rand"] rkyv = ["dep:rkyv"] rkyv-safe = ["rkyv/validation"] -rocket-traits = ["dep:rocket"] +rocket-traits = ["dep:rocket", "std"] rust-fuzz = ["dep:arbitrary"] serde = ["dep:serde"] serde-arbitrary-precision = ["serde-with-arbitrary-precision"] @@ -90,9 +91,12 @@ harness = false name = "comparison" path = "benches/comparison.rs" +[[example]] +name = "rkyv-remote" + [workspace] members = [ ".", - "./macros" + "./macros", ] resolver = "2" diff --git a/README.md b/README.md index 2587fcf..5d2d8e9 100644 --- a/README.md +++ b/README.md @@ -195,9 +195,12 @@ two). ### `rkyv` -Enables [rkyv](https://github.com/rkyv/rkyv) serialization for `Decimal`. +Enables [rkyv](https://github.com/rkyv/rkyv) serialization for `Decimal`. In order to avoid breaking changes, this is currently locked at version `0.7`. + Supports rkyv's safe API when the `rkyv-safe` feature is enabled as well. +If `rkyv` support for versions `0.8` of greater is desired, `rkyv`'s [remote derives](https://rkyv.org/derive-macro-features/remote-derive.html) should be used instead. See `examples/rkyv-remote`. + ### `rocket-traits` Enable support for Rocket forms by implementing the `FromFormField` trait. diff --git a/examples/README.md b/examples/README.md index c7eecde..73d8b92 100644 --- a/examples/README.md +++ b/examples/README.md @@ -14,3 +14,6 @@ cargo run This example shows how to use the `serde` crate to serialize and deserialize the `Decimal` type using multiple different serialization formats. +## rkyv-remote + +This example shows shows how to use the `rkyv` crate's remote derive for the `Decimal` type. \ No newline at end of file diff --git a/examples/rkyv-remote.rs b/examples/rkyv-remote.rs new file mode 100644 index 0000000..89f4dcb --- /dev/null +++ b/examples/rkyv-remote.rs @@ -0,0 +1,36 @@ +extern crate rkyv_0_8 as rkyv; + +use rkyv::{rancor::Error, Archive, Deserialize, Serialize}; +use rust_decimal::Decimal; +use rust_decimal_macros::dec; + +/// The type containing a [`Decimal`] that will be de/serialized. +#[derive(Archive, Serialize, Deserialize, Debug, PartialEq, Eq)] +struct Root { + #[rkyv(with = RkyvDecimal)] + decimal: Decimal, +} + +/// Archived layout of [`Decimal`] +#[derive(Archive, Serialize, Deserialize)] +#[rkyv(remote = Decimal)] +struct RkyvDecimal { + #[rkyv(getter = Decimal::serialize)] + bytes: [u8; 16], +} + +impl From for Decimal { + fn from(RkyvDecimal { bytes }: RkyvDecimal) -> Self { + Self::deserialize(bytes) + } +} + +fn main() { + let test_value = Root { decimal: dec!(123.456) }; + + let bytes = rkyv::to_bytes::(&test_value).expect("Failed to serialize"); + + let roundtrip_value = rkyv::from_bytes::(&bytes).expect("Failed to deserialize"); + + assert_eq!(test_value, roundtrip_value); +} diff --git a/examples/serde-json-scenarios/Cargo.toml b/examples/serde-json-scenarios/Cargo.toml index f6be4fc..06ab8d2 100644 --- a/examples/serde-json-scenarios/Cargo.toml +++ b/examples/serde-json-scenarios/Cargo.toml @@ -4,8 +4,6 @@ version = "0.0.0" edition = "2021" publish = false -[workspace] - [dependencies] rust_decimal = { path = "../..", features = ["serde-with-arbitrary-precision"] } rust_decimal_macros = { path = "../../macros" } diff --git a/src/decimal.rs b/src/decimal.rs index 5df67f3..e34fbea 100644 --- a/src/decimal.rs +++ b/src/decimal.rs @@ -573,7 +573,7 @@ impl Decimal { pub fn from_scientific(value: &str) -> Result { const ERROR_MESSAGE: &str = "Failed to parse"; - let mut split = value.splitn(2, |c| c == 'e' || c == 'E'); + let mut split = value.splitn(2, ['e', 'E']); let base = split.next().ok_or_else(|| Error::from(ERROR_MESSAGE))?; let exp = split.next().ok_or_else(|| Error::from(ERROR_MESSAGE))?; diff --git a/src/serde.rs b/src/serde.rs index c18e08e..ea19e89 100644 --- a/src/serde.rs +++ b/src/serde.rs @@ -370,8 +370,10 @@ impl<'de> serde::de::Visitor<'de> for DecimalVisitor { } } +#[cfg(any(feature = "serde-with-float", feature = "serde-with-arbitrary-precision"))] struct OptionDecimalVisitor; +#[cfg(any(feature = "serde-with-float", feature = "serde-with-arbitrary-precision"))] impl<'de> serde::de::Visitor<'de> for OptionDecimalVisitor { type Value = Option;