diff --git a/.travis.yml b/.travis.yml index 606655d6..78d97d46 100644 --- a/.travis.yml +++ b/.travis.yml @@ -27,7 +27,7 @@ matrix: before_script: - rustup target add $TARGET script: - - cargo build --verbose --target $TARGET --no-default-features --features i128 + - cargo build --verbose --target $TARGET --no-default-features --features "i128 serde" - name: "rustfmt" rust: 1.31.0 before_script: diff --git a/Cargo.toml b/Cargo.toml index 08466752..bf0b3b59 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -52,7 +52,6 @@ features = ["std"] optional = true version = "1.0" default-features = false -features = ["std"] [dependencies.quickcheck] optional = true @@ -64,9 +63,6 @@ optional = true version = "0.8" default-features = false -[dev-dependencies.serde_test] -version = "1.0" - [features] default = ["std"] i128 = ["num-integer/i128", "num-traits/i128"] diff --git a/ci/big_serde/Cargo.toml b/ci/big_serde/Cargo.toml new file mode 100644 index 00000000..2ed7f954 --- /dev/null +++ b/ci/big_serde/Cargo.toml @@ -0,0 +1,12 @@ +[package] +name = "big_serde" +version = "0.1.0" +authors = ["Josh Stone "] + +[dependencies] +num-traits = "0.2.11" +serde_test = "1.0" + +[dependencies.num-bigint] +features = ["serde"] +path = "../.." diff --git a/tests/serde.rs b/ci/big_serde/src/lib.rs similarity index 94% rename from tests/serde.rs rename to ci/big_serde/src/lib.rs index a0251b9c..4bbb8b52 100644 --- a/tests/serde.rs +++ b/ci/big_serde/src/lib.rs @@ -3,8 +3,12 @@ //! The serialized formats should not change, even if we change our //! internal representation, because we want to preserve forward and //! backward compatibility of serialized data! +//! +//! This test is in a completely separate crate so its `serde_test` +//! dependency does not "infect" the rest of the build with `serde`'s +//! default features, especially not `serde/std`. -#![cfg(feature = "serde")] +#![cfg(test)] extern crate num_bigint; extern crate num_traits; diff --git a/ci/test_full.sh b/ci/test_full.sh index 88bc4e42..c257bd89 100755 --- a/ci/test_full.sh +++ b/ci/test_full.sh @@ -13,7 +13,7 @@ esac case "$TRAVIS_RUST_VERSION" in 1.1[5-9].* | 1.2[0-9].* | 1.3[0-5].*) ;; - *) NO_STD_FEATURES="i128" ;; + *) NO_STD_FEATURES="i128 serde" ;; esac # num-bigint should build and test everywhere. @@ -54,3 +54,7 @@ fi if [[ "$TRAVIS_RUST_VERSION" == "nightly" ]]; then cargo bench --all-features --no-run fi + +case "$STD_FEATURES" in + *serde*) cargo test --manifest-path ci/big_serde/Cargo.toml +esac diff --git a/src/biguint.rs b/src/biguint.rs index e6e2ae67..f6853fd0 100644 --- a/src/biguint.rs +++ b/src/biguint.rs @@ -2678,8 +2678,8 @@ fn u32_from_u128(n: u128) -> (u32, u32, u32, u32) { } #[cfg(feature = "serde")] -#[cfg(not(u64_digit))] impl serde::Serialize for BigUint { + #[cfg(not(u64_digit))] fn serialize(&self, serializer: S) -> Result where S: serde::Serializer, @@ -2687,14 +2687,11 @@ impl serde::Serialize for BigUint { // Note: do not change the serialization format, or it may break forward // and backward compatibility of serialized data! If we ever change the // internal representation, we should still serialize in base-`u32`. - let data: &Vec = &self.data; + let data: &[u32] = &self.data; data.serialize(serializer) } -} -#[cfg(feature = "serde")] -#[cfg(u64_digit)] -impl serde::Serialize for BigUint { + #[cfg(u64_digit)] fn serialize(&self, serializer: S) -> Result where S: serde::Serializer, @@ -2722,19 +2719,6 @@ impl serde::Serialize for BigUint { } #[cfg(feature = "serde")] -#[cfg(not(u64_digit))] -impl<'de> serde::Deserialize<'de> for BigUint { - fn deserialize(deserializer: D) -> Result - where - D: serde::Deserializer<'de>, - { - let data: Vec = Vec::deserialize(deserializer)?; - Ok(biguint_from_vec(data)) - } -} - -#[cfg(feature = "serde")] -#[cfg(u64_digit)] impl<'de> serde::Deserialize<'de> for BigUint { fn deserialize(deserializer: D) -> Result where @@ -2751,6 +2735,22 @@ impl<'de> serde::Deserialize<'de> for BigUint { formatter.write_str("a sequence of unsigned 32-bit numbers") } + #[cfg(not(u64_digit))] + fn visit_seq(self, mut seq: S) -> Result + where + S: SeqAccess<'de>, + { + let len = seq.size_hint().unwrap_or(0); + let mut data = Vec::with_capacity(len); + + while let Some(value) = seq.next_element::()? { + data.push(value); + } + + Ok(biguint_from_vec(data)) + } + + #[cfg(u64_digit)] fn visit_seq(self, mut seq: S) -> Result where S: SeqAccess<'de>, @@ -2763,8 +2763,11 @@ impl<'de> serde::Deserialize<'de> for BigUint { let mut value = BigDigit::from(lo); if let Some(hi) = seq.next_element::()? { value |= BigDigit::from(hi) << 32; + data.push(value); + } else { + data.push(value); + break; } - data.push(value); } Ok(biguint_from_vec(data))