mirror of
https://github.com/pezkuwichain/serde.git
synced 2026-04-22 21:48:02 +00:00
Compare commits
34 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| 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 | |||
| fd3d1396d3 | |||
| c47b4c8e0b | |||
| 2d793b82f6 | |||
| 237be46e29 |
@@ -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.6" # remember to update html_root_url
|
||||
version = "1.0.11" # 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.
|
||||
|
||||
+166
-116
@@ -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)
|
||||
}
|
||||
}
|
||||
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)
|
||||
}
|
||||
}
|
||||
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,
|
||||
@@ -1188,43 +1147,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 +1293,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 +1573,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")),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
+3
-2
@@ -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,
|
||||
|
||||
+126
-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")
|
||||
}
|
||||
@@ -355,15 +355,84 @@ where
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
/// A deserializer holding a `&str` with a lifetime tied to another
|
||||
/// deserializer.
|
||||
#[derive(Clone, Debug)]
|
||||
pub struct BorrowedStrDeserializer<'de, E> {
|
||||
value: &'de str,
|
||||
marker: PhantomData<E>,
|
||||
}
|
||||
|
||||
impl<'de, E> BorrowedStrDeserializer<'de, E> {
|
||||
/// Create a new borrowed deserializer from the given string.
|
||||
pub fn new(value: &'de str) -> BorrowedStrDeserializer<'de, E> {
|
||||
BorrowedStrDeserializer {
|
||||
value: value,
|
||||
marker: PhantomData,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl<'de, E> de::Deserializer<'de> for BorrowedStrDeserializer<'de, E>
|
||||
where
|
||||
E: de::Error,
|
||||
{
|
||||
type Error = E;
|
||||
|
||||
fn deserialize_any<V>(self, visitor: V) -> Result<V::Value, Self::Error>
|
||||
where
|
||||
V: de::Visitor<'de>,
|
||||
{
|
||||
visitor.visit_borrowed_str(self.value)
|
||||
}
|
||||
|
||||
fn deserialize_enum<V>(
|
||||
self,
|
||||
name: &str,
|
||||
variants: &'static [&'static str],
|
||||
visitor: V,
|
||||
) -> Result<V::Value, Self::Error>
|
||||
where
|
||||
V: de::Visitor<'de>,
|
||||
{
|
||||
let _ = name;
|
||||
let _ = variants;
|
||||
visitor.visit_enum(self)
|
||||
}
|
||||
|
||||
forward_to_deserialize_any! {
|
||||
bool i8 i16 i32 i64 u8 u16 u32 u64 f32 f64 char str string bytes
|
||||
byte_buf option unit unit_struct newtype_struct seq tuple tuple_struct
|
||||
map struct identifier ignored_any
|
||||
}
|
||||
}
|
||||
|
||||
impl<'de, E> de::EnumAccess<'de> for BorrowedStrDeserializer<'de, E>
|
||||
where
|
||||
E: de::Error,
|
||||
{
|
||||
type Error = E;
|
||||
type Variant = private::UnitOnly<E>;
|
||||
|
||||
fn variant_seed<T>(self, seed: T) -> Result<(T::Value, Self::Variant), Self::Error>
|
||||
where
|
||||
T: de::DeserializeSeed<'de>,
|
||||
{
|
||||
seed.deserialize(self).map(private::unit_only)
|
||||
}
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
/// 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,
|
||||
@@ -378,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,
|
||||
@@ -413,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,
|
||||
@@ -432,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,
|
||||
@@ -454,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,
|
||||
@@ -492,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,
|
||||
@@ -510,6 +579,46 @@ where
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
/// A deserializer holding a `&[u8]` with a lifetime tied to another
|
||||
/// deserializer.
|
||||
#[derive(Clone, Debug)]
|
||||
pub struct BorrowedBytesDeserializer<'de, E> {
|
||||
value: &'de [u8],
|
||||
marker: PhantomData<E>,
|
||||
}
|
||||
|
||||
impl<'de, E> BorrowedBytesDeserializer<'de, E> {
|
||||
/// Create a new borrowed deserializer from the given byte slice.
|
||||
pub fn new(value: &'de [u8]) -> BorrowedBytesDeserializer<'de, E> {
|
||||
BorrowedBytesDeserializer {
|
||||
value: value,
|
||||
marker: PhantomData,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl<'de, E> de::Deserializer<'de> for BorrowedBytesDeserializer<'de, E>
|
||||
where
|
||||
E: de::Error,
|
||||
{
|
||||
type Error = E;
|
||||
|
||||
fn deserialize_any<V>(self, visitor: V) -> Result<V::Value, Self::Error>
|
||||
where
|
||||
V: de::Visitor<'de>,
|
||||
{
|
||||
visitor.visit_borrowed_bytes(self.value)
|
||||
}
|
||||
|
||||
forward_to_deserialize_any! {
|
||||
bool i8 i16 i32 i64 u8 u16 u32 u64 f32 f64 char str string bytes
|
||||
byte_buf option unit unit_struct newtype_struct seq tuple tuple_struct
|
||||
map struct identifier ignored_any enum
|
||||
}
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
/// A deserializer that iterates over a sequence.
|
||||
#[derive(Clone, Debug)]
|
||||
pub struct SeqDeserializer<I, E> {
|
||||
@@ -618,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>,
|
||||
@@ -631,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,
|
||||
@@ -1036,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
|
||||
|
||||
+13
-17
@@ -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.6")]
|
||||
#![doc(html_root_url = "https://docs.rs/serde/1.0.11")]
|
||||
|
||||
// Support using Serde without the standard library!
|
||||
#![cfg_attr(not(feature = "std"), no_std)]
|
||||
@@ -91,7 +91,6 @@
|
||||
#![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))]
|
||||
@@ -104,18 +103,15 @@
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
#[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 +136,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 +166,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 +183,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::*;
|
||||
|
||||
|
||||
+27
-8
@@ -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")]
|
||||
@@ -343,7 +345,7 @@ deref_impl!(<T> 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);
|
||||
|
||||
#[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.6" # remember to update html_root_url
|
||||
version = "1.0.11" # 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)]"
|
||||
@@ -20,5 +20,5 @@ proc-macro = true
|
||||
|
||||
[dependencies]
|
||||
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"] }
|
||||
|
||||
@@ -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 {
|
||||
|
||||
@@ -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.6")]
|
||||
#![doc(html_root_url = "https://docs.rs/serde_derive/1.0.11")]
|
||||
|
||||
#![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_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>"]
|
||||
license = "MIT/Apache-2.0"
|
||||
description = "AST representation used by Serde derive macros. Unstable."
|
||||
|
||||
@@ -6,7 +6,7 @@
|
||||
// option. This file may not be copied, modified, or distributed
|
||||
// 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;
|
||||
#[macro_use]
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
[package]
|
||||
name = "serde_test"
|
||||
version = "1.0.6" # remember to update html_root_url
|
||||
version = "1.0.11" # 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.6")]
|
||||
#![doc(html_root_url = "https://docs.rs/serde_test/1.0.11")]
|
||||
|
||||
#[macro_use]
|
||||
extern crate serde;
|
||||
|
||||
@@ -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() {}
|
||||
|
||||
@@ -14,7 +14,7 @@ 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};
|
||||
|
||||
@@ -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 },
|
||||
|
||||
@@ -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,10 +9,10 @@
|
||||
#[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;
|
||||
|
||||
#[cfg(unix)]
|
||||
@@ -170,6 +170,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 +330,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 },
|
||||
|
||||
@@ -41,12 +41,12 @@ 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
|
||||
@@ -56,6 +56,7 @@ else
|
||||
channel build
|
||||
|
||||
CHANNEL=beta
|
||||
cd "$DIR"
|
||||
cargo clean
|
||||
cd "$DIR/serde"
|
||||
channel build --features rc
|
||||
@@ -63,6 +64,7 @@ else
|
||||
channel test
|
||||
|
||||
CHANNEL=stable
|
||||
cd "$DIR"
|
||||
cargo clean
|
||||
cd "$DIR/serde"
|
||||
channel build --features rc
|
||||
@@ -72,6 +74,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