Compare commits

...

45 Commits

Author SHA1 Message Date
David Tolnay d4042872f5 Release 1.0.12 2017-09-04 11:11:44 -07:00
David Tolnay 64af86b830 Suppress cast_lossless lint 2017-09-04 11:10:43 -07:00
David Tolnay 370c8a91cb Merge pull request #1039 from serde-rs/rcde
Deserialize unsized Arc and Rc
2017-09-04 11:07:19 -07:00
David Tolnay 972da59ebc Deserialize unsized Arc and Rc 2017-09-04 10:56:42 -07:00
David Tolnay a42008f695 Merge pull request #1038 from serde-rs/rcser
Serialize unsized Arc and Rc
2017-09-04 10:54:20 -07:00
David Tolnay e4ea2a56e9 Serialize unsized Arc and Rc 2017-09-04 10:31:03 -07:00
David Tolnay 7650a48fdd Opt in to clippy_pedantic lints 2017-08-24 00:41:42 -07:00
David Tolnay d665a2f2b2 Merge pull request #1023 from hcpl/fix-doc-typo
Fix `SeqAcccess` typo in docs
2017-08-20 15:03:10 -07:00
hcpl 44e23254c9 Fix SeqAcccess typo in docs 2017-08-20 22:02:28 +03:00
David Tolnay 0681cd5003 Replace deprecated compiletest::default_config() 2017-08-15 22:10:18 -07:00
David Tolnay d965367238 No longer need feature(into_boxed_c_str) 2017-08-15 22:08:23 -07:00
David Tolnay a6df35b3d2 Disable no_std test on appveyor 2017-08-15 21:58:52 -07:00
David Tolnay 4831482695 Doc comment on statement is not used by rustdoc
Fixes #1014.
2017-08-05 23:35:14 -07:00
David Tolnay d3e5dd9cd7 Disagree that 0x10000 is unreadable 2017-08-05 23:26:15 -07:00
David Tolnay 26098ed877 Release 1.0.11 2017-07-27 00:56:28 -07:00
David Tolnay 42ed62cf24 Merge pull request #1003 from serde-rs/newnonzero
NonZero constructor now returns Option
2017-07-27 00:54:23 -07:00
David Tolnay 9f0973aff7 NonZero constructor now returns Option 2017-07-27 00:35:56 -07:00
David Tolnay ccec002bf3 Merge pull request #1001 from serde-rs/remotevis
Inherit the visibility of remote struct definition
2017-07-27 00:29:57 -07:00
David Tolnay f36a1e0895 Inherit the visibility of remote struct definition 2017-07-25 23:52:06 -07:00
David Tolnay e6487cf6fa Merge pull request #995 from serde-rs/nobin
Workaround for "no bin target named serde_derive_tests_no_std"
2017-07-21 00:17:25 -07:00
David Tolnay 4f2e8d5dbb Workaround for "no bin target named serde_derive_tests_no_std" 2017-07-21 00:05:30 -07:00
David Tolnay 1c2a4bff1c Merge pull request #991 from Marwes/test_systemtime
Fix SystemTime serialization test on Windows
2017-07-16 06:10:43 -07:00
Markus Westerlind 85bccf42b6 Fix SystemTime serialization test on Windows
Windows's `SystemTime` do not have nanosecond resolution which caused the test duration to be truncated https://github.com/rust-lang/rust/blob/b1363a73ede57ae595f3a1be2bb75d308ba4f7f6/src/libstd/sys/windows/time.rs#L177
2017-07-16 12:16:07 +02:00
David Tolnay 959fee024f Merge pull request #986 from Marwes/simplify_seed
refactor: Implement Deserialize of wrapper types with a macro
2017-07-12 20:36:48 -07:00
Markus Westerlind 8ede8c8e2a refactor: Implement Deserialize of wrapper types with a macro 2017-07-13 00:02:29 +02:00
David Tolnay 83537c95e1 Release 1.0.10 2017-07-11 21:19:24 -07:00
David Tolnay fa9057fa31 Merge pull request #949 from WiSaGaN/feature/support-system-time
Support std::time::SystemTime
2017-07-11 21:17:56 -07:00
Wangshan Lu 0084d82a50 Add tests for SystemTime 2017-07-12 12:01:40 +08:00
Wangshan Lu b504b08782 Fix SystemTime serde name 2017-07-12 12:01:29 +08:00
David Tolnay 775e8154e7 Fix libc dependency in no_std test 2017-07-09 10:19:19 -07:00
David Tolnay 9c679d9082 Test for serializing BTreeSet 2017-07-09 10:16:49 -07:00
David Tolnay b0f9d2a0ba Exclude macros file from being tested by itself 2017-07-09 09:24:29 -07:00
David Tolnay f39b1db96a Additional errors for some reason 2017-07-09 09:22:20 -07:00
David Tolnay 9ecb0839de Release 1.0.9 2017-06-29 20:21:29 -07:00
David Tolnay 8a4c116812 Merge pull request #971 from serde-rs/remotede
Fix deserializer bounds on remote derive
2017-06-29 20:19:36 -07:00
David Tolnay 1d3e921ba6 Fix deserializer bounds on remote derive 2017-06-29 20:12:44 -07:00
David Tolnay 4fdba725fe Revert "Support deserialization of struct keys from integers"
This is not as useful as expected because the Serializer does not know the real
index of each struct field being serialized. The best it can do is keep a
counter, which goes wrong if fields are conditionally skipped.

This reverts commit eec7101894.
2017-06-18 09:11:21 -07:00
David Tolnay 75eed8cdde Merge pull request #958 from serde-rs/unused
Fix unused seq and map macros
2017-06-17 19:14:39 -07:00
David Tolnay 6801a13650 Fix unused seq and map macros 2017-06-17 19:01:12 -07:00
David Tolnay 25ab84d4b9 Merge pull request #957 from serde-rs/alloc
Merge crate `collections` into `alloc`
2017-06-17 18:59:43 -07:00
David Tolnay e43d3f3e4f Merge crate collections into alloc 2017-06-17 18:35:56 -07:00
David Tolnay b37d47c987 Merge pull request #956 from sfackler/int-field
Support deserialization of struct keys from integers
2017-06-17 18:26:45 -07:00
Steven Fackler eec7101894 Support deserialization of struct keys from integers
serde-cbor supports a "packed" serialization flag which causes keys to
be serialized as their indices, but the deserializer currently has to
hardcode support for this format. We can simply support deserialization
of struct keys from integers as we already do for enum variants.
2017-06-17 18:12:07 -07:00
Wangshan Lu 5dd327fb02 Support std::time::SystemTime 2017-06-04 16:39:03 +08:00
David Tolnay fd3d1396d3 Release 1.0.8 2017-05-24 00:17:27 -07:00
29 changed files with 511 additions and 239 deletions
-1
View File
@@ -5,5 +5,4 @@ members = [
"serde_derive_internals", "serde_derive_internals",
"serde_test", "serde_test",
"test_suite", "test_suite",
"test_suite/no_std",
] ]
+4 -11
View File
@@ -1,6 +1,6 @@
[package] [package]
name = "serde" name = "serde"
version = "1.0.7" # remember to update html_root_url version = "1.0.12" # remember to update html_root_url
authors = ["Erick Tryzelaar <erick.tryzelaar@gmail.com>", "David Tolnay <dtolnay@gmail.com>"] authors = ["Erick Tryzelaar <erick.tryzelaar@gmail.com>", "David Tolnay <dtolnay@gmail.com>"]
license = "MIT/Apache-2.0" license = "MIT/Apache-2.0"
description = "A generic serialization/deserialization framework" description = "A generic serialization/deserialization framework"
@@ -48,22 +48,15 @@ std = []
# https://github.com/serde-rs/serde/issues/812 # https://github.com/serde-rs/serde/issues/812
unstable = [] unstable = []
# Provide impls for types that require memory allocation like Box<T> and Rc<T>. # Provide impls for types in the Rust core allocation and collections library
# This is a subset of std but may be enabled without depending on all of std. # including String, Box<T>, Vec<T>, and Cow<T>. This is a subset of std but may
# be enabled without depending on all of std.
# #
# Requires a dependency on the unstable core allocation library: # Requires a dependency on the unstable core allocation library:
# #
# https://doc.rust-lang.org/alloc/ # https://doc.rust-lang.org/alloc/
alloc = ["unstable"] alloc = ["unstable"]
# Provide impls for collection types like String and Cow<T>. This is a subset of
# std but may be enabled without depending on all of std.
#
# Requires a dependency on the unstable collections library:
#
# https://doc.rust-lang.org/collections/
collections = ["alloc"]
# Opt into impls for Rc<T> and Arc<T>. Serializing and deserializing these types # Opt into impls for Rc<T> and Arc<T>. Serializing and deserializing these types
# does not preserve identity and may result in multiple copies of the same data. # does not preserve identity and may result in multiple copies of the same data.
# Be sure that this is what you want before enabling this feature. # Be sure that this is what you want before enabling this feature.
+193 -118
View File
@@ -11,12 +11,12 @@ use lib::*;
use de::{Deserialize, Deserializer, EnumAccess, Error, SeqAccess, Unexpected, VariantAccess, use de::{Deserialize, Deserializer, EnumAccess, Error, SeqAccess, Unexpected, VariantAccess,
Visitor}; Visitor};
#[cfg(any(feature = "std", feature = "collections"))] #[cfg(any(feature = "std", feature = "alloc"))]
use de::MapAccess; use de::MapAccess;
use de::from_primitive::FromPrimitive; use de::from_primitive::FromPrimitive;
#[cfg(any(feature = "std", feature = "collections"))] #[cfg(any(feature = "std", feature = "alloc"))]
use private::de::size_hint; use private::de::size_hint;
//////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////////
@@ -208,10 +208,10 @@ impl<'de> Deserialize<'de> for char {
//////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////////
#[cfg(any(feature = "std", feature = "collections"))] #[cfg(any(feature = "std", feature = "alloc"))]
struct StringVisitor; struct StringVisitor;
#[cfg(any(feature = "std", feature = "collections"))] #[cfg(any(feature = "std", feature = "alloc"))]
impl<'de> Visitor<'de> for StringVisitor { impl<'de> Visitor<'de> for StringVisitor {
type Value = String; type Value = String;
@@ -254,7 +254,7 @@ impl<'de> Visitor<'de> for StringVisitor {
} }
} }
#[cfg(any(feature = "std", feature = "collections"))] #[cfg(any(feature = "std", feature = "alloc"))]
impl<'de> Deserialize<'de> for String { impl<'de> Deserialize<'de> for String {
fn deserialize<D>(deserializer: D) -> Result<String, D::Error> fn deserialize<D>(deserializer: D) -> Result<String, D::Error>
where where
@@ -400,16 +400,22 @@ impl<'de> Deserialize<'de> for CString {
} }
} }
#[cfg(all(feature = "std", feature = "unstable"))] macro_rules! forwarded_impl {
impl<'de> Deserialize<'de> for Box<CStr> { (( $($id: ident),* ), $ty: ty, $func: expr) => {
fn deserialize<D>(deserializer: D) -> Result<Self, D::Error> impl<'de $(, $id : Deserialize<'de>,)*> Deserialize<'de> for $ty {
where fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
D: Deserializer<'de>, where
{ D: Deserializer<'de>,
CString::deserialize(deserializer).map(CString::into_boxed_c_str) {
Deserialize::deserialize(deserializer).map($func)
}
}
} }
} }
#[cfg(all(feature = "std", feature = "unstable"))]
forwarded_impl!((), Box<CStr>, CString::into_boxed_c_str);
//////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////////
struct OptionVisitor<T> { struct OptionVisitor<T> {
@@ -497,7 +503,7 @@ impl<'de, T> Deserialize<'de> for PhantomData<T> {
//////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////////
#[cfg(any(feature = "std", feature = "collections"))] #[cfg(any(feature = "std", feature = "alloc"))]
macro_rules! seq_impl { macro_rules! seq_impl {
( (
$ty:ident < T $(: $tbound1:ident $(+ $tbound2:ident)*)* $(, $typaram:ident : $bound1:ident $(+ $bound2:ident)*)* >, $ty:ident < T $(: $tbound1:ident $(+ $tbound2:ident)*)* $(, $typaram:ident : $bound1:ident $(+ $bound2:ident)*)* >,
@@ -552,7 +558,7 @@ macro_rules! seq_impl {
} }
} }
#[cfg(any(feature = "std", feature = "collections"))] #[cfg(any(feature = "std", feature = "alloc"))]
seq_impl!( seq_impl!(
BinaryHeap<T: Ord>, BinaryHeap<T: Ord>,
seq, seq,
@@ -560,7 +566,7 @@ seq_impl!(
BinaryHeap::with_capacity(size_hint::cautious(seq.size_hint())), BinaryHeap::with_capacity(size_hint::cautious(seq.size_hint())),
BinaryHeap::push); BinaryHeap::push);
#[cfg(any(feature = "std", feature = "collections"))] #[cfg(any(feature = "std", feature = "alloc"))]
seq_impl!( seq_impl!(
BTreeSet<T: Eq + Ord>, BTreeSet<T: Eq + Ord>,
seq, seq,
@@ -568,7 +574,7 @@ seq_impl!(
BTreeSet::new(), BTreeSet::new(),
BTreeSet::insert); BTreeSet::insert);
#[cfg(any(feature = "std", feature = "collections"))] #[cfg(any(feature = "std", feature = "alloc"))]
seq_impl!( seq_impl!(
LinkedList<T>, LinkedList<T>,
seq, seq,
@@ -584,7 +590,7 @@ seq_impl!(
HashSet::with_capacity_and_hasher(size_hint::cautious(seq.size_hint()), S::default()), HashSet::with_capacity_and_hasher(size_hint::cautious(seq.size_hint()), S::default()),
HashSet::insert); HashSet::insert);
#[cfg(any(feature = "std", feature = "collections"))] #[cfg(any(feature = "std", feature = "alloc"))]
seq_impl!( seq_impl!(
Vec<T>, Vec<T>,
seq, seq,
@@ -592,7 +598,7 @@ seq_impl!(
Vec::with_capacity(size_hint::cautious(seq.size_hint())), Vec::with_capacity(size_hint::cautious(seq.size_hint())),
Vec::push); Vec::push);
#[cfg(any(feature = "std", feature = "collections"))] #[cfg(any(feature = "std", feature = "alloc"))]
seq_impl!( seq_impl!(
VecDeque<T>, VecDeque<T>,
seq, seq,
@@ -790,7 +796,7 @@ tuple_impls! {
//////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////////
#[cfg(any(feature = "std", feature = "collections"))] #[cfg(any(feature = "std", feature = "alloc"))]
macro_rules! map_impl { macro_rules! map_impl {
( (
$ty:ident < K $(: $kbound1:ident $(+ $kbound2:ident)*)*, V $(, $typaram:ident : $bound1:ident $(+ $bound2:ident)*)* >, $ty:ident < K $(: $kbound1:ident $(+ $kbound2:ident)*)*, V $(, $typaram:ident : $bound1:ident $(+ $bound2:ident)*)* >,
@@ -846,7 +852,7 @@ macro_rules! map_impl {
} }
} }
#[cfg(any(feature = "std", feature = "collections"))] #[cfg(any(feature = "std", feature = "alloc"))]
map_impl!( map_impl!(
BTreeMap<K: Ord, V>, BTreeMap<K: Ord, V>,
map, map,
@@ -1098,68 +1104,21 @@ impl<'de> Deserialize<'de> for OsString {
//////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////////
#[cfg(any(feature = "std", feature = "alloc"))] #[cfg(any(feature = "std", feature = "alloc"))]
impl<'de, T> Deserialize<'de> for Box<T> forwarded_impl!((T), Box<T>, Box::new);
where
T: Deserialize<'de>,
{
fn deserialize<D>(deserializer: D) -> Result<Box<T>, D::Error>
where
D: Deserializer<'de>,
{
T::deserialize(deserializer).map(Box::new)
}
}
#[cfg(any(feature = "std", feature = "collections"))] #[cfg(any(feature = "std", feature = "alloc"))]
impl<'de, T> Deserialize<'de> for Box<[T]> forwarded_impl!((T), Box<[T]>, Vec::into_boxed_slice);
where
T: Deserialize<'de>,
{
fn deserialize<D>(deserializer: D) -> Result<Box<[T]>, D::Error>
where
D: Deserializer<'de>,
{
Vec::<T>::deserialize(deserializer).map(Vec::into_boxed_slice)
}
}
#[cfg(any(feature = "std", feature = "collections"))] #[cfg(any(feature = "std", feature = "alloc"))]
impl<'de> Deserialize<'de> for Box<str> { forwarded_impl!((), Box<str>, String::into_boxed_str);
fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
where
D: Deserializer<'de>,
{
String::deserialize(deserializer).map(String::into_boxed_str)
}
}
#[cfg(all(feature = "rc", any(feature = "std", feature = "alloc")))] #[cfg(all(not(feature = "unstable"), feature = "rc", any(feature = "std", feature = "alloc")))]
impl<'de, T> Deserialize<'de> for Arc<T> forwarded_impl!((T), Arc<T>, Arc::new);
where
T: Deserialize<'de>,
{
fn deserialize<D>(deserializer: D) -> Result<Arc<T>, D::Error>
where
D: Deserializer<'de>,
{
T::deserialize(deserializer).map(Arc::new)
}
}
#[cfg(all(feature = "rc", any(feature = "std", feature = "alloc")))] #[cfg(all(not(feature = "unstable"), feature = "rc", any(feature = "std", feature = "alloc")))]
impl<'de, T> Deserialize<'de> for Rc<T> forwarded_impl!((T), Rc<T>, Rc::new);
where
T: Deserialize<'de>,
{
fn deserialize<D>(deserializer: D) -> Result<Rc<T>, D::Error>
where
D: Deserializer<'de>,
{
T::deserialize(deserializer).map(Rc::new)
}
}
#[cfg(any(feature = "std", feature = "collections"))] #[cfg(any(feature = "std", feature = "alloc"))]
impl<'de, 'a, T: ?Sized> Deserialize<'de> for Cow<'a, T> impl<'de, 'a, T: ?Sized> Deserialize<'de> for Cow<'a, T>
where where
T: ToOwned, T: ToOwned,
@@ -1176,6 +1135,31 @@ where
//////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////////
#[cfg(all(feature = "unstable", feature = "rc", any(feature = "std", feature = "alloc")))]
macro_rules! box_forwarded_impl {
($t:ident) => {
impl<'de, T: ?Sized> Deserialize<'de> for $t<T>
where
Box<T>: Deserialize<'de>,
{
fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
where
D: Deserializer<'de>,
{
Box::deserialize(deserializer).map(Into::into)
}
}
}
}
#[cfg(all(feature = "unstable", feature = "rc", any(feature = "std", feature = "alloc")))]
box_forwarded_impl!(Rc);
#[cfg(all(feature = "unstable", feature = "rc", any(feature = "std", feature = "alloc")))]
box_forwarded_impl!(Arc);
////////////////////////////////////////////////////////////////////////////////
impl<'de, T> Deserialize<'de> for Cell<T> impl<'de, T> Deserialize<'de> for Cell<T>
where where
T: Deserialize<'de> + Copy, T: Deserialize<'de> + Copy,
@@ -1188,43 +1172,13 @@ where
} }
} }
impl<'de, T> Deserialize<'de> for RefCell<T> forwarded_impl!((T), RefCell<T>, RefCell::new);
where
T: Deserialize<'de>,
{
fn deserialize<D>(deserializer: D) -> Result<RefCell<T>, D::Error>
where
D: Deserializer<'de>,
{
T::deserialize(deserializer).map(RefCell::new)
}
}
#[cfg(feature = "std")] #[cfg(feature = "std")]
impl<'de, T> Deserialize<'de> for Mutex<T> forwarded_impl!((T), Mutex<T>, Mutex::new);
where
T: Deserialize<'de>,
{
fn deserialize<D>(deserializer: D) -> Result<Mutex<T>, D::Error>
where
D: Deserializer<'de>,
{
T::deserialize(deserializer).map(Mutex::new)
}
}
#[cfg(feature = "std")] #[cfg(feature = "std")]
impl<'de, T> Deserialize<'de> for RwLock<T> forwarded_impl!((T), RwLock<T>, RwLock::new);
where
T: Deserialize<'de>,
{
fn deserialize<D>(deserializer: D) -> Result<RwLock<T>, D::Error>
where
D: Deserializer<'de>,
{
T::deserialize(deserializer).map(RwLock::new)
}
}
//////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////////
@@ -1364,6 +1318,132 @@ impl<'de> Deserialize<'de> for Duration {
//////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////////
#[cfg(feature = "std")]
impl<'de> Deserialize<'de> for SystemTime {
fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
where
D: Deserializer<'de>,
{
// Reuse duration
enum Field {
Secs,
Nanos,
};
impl<'de> Deserialize<'de> for Field {
fn deserialize<D>(deserializer: D) -> Result<Field, D::Error>
where
D: Deserializer<'de>,
{
struct FieldVisitor;
impl<'de> Visitor<'de> for FieldVisitor {
type Value = Field;
fn expecting(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
formatter.write_str("`secs_since_epoch` or `nanos_since_epoch`")
}
fn visit_str<E>(self, value: &str) -> Result<Field, E>
where
E: Error,
{
match value {
"secs_since_epoch" => Ok(Field::Secs),
"nanos_since_epoch" => Ok(Field::Nanos),
_ => Err(Error::unknown_field(value, FIELDS)),
}
}
fn visit_bytes<E>(self, value: &[u8]) -> Result<Field, E>
where
E: Error,
{
match value {
b"secs_since_epoch" => Ok(Field::Secs),
b"nanos_since_epoch" => Ok(Field::Nanos),
_ => {
let value = String::from_utf8_lossy(value);
Err(Error::unknown_field(&value, FIELDS))
}
}
}
}
deserializer.deserialize_identifier(FieldVisitor)
}
}
struct DurationVisitor;
impl<'de> Visitor<'de> for DurationVisitor {
type Value = Duration;
fn expecting(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
formatter.write_str("struct SystemTime")
}
fn visit_seq<A>(self, mut seq: A) -> Result<Duration, A::Error>
where
A: SeqAccess<'de>,
{
let secs: u64 = match try!(seq.next_element()) {
Some(value) => value,
None => {
return Err(Error::invalid_length(0, &self));
}
};
let nanos: u32 = match try!(seq.next_element()) {
Some(value) => value,
None => {
return Err(Error::invalid_length(1, &self));
}
};
Ok(Duration::new(secs, nanos))
}
fn visit_map<A>(self, mut map: A) -> Result<Duration, A::Error>
where
A: MapAccess<'de>,
{
let mut secs: Option<u64> = None;
let mut nanos: Option<u32> = None;
while let Some(key) = try!(map.next_key()) {
match key {
Field::Secs => {
if secs.is_some() {
return Err(<A::Error as Error>::duplicate_field("secs_since_epoch"));
}
secs = Some(try!(map.next_value()));
}
Field::Nanos => {
if nanos.is_some() {
return Err(<A::Error as Error>::duplicate_field("nanos_since_epoch"));
}
nanos = Some(try!(map.next_value()));
}
}
}
let secs = match secs {
Some(secs) => secs,
None => return Err(<A::Error as Error>::missing_field("secs_since_epoch")),
};
let nanos = match nanos {
Some(nanos) => nanos,
None => return Err(<A::Error as Error>::missing_field("nanos_since_epoch")),
};
Ok(Duration::new(secs, nanos))
}
}
const FIELDS: &'static [&'static str] = &["secs_since_epoch", "nanos_since_epoch"];
let duration = try!(deserializer.deserialize_struct("SystemTime", FIELDS, DurationVisitor));
Ok(UNIX_EPOCH + duration)
}
}
////////////////////////////////////////////////////////////////////////////////
// Similar to: // Similar to:
// //
// #[derive(Deserialize)] // #[derive(Deserialize)]
@@ -1518,14 +1598,9 @@ where
D: Deserializer<'de>, D: Deserializer<'de>,
{ {
let value = try!(Deserialize::deserialize(deserializer)); let value = try!(Deserialize::deserialize(deserializer));
unsafe { match NonZero::new(value) {
let ptr = &value as *const T as *const u8; Some(nonzero) => Ok(nonzero),
if slice::from_raw_parts(ptr, mem::size_of::<T>()).iter().all(|&b| b == 0) { None => Err(Error::custom("expected a non-zero value")),
return Err(Error::custom("expected a non-zero value"));
}
// Waiting for a safe way to construct NonZero<T>:
// https://github.com/rust-lang/rust/issues/27730#issuecomment-269726075
Ok(NonZero::new(value))
} }
} }
} }
+4 -3
View File
@@ -94,6 +94,7 @@
//! - OsString //! - OsString
//! - **Miscellaneous standard library types**: //! - **Miscellaneous standard library types**:
//! - Duration //! - Duration
//! - SystemTime
//! - Path //! - Path
//! - PathBuf //! - PathBuf
//! - Range\<T\> //! - Range\<T\>
@@ -1262,7 +1263,7 @@ pub trait Visitor<'de>: Sized {
/// The default implementation forwards to `visit_str` and then drops the /// The default implementation forwards to `visit_str` and then drops the
/// `String`. /// `String`.
#[inline] #[inline]
#[cfg(any(feature = "std", feature = "collections"))] #[cfg(any(feature = "std", feature = "alloc"))]
fn visit_string<E>(self, v: String) -> Result<Self::Value, E> fn visit_string<E>(self, v: String) -> Result<Self::Value, E>
where where
E: Error, E: Error,
@@ -1321,7 +1322,7 @@ pub trait Visitor<'de>: Sized {
/// ///
/// The default implementation forwards to `visit_bytes` and then drops the /// The default implementation forwards to `visit_bytes` and then drops the
/// `Vec<u8>`. /// `Vec<u8>`.
#[cfg(any(feature = "std", feature = "collections"))] #[cfg(any(feature = "std", feature = "alloc"))]
fn visit_byte_buf<E>(self, v: Vec<u8>) -> Result<Self::Value, E> fn visit_byte_buf<E>(self, v: Vec<u8>) -> Result<Self::Value, E>
where where
E: Error, E: Error,
@@ -1423,7 +1424,7 @@ pub trait SeqAccess<'de> {
/// `Ok(None)` if there are no more remaining items. /// `Ok(None)` if there are no more remaining items.
/// ///
/// `Deserialize` implementations should typically use /// `Deserialize` implementations should typically use
/// `SeqAcccess::next_element` instead. /// `SeqAccess::next_element` instead.
fn next_element_seed<T>(&mut self, seed: T) -> Result<Option<T::Value>, Self::Error> fn next_element_seed<T>(&mut self, seed: T) -> Result<Option<T::Value>, Self::Error>
where where
T: DeserializeSeed<'de>; T: DeserializeSeed<'de>;
+17 -17
View File
@@ -51,13 +51,13 @@ pub struct Error {
err: ErrorImpl, err: ErrorImpl,
} }
#[cfg(any(feature = "std", feature = "collections"))] #[cfg(any(feature = "std", feature = "alloc"))]
type ErrorImpl = Box<str>; type ErrorImpl = Box<str>;
#[cfg(not(any(feature = "std", feature = "collections")))] #[cfg(not(any(feature = "std", feature = "alloc")))]
type ErrorImpl = (); type ErrorImpl = ();
impl de::Error for Error { impl de::Error for Error {
#[cfg(any(feature = "std", feature = "collections"))] #[cfg(any(feature = "std", feature = "alloc"))]
fn custom<T>(msg: T) -> Self fn custom<T>(msg: T) -> Self
where where
T: Display, T: Display,
@@ -65,7 +65,7 @@ impl de::Error for Error {
Error { err: msg.to_string().into_boxed_str() } Error { err: msg.to_string().into_boxed_str() }
} }
#[cfg(not(any(feature = "std", feature = "collections")))] #[cfg(not(any(feature = "std", feature = "alloc")))]
fn custom<T>(msg: T) -> Self fn custom<T>(msg: T) -> Self
where where
T: Display, T: Display,
@@ -85,12 +85,12 @@ impl ser::Error for Error {
} }
impl Display for Error { impl Display for Error {
#[cfg(any(feature = "std", feature = "collections"))] #[cfg(any(feature = "std", feature = "alloc"))]
fn fmt(&self, formatter: &mut fmt::Formatter) -> Result<(), fmt::Error> { fn fmt(&self, formatter: &mut fmt::Formatter) -> Result<(), fmt::Error> {
formatter.write_str(&self.err) formatter.write_str(&self.err)
} }
#[cfg(not(any(feature = "std", feature = "collections")))] #[cfg(not(any(feature = "std", feature = "alloc")))]
fn fmt(&self, formatter: &mut fmt::Formatter) -> Result<(), fmt::Error> { fn fmt(&self, formatter: &mut fmt::Formatter) -> Result<(), fmt::Error> {
formatter.write_str("Serde deserialization error") formatter.write_str("Serde deserialization error")
} }
@@ -425,14 +425,14 @@ where
//////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////////
/// A deserializer holding a `String`. /// A deserializer holding a `String`.
#[cfg(any(feature = "std", feature = "collections"))] #[cfg(any(feature = "std", feature = "alloc"))]
#[derive(Clone, Debug)] #[derive(Clone, Debug)]
pub struct StringDeserializer<E> { pub struct StringDeserializer<E> {
value: String, value: String,
marker: PhantomData<E>, marker: PhantomData<E>,
} }
#[cfg(any(feature = "std", feature = "collections"))] #[cfg(any(feature = "std", feature = "alloc"))]
impl<'de, E> IntoDeserializer<'de, E> for String impl<'de, E> IntoDeserializer<'de, E> for String
where where
E: de::Error, E: de::Error,
@@ -447,7 +447,7 @@ where
} }
} }
#[cfg(any(feature = "std", feature = "collections"))] #[cfg(any(feature = "std", feature = "alloc"))]
impl<'de, E> de::Deserializer<'de> for StringDeserializer<E> impl<'de, E> de::Deserializer<'de> for StringDeserializer<E>
where where
E: de::Error, E: de::Error,
@@ -482,7 +482,7 @@ where
} }
} }
#[cfg(any(feature = "std", feature = "collections"))] #[cfg(any(feature = "std", feature = "alloc"))]
impl<'de, 'a, E> de::EnumAccess<'de> for StringDeserializer<E> impl<'de, 'a, E> de::EnumAccess<'de> for StringDeserializer<E>
where where
E: de::Error, E: de::Error,
@@ -501,14 +501,14 @@ where
//////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////////
/// A deserializer holding a `Cow<str>`. /// A deserializer holding a `Cow<str>`.
#[cfg(any(feature = "std", feature = "collections"))] #[cfg(any(feature = "std", feature = "alloc"))]
#[derive(Clone, Debug)] #[derive(Clone, Debug)]
pub struct CowStrDeserializer<'a, E> { pub struct CowStrDeserializer<'a, E> {
value: Cow<'a, str>, value: Cow<'a, str>,
marker: PhantomData<E>, marker: PhantomData<E>,
} }
#[cfg(any(feature = "std", feature = "collections"))] #[cfg(any(feature = "std", feature = "alloc"))]
impl<'de, 'a, E> IntoDeserializer<'de, E> for Cow<'a, str> impl<'de, 'a, E> IntoDeserializer<'de, E> for Cow<'a, str>
where where
E: de::Error, E: de::Error,
@@ -523,7 +523,7 @@ where
} }
} }
#[cfg(any(feature = "std", feature = "collections"))] #[cfg(any(feature = "std", feature = "alloc"))]
impl<'de, 'a, E> de::Deserializer<'de> for CowStrDeserializer<'a, E> impl<'de, 'a, E> de::Deserializer<'de> for CowStrDeserializer<'a, E>
where where
E: de::Error, E: de::Error,
@@ -561,7 +561,7 @@ where
} }
} }
#[cfg(any(feature = "std", feature = "collections"))] #[cfg(any(feature = "std", feature = "alloc"))]
impl<'de, 'a, E> de::EnumAccess<'de> for CowStrDeserializer<'a, E> impl<'de, 'a, E> de::EnumAccess<'de> for CowStrDeserializer<'a, E>
where where
E: de::Error, E: de::Error,
@@ -727,7 +727,7 @@ impl Expected for ExpectedInSeq {
//////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////////
#[cfg(any(feature = "std", feature = "collections"))] #[cfg(any(feature = "std", feature = "alloc"))]
impl<'de, T, E> IntoDeserializer<'de, E> for Vec<T> impl<'de, T, E> IntoDeserializer<'de, E> for Vec<T>
where where
T: IntoDeserializer<'de, E>, T: IntoDeserializer<'de, E>,
@@ -740,7 +740,7 @@ where
} }
} }
#[cfg(any(feature = "std", feature = "collections"))] #[cfg(any(feature = "std", feature = "alloc"))]
impl<'de, T, E> IntoDeserializer<'de, E> for BTreeSet<T> impl<'de, T, E> IntoDeserializer<'de, E> for BTreeSet<T>
where where
T: IntoDeserializer<'de, E> + Eq + Ord, T: IntoDeserializer<'de, E> + Eq + Ord,
@@ -1145,7 +1145,7 @@ impl Expected for ExpectedInMap {
//////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////////
#[cfg(any(feature = "std", feature = "collections"))] #[cfg(any(feature = "std", feature = "alloc"))]
impl<'de, K, V, E> IntoDeserializer<'de, E> for BTreeMap<K, V> impl<'de, K, V, E> IntoDeserializer<'de, E> for BTreeMap<K, V>
where where
K: IntoDeserializer<'de, E> + Eq + Ord, K: IntoDeserializer<'de, E> + Eq + Ord,
+2 -2
View File
@@ -19,7 +19,7 @@ pub use self::string::from_utf8_lossy;
mod string { mod string {
use lib::*; use lib::*;
#[cfg(any(feature = "std", feature = "collections"))] #[cfg(any(feature = "std", feature = "alloc"))]
pub fn from_utf8_lossy(bytes: &[u8]) -> Cow<str> { pub fn from_utf8_lossy(bytes: &[u8]) -> Cow<str> {
String::from_utf8_lossy(bytes) String::from_utf8_lossy(bytes)
} }
@@ -31,7 +31,7 @@ mod string {
// //
// so it is okay for the return type to be different from the std case as long // so it is okay for the return type to be different from the std case as long
// as the above works. // as the above works.
#[cfg(not(any(feature = "std", feature = "collections")))] #[cfg(not(any(feature = "std", feature = "alloc")))]
pub fn from_utf8_lossy(bytes: &[u8]) -> &str { pub fn from_utf8_lossy(bytes: &[u8]) -> &str {
// Three unicode replacement characters if it fails. They look like a // Three unicode replacement characters if it fails. They look like a
// white-on-black question mark. The user will recognize it as invalid // white-on-black question mark. The user will recognize it as invalid
+45 -23
View File
@@ -79,7 +79,7 @@
//////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////////
// Serde types in rustdoc of other crates get linked to here. // Serde types in rustdoc of other crates get linked to here.
#![doc(html_root_url = "https://docs.rs/serde/1.0.7")] #![doc(html_root_url = "https://docs.rs/serde/1.0.12")]
// Support using Serde without the standard library! // Support using Serde without the standard library!
#![cfg_attr(not(feature = "std"), no_std)] #![cfg_attr(not(feature = "std"), no_std)]
@@ -89,33 +89,55 @@
// //
// https://github.com/serde-rs/serde/issues/812 // https://github.com/serde-rs/serde/issues/812
#![cfg_attr(feature = "unstable", feature(nonzero, specialization))] #![cfg_attr(feature = "unstable", feature(nonzero, specialization))]
#![cfg_attr(all(feature = "std", feature = "unstable"), feature(into_boxed_c_str))]
#![cfg_attr(feature = "alloc", feature(alloc))] #![cfg_attr(feature = "alloc", feature(alloc))]
#![cfg_attr(feature = "collections", feature(collections))]
// Whitelisted clippy lints. #![cfg_attr(feature = "cargo-clippy", deny(clippy, clippy_pedantic))]
#![cfg_attr(feature = "cargo-clippy", allow(doc_markdown))] // Whitelisted clippy lints
#![cfg_attr(feature = "cargo-clippy", allow(linkedlist))] #![cfg_attr(feature = "cargo-clippy", allow(
#![cfg_attr(feature = "cargo-clippy", allow(type_complexity))] cast_lossless,
#![cfg_attr(feature = "cargo-clippy", allow(zero_prefixed_literal))] doc_markdown,
linkedlist,
type_complexity,
unreadable_literal,
zero_prefixed_literal,
))]
// Whitelisted clippy_pedantic lints
#![cfg_attr(feature = "cargo-clippy", allow(
// integer and float ser/de requires these sorts of casts
cast_possible_truncation,
cast_possible_wrap,
cast_precision_loss,
cast_sign_loss,
// simplifies some macros
invalid_upcast_comparisons,
// things are often more readable this way
option_unwrap_used,
result_unwrap_used,
shadow_reuse,
single_match_else,
stutter,
use_self,
// not practical
missing_docs_in_private_items,
// alternative is not stable
empty_enum,
use_debug,
))]
// Blacklisted Rust lints. // Blacklisted Rust lints.
#![deny(missing_docs, unused_imports)] #![deny(missing_docs, unused_imports)]
//////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////////
#[cfg(feature = "collections")]
extern crate collections;
#[cfg(feature = "alloc")] #[cfg(feature = "alloc")]
extern crate alloc; extern crate alloc;
#[cfg(all(feature = "unstable", feature = "std"))] #[cfg(all(feature = "unstable", feature = "std"))]
extern crate core; extern crate core;
/// A facade around all the types we need from the `std`, `core`, `alloc`, and /// A facade around all the types we need from the `std`, `core`, and `alloc`
/// `collections` crates. This avoids elaborate import wrangling having to /// crates. This avoids elaborate import wrangling having to happen in every
/// happen in every module. /// module.
mod lib { mod lib {
mod core { mod core {
#[cfg(feature = "std")] #[cfg(feature = "std")]
@@ -140,18 +162,18 @@ mod lib {
#[cfg(feature = "std")] #[cfg(feature = "std")]
pub use std::borrow::{Cow, ToOwned}; pub use std::borrow::{Cow, ToOwned};
#[cfg(all(feature = "collections", not(feature = "std")))] #[cfg(all(feature = "alloc", not(feature = "std")))]
pub use collections::borrow::{Cow, ToOwned}; pub use alloc::borrow::{Cow, ToOwned};
#[cfg(feature = "std")] #[cfg(feature = "std")]
pub use std::string::String; pub use std::string::String;
#[cfg(all(feature = "collections", not(feature = "std")))] #[cfg(all(feature = "alloc", not(feature = "std")))]
pub use collections::string::{String, ToString}; pub use alloc::string::{String, ToString};
#[cfg(feature = "std")] #[cfg(feature = "std")]
pub use std::vec::Vec; pub use std::vec::Vec;
#[cfg(all(feature = "collections", not(feature = "std")))] #[cfg(all(feature = "alloc", not(feature = "std")))]
pub use collections::vec::Vec; pub use alloc::vec::Vec;
#[cfg(feature = "std")] #[cfg(feature = "std")]
pub use std::boxed::Box; pub use std::boxed::Box;
@@ -170,8 +192,8 @@ mod lib {
#[cfg(feature = "std")] #[cfg(feature = "std")]
pub use std::collections::{BinaryHeap, BTreeMap, BTreeSet, LinkedList, VecDeque}; pub use std::collections::{BinaryHeap, BTreeMap, BTreeSet, LinkedList, VecDeque};
#[cfg(all(feature = "collections", not(feature = "std")))] #[cfg(all(feature = "alloc", not(feature = "std")))]
pub use collections::{BinaryHeap, BTreeMap, BTreeSet, LinkedList, VecDeque}; pub use alloc::{BinaryHeap, BTreeMap, BTreeSet, LinkedList, VecDeque};
#[cfg(feature = "std")] #[cfg(feature = "std")]
pub use std::{error, net}; pub use std::{error, net};
@@ -187,7 +209,7 @@ mod lib {
#[cfg(feature = "std")] #[cfg(feature = "std")]
pub use std::path::{Path, PathBuf}; pub use std::path::{Path, PathBuf};
#[cfg(feature = "std")] #[cfg(feature = "std")]
pub use std::time::Duration; pub use std::time::{Duration, SystemTime, UNIX_EPOCH};
#[cfg(feature = "std")] #[cfg(feature = "std")]
pub use std::sync::{Mutex, RwLock}; pub use std::sync::{Mutex, RwLock};
+5 -5
View File
@@ -10,10 +10,10 @@ use lib::*;
use de::{Deserialize, Deserializer, IntoDeserializer, Error, Visitor}; use de::{Deserialize, Deserializer, IntoDeserializer, Error, Visitor};
#[cfg(any(feature = "std", feature = "collections"))] #[cfg(any(feature = "std", feature = "alloc"))]
use de::Unexpected; use de::Unexpected;
#[cfg(any(feature = "std", feature = "collections"))] #[cfg(any(feature = "std", feature = "alloc"))]
pub use self::content::{Content, ContentRefDeserializer, ContentDeserializer, pub use self::content::{Content, ContentRefDeserializer, ContentDeserializer,
TaggedContentVisitor, TagOrContentField, TagOrContentFieldVisitor, TaggedContentVisitor, TagOrContentField, TagOrContentFieldVisitor,
TagContentOtherField, TagContentOtherFieldVisitor, TagContentOtherField, TagContentOtherFieldVisitor,
@@ -59,7 +59,7 @@ where
Deserialize::deserialize(deserializer) Deserialize::deserialize(deserializer)
} }
#[cfg(any(feature = "std", feature = "collections"))] #[cfg(any(feature = "std", feature = "alloc"))]
pub fn borrow_cow_str<'de: 'a, 'a, D>(deserializer: D) -> Result<Cow<'a, str>, D::Error> pub fn borrow_cow_str<'de: 'a, 'a, D>(deserializer: D) -> Result<Cow<'a, str>, D::Error>
where where
D: Deserializer<'de>, D: Deserializer<'de>,
@@ -128,7 +128,7 @@ where
deserializer.deserialize_str(CowStrVisitor) deserializer.deserialize_str(CowStrVisitor)
} }
#[cfg(any(feature = "std", feature = "collections"))] #[cfg(any(feature = "std", feature = "alloc"))]
pub fn borrow_cow_bytes<'de: 'a, 'a, D>(deserializer: D) -> Result<Cow<'a, [u8]>, D::Error> pub fn borrow_cow_bytes<'de: 'a, 'a, D>(deserializer: D) -> Result<Cow<'a, [u8]>, D::Error>
where where
D: Deserializer<'de>, D: Deserializer<'de>,
@@ -210,7 +210,7 @@ pub mod size_hint {
} }
} }
#[cfg(any(feature = "std", feature = "collections"))] #[cfg(any(feature = "std", feature = "alloc"))]
mod content { mod content {
// This module is private and nothing here should be used outside of // This module is private and nothing here should be used outside of
// generated code. // generated code.
+13 -13
View File
@@ -10,7 +10,7 @@ use lib::*;
use ser::{self, Serialize, Serializer, SerializeMap, SerializeStruct, Impossible}; use ser::{self, Serialize, Serializer, SerializeMap, SerializeStruct, Impossible};
#[cfg(any(feature = "std", feature = "collections"))] #[cfg(any(feature = "std", feature = "alloc"))]
use self::content::{SerializeTupleVariantAsMapValue, SerializeStructVariantAsMapValue}; use self::content::{SerializeTupleVariantAsMapValue, SerializeStructVariantAsMapValue};
/// Used to check that serde(getter) attributes return the expected type. /// Used to check that serde(getter) attributes return the expected type.
@@ -64,7 +64,7 @@ enum Unsupported {
Sequence, Sequence,
Tuple, Tuple,
TupleStruct, TupleStruct,
#[cfg(not(any(feature = "std", feature = "collections")))] #[cfg(not(any(feature = "std", feature = "alloc")))]
Enum, Enum,
} }
@@ -83,7 +83,7 @@ impl Display for Unsupported {
Unsupported::Sequence => formatter.write_str("a sequence"), Unsupported::Sequence => formatter.write_str("a sequence"),
Unsupported::Tuple => formatter.write_str("a tuple"), Unsupported::Tuple => formatter.write_str("a tuple"),
Unsupported::TupleStruct => formatter.write_str("a tuple struct"), Unsupported::TupleStruct => formatter.write_str("a tuple struct"),
#[cfg(not(any(feature = "std", feature = "collections")))] #[cfg(not(any(feature = "std", feature = "alloc")))]
Unsupported::Enum => formatter.write_str("an enum"), Unsupported::Enum => formatter.write_str("an enum"),
} }
} }
@@ -117,14 +117,14 @@ where
type SerializeMap = S::SerializeMap; type SerializeMap = S::SerializeMap;
type SerializeStruct = S::SerializeStruct; type SerializeStruct = S::SerializeStruct;
#[cfg(not(any(feature = "std", feature = "collections")))] #[cfg(not(any(feature = "std", feature = "alloc")))]
type SerializeTupleVariant = Impossible<S::Ok, S::Error>; type SerializeTupleVariant = Impossible<S::Ok, S::Error>;
#[cfg(any(feature = "std", feature = "collections"))] #[cfg(any(feature = "std", feature = "alloc"))]
type SerializeTupleVariant = SerializeTupleVariantAsMapValue<S::SerializeMap>; type SerializeTupleVariant = SerializeTupleVariantAsMapValue<S::SerializeMap>;
#[cfg(not(any(feature = "std", feature = "collections")))] #[cfg(not(any(feature = "std", feature = "alloc")))]
type SerializeStructVariant = Impossible<S::Ok, S::Error>; type SerializeStructVariant = Impossible<S::Ok, S::Error>;
#[cfg(any(feature = "std", feature = "collections"))] #[cfg(any(feature = "std", feature = "alloc"))]
type SerializeStructVariant = SerializeStructVariantAsMapValue<S::SerializeMap>; type SerializeStructVariant = SerializeStructVariantAsMapValue<S::SerializeMap>;
fn serialize_bool(self, _: bool) -> Result<Self::Ok, Self::Error> { fn serialize_bool(self, _: bool) -> Result<Self::Ok, Self::Error> {
@@ -257,7 +257,7 @@ where
Err(self.bad_type(Unsupported::TupleStruct)) Err(self.bad_type(Unsupported::TupleStruct))
} }
#[cfg(not(any(feature = "std", feature = "collections")))] #[cfg(not(any(feature = "std", feature = "alloc")))]
fn serialize_tuple_variant( fn serialize_tuple_variant(
self, self,
_: &'static str, _: &'static str,
@@ -270,7 +270,7 @@ where
Err(self.bad_type(Unsupported::Enum)) Err(self.bad_type(Unsupported::Enum))
} }
#[cfg(any(feature = "std", feature = "collections"))] #[cfg(any(feature = "std", feature = "alloc"))]
fn serialize_tuple_variant( fn serialize_tuple_variant(
self, self,
_: &'static str, _: &'static str,
@@ -300,7 +300,7 @@ where
Ok(state) Ok(state)
} }
#[cfg(not(any(feature = "std", feature = "collections")))] #[cfg(not(any(feature = "std", feature = "alloc")))]
fn serialize_struct_variant( fn serialize_struct_variant(
self, self,
_: &'static str, _: &'static str,
@@ -313,7 +313,7 @@ where
Err(self.bad_type(Unsupported::Enum)) Err(self.bad_type(Unsupported::Enum))
} }
#[cfg(any(feature = "std", feature = "collections"))] #[cfg(any(feature = "std", feature = "alloc"))]
fn serialize_struct_variant( fn serialize_struct_variant(
self, self,
_: &'static str, _: &'static str,
@@ -327,7 +327,7 @@ where
Ok(SerializeStructVariantAsMapValue::new(map, inner_variant, len),) Ok(SerializeStructVariantAsMapValue::new(map, inner_variant, len),)
} }
#[cfg(not(any(feature = "std", feature = "collections")))] #[cfg(not(any(feature = "std", feature = "alloc")))]
fn collect_str<T: ?Sized>(self, _: &T) -> Result<Self::Ok, Self::Error> fn collect_str<T: ?Sized>(self, _: &T) -> Result<Self::Ok, Self::Error>
where where
T: Display, T: Display,
@@ -363,7 +363,7 @@ impl Display for Error {
} }
} }
#[cfg(any(feature = "std", feature = "collections"))] #[cfg(any(feature = "std", feature = "alloc"))]
mod content { mod content {
use lib::*; use lib::*;
+29 -10
View File
@@ -56,7 +56,7 @@ impl Serialize for str {
} }
} }
#[cfg(any(feature = "std", feature = "collections"))] #[cfg(any(feature = "std", feature = "alloc"))]
impl Serialize for String { impl Serialize for String {
#[inline] #[inline]
fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error> fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
@@ -177,6 +177,7 @@ where
} }
} }
#[cfg(any(feature = "std", feature = "alloc"))]
macro_rules! seq_impl { macro_rules! seq_impl {
($ty:ident < T $(: $tbound1:ident $(+ $tbound2:ident)*)* $(, $typaram:ident : $bound:ident)* >) => { ($ty:ident < T $(: $tbound1:ident $(+ $tbound2:ident)*)* $(, $typaram:ident : $bound:ident)* >) => {
impl<T $(, $typaram)*> Serialize for $ty<T $(, $typaram)*> impl<T $(, $typaram)*> Serialize for $ty<T $(, $typaram)*>
@@ -195,22 +196,22 @@ macro_rules! seq_impl {
} }
} }
#[cfg(any(feature = "std", feature = "collections"))] #[cfg(any(feature = "std", feature = "alloc"))]
seq_impl!(BinaryHeap<T: Ord>); seq_impl!(BinaryHeap<T: Ord>);
#[cfg(any(feature = "std", feature = "collections"))] #[cfg(any(feature = "std", feature = "alloc"))]
seq_impl!(BTreeSet<T: Ord>); seq_impl!(BTreeSet<T: Ord>);
#[cfg(feature = "std")] #[cfg(feature = "std")]
seq_impl!(HashSet<T: Eq + Hash, H: BuildHasher>); seq_impl!(HashSet<T: Eq + Hash, H: BuildHasher>);
#[cfg(any(feature = "std", feature = "collections"))] #[cfg(any(feature = "std", feature = "alloc"))]
seq_impl!(LinkedList<T>); seq_impl!(LinkedList<T>);
#[cfg(any(feature = "std", feature = "collections"))] #[cfg(any(feature = "std", feature = "alloc"))]
seq_impl!(Vec<T>); seq_impl!(Vec<T>);
#[cfg(any(feature = "std", feature = "collections"))] #[cfg(any(feature = "std", feature = "alloc"))]
seq_impl!(VecDeque<T>); seq_impl!(VecDeque<T>);
//////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////////
@@ -290,6 +291,7 @@ tuple_impls! {
//////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////////
#[cfg(any(feature = "std", feature = "alloc"))]
macro_rules! map_impl { macro_rules! map_impl {
($ty:ident < K $(: $kbound1:ident $(+ $kbound2:ident)*)*, V $(, $typaram:ident : $bound:ident)* >) => { ($ty:ident < K $(: $kbound1:ident $(+ $kbound2:ident)*)*, V $(, $typaram:ident : $bound:ident)* >) => {
impl<K, V $(, $typaram)*> Serialize for $ty<K, V $(, $typaram)*> impl<K, V $(, $typaram)*> Serialize for $ty<K, V $(, $typaram)*>
@@ -309,7 +311,7 @@ macro_rules! map_impl {
} }
} }
#[cfg(any(feature = "std", feature = "collections"))] #[cfg(any(feature = "std", feature = "alloc"))]
map_impl!(BTreeMap<K: Ord, V>); map_impl!(BTreeMap<K: Ord, V>);
#[cfg(feature = "std")] #[cfg(feature = "std")]
@@ -338,12 +340,12 @@ deref_impl!(<'a, T: ?Sized> Serialize for &'a mut T where T: Serialize);
deref_impl!(<T: ?Sized> Serialize for Box<T> where T: Serialize); deref_impl!(<T: ?Sized> Serialize for Box<T> where T: Serialize);
#[cfg(all(feature = "rc", any(feature = "std", feature = "alloc")))] #[cfg(all(feature = "rc", any(feature = "std", feature = "alloc")))]
deref_impl!(<T> Serialize for Rc<T> where T: Serialize); deref_impl!(<T: ?Sized> Serialize for Rc<T> where T: Serialize);
#[cfg(all(feature = "rc", any(feature = "std", feature = "alloc")))] #[cfg(all(feature = "rc", any(feature = "std", feature = "alloc")))]
deref_impl!(<T> Serialize for Arc<T> where T: Serialize); deref_impl!(<T: ?Sized> Serialize for Arc<T> where T: Serialize);
#[cfg(any(feature = "std", feature = "collections"))] #[cfg(any(feature = "std", feature = "alloc"))]
deref_impl!(<'a, T: ?Sized> Serialize for Cow<'a, T> where T: Serialize + ToOwned); deref_impl!(<'a, T: ?Sized> Serialize for Cow<'a, T> where T: Serialize + ToOwned);
//////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////////
@@ -455,6 +457,23 @@ impl Serialize for Duration {
//////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////////
#[cfg(feature = "std")]
impl Serialize for SystemTime {
fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
where
S: Serializer,
{
use super::SerializeStruct;
let duration_since_epoch = self.duration_since(UNIX_EPOCH).expect("SystemTime must be later than UNIX_EPOCH");
let mut state = try!(serializer.serialize_struct("SystemTime", 2));
try!(state.serialize_field("secs_since_epoch", &duration_since_epoch.as_secs()));
try!(state.serialize_field("nanos_since_epoch", &duration_since_epoch.subsec_nanos()));
state.end()
}
}
////////////////////////////////////////////////////////////////////////////////
/// Serialize a value that implements `Display` as a string, when that string is /// Serialize a value that implements `Display` as a string, when that string is
/// statically known to never have more than a constant `MAX_LEN` bytes. /// statically known to never have more than a constant `MAX_LEN` bytes.
/// ///
+3 -2
View File
@@ -89,6 +89,7 @@
//! - OsString //! - OsString
//! - **Miscellaneous standard library types**: //! - **Miscellaneous standard library types**:
//! - Duration //! - Duration
//! - SystemTime
//! - Path //! - Path
//! - PathBuf //! - PathBuf
//! - Range\<T\> //! - Range\<T\>
@@ -1321,7 +1322,7 @@ pub trait Serializer: Sized {
/// ///
/// [`String`]: https://doc.rust-lang.org/std/string/struct.String.html /// [`String`]: https://doc.rust-lang.org/std/string/struct.String.html
/// [`serialize_str`]: #tymethod.serialize_str /// [`serialize_str`]: #tymethod.serialize_str
#[cfg(any(feature = "std", feature = "collections"))] #[cfg(any(feature = "std", feature = "alloc"))]
fn collect_str<T: ?Sized>(self, value: &T) -> Result<Self::Ok, Self::Error> fn collect_str<T: ?Sized>(self, value: &T) -> Result<Self::Ok, Self::Error>
where where
T: Display, T: Display,
@@ -1358,7 +1359,7 @@ pub trait Serializer: Sized {
/// } /// }
/// } /// }
/// ``` /// ```
#[cfg(not(any(feature = "std", feature = "collections")))] #[cfg(not(any(feature = "std", feature = "alloc")))]
fn collect_str<T: ?Sized>(self, value: &T) -> Result<Self::Ok, Self::Error> fn collect_str<T: ?Sized>(self, value: &T) -> Result<Self::Ok, Self::Error>
where where
T: Display; T: Display;
+2 -2
View File
@@ -1,6 +1,6 @@
[package] [package]
name = "serde_derive" name = "serde_derive"
version = "1.0.7" # remember to update html_root_url version = "1.0.12" # remember to update html_root_url
authors = ["Erick Tryzelaar <erick.tryzelaar@gmail.com>", "David Tolnay <dtolnay@gmail.com>"] authors = ["Erick Tryzelaar <erick.tryzelaar@gmail.com>", "David Tolnay <dtolnay@gmail.com>"]
license = "MIT/Apache-2.0" license = "MIT/Apache-2.0"
description = "Macros 1.1 implementation of #[derive(Serialize, Deserialize)]" description = "Macros 1.1 implementation of #[derive(Serialize, Deserialize)]"
@@ -20,5 +20,5 @@ proc-macro = true
[dependencies] [dependencies]
quote = "0.3.8" quote = "0.3.8"
serde_derive_internals = { version = "=0.15.0", default-features = false, path = "../serde_derive_internals" } serde_derive_internals = { version = "=0.15.1", default-features = false, path = "../serde_derive_internals" }
syn = { version = "0.11", features = ["visit"] } syn = { version = "0.11", features = ["visit"] }
+12 -14
View File
@@ -23,15 +23,15 @@ pub fn expand_derive_deserialize(input: &syn::DeriveInput) -> Result<Tokens, Str
let ident = &cont.ident; let ident = &cont.ident;
let params = Parameters::new(&cont); let params = Parameters::new(&cont);
let (de_impl_generics, _, ty_generics, where_clause) = split_with_de_lifetime(&params);
let dummy_const = Ident::new(format!("_IMPL_DESERIALIZE_FOR_{}", ident)); let dummy_const = Ident::new(format!("_IMPL_DESERIALIZE_FOR_{}", ident));
let body = Stmts(deserialize_body(&cont, &params)); let body = Stmts(deserialize_body(&cont, &params));
let impl_block = if let Some(remote) = cont.attrs.remote() { let impl_block = if let Some(remote) = cont.attrs.remote() {
let (impl_generics, ty_generics, where_clause) = cont.generics.split_for_impl(); let vis = &input.vis;
let de_lifetime = params.de_lifetime_def();
quote! { quote! {
impl #impl_generics #ident #ty_generics #where_clause { impl #de_impl_generics #ident #ty_generics #where_clause {
fn deserialize<#de_lifetime, __D>(__deserializer: __D) -> _serde::export::Result<#remote #ty_generics, __D::Error> #vis fn deserialize<__D>(__deserializer: __D) -> _serde::export::Result<#remote #ty_generics, __D::Error>
where __D: _serde::Deserializer<'de> where __D: _serde::Deserializer<'de>
{ {
#body #body
@@ -39,7 +39,6 @@ pub fn expand_derive_deserialize(input: &syn::DeriveInput) -> Result<Tokens, Str
} }
} }
} else { } else {
let (de_impl_generics, _, ty_generics, where_clause) = split_with_de_lifetime(&params);
quote! { quote! {
#[automatically_derived] #[automatically_derived]
impl #de_impl_generics _serde::Deserialize<'de> for #ident #ty_generics #where_clause { impl #de_impl_generics _serde::Deserialize<'de> for #ident #ty_generics #where_clause {
@@ -797,9 +796,8 @@ fn deserialize_adjacently_tagged_enum(
let type_name = cattrs.name().deserialize_name(); let type_name = cattrs.name().deserialize_name();
let deny_unknown_fields = cattrs.deny_unknown_fields(); let deny_unknown_fields = cattrs.deny_unknown_fields();
/// If unknown fields are allowed, we pick the visitor that can // If unknown fields are allowed, we pick the visitor that can step over
/// step over those. Otherwise we pick the visitor that fails on // those. Otherwise we pick the visitor that fails on unknown keys.
/// unknown keys.
let field_visitor_ty = if deny_unknown_fields { let field_visitor_ty = if deny_unknown_fields {
quote! { _serde::private::de::TagOrContentFieldVisitor } quote! { _serde::private::de::TagOrContentFieldVisitor }
} else { } else {
@@ -854,13 +852,13 @@ fn deserialize_adjacently_tagged_enum(
}; };
} }
/// Advance the map by one key, returning early in case of error. // Advance the map by one key, returning early in case of error.
let next_key = quote! { let next_key = quote! {
try!(_serde::de::MapAccess::next_key_seed(&mut __map, #tag_or_content)) try!(_serde::de::MapAccess::next_key_seed(&mut __map, #tag_or_content))
}; };
/// When allowing unknown fields, we want to transparently step through keys we don't care // When allowing unknown fields, we want to transparently step through keys
/// about until we find `tag`, `content`, or run out of keys. // we don't care about until we find `tag`, `content`, or run out of keys.
let next_relevant_key = if deny_unknown_fields { let next_relevant_key = if deny_unknown_fields {
next_key next_key
} else { } else {
@@ -889,9 +887,9 @@ fn deserialize_adjacently_tagged_enum(
} }
}; };
/// Step through remaining keys, looking for duplicates of previously-seen keys. // Step through remaining keys, looking for duplicates of previously-seen
/// When unknown fields are denied, any key that isn't a duplicate will at this // keys. When unknown fields are denied, any key that isn't a duplicate will
/// point immediately produce an error. // at this point immediately produce an error.
let visit_remaining_keys = quote! { let visit_remaining_keys = quote! {
match #next_relevant_key { match #next_relevant_key {
_serde::export::Some(_serde::private::de::TagOrContentField::Tag) => { _serde::export::Some(_serde::private::de::TagOrContentField::Tag) => {
+1 -1
View File
@@ -16,7 +16,7 @@
//! //!
//! [https://serde.rs/derive.html]: https://serde.rs/derive.html //! [https://serde.rs/derive.html]: https://serde.rs/derive.html
#![doc(html_root_url = "https://docs.rs/serde_derive/1.0.7")] #![doc(html_root_url = "https://docs.rs/serde_derive/1.0.12")]
#![cfg_attr(feature = "cargo-clippy", allow(too_many_arguments))] #![cfg_attr(feature = "cargo-clippy", allow(too_many_arguments))]
#![cfg_attr(feature = "cargo-clippy", allow(used_underscore_binding))] #![cfg_attr(feature = "cargo-clippy", allow(used_underscore_binding))]
+2 -1
View File
@@ -29,9 +29,10 @@ pub fn expand_derive_serialize(input: &syn::DeriveInput) -> Result<Tokens, Strin
let body = Stmts(serialize_body(&cont, &params)); let body = Stmts(serialize_body(&cont, &params));
let impl_block = if let Some(remote) = cont.attrs.remote() { let impl_block = if let Some(remote) = cont.attrs.remote() {
let vis = &input.vis;
quote! { quote! {
impl #impl_generics #ident #ty_generics #where_clause { impl #impl_generics #ident #ty_generics #where_clause {
fn serialize<__S>(__self: &#remote #ty_generics, __serializer: __S) -> _serde::export::Result<__S::Ok, __S::Error> #vis fn serialize<__S>(__self: &#remote #ty_generics, __serializer: __S) -> _serde::export::Result<__S::Ok, __S::Error>
where __S: _serde::Serializer where __S: _serde::Serializer
{ {
#body #body
+1 -1
View File
@@ -1,6 +1,6 @@
[package] [package]
name = "serde_derive_internals" name = "serde_derive_internals"
version = "0.15.0" # remember to update html_root_url version = "0.15.1" # remember to update html_root_url
authors = ["Erick Tryzelaar <erick.tryzelaar@gmail.com>", "David Tolnay <dtolnay@gmail.com>"] authors = ["Erick Tryzelaar <erick.tryzelaar@gmail.com>", "David Tolnay <dtolnay@gmail.com>"]
license = "MIT/Apache-2.0" license = "MIT/Apache-2.0"
description = "AST representation used by Serde derive macros. Unstable." description = "AST representation used by Serde derive macros. Unstable."
+1 -1
View File
@@ -6,7 +6,7 @@
// option. This file may not be copied, modified, or distributed // option. This file may not be copied, modified, or distributed
// except according to those terms. // except according to those terms.
#![doc(html_root_url = "https://docs.rs/serde_derive_internals/0.15.0")] #![doc(html_root_url = "https://docs.rs/serde_derive_internals/0.15.1")]
extern crate syn; extern crate syn;
#[macro_use] #[macro_use]
+1 -1
View File
@@ -1,6 +1,6 @@
[package] [package]
name = "serde_test" name = "serde_test"
version = "1.0.7" # remember to update html_root_url version = "1.0.12" # remember to update html_root_url
authors = ["Erick Tryzelaar <erick.tryzelaar@gmail.com>", "David Tolnay <dtolnay@gmail.com>"] authors = ["Erick Tryzelaar <erick.tryzelaar@gmail.com>", "David Tolnay <dtolnay@gmail.com>"]
license = "MIT/Apache-2.0" license = "MIT/Apache-2.0"
description = "Token De/Serializer for testing De/Serialize implementations" description = "Token De/Serializer for testing De/Serialize implementations"
+1 -1
View File
@@ -155,7 +155,7 @@
//! # } //! # }
//! ``` //! ```
#![doc(html_root_url = "https://docs.rs/serde_test/1.0.7")] #![doc(html_root_url = "https://docs.rs/serde_test/1.0.12")]
#[macro_use] #[macro_use]
extern crate serde; extern crate serde;
+1 -1
View File
@@ -10,7 +10,7 @@ unstable = ["serde/unstable", "compiletest_rs"]
[dev-dependencies] [dev-dependencies]
fnv = "1.0" fnv = "1.0"
rustc-serialize = "0.3.16" rustc-serialize = "0.3.16"
serde = { path = "../serde" } serde = { path = "../serde", features = ["rc"] }
serde_derive = { path = "../serde_derive" } serde_derive = { path = "../serde_derive" }
serde_test = { path = "../serde_test" } serde_test = { path = "../serde_test" }
+3
View File
@@ -4,5 +4,8 @@ version = "0.0.0"
publish = false publish = false
[dependencies] [dependencies]
libc = { version = "0.2", default-features = false }
serde = { path = "../../serde", default-features = false } serde = { path = "../../serde", default-features = false }
serde_derive = { path = "../../serde_derive" } serde_derive = { path = "../../serde_derive" }
[workspace]
+1 -1
View File
@@ -1,4 +1,4 @@
#![feature(lang_items, start, libc, compiler_builtins_lib)] #![feature(lang_items, start, compiler_builtins_lib)]
#![no_std] #![no_std]
extern crate libc; extern crate libc;
@@ -18,7 +18,9 @@ mod remote {
#[derive(Serialize, Deserialize)] #[derive(Serialize, Deserialize)]
#[serde(remote = "remote::S")] #[serde(remote = "remote::S")]
struct S { struct S {
b: u8, //~^^^ ERROR: no field `b` on type `&remote::S` //~^^^ ERROR: struct `remote::S` has no field named `b`
//~^^^^ ERROR: struct `remote::S` has no field named `b`
b: u8, //~^^^^^ ERROR: no field `b` on type `&remote::S`
} }
fn main() {} fn main() {}
+1 -1
View File
@@ -13,7 +13,7 @@ extern crate compiletest_rs as compiletest;
use std::env; use std::env;
fn run_mode(mode: &'static str) { fn run_mode(mode: &'static str) {
let mut config = compiletest::default_config(); let mut config = compiletest::Config::default();
config.mode = mode.parse().expect("invalid mode"); config.mode = mode.parse().expect("invalid mode");
config.target_rustcflags = Some("-L deps/target/debug/deps".to_owned()); config.target_rustcflags = Some("-L deps/target/debug/deps".to_owned());
+54 -3
View File
@@ -6,17 +6,17 @@
// option. This file may not be copied, modified, or distributed // option. This file may not be copied, modified, or distributed
// except according to those terms. // except according to those terms.
#![cfg_attr(feature = "unstable", feature(into_boxed_c_str))]
#[macro_use] #[macro_use]
extern crate serde_derive; extern crate serde_derive;
use std::collections::{BTreeMap, BTreeSet, HashMap, HashSet}; use std::collections::{BTreeMap, BTreeSet, HashMap, HashSet};
use std::net; use std::net;
use std::path::{Path, PathBuf}; use std::path::{Path, PathBuf};
use std::time::Duration; use std::time::{Duration, UNIX_EPOCH};
use std::default::Default; use std::default::Default;
use std::ffi::{CString, OsString}; use std::ffi::{CString, OsString};
use std::rc::Rc;
use std::sync::Arc;
#[cfg(feature = "unstable")] #[cfg(feature = "unstable")]
use std::ffi::CStr; use std::ffi::CStr;
@@ -682,6 +682,23 @@ declare_tests! {
Token::SeqEnd, Token::SeqEnd,
], ],
} }
test_system_time {
UNIX_EPOCH + Duration::new(1, 2) => &[
Token::Struct { name: "SystemTime", len: 2 },
Token::Str("secs_since_epoch"),
Token::U64(1),
Token::Str("nanos_since_epoch"),
Token::U32(2),
Token::StructEnd,
],
UNIX_EPOCH + Duration::new(1, 2) => &[
Token::Seq { len: Some(2) },
Token::I64(1),
Token::I64(2),
Token::SeqEnd,
],
}
test_range { test_range {
1u32..2u32 => &[ 1u32..2u32 => &[
Token::Struct { name: "Range", len: 2 }, Token::Struct { name: "Range", len: 2 },
@@ -725,6 +742,40 @@ declare_tests! {
Token::Bytes(b"abc"), Token::Bytes(b"abc"),
], ],
} }
test_rc {
Rc::new(true) => &[
Token::Bool(true),
],
}
test_arc {
Arc::new(true) => &[
Token::Bool(true),
],
}
}
#[cfg(feature = "unstable")]
declare_tests! {
test_rc_dst {
Rc::<str>::from("s") => &[
Token::Str("s"),
],
Rc::<[bool]>::from(&[true][..]) => &[
Token::Seq { len: Some(1) },
Token::Bool(true),
Token::SeqEnd,
],
}
test_arc_dst {
Arc::<str>::from("s") => &[
Token::Str("s"),
],
Arc::<[bool]>::from(&[true][..]) => &[
Token::Seq { len: Some(1) },
Token::Bool(true),
Token::SeqEnd,
],
}
} }
#[cfg(unix)] #[cfg(unix)]
+43
View File
@@ -330,6 +330,49 @@ fn test_gen() {
struct EmptyArray { struct EmptyArray {
empty: [X; 0], empty: [X; 0],
} }
enum Or<A, B> {
A(A),
B(B),
}
#[derive(Serialize, Deserialize)]
#[serde(untagged, remote = "Or")]
enum OrDef<A, B> {
#[allow(dead_code)]
A(A),
#[allow(dead_code)]
B(B),
}
struct Str<'a>(&'a str);
#[derive(Serialize, Deserialize)]
#[serde(remote = "Str")]
struct StrDef<'a>(&'a str);
#[derive(Serialize, Deserialize)]
struct Remote<'a> {
#[serde(with = "OrDef")]
or: Or<u8, bool>,
#[serde(borrow, with = "StrDef")]
s: Str<'a>,
}
mod vis {
pub struct S;
#[derive(Serialize, Deserialize)]
#[serde(remote = "S")]
pub struct SDef;
}
// This would not work if SDef::serialize / deserialize are private.
#[derive(Serialize, Deserialize)]
struct RemoteVisibility {
#[serde(with = "vis::SDef")]
s: vis::S,
}
} }
////////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////////
+61 -2
View File
@@ -9,11 +9,13 @@
#[macro_use] #[macro_use]
extern crate serde_derive; extern crate serde_derive;
use std::collections::{BTreeMap, HashMap, HashSet}; use std::collections::{BTreeMap, BTreeSet, HashMap, HashSet};
use std::net; use std::net;
use std::path::{Path, PathBuf}; use std::path::{Path, PathBuf};
use std::time::Duration; use std::time::{Duration, UNIX_EPOCH};
use std::ffi::CString; use std::ffi::CString;
use std::rc::Rc;
use std::sync::Arc;
#[cfg(unix)] #[cfg(unix)]
use std::str; use std::str;
@@ -170,6 +172,17 @@ declare_tests! {
Token::SeqEnd, Token::SeqEnd,
], ],
} }
test_btreeset {
BTreeSet::<isize>::new() => &[
Token::Seq { len: Some(0) },
Token::SeqEnd,
],
btreeset![1] => &[
Token::Seq { len: Some(1) },
Token::I32(1),
Token::SeqEnd,
],
}
test_hashset { test_hashset {
HashSet::<isize>::new() => &[ HashSet::<isize>::new() => &[
Token::Seq { len: Some(0) }, Token::Seq { len: Some(0) },
@@ -319,6 +332,17 @@ declare_tests! {
Token::StructEnd, Token::StructEnd,
], ],
} }
test_system_time {
UNIX_EPOCH + Duration::new(1, 200) => &[
Token::Struct { name: "SystemTime", len: 2 },
Token::Str("secs_since_epoch"),
Token::U64(1),
Token::Str("nanos_since_epoch"),
Token::U32(200),
Token::StructEnd,
],
}
test_range { test_range {
1u32..2u32 => &[ 1u32..2u32 => &[
Token::Struct { name: "Range", len: 2 }, Token::Struct { name: "Range", len: 2 },
@@ -361,6 +385,41 @@ declare_tests! {
Token::Bytes(b"abc"), Token::Bytes(b"abc"),
], ],
} }
test_rc {
Rc::new(true) => &[
Token::Bool(true),
],
}
test_arc {
Arc::new(true) => &[
Token::Bool(true),
],
}
}
// Serde's implementation is not unstable, but the constructors are.
#[cfg(feature = "unstable")]
declare_tests! {
test_rc_dst {
Rc::<str>::from("s") => &[
Token::Str("s"),
],
Rc::<[bool]>::from(&[true][..]) => &[
Token::Seq { len: Some(1) },
Token::Bool(true),
Token::SeqEnd,
],
}
test_arc_dst {
Arc::<str>::from("s") => &[
Token::Str("s"),
],
Arc::<[bool]>::from(&[true][..]) => &[
Token::Seq { len: Some(1) },
Token::Bool(true),
Token::SeqEnd,
],
}
} }
#[cfg(feature = "unstable")] #[cfg(feature = "unstable")]
+8 -3
View File
@@ -41,21 +41,24 @@ if [ -n "${CLIPPY}" ]; then
cargo clippy -- -Dclippy cargo clippy -- -Dclippy
else else
CHANNEL=nightly CHANNEL=nightly
cd "$DIR"
cargo clean cargo clean
cd "$DIR/serde" cd "$DIR/serde"
channel build channel build
channel build --no-default-features channel build --no-default-features
channel build --no-default-features --features alloc channel build --no-default-features --features alloc
channel build --no-default-features --features collections
channel test --features 'rc unstable' channel test --features 'rc unstable'
cd "$DIR/test_suite/deps" cd "$DIR/test_suite/deps"
channel build channel build
cd "$DIR/test_suite" cd "$DIR/test_suite"
channel test --features unstable channel test --features unstable
cd "$DIR/test_suite/no_std" if [ -z "${APPVEYOR}" ]; then
channel build cd "$DIR/test_suite/no_std"
channel build
fi
CHANNEL=beta CHANNEL=beta
cd "$DIR"
cargo clean cargo clean
cd "$DIR/serde" cd "$DIR/serde"
channel build --features rc channel build --features rc
@@ -63,6 +66,7 @@ else
channel test channel test
CHANNEL=stable CHANNEL=stable
cd "$DIR"
cargo clean cargo clean
cd "$DIR/serde" cd "$DIR/serde"
channel build --features rc channel build --features rc
@@ -72,6 +76,7 @@ else
channel test channel test
CHANNEL=1.13.0 CHANNEL=1.13.0
cd "$DIR"
cargo clean cargo clean
cd "$DIR/serde" cd "$DIR/serde"
channel build --features rc channel build --features rc