-
Notifications
You must be signed in to change notification settings - Fork 97
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Serde support #47
Serde support #47
Conversation
37554e0
to
2961a75
Compare
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I've never used Serde before so I still want to go through their documentation, however the initial review looks good. When you get to uom
's documentation lib.rs
and README.md
will need the same text explaining the serde
feature. I don't have a good way to update both without copy-paste-fix-formatting currently.
Cargo.toml
Outdated
@@ -23,6 +23,7 @@ maintenance = { status = "actively-developed" } | |||
[dependencies] | |||
num = "0.1" | |||
typenum = "1.9.0" | |||
serde = { version = "1.0", optional = true, features = ["derive"] } |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Move above typenum
so dependencies are in alphabetical order.
src/lib.rs
Outdated
@@ -155,6 +155,9 @@ compile_error!("A least one underlying storage type must be enabled. See the fea | |||
|
|||
#[doc(hidden)] | |||
pub extern crate num; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Add a blank line just below num
.
src/system.rs
Outdated
U: Units<V> + ?Sized, | ||
V: $crate::num::Num + $crate::Conversion<V> + $crate::serde::ser::Serialize, | ||
{ | ||
fn serialize<S: $crate::serde::ser::Serializer>(&self, serializer: S) -> Result<S::Ok, S::Error> { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Put S
's type bounds in a where
clause instead of inline.
src/system.rs
Outdated
where | ||
De: $crate::serde::de::Deserializer<'de>, | ||
{ | ||
let value: V = $crate::serde::de::Deserialize::deserialize(deserializer)?; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Blank line beneath this one.
src/lib.rs
Outdated
@@ -155,6 +155,9 @@ compile_error!("A least one underlying storage type must be enabled. See the fea | |||
|
|||
#[doc(hidden)] | |||
pub extern crate num; | |||
#[doc(hidden)] |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think this should be #[cfg_attr(feature = "serde", doc(hidden)]
so that the attribute only appears when serde
is enabled. Didn't test with the compiler however.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I tested running cargo doc
with and without the serde
feature enabled and it seemed to work fine in both cases (not showing docs for serde in either case). However, of course, if you'd like me to specify a cfg_attr anyway I can do that.
I've addressed your comments, but I still need to write some tests. I should be able to get to that tomorrow! :) |
Okay, this is probably ready for another review pass. I've implemented simple tests. Note that I've also set up travis to run the serde tests in addition to the default-feature tests. |
Oh, I'll also update CHANGELOG.md. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Include cargo test --verbose --features serde
in .appveyor.yml
. Comments for README.md
also apply to lib.rs
.
CHANGELOG.md
Outdated
@@ -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`. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Mention that this functionality is disabled by default and can be enabled with the serde
feature.
@@ -156,6 +159,13 @@ compile_error!("A least one underlying storage type must be enabled. See the fea | |||
#[doc(hidden)] | |||
pub extern crate num; | |||
|
|||
#[doc(hidden)] |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Looks like cfg_attr
isn't necessary. The compiler is smart enough that #[doc(hidden)]
doesn't "fall through" to the next item when the serde
feature is not enabled.
src/lib.rs
Outdated
#[cfg(feature = "serde")] | ||
pub extern crate serde; | ||
|
||
#[cfg(all(feature = "serde", test))] |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Change order so that test
appears first. #[cfg(all(test, feature = "serde"))]
. I also have the dev-dependencies in a separate section beneath the regular dependencies. Not sure if this should be maintained or if all dependencies should just be included in order. Thoughts?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I'm happy to maintain the current style, I'll move it below.
src/tests.rs
Outdated
@@ -7,6 +7,8 @@ use num::{Float, FromPrimitive, One, Saturating, Signed, Zero}; | |||
use quickcheck::TestResult; | |||
use lib::fmt::Debug; | |||
use lib::marker::PhantomData; | |||
#[cfg(all(feature = "serde", test))] |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
test
isn't necessary since this module is only compiled when test
is set.
src/tests.rs
Outdated
#[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 deserialize num"); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I believe the expect(...)
should say serialize and not deserialize.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Right you are!
src/tests.rs
Outdated
#[allow(trivial_casts)] | ||
fn serde_serialize(v: A<V>) -> bool { | ||
let m = Length::new::<meter>((*v).clone()); | ||
let json_q = serde_json::to_string(&m).expect("Must be able to serialize Quantity"); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Put let json_q = ...
after let json_f = ...
to match comparison order below.
src/tests.rs
Outdated
let length: Length = serde_json::from_str(&json_f) | ||
.expect("Must be able to deserialize Quantity"); | ||
|
||
Test::approx_eq(&length.get(meter), &*v) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Make &*v
the first parameter.
README.md
Outdated
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: |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Wrap at 100 characters.
README.md
Outdated
@@ -88,12 +88,15 @@ uom = { | |||
`rational`, `rational32`, `rational64`, `bigrational`, `f32`, `f64` -- Features to enable | |||
underlying storage types. At least one of these features must be enabled. `f32` and `f64` are | |||
enabled by default. | |||
* `serde` -- Feature to enable support for serialization and deserialization of quantities with | |||
the [serde][serde] crate. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Note that the feature is disabled by default. Also include the serde
feature in the toml
block above: "serde", # Serde support.
faca99e
to
a727657
Compare
I believe I've addressed your comments, thanks for the review! |
FWIW, the appveyor failures are only in the old |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
With these changes I think we'll be ready to merge!
.appveyor.yml
Outdated
@@ -56,6 +56,7 @@ build: false | |||
test_script: | |||
- cargo build --verbose | |||
- cargo test --verbose |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
You can remove this line. The next line runs the same tests + serde tests.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
That's fair. I should say that I did it this way intentionally, to make sure that the crate still builds and tests correctly without the serde feature enabled (making sure I set up my cfg
attributes correctly etc). But with enough of these kinds of features it would lead to ridiculous test times, having to run through the test suite several times... so yeah, I can remove it :)
CHANGELOG.md
Outdated
@@ -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 `serde` cargo feature. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Just say "serde
feature".
README.md
Outdated
@@ -79,6 +79,7 @@ uom = { | |||
"bigint", "biguint", # Arbitrary width integer storage types. | |||
"rational", "rational32", "rational64", "bigrational", # Integer ratio storage types. | |||
"f32", "f64", # Floating point storage types. | |||
"serde", # Serde support. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Looks like this line didn't get indented.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
oops, that was a sneaky tab character.
src/tests.rs
Outdated
@@ -7,6 +7,8 @@ use num::{Float, FromPrimitive, One, Saturating, Signed, Zero}; | |||
use quickcheck::TestResult; | |||
use lib::fmt::Debug; | |||
use lib::marker::PhantomData; | |||
#[cfg(all(feature = "serde"))] |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
all(...)
isn't needed anymore.
I spoke a bit too soon about being ready to merge. I finally read through the Serde documentation and have a few more questions:
|
@iliekturtles no problem!
|
Okay, about point 1: https://github.com/ron-rs/ron serializes "serializes_newtype_struct" differently, so the name you pass is actually encoded into the output. I could also perhaps pass the name of the base unit as the newtype name, to make that output a bit more descriptive. I'll also have to deserialize with deserialize_newtype_struct. I'll make that change and let you know! |
Thanks for the information. Leave points 1 and 2 as-is for the moment. I'm going to do a bit more digging. |
@iliekturtles Just FYI I was looking into using serialize_newtype_struct -- that's easy enough, but the deserialization side is more complicated. It needs a visitor to be passed, and I was trying to figure out how to generate one of those without too much work. But okay, I'll leave that alone and get back to disabling serde's |
Okay, I think I fixed the third point, but I was real confused for a while. Basically, there is a cargo bug when building uom directly with serde enabled: rust-lang/cargo#4664 Basically, because we have a dev-dependency on serde_json, which depends on serde (with default features), cargo commands run directly against uom still build serde with default features. However, when uom is used as a dependency, uom's dev-dependencies is ignored and so serde won't require std. I verified this manually by creating an example project that depends on my fork of uom, with serde enabled. I built it with --verbose and saw that it does not include serde's std feature. |
btw, @iliekturtles , if you want to chat about any of these things in real-time, I am on the various rust-related channels on the mozilla IRC channels as |
One more issue I found when running Once this is resolved I'll merge for real. I still want to look at points 1 and 2 above, but will complete that before releasing v0.17.0. I used to be on IRC via a very old laptop that was lost to a storm this fall. I'll see about getting connected again. |
Ooookay. Unfortunately I think this is going to cause a bit of a pain, because of this bug: rust-lang/cargo#1286 I think what we want is to define a feature that both enables a dependency (serde) and enables features in other dependencies (num-bigint/serde, et al). But because of that linked bug, we cannot name this feature "serde", because all optional dependencies have names equal to the package name -- and sadly cargo doesn't just merge the features in the So this means we need to bikeshed a name: what should it be? |
Ah! Even more confounding problems! 😠 Apparently the So I suppose we should just disable the tests for those backend types for now. However, I suppose we should still standardize/document a feature like So I'll
|
|
Okay, sorry for the delay @iliekturtles ! I think I've addressed the outstanding comments. Oh, one minor difference which I'm not even sure was intentional on your part: I changed the build command to |
Merged, thanks! I ended up fixing a formatting issue in |
Hmm, well that's definitely strange. As you can see, other builds do show output, even from the same travis run as you linked. I wonder if there is just some caching going on that's causing cargo to realize it has nothing to do. |
I get the same thing locally which is where I found the issue originally:
|
Implement Serialize and Deserialize for Quantity, with tests.
Fixes #37.