Skip to content

Commit

Permalink
Merge pull request #32 from adeschamps/serde
Browse files Browse the repository at this point in the history
Add serde support behind a feature flag.
  • Loading branch information
paholg authored Jun 21, 2018
2 parents 1262612 + 2f4d7a7 commit a946893
Show file tree
Hide file tree
Showing 4 changed files with 82 additions and 3 deletions.
4 changes: 3 additions & 1 deletion Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,7 @@ Never again should you need to specify units in a comment!"""
default = []
oibit = []
spec = []
test = ["clippy", "quickcheck", "quickcheck_macros", "approx", "oibit", "spec"]
test = ["clippy", "quickcheck", "quickcheck_macros", "approx", "oibit", "spec", "serde", "serde_test"]

[dependencies]
typenum = "1.6.0"
Expand All @@ -33,3 +33,5 @@ Never again should you need to specify units in a comment!"""
quickcheck = { version = "0.4.1", optional = true }
quickcheck_macros = { version = "0.4.1", optional = true }
approx = { version = "0.1.1", optional = true, features = ["no_std"] }
serde = { version = "1.0.0", optional = true }
serde_test = { version = "1.0.0", optional = true }
23 changes: 22 additions & 1 deletion src/build/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -155,9 +155,12 @@ pub mod {} {{
fmt = {};
}}
#[cfg(feature = \"serde\")]
impl_serde!({});
pub use self::f64consts::*;
", self.fmt)?;
", self.fmt, self.name)?;

write!(f, "
#[test]
Expand All @@ -173,8 +176,26 @@ pub mod {} {{
assert_eq!({}, {});", c.constant, c.nice_value())?;
}
write!(f, "
}}")?;

write!(f, "
/// Test that serializing/deserializing values with units is
/// equivalent to doing so with raw numeric types.
#[cfg(feature = \"serde\")]
#[test]
fn test_{}_serde() {{
use ::serde_test::{{assert_tokens, Token}};
", self.module)?;
for base in &self.base {
write!(f, "
let value = 1.0 * {};
assert_tokens(&value, &[Token::F64(1.0)]);
", base.constant)?;
}
write!(f, "
}}
}}")?;

Ok(())
}
}
Expand Down
5 changes: 5 additions & 0 deletions src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -154,6 +154,11 @@ pub extern crate generic_array;
#[cfg(feature = "approx")]
pub extern crate approx;

#[cfg(feature = "serde")]
pub extern crate serde;
#[cfg(feature = "serde_test")]
extern crate serde_test;

#[macro_use] mod make_units;
mod fmt;

Expand Down
53 changes: 52 additions & 1 deletion src/make_units.rs
Original file line number Diff line number Diff line change
Expand Up @@ -130,7 +130,8 @@ which allows the use of `consts::PI` in the `PI definition.
Finally, we have the `fmt` line. This line can either be `fmt = true;` or `fmt = false;`. In either
case, the trait `core::fmt::Debug` is implemented for your unit system, but all of the other `fmt`
traits are implemented only if this is true. Setting it to false allows you to have custom printing for your system.
traits are implemented only if this is true. Setting it to `false` allows you to have custom
printing for your system.
```ignore
fmt = true;
Expand Down Expand Up @@ -1041,6 +1042,56 @@ macro_rules! __derived_internal {
(@mu commas $($tail:tt)*) => (__derived_internal!(@mu eval $($tail,)*));
}

/// Implement serde traits for a unit system.
///
/// The implementations generated by this macro only serialize the
/// numeric values - not the actual units. Therefore, serialization is
/// dimensionally unsafe, but it does not add any overhead over using
/// plain numeric types.
///
/// All of the unit systems defined in this crate implement
/// `Serialize` and `Deserialize` using this macro. If you define your
/// own system you may use this macro to implement those traits
/// automatically, or define them yourself:
///
/// ```rust,ignore
/// impl_serde!(UnitSystem);
/// ```
#[cfg(feature = "serde")]
#[macro_export]
macro_rules! impl_serde {
($System:ident) => {
use $crate::serde::{Deserialize, Deserializer, Serialize, Serializer};

impl<'de, V, U> Deserialize<'de> for $System<V, U>
where
V: Deserialize<'de>,
{
fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
where
D: Deserializer<'de>,
{
let value_unsafe = V::deserialize(deserializer)?;
Ok($System {
value_unsafe,
_marker: marker::PhantomData,
})
}
}

impl<V, U> Serialize for $System<V, U>
where
V: Serialize,
{
fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
where
S: Serializer,
{
self.value_unsafe.serialize(serializer)
}
}
};
}

// tests to see if we can rewrite derived! macro better
// #[test]
Expand Down

0 comments on commit a946893

Please # to comment.