diff --git a/Cargo.lock b/Cargo.lock index 1ba7c01..c9d9d5c 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -64,6 +64,15 @@ dependencies = [ "wyz", ] +[[package]] +name = "borsh" +version = "1.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bf617fabf5cdbdc92f774bfe5062d870f228b80056d41180797abf48bed4056e" +dependencies = [ + "cfg_aliases", +] + [[package]] name = "bytecheck" version = "0.6.11" @@ -97,6 +106,12 @@ version = "1.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd" +[[package]] +name = "cfg_aliases" +version = "0.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fd16c4719339c4530435d38e511904438d07cce7950afa3718a84ac36c10e89e" + [[package]] name = "dyn-clone" version = "1.0.14" @@ -211,6 +226,7 @@ name = "ordered-float" version = "4.1.1" dependencies = [ "arbitrary", + "borsh", "bytemuck", "num-traits", "proptest", diff --git a/Cargo.toml b/Cargo.toml index f8715fd..c7d4b78 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -24,6 +24,7 @@ arbitrary = { version = "1.0.0", optional = true } proptest = { version = "1.0.0", optional = true } speedy = { version = "0.8.3", optional = true, default-features = false } bytemuck = { version = "1.12.2", optional = true, default-features = false } +borsh = { version = "1.2.0", optional = true, default-features = false } [dev-dependencies] serde_test = "1.0" diff --git a/src/lib.rs b/src/lib.rs index 5a512e7..bbc1408 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -2173,6 +2173,77 @@ mod impl_speedy { } } +#[cfg(feature = "borsh")] +mod impl_borsh { + extern crate borsh; + use super::{NotNan, OrderedFloat}; + use num_traits::float::FloatCore; + + impl borsh::BorshSerialize for OrderedFloat + where + T: borsh::BorshSerialize, + { + #[inline] + fn serialize(&self, writer: &mut W) -> borsh::io::Result<()> { + ::serialize(&self.0, writer) + } + } + + impl borsh::BorshDeserialize for OrderedFloat + where + T: borsh::BorshDeserialize, + { + #[inline] + fn deserialize_reader(reader: &mut R) -> borsh::io::Result { + ::deserialize_reader(reader).map(Self) + } + } + + impl borsh::BorshSerialize for NotNan + where + T: borsh::BorshSerialize, + { + #[inline] + fn serialize(&self, writer: &mut W) -> borsh::io::Result<()> { + ::serialize(&self.0, writer) + } + } + + impl borsh::BorshDeserialize for NotNan + where + T: FloatCore + borsh::BorshDeserialize, + { + #[inline] + fn deserialize_reader(reader: &mut R) -> borsh::io::Result { + let float = ::deserialize_reader(reader)?; + NotNan::new(float).map_err(|_| { + borsh::io::Error::new( + borsh::io::ErrorKind::InvalidData, + "expected a non-NaN float", + ) + }) + } + } + + #[test] + fn test_ordered_float() { + let float = crate::OrderedFloat(1.0f64); + let buffer = borsh::to_vec(&float).expect("failed to serialize value"); + let deser_float: crate::OrderedFloat = + borsh::from_slice(&buffer).expect("failed to deserialize value"); + assert_eq!(deser_float, float); + } + + #[test] + fn test_not_nan() { + let float = crate::NotNan(1.0f64); + let buffer = borsh::to_vec(&float).expect("failed to serialize value"); + let deser_float: crate::NotNan = + borsh::from_slice(&buffer).expect("failed to deserialize value"); + assert_eq!(deser_float, float); + } +} + #[cfg(all(feature = "std", feature = "schemars"))] mod impl_schemars { extern crate schemars;