Skip to content

Commit

Permalink
Implement serde::Serialize and serde::Deserialize.
Browse files Browse the repository at this point in the history
Fixes #37.
  • Loading branch information
radix authored and iliekturtles committed Jan 2, 2018
1 parent d50651e commit fd14b3b
Show file tree
Hide file tree
Showing 8 changed files with 97 additions and 13 deletions.
4 changes: 2 additions & 2 deletions .appveyor.yml
Original file line number Diff line number Diff line change
Expand Up @@ -54,8 +54,8 @@ install:
## Build Script ##
build: false
test_script:
- cargo build --verbose
- cargo test --verbose
- cargo build --verbose --all-features --tests
- cargo test --verbose --features serde

notifications:
- provider: Email
Expand Down
4 changes: 2 additions & 2 deletions .travis.yml
Original file line number Diff line number Diff line change
Expand Up @@ -30,8 +30,8 @@ before_script: |
(test $(grep "cargo-travis" /home/travis/.cargo/.crates.toml | sed -r "s/\"cargo-travis ([^\ ]+).+/\1/") = $(cargo search cargo-travis --limit 1 | sed -r "s/cargo-travis \(([^\)]+)\).+/\1/") || cargoo install cargo-travis --force)
script: |
cargo build --verbose &&
(test "$TRAVIS_RUST_VERSION" == "1.20.0" || cargo test --verbose)
cargo build --verbose --all-features --tests &&
(test "$TRAVIS_RUST_VERSION" == "1.20.0" || cargo test --verbose --features serde)
after_success: |
test "$TRAVIS_RUST_VERSION" != "stable" || cargo coveralls
Expand Down
2 changes: 2 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,8 @@
### Added
* [#26](https://github.com/iliekturtles/uom/issues/26) Implement `num::Zero`.
* [#35](https://github.com/iliekturtles/uom/issues/35) Implement `num::Saturating`.
* [#37](https://github.com/iliekturtles/uom/issues/35) Implement `serde::Serialize` and
`serde::Deserialize`. Disabled by default. Enabled with the `use_serde` feature.

## [v0.16.0] — 2017-12-21
This release contains significant changes in order to support underlying storage types that
Expand Down
7 changes: 7 additions & 0 deletions Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -22,11 +22,13 @@ maintenance = { status = "actively-developed" }

[dependencies]
num = "0.1"
serde = { version = "1.0", optional = true, default-features = false }
typenum = "1.9.0"

[dev-dependencies]
approx = "0.1.1"
quickcheck = "0.5.0"
serde_json = "1.0"
static_assertions = "0.2.5"

[features]
Expand All @@ -51,6 +53,11 @@ f32 = []
f64 = []
si = []
std = []
# The `use_serde` feature exists so that, in the future, other dependency features like num/serde
# can be added. However, num/serde is currently left out because it has not yet been updated to
# Serde 1.0. It is also necessary to name the feature something other than `serde` because of a
# cargo bug: https://github.com/rust-lang/cargo/issues/1286
use_serde = ["serde"]

[[example]]
name = "base"
Expand Down
12 changes: 8 additions & 4 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -63,10 +63,10 @@ See the [examples](examples) directory for more advanced usage:

## Features
`uom` has multiple `Cargo` features for controlling available underlying storage types, the
inclusion of the pre-built [International System of Units][si] (SI), and `no_std` functionality. The
features are described below. `f32`, `f64`, `std`, and `si` are enabled by default. Features can be
cherry-picked by using the `--no-default-features` and `--features "..."` flags when compiling `uom`
or specifying features in Cargo.toml:
inclusion of the pre-built [International System of Units][si] (SI), support for [Serde][serde],
and `no_std` functionality. The features are described below. `f32`, `f64`, `std`, and `si` are
enabled by default. Features can be cherry-picked by using the `--no-default-features` and
`--features "..."` flags when compiling `uom` or specifying features in Cargo.toml:

```toml
[dependencies]
Expand All @@ -80,6 +80,7 @@ uom = {
"rational", "rational32", "rational64", "bigrational", # Integer ratio storage types.
"f32", "f64", # Floating point storage types.
"si", "std", # Built-in SI system and std library support.
"use_serde", # Serde support.
]
}
```
Expand All @@ -92,8 +93,11 @@ uom = {
default.
* `std` -- Feature to compile with standard library support. Disabling this feature compiles `uom`
with `no_std`. Enabled by default.
* `use_serde` -- Feature to enable support for serialization and deserialization of quantities
with the [Serde][serde] crate. Disabled by default.

[si]: http://jcgm.bipm.org/vim/en/1.16.html
[serde]: https://serde.rs/

## Design
Rather than working with [measurement units](http://jcgm.bipm.org/vim/en/1.9.html) (meter,
Expand Down
19 changes: 15 additions & 4 deletions src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -52,10 +52,11 @@
//!
//! ## Features
//! `uom` has multiple `Cargo` features for controlling available underlying storage types, the
//! inclusion of the pre-built [International System of Units][si] (SI), and `no_std` functionality.
//! The features are described below. `f32`, `f64`, `std`, and `si` are enabled by default. Features
//! can be cherry-picked by using the `--no-default-features` and `--features "..."` flags when
//! compiling `uom` or specifying features in Cargo.toml:
//! inclusion of the pre-built [International System of Units][si] (SI), support for
//! [Serde][serde], and `no_std` functionality. The features are described below. `f32`, `f64`,
//! `std`, and `si` are enabled by default. Features can be cherry-picked by using the
//! `--no-default-features` and `--features "..."` flags when compiling `uom` or specifying
//! features in Cargo.toml:
//!
//! ```toml
//! [dependencies]
Expand All @@ -69,6 +70,7 @@
//! "rational", "rational32", "rational64", "bigrational", # Integer ratio storage types.
//! "f32", "f64", # Floating point storage types.
//! "si", "std", # Built-in SI system and std library support.
//! "use_serde", # Serde support.
//! ]
//! }
//! ```
Expand All @@ -81,8 +83,11 @@
//! default.
//! * `std` -- Feature to compile with standard library support. Disabling this feature compiles
//! `uom` with `no_std`. Enabled by default.
//! * `use_serde` -- Feature to enable support for serialization and deserialization of quantities
//! with the [Serde][serde] crate. Disabled by default.
//!
//! [si]: http://jcgm.bipm.org/vim/en/1.16.html
//! [serde]: https://serde.rs/
//!
//! ## Design
//! Rather than working with [measurement units](http://jcgm.bipm.org/vim/en/1.9.html) (meter,
Expand Down Expand Up @@ -156,6 +161,10 @@ compile_error!("A least one underlying storage type must be enabled. See the fea
#[doc(hidden)]
pub extern crate num;

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

#[doc(hidden)]
pub extern crate typenum;

Expand All @@ -165,6 +174,8 @@ extern crate approx;
#[cfg(test)]
#[macro_use]
extern crate quickcheck;
#[cfg(all(test, feature = "serde"))]
extern crate serde_json;
#[cfg(test)]
#[macro_use]
extern crate static_assertions;
Expand Down
36 changes: 36 additions & 0 deletions src/system.rs
Original file line number Diff line number Diff line change
Expand Up @@ -873,6 +873,42 @@ macro_rules! system {
}
}

#[cfg(feature = "serde")]
impl<D, U, V> $crate::serde::Serialize for Quantity<D, U, V>
where
D: Dimension + ?Sized,
U: Units<V> + ?Sized,
V: $crate::num::Num + $crate::Conversion<V> + $crate::serde::Serialize,
{
fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
where
S: $crate::serde::Serializer
{
self.value.serialize(serializer)
}
}

#[cfg(feature = "serde")]
impl<'de, D, U, V> $crate::serde::Deserialize<'de> for Quantity<D, U, V>
where
D: Dimension + ?Sized,
U: Units<V> + ?Sized,
V: $crate::num::Num + $crate::Conversion<V> + $crate::serde::Deserialize<'de>,
{
fn deserialize<De>(deserializer: De) -> Result<Self, De::Error>
where
De: $crate::serde::Deserializer<'de>,
{
let value: V = $crate::serde::Deserialize::deserialize(deserializer)?;

Ok(Quantity {
dimension: $crate::lib::marker::PhantomData,
units: $crate::lib::marker::PhantomData,
value,
})
}
}

/// Macro to implement [`quantity`](si/struct.Quantity.html) type aliases for a specific
/// [system of units][units] and value storage type.
///
Expand Down
26 changes: 25 additions & 1 deletion src/tests.rs
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,8 @@ use num::{Float, FromPrimitive, One, Saturating, Signed, Zero};
use quickcheck::TestResult;
use lib::fmt::Debug;
use lib::marker::PhantomData;
#[cfg(feature = "serde")]
use serde_json;
#[allow(unused_imports)]
use typenum::{N1, P1, P2, P3, Z0};

Expand Down Expand Up @@ -710,7 +712,7 @@ mod system_macro {
}
}

mod op_assign {
mod primitive {
storage_types! {
types: Float, PrimInt;

Expand Down Expand Up @@ -781,6 +783,28 @@ mod system_macro {

TestResult::from_bool(Test::approx_eq(&f, &v.get(meter)))
}

// These serde tests can't be run against num-backed numeric backends because the num
// crate hasn't been updated to Serde 1.0 yet.
#[cfg(feature = "serde")]
#[allow(trivial_casts)]
fn serde_serialize(v: A<V>) -> bool {
let m = Length::new::<meter>((*v).clone());
let json_f = serde_json::to_string(&*v).expect("Must be able to serialize num");
let json_q = serde_json::to_string(&m).expect("Must be able to serialize Quantity");

json_f == json_q
}

#[cfg(feature = "serde")]
#[allow(trivial_casts)]
fn serde_deserialize(v: A<V>) -> bool {
let json_f = serde_json::to_string(&*v).expect("Must be able to serialize num");
let length: Length = serde_json::from_str(&json_f)
.expect("Must be able to deserialize Quantity");

Test::approx_eq(&*v, &length.get(meter))
}
}
}
}
Expand Down

0 comments on commit fd14b3b

Please sign in to comment.