mirror of
https://github.com/pezkuwichain/serde.git
synced 2026-04-22 21:48:02 +00:00
Compare commits
44 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| d4042872f5 | |||
| 64af86b830 | |||
| 370c8a91cb | |||
| 972da59ebc | |||
| a42008f695 | |||
| e4ea2a56e9 | |||
| 7650a48fdd | |||
| d665a2f2b2 | |||
| 44e23254c9 | |||
| 0681cd5003 | |||
| d965367238 | |||
| a6df35b3d2 | |||
| 4831482695 | |||
| d3e5dd9cd7 | |||
| 26098ed877 | |||
| 42ed62cf24 | |||
| 9f0973aff7 | |||
| ccec002bf3 | |||
| f36a1e0895 | |||
| e6487cf6fa | |||
| 4f2e8d5dbb | |||
| 1c2a4bff1c | |||
| 85bccf42b6 | |||
| 959fee024f | |||
| 8ede8c8e2a | |||
| 83537c95e1 | |||
| fa9057fa31 | |||
| 0084d82a50 | |||
| b504b08782 | |||
| 775e8154e7 | |||
| 9c679d9082 | |||
| b0f9d2a0ba | |||
| f39b1db96a | |||
| 9ecb0839de | |||
| 8a4c116812 | |||
| 1d3e921ba6 | |||
| 4fdba725fe | |||
| 75eed8cdde | |||
| 6801a13650 | |||
| 25ab84d4b9 | |||
| e43d3f3e4f | |||
| b37d47c987 | |||
| eec7101894 | |||
| 5dd327fb02 |
@@ -5,5 +5,4 @@ members = [
|
||||
"serde_derive_internals",
|
||||
"serde_test",
|
||||
"test_suite",
|
||||
"test_suite/no_std",
|
||||
]
|
||||
|
||||
+4
-11
@@ -1,6 +1,6 @@
|
||||
[package]
|
||||
name = "serde"
|
||||
version = "1.0.8" # 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>"]
|
||||
license = "MIT/Apache-2.0"
|
||||
description = "A generic serialization/deserialization framework"
|
||||
@@ -48,22 +48,15 @@ std = []
|
||||
# https://github.com/serde-rs/serde/issues/812
|
||||
unstable = []
|
||||
|
||||
# Provide impls for types that require memory allocation like Box<T> and Rc<T>.
|
||||
# This is a subset of std but may be enabled without depending on all of std.
|
||||
# Provide impls for types in the Rust core allocation and collections library
|
||||
# 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:
|
||||
#
|
||||
# https://doc.rust-lang.org/alloc/
|
||||
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
|
||||
# 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.
|
||||
|
||||
+193
-118
@@ -11,12 +11,12 @@ use lib::*;
|
||||
use de::{Deserialize, Deserializer, EnumAccess, Error, SeqAccess, Unexpected, VariantAccess,
|
||||
Visitor};
|
||||
|
||||
#[cfg(any(feature = "std", feature = "collections"))]
|
||||
#[cfg(any(feature = "std", feature = "alloc"))]
|
||||
use de::MapAccess;
|
||||
|
||||
use de::from_primitive::FromPrimitive;
|
||||
|
||||
#[cfg(any(feature = "std", feature = "collections"))]
|
||||
#[cfg(any(feature = "std", feature = "alloc"))]
|
||||
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;
|
||||
|
||||
#[cfg(any(feature = "std", feature = "collections"))]
|
||||
#[cfg(any(feature = "std", feature = "alloc"))]
|
||||
impl<'de> Visitor<'de> for StringVisitor {
|
||||
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 {
|
||||
fn deserialize<D>(deserializer: D) -> Result<String, D::Error>
|
||||
where
|
||||
@@ -400,16 +400,22 @@ impl<'de> Deserialize<'de> for CString {
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(all(feature = "std", feature = "unstable"))]
|
||||
impl<'de> Deserialize<'de> for Box<CStr> {
|
||||
fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
|
||||
where
|
||||
D: Deserializer<'de>,
|
||||
{
|
||||
CString::deserialize(deserializer).map(CString::into_boxed_c_str)
|
||||
macro_rules! forwarded_impl {
|
||||
(( $($id: ident),* ), $ty: ty, $func: expr) => {
|
||||
impl<'de $(, $id : Deserialize<'de>,)*> Deserialize<'de> for $ty {
|
||||
fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
|
||||
where
|
||||
D: Deserializer<'de>,
|
||||
{
|
||||
Deserialize::deserialize(deserializer).map($func)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(all(feature = "std", feature = "unstable"))]
|
||||
forwarded_impl!((), Box<CStr>, CString::into_boxed_c_str);
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
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 {
|
||||
(
|
||||
$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!(
|
||||
BinaryHeap<T: Ord>,
|
||||
seq,
|
||||
@@ -560,7 +566,7 @@ seq_impl!(
|
||||
BinaryHeap::with_capacity(size_hint::cautious(seq.size_hint())),
|
||||
BinaryHeap::push);
|
||||
|
||||
#[cfg(any(feature = "std", feature = "collections"))]
|
||||
#[cfg(any(feature = "std", feature = "alloc"))]
|
||||
seq_impl!(
|
||||
BTreeSet<T: Eq + Ord>,
|
||||
seq,
|
||||
@@ -568,7 +574,7 @@ seq_impl!(
|
||||
BTreeSet::new(),
|
||||
BTreeSet::insert);
|
||||
|
||||
#[cfg(any(feature = "std", feature = "collections"))]
|
||||
#[cfg(any(feature = "std", feature = "alloc"))]
|
||||
seq_impl!(
|
||||
LinkedList<T>,
|
||||
seq,
|
||||
@@ -584,7 +590,7 @@ seq_impl!(
|
||||
HashSet::with_capacity_and_hasher(size_hint::cautious(seq.size_hint()), S::default()),
|
||||
HashSet::insert);
|
||||
|
||||
#[cfg(any(feature = "std", feature = "collections"))]
|
||||
#[cfg(any(feature = "std", feature = "alloc"))]
|
||||
seq_impl!(
|
||||
Vec<T>,
|
||||
seq,
|
||||
@@ -592,7 +598,7 @@ seq_impl!(
|
||||
Vec::with_capacity(size_hint::cautious(seq.size_hint())),
|
||||
Vec::push);
|
||||
|
||||
#[cfg(any(feature = "std", feature = "collections"))]
|
||||
#[cfg(any(feature = "std", feature = "alloc"))]
|
||||
seq_impl!(
|
||||
VecDeque<T>,
|
||||
seq,
|
||||
@@ -790,7 +796,7 @@ tuple_impls! {
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
#[cfg(any(feature = "std", feature = "collections"))]
|
||||
#[cfg(any(feature = "std", feature = "alloc"))]
|
||||
macro_rules! map_impl {
|
||||
(
|
||||
$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!(
|
||||
BTreeMap<K: Ord, V>,
|
||||
map,
|
||||
@@ -1098,68 +1104,21 @@ impl<'de> Deserialize<'de> for OsString {
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
#[cfg(any(feature = "std", feature = "alloc"))]
|
||||
impl<'de, T> Deserialize<'de> for Box<T>
|
||||
where
|
||||
T: Deserialize<'de>,
|
||||
{
|
||||
fn deserialize<D>(deserializer: D) -> Result<Box<T>, D::Error>
|
||||
where
|
||||
D: Deserializer<'de>,
|
||||
{
|
||||
T::deserialize(deserializer).map(Box::new)
|
||||
}
|
||||
}
|
||||
forwarded_impl!((T), Box<T>, Box::new);
|
||||
|
||||
#[cfg(any(feature = "std", feature = "collections"))]
|
||||
impl<'de, T> Deserialize<'de> for Box<[T]>
|
||||
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 = "alloc"))]
|
||||
forwarded_impl!((T), Box<[T]>, Vec::into_boxed_slice);
|
||||
|
||||
#[cfg(any(feature = "std", feature = "collections"))]
|
||||
impl<'de> Deserialize<'de> for Box<str> {
|
||||
fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
|
||||
where
|
||||
D: Deserializer<'de>,
|
||||
{
|
||||
String::deserialize(deserializer).map(String::into_boxed_str)
|
||||
}
|
||||
}
|
||||
#[cfg(any(feature = "std", feature = "alloc"))]
|
||||
forwarded_impl!((), Box<str>, String::into_boxed_str);
|
||||
|
||||
#[cfg(all(feature = "rc", any(feature = "std", feature = "alloc")))]
|
||||
impl<'de, T> Deserialize<'de> for Arc<T>
|
||||
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(not(feature = "unstable"), feature = "rc", any(feature = "std", feature = "alloc")))]
|
||||
forwarded_impl!((T), Arc<T>, Arc::new);
|
||||
|
||||
#[cfg(all(feature = "rc", any(feature = "std", feature = "alloc")))]
|
||||
impl<'de, T> Deserialize<'de> for Rc<T>
|
||||
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(all(not(feature = "unstable"), feature = "rc", any(feature = "std", feature = "alloc")))]
|
||||
forwarded_impl!((T), Rc<T>, 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>
|
||||
where
|
||||
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>
|
||||
where
|
||||
T: Deserialize<'de> + Copy,
|
||||
@@ -1188,43 +1172,13 @@ where
|
||||
}
|
||||
}
|
||||
|
||||
impl<'de, T> Deserialize<'de> for RefCell<T>
|
||||
where
|
||||
T: Deserialize<'de>,
|
||||
{
|
||||
fn deserialize<D>(deserializer: D) -> Result<RefCell<T>, D::Error>
|
||||
where
|
||||
D: Deserializer<'de>,
|
||||
{
|
||||
T::deserialize(deserializer).map(RefCell::new)
|
||||
}
|
||||
}
|
||||
forwarded_impl!((T), RefCell<T>, RefCell::new);
|
||||
|
||||
#[cfg(feature = "std")]
|
||||
impl<'de, T> Deserialize<'de> for Mutex<T>
|
||||
where
|
||||
T: Deserialize<'de>,
|
||||
{
|
||||
fn deserialize<D>(deserializer: D) -> Result<Mutex<T>, D::Error>
|
||||
where
|
||||
D: Deserializer<'de>,
|
||||
{
|
||||
T::deserialize(deserializer).map(Mutex::new)
|
||||
}
|
||||
}
|
||||
forwarded_impl!((T), Mutex<T>, Mutex::new);
|
||||
|
||||
#[cfg(feature = "std")]
|
||||
impl<'de, T> Deserialize<'de> for RwLock<T>
|
||||
where
|
||||
T: Deserialize<'de>,
|
||||
{
|
||||
fn deserialize<D>(deserializer: D) -> Result<RwLock<T>, D::Error>
|
||||
where
|
||||
D: Deserializer<'de>,
|
||||
{
|
||||
T::deserialize(deserializer).map(RwLock::new)
|
||||
}
|
||||
}
|
||||
forwarded_impl!((T), RwLock<T>, 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:
|
||||
//
|
||||
// #[derive(Deserialize)]
|
||||
@@ -1518,14 +1598,9 @@ where
|
||||
D: Deserializer<'de>,
|
||||
{
|
||||
let value = try!(Deserialize::deserialize(deserializer));
|
||||
unsafe {
|
||||
let ptr = &value as *const T as *const u8;
|
||||
if slice::from_raw_parts(ptr, mem::size_of::<T>()).iter().all(|&b| b == 0) {
|
||||
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))
|
||||
match NonZero::new(value) {
|
||||
Some(nonzero) => Ok(nonzero),
|
||||
None => Err(Error::custom("expected a non-zero value")),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
+4
-3
@@ -94,6 +94,7 @@
|
||||
//! - OsString
|
||||
//! - **Miscellaneous standard library types**:
|
||||
//! - Duration
|
||||
//! - SystemTime
|
||||
//! - Path
|
||||
//! - PathBuf
|
||||
//! - Range\<T\>
|
||||
@@ -1262,7 +1263,7 @@ pub trait Visitor<'de>: Sized {
|
||||
/// The default implementation forwards to `visit_str` and then drops the
|
||||
/// `String`.
|
||||
#[inline]
|
||||
#[cfg(any(feature = "std", feature = "collections"))]
|
||||
#[cfg(any(feature = "std", feature = "alloc"))]
|
||||
fn visit_string<E>(self, v: String) -> Result<Self::Value, E>
|
||||
where
|
||||
E: Error,
|
||||
@@ -1321,7 +1322,7 @@ pub trait Visitor<'de>: Sized {
|
||||
///
|
||||
/// The default implementation forwards to `visit_bytes` and then drops the
|
||||
/// `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>
|
||||
where
|
||||
E: Error,
|
||||
@@ -1423,7 +1424,7 @@ pub trait SeqAccess<'de> {
|
||||
/// `Ok(None)` if there are no more remaining items.
|
||||
///
|
||||
/// `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>
|
||||
where
|
||||
T: DeserializeSeed<'de>;
|
||||
|
||||
+17
-17
@@ -51,13 +51,13 @@ pub struct Error {
|
||||
err: ErrorImpl,
|
||||
}
|
||||
|
||||
#[cfg(any(feature = "std", feature = "collections"))]
|
||||
#[cfg(any(feature = "std", feature = "alloc"))]
|
||||
type ErrorImpl = Box<str>;
|
||||
#[cfg(not(any(feature = "std", feature = "collections")))]
|
||||
#[cfg(not(any(feature = "std", feature = "alloc")))]
|
||||
type ErrorImpl = ();
|
||||
|
||||
impl de::Error for Error {
|
||||
#[cfg(any(feature = "std", feature = "collections"))]
|
||||
#[cfg(any(feature = "std", feature = "alloc"))]
|
||||
fn custom<T>(msg: T) -> Self
|
||||
where
|
||||
T: Display,
|
||||
@@ -65,7 +65,7 @@ impl de::Error for Error {
|
||||
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
|
||||
where
|
||||
T: Display,
|
||||
@@ -85,12 +85,12 @@ impl ser::Error 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> {
|
||||
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> {
|
||||
formatter.write_str("Serde deserialization error")
|
||||
}
|
||||
@@ -425,14 +425,14 @@ where
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
/// A deserializer holding a `String`.
|
||||
#[cfg(any(feature = "std", feature = "collections"))]
|
||||
#[cfg(any(feature = "std", feature = "alloc"))]
|
||||
#[derive(Clone, Debug)]
|
||||
pub struct StringDeserializer<E> {
|
||||
value: String,
|
||||
marker: PhantomData<E>,
|
||||
}
|
||||
|
||||
#[cfg(any(feature = "std", feature = "collections"))]
|
||||
#[cfg(any(feature = "std", feature = "alloc"))]
|
||||
impl<'de, E> IntoDeserializer<'de, E> for String
|
||||
where
|
||||
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>
|
||||
where
|
||||
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>
|
||||
where
|
||||
E: de::Error,
|
||||
@@ -501,14 +501,14 @@ where
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
/// A deserializer holding a `Cow<str>`.
|
||||
#[cfg(any(feature = "std", feature = "collections"))]
|
||||
#[cfg(any(feature = "std", feature = "alloc"))]
|
||||
#[derive(Clone, Debug)]
|
||||
pub struct CowStrDeserializer<'a, E> {
|
||||
value: Cow<'a, str>,
|
||||
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>
|
||||
where
|
||||
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>
|
||||
where
|
||||
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>
|
||||
where
|
||||
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>
|
||||
where
|
||||
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>
|
||||
where
|
||||
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>
|
||||
where
|
||||
K: IntoDeserializer<'de, E> + Eq + Ord,
|
||||
|
||||
+2
-2
@@ -19,7 +19,7 @@ pub use self::string::from_utf8_lossy;
|
||||
mod string {
|
||||
use lib::*;
|
||||
|
||||
#[cfg(any(feature = "std", feature = "collections"))]
|
||||
#[cfg(any(feature = "std", feature = "alloc"))]
|
||||
pub fn from_utf8_lossy(bytes: &[u8]) -> Cow<str> {
|
||||
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
|
||||
// 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 {
|
||||
// Three unicode replacement characters if it fails. They look like a
|
||||
// white-on-black question mark. The user will recognize it as invalid
|
||||
|
||||
+45
-23
@@ -79,7 +79,7 @@
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
// Serde types in rustdoc of other crates get linked to here.
|
||||
#![doc(html_root_url = "https://docs.rs/serde/1.0.8")]
|
||||
#![doc(html_root_url = "https://docs.rs/serde/1.0.12")]
|
||||
|
||||
// Support using Serde without the standard library!
|
||||
#![cfg_attr(not(feature = "std"), no_std)]
|
||||
@@ -89,33 +89,55 @@
|
||||
//
|
||||
// https://github.com/serde-rs/serde/issues/812
|
||||
#![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 = "collections", feature(collections))]
|
||||
|
||||
// Whitelisted clippy lints.
|
||||
#![cfg_attr(feature = "cargo-clippy", allow(doc_markdown))]
|
||||
#![cfg_attr(feature = "cargo-clippy", allow(linkedlist))]
|
||||
#![cfg_attr(feature = "cargo-clippy", allow(type_complexity))]
|
||||
#![cfg_attr(feature = "cargo-clippy", allow(zero_prefixed_literal))]
|
||||
#![cfg_attr(feature = "cargo-clippy", deny(clippy, clippy_pedantic))]
|
||||
// Whitelisted clippy lints
|
||||
#![cfg_attr(feature = "cargo-clippy", allow(
|
||||
cast_lossless,
|
||||
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.
|
||||
#![deny(missing_docs, unused_imports)]
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
#[cfg(feature = "collections")]
|
||||
extern crate collections;
|
||||
|
||||
#[cfg(feature = "alloc")]
|
||||
extern crate alloc;
|
||||
|
||||
#[cfg(all(feature = "unstable", feature = "std"))]
|
||||
extern crate core;
|
||||
|
||||
/// A facade around all the types we need from the `std`, `core`, `alloc`, and
|
||||
/// `collections` crates. This avoids elaborate import wrangling having to
|
||||
/// happen in every module.
|
||||
/// A facade around all the types we need from the `std`, `core`, and `alloc`
|
||||
/// crates. This avoids elaborate import wrangling having to happen in every
|
||||
/// module.
|
||||
mod lib {
|
||||
mod core {
|
||||
#[cfg(feature = "std")]
|
||||
@@ -140,18 +162,18 @@ mod lib {
|
||||
|
||||
#[cfg(feature = "std")]
|
||||
pub use std::borrow::{Cow, ToOwned};
|
||||
#[cfg(all(feature = "collections", not(feature = "std")))]
|
||||
pub use collections::borrow::{Cow, ToOwned};
|
||||
#[cfg(all(feature = "alloc", not(feature = "std")))]
|
||||
pub use alloc::borrow::{Cow, ToOwned};
|
||||
|
||||
#[cfg(feature = "std")]
|
||||
pub use std::string::String;
|
||||
#[cfg(all(feature = "collections", not(feature = "std")))]
|
||||
pub use collections::string::{String, ToString};
|
||||
#[cfg(all(feature = "alloc", not(feature = "std")))]
|
||||
pub use alloc::string::{String, ToString};
|
||||
|
||||
#[cfg(feature = "std")]
|
||||
pub use std::vec::Vec;
|
||||
#[cfg(all(feature = "collections", not(feature = "std")))]
|
||||
pub use collections::vec::Vec;
|
||||
#[cfg(all(feature = "alloc", not(feature = "std")))]
|
||||
pub use alloc::vec::Vec;
|
||||
|
||||
#[cfg(feature = "std")]
|
||||
pub use std::boxed::Box;
|
||||
@@ -170,8 +192,8 @@ mod lib {
|
||||
|
||||
#[cfg(feature = "std")]
|
||||
pub use std::collections::{BinaryHeap, BTreeMap, BTreeSet, LinkedList, VecDeque};
|
||||
#[cfg(all(feature = "collections", not(feature = "std")))]
|
||||
pub use collections::{BinaryHeap, BTreeMap, BTreeSet, LinkedList, VecDeque};
|
||||
#[cfg(all(feature = "alloc", not(feature = "std")))]
|
||||
pub use alloc::{BinaryHeap, BTreeMap, BTreeSet, LinkedList, VecDeque};
|
||||
|
||||
#[cfg(feature = "std")]
|
||||
pub use std::{error, net};
|
||||
@@ -187,7 +209,7 @@ mod lib {
|
||||
#[cfg(feature = "std")]
|
||||
pub use std::path::{Path, PathBuf};
|
||||
#[cfg(feature = "std")]
|
||||
pub use std::time::Duration;
|
||||
pub use std::time::{Duration, SystemTime, UNIX_EPOCH};
|
||||
#[cfg(feature = "std")]
|
||||
pub use std::sync::{Mutex, RwLock};
|
||||
|
||||
|
||||
@@ -10,10 +10,10 @@ use lib::*;
|
||||
|
||||
use de::{Deserialize, Deserializer, IntoDeserializer, Error, Visitor};
|
||||
|
||||
#[cfg(any(feature = "std", feature = "collections"))]
|
||||
#[cfg(any(feature = "std", feature = "alloc"))]
|
||||
use de::Unexpected;
|
||||
|
||||
#[cfg(any(feature = "std", feature = "collections"))]
|
||||
#[cfg(any(feature = "std", feature = "alloc"))]
|
||||
pub use self::content::{Content, ContentRefDeserializer, ContentDeserializer,
|
||||
TaggedContentVisitor, TagOrContentField, TagOrContentFieldVisitor,
|
||||
TagContentOtherField, TagContentOtherFieldVisitor,
|
||||
@@ -59,7 +59,7 @@ where
|
||||
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>
|
||||
where
|
||||
D: Deserializer<'de>,
|
||||
@@ -128,7 +128,7 @@ where
|
||||
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>
|
||||
where
|
||||
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 {
|
||||
// This module is private and nothing here should be used outside of
|
||||
// generated code.
|
||||
|
||||
+13
-13
@@ -10,7 +10,7 @@ use lib::*;
|
||||
|
||||
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};
|
||||
|
||||
/// Used to check that serde(getter) attributes return the expected type.
|
||||
@@ -64,7 +64,7 @@ enum Unsupported {
|
||||
Sequence,
|
||||
Tuple,
|
||||
TupleStruct,
|
||||
#[cfg(not(any(feature = "std", feature = "collections")))]
|
||||
#[cfg(not(any(feature = "std", feature = "alloc")))]
|
||||
Enum,
|
||||
}
|
||||
|
||||
@@ -83,7 +83,7 @@ impl Display for Unsupported {
|
||||
Unsupported::Sequence => formatter.write_str("a sequence"),
|
||||
Unsupported::Tuple => formatter.write_str("a tuple"),
|
||||
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"),
|
||||
}
|
||||
}
|
||||
@@ -117,14 +117,14 @@ where
|
||||
type SerializeMap = S::SerializeMap;
|
||||
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>;
|
||||
#[cfg(any(feature = "std", feature = "collections"))]
|
||||
#[cfg(any(feature = "std", feature = "alloc"))]
|
||||
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>;
|
||||
#[cfg(any(feature = "std", feature = "collections"))]
|
||||
#[cfg(any(feature = "std", feature = "alloc"))]
|
||||
type SerializeStructVariant = SerializeStructVariantAsMapValue<S::SerializeMap>;
|
||||
|
||||
fn serialize_bool(self, _: bool) -> Result<Self::Ok, Self::Error> {
|
||||
@@ -257,7 +257,7 @@ where
|
||||
Err(self.bad_type(Unsupported::TupleStruct))
|
||||
}
|
||||
|
||||
#[cfg(not(any(feature = "std", feature = "collections")))]
|
||||
#[cfg(not(any(feature = "std", feature = "alloc")))]
|
||||
fn serialize_tuple_variant(
|
||||
self,
|
||||
_: &'static str,
|
||||
@@ -270,7 +270,7 @@ where
|
||||
Err(self.bad_type(Unsupported::Enum))
|
||||
}
|
||||
|
||||
#[cfg(any(feature = "std", feature = "collections"))]
|
||||
#[cfg(any(feature = "std", feature = "alloc"))]
|
||||
fn serialize_tuple_variant(
|
||||
self,
|
||||
_: &'static str,
|
||||
@@ -300,7 +300,7 @@ where
|
||||
Ok(state)
|
||||
}
|
||||
|
||||
#[cfg(not(any(feature = "std", feature = "collections")))]
|
||||
#[cfg(not(any(feature = "std", feature = "alloc")))]
|
||||
fn serialize_struct_variant(
|
||||
self,
|
||||
_: &'static str,
|
||||
@@ -313,7 +313,7 @@ where
|
||||
Err(self.bad_type(Unsupported::Enum))
|
||||
}
|
||||
|
||||
#[cfg(any(feature = "std", feature = "collections"))]
|
||||
#[cfg(any(feature = "std", feature = "alloc"))]
|
||||
fn serialize_struct_variant(
|
||||
self,
|
||||
_: &'static str,
|
||||
@@ -327,7 +327,7 @@ where
|
||||
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>
|
||||
where
|
||||
T: Display,
|
||||
@@ -363,7 +363,7 @@ impl Display for Error {
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(any(feature = "std", feature = "collections"))]
|
||||
#[cfg(any(feature = "std", feature = "alloc"))]
|
||||
mod content {
|
||||
use lib::*;
|
||||
|
||||
|
||||
+29
-10
@@ -56,7 +56,7 @@ impl Serialize for str {
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(any(feature = "std", feature = "collections"))]
|
||||
#[cfg(any(feature = "std", feature = "alloc"))]
|
||||
impl Serialize for String {
|
||||
#[inline]
|
||||
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 {
|
||||
($ty:ident < T $(: $tbound1:ident $(+ $tbound2:ident)*)* $(, $typaram:ident : $bound:ident)* >) => {
|
||||
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>);
|
||||
|
||||
#[cfg(any(feature = "std", feature = "collections"))]
|
||||
#[cfg(any(feature = "std", feature = "alloc"))]
|
||||
seq_impl!(BTreeSet<T: Ord>);
|
||||
|
||||
#[cfg(feature = "std")]
|
||||
seq_impl!(HashSet<T: Eq + Hash, H: BuildHasher>);
|
||||
|
||||
#[cfg(any(feature = "std", feature = "collections"))]
|
||||
#[cfg(any(feature = "std", feature = "alloc"))]
|
||||
seq_impl!(LinkedList<T>);
|
||||
|
||||
#[cfg(any(feature = "std", feature = "collections"))]
|
||||
#[cfg(any(feature = "std", feature = "alloc"))]
|
||||
seq_impl!(Vec<T>);
|
||||
|
||||
#[cfg(any(feature = "std", feature = "collections"))]
|
||||
#[cfg(any(feature = "std", feature = "alloc"))]
|
||||
seq_impl!(VecDeque<T>);
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
@@ -290,6 +291,7 @@ tuple_impls! {
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
#[cfg(any(feature = "std", feature = "alloc"))]
|
||||
macro_rules! map_impl {
|
||||
($ty:ident < K $(: $kbound1:ident $(+ $kbound2:ident)*)*, V $(, $typaram:ident : $bound:ident)* >) => {
|
||||
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>);
|
||||
|
||||
#[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);
|
||||
|
||||
#[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")))]
|
||||
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);
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
@@ -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
|
||||
/// statically known to never have more than a constant `MAX_LEN` bytes.
|
||||
///
|
||||
|
||||
@@ -89,6 +89,7 @@
|
||||
//! - OsString
|
||||
//! - **Miscellaneous standard library types**:
|
||||
//! - Duration
|
||||
//! - SystemTime
|
||||
//! - Path
|
||||
//! - PathBuf
|
||||
//! - Range\<T\>
|
||||
@@ -1321,7 +1322,7 @@ pub trait Serializer: Sized {
|
||||
///
|
||||
/// [`String`]: https://doc.rust-lang.org/std/string/struct.String.html
|
||||
/// [`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>
|
||||
where
|
||||
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>
|
||||
where
|
||||
T: Display;
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
[package]
|
||||
name = "serde_derive"
|
||||
version = "1.0.8" # 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>"]
|
||||
license = "MIT/Apache-2.0"
|
||||
description = "Macros 1.1 implementation of #[derive(Serialize, Deserialize)]"
|
||||
|
||||
+12
-14
@@ -23,15 +23,15 @@ pub fn expand_derive_deserialize(input: &syn::DeriveInput) -> Result<Tokens, Str
|
||||
|
||||
let ident = &cont.ident;
|
||||
let params = Parameters::new(&cont);
|
||||
let (de_impl_generics, _, ty_generics, where_clause) = split_with_de_lifetime(¶ms);
|
||||
let dummy_const = Ident::new(format!("_IMPL_DESERIALIZE_FOR_{}", ident));
|
||||
let body = Stmts(deserialize_body(&cont, ¶ms));
|
||||
|
||||
let impl_block = if let Some(remote) = cont.attrs.remote() {
|
||||
let (impl_generics, ty_generics, where_clause) = cont.generics.split_for_impl();
|
||||
let de_lifetime = params.de_lifetime_def();
|
||||
let vis = &input.vis;
|
||||
quote! {
|
||||
impl #impl_generics #ident #ty_generics #where_clause {
|
||||
fn deserialize<#de_lifetime, __D>(__deserializer: __D) -> _serde::export::Result<#remote #ty_generics, __D::Error>
|
||||
impl #de_impl_generics #ident #ty_generics #where_clause {
|
||||
#vis fn deserialize<__D>(__deserializer: __D) -> _serde::export::Result<#remote #ty_generics, __D::Error>
|
||||
where __D: _serde::Deserializer<'de>
|
||||
{
|
||||
#body
|
||||
@@ -39,7 +39,6 @@ pub fn expand_derive_deserialize(input: &syn::DeriveInput) -> Result<Tokens, Str
|
||||
}
|
||||
}
|
||||
} else {
|
||||
let (de_impl_generics, _, ty_generics, where_clause) = split_with_de_lifetime(¶ms);
|
||||
quote! {
|
||||
#[automatically_derived]
|
||||
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 deny_unknown_fields = cattrs.deny_unknown_fields();
|
||||
|
||||
/// If unknown fields are allowed, we pick the visitor that can
|
||||
/// step over those. Otherwise we pick the visitor that fails on
|
||||
/// unknown keys.
|
||||
// If unknown fields are allowed, we pick the visitor that can step over
|
||||
// those. Otherwise we pick the visitor that fails on unknown keys.
|
||||
let field_visitor_ty = if deny_unknown_fields {
|
||||
quote! { _serde::private::de::TagOrContentFieldVisitor }
|
||||
} 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! {
|
||||
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
|
||||
/// about until we find `tag`, `content`, or run out of keys.
|
||||
// When allowing unknown fields, we want to transparently step through keys
|
||||
// we don't care about until we find `tag`, `content`, or run out of keys.
|
||||
let next_relevant_key = if deny_unknown_fields {
|
||||
next_key
|
||||
} else {
|
||||
@@ -889,9 +887,9 @@ fn deserialize_adjacently_tagged_enum(
|
||||
}
|
||||
};
|
||||
|
||||
/// Step through remaining keys, looking for duplicates of previously-seen keys.
|
||||
/// When unknown fields are denied, any key that isn't a duplicate will at this
|
||||
/// point immediately produce an error.
|
||||
// Step through remaining keys, looking for duplicates of previously-seen
|
||||
// keys. When unknown fields are denied, any key that isn't a duplicate will
|
||||
// at this point immediately produce an error.
|
||||
let visit_remaining_keys = quote! {
|
||||
match #next_relevant_key {
|
||||
_serde::export::Some(_serde::private::de::TagOrContentField::Tag) => {
|
||||
|
||||
@@ -16,7 +16,7 @@
|
||||
//!
|
||||
//! [https://serde.rs/derive.html]: https://serde.rs/derive.html
|
||||
|
||||
#![doc(html_root_url = "https://docs.rs/serde_derive/1.0.8")]
|
||||
#![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(used_underscore_binding))]
|
||||
|
||||
@@ -29,9 +29,10 @@ pub fn expand_derive_serialize(input: &syn::DeriveInput) -> Result<Tokens, Strin
|
||||
let body = Stmts(serialize_body(&cont, ¶ms));
|
||||
|
||||
let impl_block = if let Some(remote) = cont.attrs.remote() {
|
||||
let vis = &input.vis;
|
||||
quote! {
|
||||
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
|
||||
{
|
||||
#body
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
[package]
|
||||
name = "serde_test"
|
||||
version = "1.0.8" # 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>"]
|
||||
license = "MIT/Apache-2.0"
|
||||
description = "Token De/Serializer for testing De/Serialize implementations"
|
||||
|
||||
@@ -155,7 +155,7 @@
|
||||
//! # }
|
||||
//! ```
|
||||
|
||||
#![doc(html_root_url = "https://docs.rs/serde_test/1.0.8")]
|
||||
#![doc(html_root_url = "https://docs.rs/serde_test/1.0.12")]
|
||||
|
||||
#[macro_use]
|
||||
extern crate serde;
|
||||
|
||||
@@ -10,7 +10,7 @@ unstable = ["serde/unstable", "compiletest_rs"]
|
||||
[dev-dependencies]
|
||||
fnv = "1.0"
|
||||
rustc-serialize = "0.3.16"
|
||||
serde = { path = "../serde" }
|
||||
serde = { path = "../serde", features = ["rc"] }
|
||||
serde_derive = { path = "../serde_derive" }
|
||||
serde_test = { path = "../serde_test" }
|
||||
|
||||
|
||||
@@ -4,5 +4,8 @@ version = "0.0.0"
|
||||
publish = false
|
||||
|
||||
[dependencies]
|
||||
libc = { version = "0.2", default-features = false }
|
||||
serde = { path = "../../serde", default-features = false }
|
||||
serde_derive = { path = "../../serde_derive" }
|
||||
|
||||
[workspace]
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
#![feature(lang_items, start, libc, compiler_builtins_lib)]
|
||||
#![feature(lang_items, start, compiler_builtins_lib)]
|
||||
#![no_std]
|
||||
|
||||
extern crate libc;
|
||||
|
||||
@@ -18,7 +18,9 @@ mod remote {
|
||||
#[derive(Serialize, Deserialize)]
|
||||
#[serde(remote = "remote::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() {}
|
||||
|
||||
@@ -13,7 +13,7 @@ extern crate compiletest_rs as compiletest;
|
||||
use std::env;
|
||||
|
||||
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.target_rustcflags = Some("-L deps/target/debug/deps".to_owned());
|
||||
|
||||
@@ -6,17 +6,17 @@
|
||||
// option. This file may not be copied, modified, or distributed
|
||||
// except according to those terms.
|
||||
|
||||
#![cfg_attr(feature = "unstable", feature(into_boxed_c_str))]
|
||||
|
||||
#[macro_use]
|
||||
extern crate serde_derive;
|
||||
|
||||
use std::collections::{BTreeMap, BTreeSet, HashMap, HashSet};
|
||||
use std::net;
|
||||
use std::path::{Path, PathBuf};
|
||||
use std::time::Duration;
|
||||
use std::time::{Duration, UNIX_EPOCH};
|
||||
use std::default::Default;
|
||||
use std::ffi::{CString, OsString};
|
||||
use std::rc::Rc;
|
||||
use std::sync::Arc;
|
||||
|
||||
#[cfg(feature = "unstable")]
|
||||
use std::ffi::CStr;
|
||||
@@ -682,6 +682,23 @@ declare_tests! {
|
||||
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 {
|
||||
1u32..2u32 => &[
|
||||
Token::Struct { name: "Range", len: 2 },
|
||||
@@ -725,6 +742,40 @@ declare_tests! {
|
||||
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)]
|
||||
|
||||
@@ -330,6 +330,49 @@ fn test_gen() {
|
||||
struct EmptyArray {
|
||||
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,
|
||||
}
|
||||
}
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
|
||||
@@ -9,11 +9,13 @@
|
||||
#[macro_use]
|
||||
extern crate serde_derive;
|
||||
|
||||
use std::collections::{BTreeMap, HashMap, HashSet};
|
||||
use std::collections::{BTreeMap, BTreeSet, HashMap, HashSet};
|
||||
use std::net;
|
||||
use std::path::{Path, PathBuf};
|
||||
use std::time::Duration;
|
||||
use std::time::{Duration, UNIX_EPOCH};
|
||||
use std::ffi::CString;
|
||||
use std::rc::Rc;
|
||||
use std::sync::Arc;
|
||||
|
||||
#[cfg(unix)]
|
||||
use std::str;
|
||||
@@ -170,6 +172,17 @@ declare_tests! {
|
||||
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 {
|
||||
HashSet::<isize>::new() => &[
|
||||
Token::Seq { len: Some(0) },
|
||||
@@ -319,6 +332,17 @@ declare_tests! {
|
||||
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 {
|
||||
1u32..2u32 => &[
|
||||
Token::Struct { name: "Range", len: 2 },
|
||||
@@ -361,6 +385,41 @@ declare_tests! {
|
||||
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")]
|
||||
|
||||
@@ -41,21 +41,24 @@ if [ -n "${CLIPPY}" ]; then
|
||||
cargo clippy -- -Dclippy
|
||||
else
|
||||
CHANNEL=nightly
|
||||
cd "$DIR"
|
||||
cargo clean
|
||||
cd "$DIR/serde"
|
||||
channel build
|
||||
channel build --no-default-features
|
||||
channel build --no-default-features --features alloc
|
||||
channel build --no-default-features --features collections
|
||||
channel test --features 'rc unstable'
|
||||
cd "$DIR/test_suite/deps"
|
||||
channel build
|
||||
cd "$DIR/test_suite"
|
||||
channel test --features unstable
|
||||
cd "$DIR/test_suite/no_std"
|
||||
channel build
|
||||
if [ -z "${APPVEYOR}" ]; then
|
||||
cd "$DIR/test_suite/no_std"
|
||||
channel build
|
||||
fi
|
||||
|
||||
CHANNEL=beta
|
||||
cd "$DIR"
|
||||
cargo clean
|
||||
cd "$DIR/serde"
|
||||
channel build --features rc
|
||||
@@ -63,6 +66,7 @@ else
|
||||
channel test
|
||||
|
||||
CHANNEL=stable
|
||||
cd "$DIR"
|
||||
cargo clean
|
||||
cd "$DIR/serde"
|
||||
channel build --features rc
|
||||
@@ -72,6 +76,7 @@ else
|
||||
channel test
|
||||
|
||||
CHANNEL=1.13.0
|
||||
cd "$DIR"
|
||||
cargo clean
|
||||
cd "$DIR/serde"
|
||||
channel build --features rc
|
||||
|
||||
Reference in New Issue
Block a user