Enable use in no_std environments
These changes are fairly invasive to imports and uses of non-libcore types, but allow for some or none of the freestanding crates (core, rustc_unicode, alloc, collections) to be supported by serde.
This commit is contained in:
parent
5716e8c508
commit
9c0140968d
@ -18,6 +18,11 @@ script:
|
|||||||
- (cd serde && travis-cargo build)
|
- (cd serde && travis-cargo build)
|
||||||
- (cd serde && travis-cargo test)
|
- (cd serde && travis-cargo test)
|
||||||
- (cd serde && travis-cargo --only nightly test -- --features nightly-testing)
|
- (cd serde && travis-cargo --only nightly test -- --features nightly-testing)
|
||||||
|
- (cd serde && travis-cargo --skip 1.5.0 build -- --no-default-features)
|
||||||
|
- (cd serde && travis-cargo --only nightly build -- --no-default-features)
|
||||||
|
- (cd serde && travis-cargo --only nightly build -- --no-default-features --features alloc)
|
||||||
|
- (cd serde && travis-cargo --only nightly build -- --no-default-features --features collections)
|
||||||
|
- (cd serde && travis-cargo --only nightly build -- --no-default-features --features rustc_unicode)
|
||||||
- (cd serde_tests && travis-cargo test)
|
- (cd serde_tests && travis-cargo test)
|
||||||
- (cd serde_tests && travis-cargo --only nightly test -- --features nightly-testing)
|
- (cd serde_tests && travis-cargo --only nightly test -- --features nightly-testing)
|
||||||
- (cd serde_macros && travis-cargo --only nightly test -- --features nightly-testing)
|
- (cd serde_macros && travis-cargo --only nightly test -- --features nightly-testing)
|
||||||
|
14
README.md
14
README.md
@ -718,6 +718,20 @@ Field Annotations:
|
|||||||
| `#[serde(serialize_with="$path")]` | Call a function `fn<T, S>(&T, &mut S) -> Result<(), S::Error> where S: Serializer` to serialize this value |
|
| `#[serde(serialize_with="$path")]` | Call a function `fn<T, S>(&T, &mut S) -> Result<(), S::Error> where S: Serializer` to serialize this value |
|
||||||
| `#[serde(deserialize_with="$path")]` | Call a function `fn<T, D>(&mut D) -> Result<T, D::Error> where D: Deserializer` to deserialize this value |
|
| `#[serde(deserialize_with="$path")]` | Call a function `fn<T, D>(&mut D) -> Result<T, D::Error> where D: Deserializer` to deserialize this value |
|
||||||
|
|
||||||
|
Using in `no_std` crates
|
||||||
|
========================
|
||||||
|
|
||||||
|
The core `serde` package defines a number of features to enable usage in a
|
||||||
|
variety of freestanding environments. Enable any or none of the following
|
||||||
|
features, and use `default-features = false` in your `Cargo.toml`:
|
||||||
|
|
||||||
|
- `alloc` (implies `nightly`)
|
||||||
|
- `collections` (implies `alloc` and `nightly`)
|
||||||
|
- `std` (default)
|
||||||
|
|
||||||
|
If you only use `default-features = false`, you will receive a stock `no_std`
|
||||||
|
serde with no support for any of the collection types.
|
||||||
|
|
||||||
Upgrading from Serde 0.6
|
Upgrading from Serde 0.6
|
||||||
========================
|
========================
|
||||||
|
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
[package]
|
[package]
|
||||||
name = "serde"
|
name = "serde"
|
||||||
version = "0.7.3"
|
version = "0.7.4"
|
||||||
authors = ["Erick Tryzelaar <erick.tryzelaar@gmail.com>"]
|
authors = ["Erick Tryzelaar <erick.tryzelaar@gmail.com>"]
|
||||||
license = "MIT/Apache-2.0"
|
license = "MIT/Apache-2.0"
|
||||||
description = "A generic serialization/deserialization framework"
|
description = "A generic serialization/deserialization framework"
|
||||||
@ -10,8 +10,13 @@ readme = "../README.md"
|
|||||||
keywords = ["serde", "serialization"]
|
keywords = ["serde", "serialization"]
|
||||||
|
|
||||||
[features]
|
[features]
|
||||||
|
default = ["std"]
|
||||||
|
|
||||||
|
std = []
|
||||||
nightly = []
|
nightly = []
|
||||||
nightly-testing = ["clippy", "nightly"]
|
alloc = ["nightly"]
|
||||||
|
collections = ["alloc"]
|
||||||
|
nightly-testing = ["clippy", "nightly", "std"]
|
||||||
|
|
||||||
[dependencies]
|
[dependencies]
|
||||||
clippy = { version = "^0.*", optional = true }
|
clippy = { version = "^0.*", optional = true }
|
||||||
|
@ -1,11 +1,15 @@
|
|||||||
//! Helper module to enable serializing bytes more efficiently
|
//! Helper module to enable serializing bytes more efficiently
|
||||||
|
|
||||||
use std::ops;
|
use core::{ops, fmt, char, iter, slice};
|
||||||
use std::fmt;
|
use core::fmt::Write;
|
||||||
use std::ascii;
|
|
||||||
|
|
||||||
use ser;
|
use ser;
|
||||||
use de;
|
|
||||||
|
#[cfg(any(feature = "std", feature = "collections"))]
|
||||||
|
pub use self::bytebuf::{ByteBuf, ByteBufVisitor};
|
||||||
|
|
||||||
|
#[cfg(feature = "collections")]
|
||||||
|
use collections::Vec;
|
||||||
|
|
||||||
///////////////////////////////////////////////////////////////////////////////
|
///////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
@ -17,7 +21,11 @@ pub struct Bytes<'a> {
|
|||||||
|
|
||||||
impl<'a> fmt::Debug for Bytes<'a> {
|
impl<'a> fmt::Debug for Bytes<'a> {
|
||||||
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
|
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
|
||||||
write!(f, "b\"{}\"", escape_bytestring(self.bytes))
|
try!(f.write_str("b\""));
|
||||||
|
for c in escape_bytestring(self.bytes) {
|
||||||
|
try!(f.write_char(c));
|
||||||
|
}
|
||||||
|
f.write_char('"')
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -29,6 +37,7 @@ impl<'a> From<&'a [u8]> for Bytes<'a> {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[cfg(any(feature = "std", feature = "collections"))]
|
||||||
impl<'a> From<&'a Vec<u8>> for Bytes<'a> {
|
impl<'a> From<&'a Vec<u8>> for Bytes<'a> {
|
||||||
fn from(bytes: &'a Vec<u8>) -> Self {
|
fn from(bytes: &'a Vec<u8>) -> Self {
|
||||||
Bytes {
|
Bytes {
|
||||||
@ -60,157 +69,172 @@ impl<'a> ser::Serialize for Bytes<'a> {
|
|||||||
|
|
||||||
///////////////////////////////////////////////////////////////////////////////
|
///////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
/// `ByteBuf` wraps a `Vec<u8>` and serializes as a byte array.
|
#[cfg(any(feature = "std", feature = "collections"))]
|
||||||
#[derive(Clone, Default, Eq, Hash, PartialEq, PartialOrd, Ord)]
|
mod bytebuf {
|
||||||
pub struct ByteBuf {
|
use core::ops;
|
||||||
bytes: Vec<u8>,
|
use core::fmt;
|
||||||
}
|
use core::fmt::Write;
|
||||||
|
|
||||||
impl ByteBuf {
|
use ser;
|
||||||
/// Construct a new, empty `ByteBuf`.
|
use de;
|
||||||
pub fn new() -> Self {
|
|
||||||
ByteBuf {
|
#[cfg(feature = "collections")]
|
||||||
bytes: Vec::new(),
|
use collections::Vec;
|
||||||
|
|
||||||
|
/// `ByteBuf` wraps a `Vec<u8>` and serializes as a byte array.
|
||||||
|
#[derive(Clone, Default, Eq, Hash, PartialEq, PartialOrd, Ord)]
|
||||||
|
pub struct ByteBuf {
|
||||||
|
bytes: Vec<u8>,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl ByteBuf {
|
||||||
|
/// Construct a new, empty `ByteBuf`.
|
||||||
|
pub fn new() -> Self {
|
||||||
|
ByteBuf {
|
||||||
|
bytes: Vec::new(),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Construct a new, empty `ByteBuf` with the specified capacity.
|
||||||
|
pub fn with_capacity(cap: usize) -> Self {
|
||||||
|
ByteBuf {
|
||||||
|
bytes: Vec::with_capacity(cap)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Construct a new, empty `ByteBuf` with the specified capacity.
|
impl fmt::Debug for ByteBuf {
|
||||||
pub fn with_capacity(cap: usize) -> Self {
|
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
|
||||||
ByteBuf {
|
try!(f.write_str("b\""));
|
||||||
bytes: Vec::with_capacity(cap)
|
for c in super::escape_bytestring(self.bytes.as_ref()) {
|
||||||
|
try!(f.write_char(c));
|
||||||
|
}
|
||||||
|
f.write_char('"')
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
impl fmt::Debug for ByteBuf {
|
impl Into<Vec<u8>> for ByteBuf {
|
||||||
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
|
fn into(self) -> Vec<u8> {
|
||||||
write!(f, "b\"{}\"", escape_bytestring(self.bytes.as_ref()))
|
self.bytes
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl Into<Vec<u8>> for ByteBuf {
|
|
||||||
fn into(self) -> Vec<u8> {
|
|
||||||
self.bytes
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl From<Vec<u8>> for ByteBuf {
|
|
||||||
fn from(bytes: Vec<u8>) -> Self {
|
|
||||||
ByteBuf {
|
|
||||||
bytes: bytes,
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
impl AsRef<Vec<u8>> for ByteBuf {
|
impl From<Vec<u8>> for ByteBuf {
|
||||||
fn as_ref(&self) -> &Vec<u8> {
|
fn from(bytes: Vec<u8>) -> Self {
|
||||||
&self.bytes
|
ByteBuf {
|
||||||
}
|
bytes: bytes,
|
||||||
}
|
}
|
||||||
|
}
|
||||||
impl AsRef<[u8]> for ByteBuf {
|
|
||||||
fn as_ref(&self) -> &[u8] {
|
|
||||||
&self.bytes
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl AsMut<Vec<u8>> for ByteBuf {
|
|
||||||
fn as_mut(&mut self) -> &mut Vec<u8> {
|
|
||||||
&mut self.bytes
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl AsMut<[u8]> for ByteBuf {
|
|
||||||
fn as_mut(&mut self) -> &mut [u8] {
|
|
||||||
&mut self.bytes
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl ops::Deref for ByteBuf {
|
|
||||||
type Target = [u8];
|
|
||||||
|
|
||||||
fn deref(&self) -> &[u8] { &self.bytes[..] }
|
|
||||||
}
|
|
||||||
|
|
||||||
impl ops::DerefMut for ByteBuf {
|
|
||||||
fn deref_mut(&mut self) -> &mut [u8] { &mut self.bytes[..] }
|
|
||||||
}
|
|
||||||
|
|
||||||
impl ser::Serialize for ByteBuf {
|
|
||||||
fn serialize<S>(&self, serializer: &mut S) -> Result<(), S::Error>
|
|
||||||
where S: ser::Serializer
|
|
||||||
{
|
|
||||||
serializer.serialize_bytes(&self)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/// This type implements the `serde::de::Visitor` trait for a `ByteBuf`.
|
|
||||||
pub struct ByteBufVisitor;
|
|
||||||
|
|
||||||
impl de::Visitor for ByteBufVisitor {
|
|
||||||
type Value = ByteBuf;
|
|
||||||
|
|
||||||
#[inline]
|
|
||||||
fn visit_unit<E>(&mut self) -> Result<ByteBuf, E>
|
|
||||||
where E: de::Error,
|
|
||||||
{
|
|
||||||
Ok(ByteBuf {
|
|
||||||
bytes: Vec::new(),
|
|
||||||
})
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#[inline]
|
impl AsRef<Vec<u8>> for ByteBuf {
|
||||||
fn visit_seq<V>(&mut self, mut visitor: V) -> Result<ByteBuf, V::Error>
|
fn as_ref(&self) -> &Vec<u8> {
|
||||||
where V: de::SeqVisitor,
|
&self.bytes
|
||||||
{
|
}
|
||||||
let (len, _) = visitor.size_hint();
|
}
|
||||||
let mut values = Vec::with_capacity(len);
|
|
||||||
|
|
||||||
while let Some(value) = try!(visitor.visit()) {
|
impl AsRef<[u8]> for ByteBuf {
|
||||||
values.push(value);
|
fn as_ref(&self) -> &[u8] {
|
||||||
|
&self.bytes
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl AsMut<Vec<u8>> for ByteBuf {
|
||||||
|
fn as_mut(&mut self) -> &mut Vec<u8> {
|
||||||
|
&mut self.bytes
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl AsMut<[u8]> for ByteBuf {
|
||||||
|
fn as_mut(&mut self) -> &mut [u8] {
|
||||||
|
&mut self.bytes
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl ops::Deref for ByteBuf {
|
||||||
|
type Target = [u8];
|
||||||
|
|
||||||
|
fn deref(&self) -> &[u8] { &self.bytes[..] }
|
||||||
|
}
|
||||||
|
|
||||||
|
impl ops::DerefMut for ByteBuf {
|
||||||
|
fn deref_mut(&mut self) -> &mut [u8] { &mut self.bytes[..] }
|
||||||
|
}
|
||||||
|
|
||||||
|
impl ser::Serialize for ByteBuf {
|
||||||
|
fn serialize<S>(&self, serializer: &mut S) -> Result<(), S::Error>
|
||||||
|
where S: ser::Serializer
|
||||||
|
{
|
||||||
|
serializer.serialize_bytes(&self)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// This type implements the `serde::de::Visitor` trait for a `ByteBuf`.
|
||||||
|
pub struct ByteBufVisitor;
|
||||||
|
|
||||||
|
impl de::Visitor for ByteBufVisitor {
|
||||||
|
type Value = ByteBuf;
|
||||||
|
|
||||||
|
#[inline]
|
||||||
|
fn visit_unit<E>(&mut self) -> Result<ByteBuf, E>
|
||||||
|
where E: de::Error,
|
||||||
|
{
|
||||||
|
Ok(ByteBuf {
|
||||||
|
bytes: Vec::new(),
|
||||||
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
try!(visitor.end());
|
#[inline]
|
||||||
|
fn visit_seq<V>(&mut self, mut visitor: V) -> Result<ByteBuf, V::Error>
|
||||||
|
where V: de::SeqVisitor,
|
||||||
|
{
|
||||||
|
let (len, _) = visitor.size_hint();
|
||||||
|
let mut values = Vec::with_capacity(len);
|
||||||
|
|
||||||
Ok(ByteBuf {
|
while let Some(value) = try!(visitor.visit()) {
|
||||||
bytes: values,
|
values.push(value);
|
||||||
})
|
}
|
||||||
|
|
||||||
|
try!(visitor.end());
|
||||||
|
|
||||||
|
Ok(ByteBuf {
|
||||||
|
bytes: values,
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
#[inline]
|
||||||
|
fn visit_bytes<E>(&mut self, v: &[u8]) -> Result<ByteBuf, E>
|
||||||
|
where E: de::Error,
|
||||||
|
{
|
||||||
|
self.visit_byte_buf(v.to_vec())
|
||||||
|
}
|
||||||
|
|
||||||
|
#[inline]
|
||||||
|
fn visit_byte_buf<E>(&mut self, v: Vec<u8>) -> Result<ByteBuf, E>
|
||||||
|
where E: de::Error,
|
||||||
|
{
|
||||||
|
Ok(ByteBuf {
|
||||||
|
bytes: v,
|
||||||
|
})
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[inline]
|
impl de::Deserialize for ByteBuf {
|
||||||
fn visit_bytes<E>(&mut self, v: &[u8]) -> Result<ByteBuf, E>
|
#[inline]
|
||||||
where E: de::Error,
|
fn deserialize<D>(deserializer: &mut D) -> Result<ByteBuf, D::Error>
|
||||||
{
|
where D: de::Deserializer
|
||||||
self.visit_byte_buf(v.to_vec())
|
{
|
||||||
}
|
deserializer.deserialize_bytes(ByteBufVisitor)
|
||||||
|
}
|
||||||
#[inline]
|
|
||||||
fn visit_byte_buf<E>(&mut self, v: Vec<u8>) -> Result<ByteBuf, E>
|
|
||||||
where E: de::Error,
|
|
||||||
{
|
|
||||||
Ok(ByteBuf {
|
|
||||||
bytes: v,
|
|
||||||
})
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl de::Deserialize for ByteBuf {
|
|
||||||
#[inline]
|
|
||||||
fn deserialize<D>(deserializer: &mut D) -> Result<ByteBuf, D::Error>
|
|
||||||
where D: de::Deserializer
|
|
||||||
{
|
|
||||||
deserializer.deserialize_bytes(ByteBufVisitor)
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
///////////////////////////////////////////////////////////////////////////////
|
///////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
fn escape_bytestring(bytes: &[u8]) -> String {
|
#[inline]
|
||||||
let mut result = String::new();
|
fn escape_bytestring<'a>(bytes: &'a [u8]) -> iter::FlatMap<slice::Iter<'a, u8>, char::EscapeDefault, fn(&u8) -> char::EscapeDefault> {
|
||||||
for &b in bytes {
|
fn f(b: &u8) -> char::EscapeDefault {
|
||||||
for esc in ascii::escape_default(b) {
|
char::from_u32(*b as u32).unwrap().escape_default()
|
||||||
result.push(esc as char);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
result
|
bytes.iter().flat_map(f as fn(&u8) -> char::EscapeDefault)
|
||||||
}
|
}
|
||||||
|
@ -13,10 +13,10 @@
|
|||||||
// Rust 1.5 is unhappy that this private module is undocumented.
|
// Rust 1.5 is unhappy that this private module is undocumented.
|
||||||
#![allow(missing_docs)]
|
#![allow(missing_docs)]
|
||||||
|
|
||||||
use std::{usize, u8, u16, u32, u64};
|
use core::{usize, u8, u16, u32, u64};
|
||||||
use std::{isize, i8, i16, i32, i64};
|
use core::{isize, i8, i16, i32, i64};
|
||||||
use std::{f32, f64};
|
use core::{f32, f64};
|
||||||
use std::mem::size_of;
|
use core::mem::size_of;
|
||||||
|
|
||||||
/// Numbers which have upper and lower bounds
|
/// Numbers which have upper and lower bounds
|
||||||
pub trait Bounded {
|
pub trait Bounded {
|
||||||
@ -274,7 +274,7 @@ macro_rules! impl_to_primitive_float_to_float {
|
|||||||
Some($slf as $DstT)
|
Some($slf as $DstT)
|
||||||
} else {
|
} else {
|
||||||
let n = $slf as f64;
|
let n = $slf as f64;
|
||||||
let max_value: $SrcT = ::std::$SrcT::MAX;
|
let max_value: $SrcT = ::core::$SrcT::MAX;
|
||||||
if -max_value as f64 <= n && n <= max_value as f64 {
|
if -max_value as f64 <= n && n <= max_value as f64 {
|
||||||
Some($slf as $DstT)
|
Some($slf as $DstT)
|
||||||
} else {
|
} else {
|
||||||
|
@ -1,30 +1,63 @@
|
|||||||
//! This module contains `Deserialize` and `Visitor` implementations.
|
//! This module contains `Deserialize` and `Visitor` implementations.
|
||||||
|
|
||||||
|
#[cfg(feature = "std")]
|
||||||
use std::borrow::Cow;
|
use std::borrow::Cow;
|
||||||
use std::collections::{
|
#[cfg(all(feature = "nightly", feature = "collections", not(feature = "std")))]
|
||||||
|
use collections::borrow::Cow;
|
||||||
|
|
||||||
|
#[cfg(all(feature = "collections", not(feature = "std")))]
|
||||||
|
use collections::{
|
||||||
BinaryHeap,
|
BinaryHeap,
|
||||||
BTreeMap,
|
BTreeMap,
|
||||||
BTreeSet,
|
BTreeSet,
|
||||||
LinkedList,
|
LinkedList,
|
||||||
|
VecDeque,
|
||||||
|
Vec,
|
||||||
|
String,
|
||||||
|
};
|
||||||
|
|
||||||
|
#[cfg(feature = "std")]
|
||||||
|
use std::collections::{
|
||||||
HashMap,
|
HashMap,
|
||||||
HashSet,
|
HashSet,
|
||||||
|
BinaryHeap,
|
||||||
|
BTreeMap,
|
||||||
|
BTreeSet,
|
||||||
|
LinkedList,
|
||||||
VecDeque,
|
VecDeque,
|
||||||
};
|
};
|
||||||
#[cfg(feature = "nightly")]
|
|
||||||
|
#[cfg(all(feature = "nightly", feature = "collections"))]
|
||||||
use collections::enum_set::{CLike, EnumSet};
|
use collections::enum_set::{CLike, EnumSet};
|
||||||
use std::hash::Hash;
|
#[cfg(all(feature = "nightly", feature = "collections"))]
|
||||||
use std::marker::PhantomData;
|
use collections::borrow::ToOwned;
|
||||||
|
|
||||||
|
use core::hash::Hash;
|
||||||
|
use core::marker::PhantomData;
|
||||||
|
#[cfg(feature = "std")]
|
||||||
use std::net;
|
use std::net;
|
||||||
|
#[cfg(feature = "std")]
|
||||||
use std::path;
|
use std::path;
|
||||||
|
use core::str;
|
||||||
|
|
||||||
|
#[cfg(feature = "std")]
|
||||||
use std::rc::Rc;
|
use std::rc::Rc;
|
||||||
use std::str;
|
#[cfg(all(feature = "nightly", feature = "alloc", not(feature = "std")))]
|
||||||
|
use alloc::rc::Rc;
|
||||||
|
|
||||||
|
#[cfg(feature = "std")]
|
||||||
use std::sync::Arc;
|
use std::sync::Arc;
|
||||||
|
#[cfg(all(feature = "nightly", feature = "alloc", not(feature = "std")))]
|
||||||
|
use alloc::arc::Arc;
|
||||||
|
|
||||||
|
#[cfg(all(feature = "nightly", feature = "alloc", not(feature = "std")))]
|
||||||
|
use alloc::boxed::Box;
|
||||||
|
|
||||||
#[cfg(feature = "nightly")]
|
#[cfg(feature = "nightly")]
|
||||||
use core::nonzero::{NonZero, Zeroable};
|
use core::nonzero::{NonZero, Zeroable};
|
||||||
|
|
||||||
#[cfg(feature = "nightly")]
|
#[cfg(feature = "nightly")]
|
||||||
use std::num::Zero;
|
use core::num::Zero;
|
||||||
|
|
||||||
use de::{
|
use de::{
|
||||||
Deserialize,
|
Deserialize,
|
||||||
@ -85,7 +118,7 @@ impl Visitor for BoolVisitor {
|
|||||||
fn visit_str<E>(&mut self, s: &str) -> Result<bool, E>
|
fn visit_str<E>(&mut self, s: &str) -> Result<bool, E>
|
||||||
where E: Error,
|
where E: Error,
|
||||||
{
|
{
|
||||||
match s.trim() {
|
match s.trim_matches(|c| ::utils::Pattern_White_Space(c)) {
|
||||||
"true" => Ok(true),
|
"true" => Ok(true),
|
||||||
"false" => Ok(false),
|
"false" => Ok(false),
|
||||||
_ => Err(Error::invalid_type(Type::Bool)),
|
_ => Err(Error::invalid_type(Type::Bool)),
|
||||||
@ -151,10 +184,10 @@ impl<T> Visitor for PrimitiveVisitor<T>
|
|||||||
impl_deserialize_num_method!(f64, visit_f64, from_f64, Type::F64);
|
impl_deserialize_num_method!(f64, visit_f64, from_f64, Type::F64);
|
||||||
|
|
||||||
#[inline]
|
#[inline]
|
||||||
fn visit_str<E>(&mut self, v: &str) -> Result<T, E>
|
fn visit_str<E>(&mut self, s: &str) -> Result<T, E>
|
||||||
where E: Error,
|
where E: Error,
|
||||||
{
|
{
|
||||||
str::FromStr::from_str(v.trim()).or_else(|_| {
|
str::FromStr::from_str(s.trim_matches(::utils::Pattern_White_Space)).or_else(|_| {
|
||||||
Err(Error::invalid_type(Type::Str))
|
Err(Error::invalid_type(Type::Str))
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
@ -228,8 +261,10 @@ impl Deserialize for char {
|
|||||||
|
|
||||||
///////////////////////////////////////////////////////////////////////////////
|
///////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
|
#[cfg(any(feature = "std", feature = "collections"))]
|
||||||
struct StringVisitor;
|
struct StringVisitor;
|
||||||
|
|
||||||
|
#[cfg(any(feature = "std", feature = "collections"))]
|
||||||
impl Visitor for StringVisitor {
|
impl Visitor for StringVisitor {
|
||||||
type Value = String;
|
type Value = String;
|
||||||
|
|
||||||
@ -264,6 +299,7 @@ impl Visitor for StringVisitor {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[cfg(any(feature = "std", feature = "collections"))]
|
||||||
impl Deserialize for String {
|
impl Deserialize for String {
|
||||||
fn deserialize<D>(deserializer: &mut D) -> Result<String, D::Error>
|
fn deserialize<D>(deserializer: &mut D) -> Result<String, D::Error>
|
||||||
where D: Deserializer,
|
where D: Deserializer,
|
||||||
@ -406,6 +442,7 @@ macro_rules! seq_impl {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[cfg(any(feature = "std", feature = "collections"))]
|
||||||
seq_impl!(
|
seq_impl!(
|
||||||
BinaryHeap<T>,
|
BinaryHeap<T>,
|
||||||
<Deserialize, Ord>,
|
<Deserialize, Ord>,
|
||||||
@ -415,6 +452,7 @@ seq_impl!(
|
|||||||
BinaryHeap::with_capacity(visitor.size_hint().0),
|
BinaryHeap::with_capacity(visitor.size_hint().0),
|
||||||
BinaryHeap::push);
|
BinaryHeap::push);
|
||||||
|
|
||||||
|
#[cfg(any(feature = "std", feature = "collections"))]
|
||||||
seq_impl!(
|
seq_impl!(
|
||||||
BTreeSet<T>,
|
BTreeSet<T>,
|
||||||
<Deserialize, Eq, Ord>,
|
<Deserialize, Eq, Ord>,
|
||||||
@ -424,7 +462,7 @@ seq_impl!(
|
|||||||
BTreeSet::new(),
|
BTreeSet::new(),
|
||||||
BTreeSet::insert);
|
BTreeSet::insert);
|
||||||
|
|
||||||
#[cfg(feature = "nightly")]
|
#[cfg(all(feature = "nightly", feature = "collections"))]
|
||||||
seq_impl!(
|
seq_impl!(
|
||||||
EnumSet<T>,
|
EnumSet<T>,
|
||||||
<Deserialize, CLike>,
|
<Deserialize, CLike>,
|
||||||
@ -434,6 +472,7 @@ seq_impl!(
|
|||||||
EnumSet::new(),
|
EnumSet::new(),
|
||||||
EnumSet::insert);
|
EnumSet::insert);
|
||||||
|
|
||||||
|
#[cfg(any(feature = "std", feature = "collections"))]
|
||||||
seq_impl!(
|
seq_impl!(
|
||||||
LinkedList<T>,
|
LinkedList<T>,
|
||||||
<Deserialize>,
|
<Deserialize>,
|
||||||
@ -443,6 +482,7 @@ seq_impl!(
|
|||||||
LinkedList::new(),
|
LinkedList::new(),
|
||||||
LinkedList::push_back);
|
LinkedList::push_back);
|
||||||
|
|
||||||
|
#[cfg(feature = "std")]
|
||||||
seq_impl!(
|
seq_impl!(
|
||||||
HashSet<T>,
|
HashSet<T>,
|
||||||
<Deserialize, Eq, Hash>,
|
<Deserialize, Eq, Hash>,
|
||||||
@ -452,6 +492,7 @@ seq_impl!(
|
|||||||
HashSet::with_capacity(visitor.size_hint().0),
|
HashSet::with_capacity(visitor.size_hint().0),
|
||||||
HashSet::insert);
|
HashSet::insert);
|
||||||
|
|
||||||
|
#[cfg(any(feature = "std", feature = "collections"))]
|
||||||
seq_impl!(
|
seq_impl!(
|
||||||
Vec<T>,
|
Vec<T>,
|
||||||
<Deserialize>,
|
<Deserialize>,
|
||||||
@ -461,6 +502,7 @@ seq_impl!(
|
|||||||
Vec::with_capacity(visitor.size_hint().0),
|
Vec::with_capacity(visitor.size_hint().0),
|
||||||
Vec::push);
|
Vec::push);
|
||||||
|
|
||||||
|
#[cfg(any(feature = "std", feature = "collections"))]
|
||||||
seq_impl!(
|
seq_impl!(
|
||||||
VecDeque<T>,
|
VecDeque<T>,
|
||||||
<Deserialize>,
|
<Deserialize>,
|
||||||
@ -747,6 +789,7 @@ macro_rules! map_impl {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[cfg(any(feature = "std", feature = "collections"))]
|
||||||
map_impl!(
|
map_impl!(
|
||||||
BTreeMap<K, V>,
|
BTreeMap<K, V>,
|
||||||
<Deserialize, Eq, Ord>,
|
<Deserialize, Eq, Ord>,
|
||||||
@ -756,6 +799,7 @@ map_impl!(
|
|||||||
BTreeMap::new(),
|
BTreeMap::new(),
|
||||||
BTreeMap::insert);
|
BTreeMap::insert);
|
||||||
|
|
||||||
|
#[cfg(feature = "std")]
|
||||||
map_impl!(
|
map_impl!(
|
||||||
HashMap<K, V>,
|
HashMap<K, V>,
|
||||||
<Deserialize, Eq, Hash>,
|
<Deserialize, Eq, Hash>,
|
||||||
@ -767,7 +811,7 @@ map_impl!(
|
|||||||
|
|
||||||
///////////////////////////////////////////////////////////////////////////////
|
///////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
#[cfg(feature = "nightly")]
|
#[cfg(all(feature = "nightly", feature = "std"))]
|
||||||
impl Deserialize for net::IpAddr {
|
impl Deserialize for net::IpAddr {
|
||||||
fn deserialize<D>(deserializer: &mut D) -> Result<Self, D::Error>
|
fn deserialize<D>(deserializer: &mut D) -> Result<Self, D::Error>
|
||||||
where D: Deserializer,
|
where D: Deserializer,
|
||||||
@ -780,6 +824,7 @@ impl Deserialize for net::IpAddr {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[cfg(feature = "std")]
|
||||||
impl Deserialize for net::Ipv4Addr {
|
impl Deserialize for net::Ipv4Addr {
|
||||||
fn deserialize<D>(deserializer: &mut D) -> Result<Self, D::Error>
|
fn deserialize<D>(deserializer: &mut D) -> Result<Self, D::Error>
|
||||||
where D: Deserializer,
|
where D: Deserializer,
|
||||||
@ -792,6 +837,7 @@ impl Deserialize for net::Ipv4Addr {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[cfg(feature = "std")]
|
||||||
impl Deserialize for net::Ipv6Addr {
|
impl Deserialize for net::Ipv6Addr {
|
||||||
fn deserialize<D>(deserializer: &mut D) -> Result<Self, D::Error>
|
fn deserialize<D>(deserializer: &mut D) -> Result<Self, D::Error>
|
||||||
where D: Deserializer,
|
where D: Deserializer,
|
||||||
@ -806,6 +852,7 @@ impl Deserialize for net::Ipv6Addr {
|
|||||||
|
|
||||||
///////////////////////////////////////////////////////////////////////////////
|
///////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
|
#[cfg(feature = "std")]
|
||||||
impl Deserialize for net::SocketAddr {
|
impl Deserialize for net::SocketAddr {
|
||||||
fn deserialize<D>(deserializer: &mut D) -> Result<Self, D::Error>
|
fn deserialize<D>(deserializer: &mut D) -> Result<Self, D::Error>
|
||||||
where D: Deserializer,
|
where D: Deserializer,
|
||||||
@ -818,6 +865,7 @@ impl Deserialize for net::SocketAddr {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[cfg(feature = "std")]
|
||||||
impl Deserialize for net::SocketAddrV4 {
|
impl Deserialize for net::SocketAddrV4 {
|
||||||
fn deserialize<D>(deserializer: &mut D) -> Result<Self, D::Error>
|
fn deserialize<D>(deserializer: &mut D) -> Result<Self, D::Error>
|
||||||
where D: Deserializer,
|
where D: Deserializer,
|
||||||
@ -830,6 +878,7 @@ impl Deserialize for net::SocketAddrV4 {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[cfg(feature = "std")]
|
||||||
impl Deserialize for net::SocketAddrV6 {
|
impl Deserialize for net::SocketAddrV6 {
|
||||||
fn deserialize<D>(deserializer: &mut D) -> Result<Self, D::Error>
|
fn deserialize<D>(deserializer: &mut D) -> Result<Self, D::Error>
|
||||||
where D: Deserializer,
|
where D: Deserializer,
|
||||||
@ -844,8 +893,10 @@ impl Deserialize for net::SocketAddrV6 {
|
|||||||
|
|
||||||
///////////////////////////////////////////////////////////////////////////////
|
///////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
|
#[cfg(feature = "std")]
|
||||||
struct PathBufVisitor;
|
struct PathBufVisitor;
|
||||||
|
|
||||||
|
#[cfg(feature = "std")]
|
||||||
impl Visitor for PathBufVisitor {
|
impl Visitor for PathBufVisitor {
|
||||||
type Value = path::PathBuf;
|
type Value = path::PathBuf;
|
||||||
|
|
||||||
@ -862,6 +913,7 @@ impl Visitor for PathBufVisitor {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[cfg(feature = "std")]
|
||||||
impl Deserialize for path::PathBuf {
|
impl Deserialize for path::PathBuf {
|
||||||
fn deserialize<D>(deserializer: &mut D) -> Result<path::PathBuf, D::Error>
|
fn deserialize<D>(deserializer: &mut D) -> Result<path::PathBuf, D::Error>
|
||||||
where D: Deserializer,
|
where D: Deserializer,
|
||||||
@ -872,6 +924,7 @@ impl Deserialize for path::PathBuf {
|
|||||||
|
|
||||||
///////////////////////////////////////////////////////////////////////////////
|
///////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
|
#[cfg(any(feature = "std", feature = "alloc"))]
|
||||||
impl<T: Deserialize> Deserialize for Box<T> {
|
impl<T: Deserialize> Deserialize for Box<T> {
|
||||||
fn deserialize<D>(deserializer: &mut D) -> Result<Box<T>, D::Error>
|
fn deserialize<D>(deserializer: &mut D) -> Result<Box<T>, D::Error>
|
||||||
where D: Deserializer,
|
where D: Deserializer,
|
||||||
@ -881,6 +934,7 @@ impl<T: Deserialize> Deserialize for Box<T> {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[cfg(any(feature = "std", feature = "collections"))]
|
||||||
impl<T: Deserialize> Deserialize for Box<[T]> {
|
impl<T: Deserialize> Deserialize for Box<[T]> {
|
||||||
fn deserialize<D>(deserializer: &mut D) -> Result<Box<[T]>, D::Error>
|
fn deserialize<D>(deserializer: &mut D) -> Result<Box<[T]>, D::Error>
|
||||||
where D: Deserializer,
|
where D: Deserializer,
|
||||||
@ -890,6 +944,7 @@ impl<T: Deserialize> Deserialize for Box<[T]> {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[cfg(any(feature = "std", feature = "alloc"))]
|
||||||
impl<T: Deserialize> Deserialize for Arc<T> {
|
impl<T: Deserialize> Deserialize for Arc<T> {
|
||||||
fn deserialize<D>(deserializer: &mut D) -> Result<Arc<T>, D::Error>
|
fn deserialize<D>(deserializer: &mut D) -> Result<Arc<T>, D::Error>
|
||||||
where D: Deserializer,
|
where D: Deserializer,
|
||||||
@ -899,6 +954,7 @@ impl<T: Deserialize> Deserialize for Arc<T> {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[cfg(any(feature = "std", feature = "alloc"))]
|
||||||
impl<T: Deserialize> Deserialize for Rc<T> {
|
impl<T: Deserialize> Deserialize for Rc<T> {
|
||||||
fn deserialize<D>(deserializer: &mut D) -> Result<Rc<T>, D::Error>
|
fn deserialize<D>(deserializer: &mut D) -> Result<Rc<T>, D::Error>
|
||||||
where D: Deserializer,
|
where D: Deserializer,
|
||||||
@ -908,6 +964,7 @@ impl<T: Deserialize> Deserialize for Rc<T> {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[cfg(any(feature = "std", feature = "collections"))]
|
||||||
impl<'a, T: ?Sized> Deserialize for Cow<'a, T> where T: ToOwned, T::Owned: Deserialize, {
|
impl<'a, T: ?Sized> Deserialize for Cow<'a, T> where T: ToOwned, T::Owned: Deserialize, {
|
||||||
#[inline]
|
#[inline]
|
||||||
fn deserialize<D>(deserializer: &mut D) -> Result<Cow<'a, T>, D::Error>
|
fn deserialize<D>(deserializer: &mut D) -> Result<Cow<'a, T>, D::Error>
|
||||||
@ -954,7 +1011,10 @@ impl<T, E> Deserialize for Result<T, E> where T: Deserialize, E: Deserialize {
|
|||||||
impl ::de::Visitor for FieldVisitor {
|
impl ::de::Visitor for FieldVisitor {
|
||||||
type Value = Field;
|
type Value = Field;
|
||||||
|
|
||||||
|
#[cfg(any(feature = "std", feature = "collections"))]
|
||||||
fn visit_usize<E>(&mut self, value: usize) -> Result<Field, E> where E: Error {
|
fn visit_usize<E>(&mut self, value: usize) -> Result<Field, E> where E: Error {
|
||||||
|
#[cfg(feature = "collections")]
|
||||||
|
use collections::string::ToString;
|
||||||
match value {
|
match value {
|
||||||
0 => Ok(Field::Ok),
|
0 => Ok(Field::Ok),
|
||||||
1 => Ok(Field::Err),
|
1 => Ok(Field::Err),
|
||||||
@ -962,6 +1022,17 @@ impl<T, E> Deserialize for Result<T, E> where T: Deserialize, E: Deserialize {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[cfg(all(not(feature = "std"), not(feature = "collections")))]
|
||||||
|
fn visit_usize<E>(&mut self, value: usize) -> Result<Field, E> where E: Error {
|
||||||
|
#[cfg(feature = "collections")]
|
||||||
|
use collections::string::ToString;
|
||||||
|
match value {
|
||||||
|
0 => Ok(Field::Ok),
|
||||||
|
1 => Ok(Field::Err),
|
||||||
|
_ => Err(Error::unknown_field("some number")),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
fn visit_str<E>(&mut self, value: &str) -> Result<Field, E> where E: Error {
|
fn visit_str<E>(&mut self, value: &str) -> Result<Field, E> where E: Error {
|
||||||
match value {
|
match value {
|
||||||
"Ok" => Ok(Field::Ok),
|
"Ok" => Ok(Field::Ok),
|
||||||
|
@ -1,6 +1,12 @@
|
|||||||
//! Generic deserialization framework.
|
//! Generic deserialization framework.
|
||||||
|
|
||||||
|
#[cfg(feature = "std")]
|
||||||
use std::error;
|
use std::error;
|
||||||
|
#[cfg(not(feature = "std"))]
|
||||||
|
use error;
|
||||||
|
|
||||||
|
#[cfg(all(not(feature = "std"), feature = "collections"))]
|
||||||
|
use collections::{String, Vec};
|
||||||
|
|
||||||
pub mod impls;
|
pub mod impls;
|
||||||
pub mod value;
|
pub mod value;
|
||||||
@ -12,8 +18,13 @@ mod from_primitive;
|
|||||||
/// `Deserializer` error.
|
/// `Deserializer` error.
|
||||||
pub trait Error: Sized + error::Error {
|
pub trait Error: Sized + error::Error {
|
||||||
/// Raised when there is general error when deserializing a type.
|
/// Raised when there is general error when deserializing a type.
|
||||||
|
#[cfg(any(feature = "std", feature = "collections"))]
|
||||||
fn custom<T: Into<String>>(msg: T) -> Self;
|
fn custom<T: Into<String>>(msg: T) -> Self;
|
||||||
|
|
||||||
|
/// Raised when there is general error when deserializing a type.
|
||||||
|
#[cfg(all(not(feature = "std"), not(feature = "collections")))]
|
||||||
|
fn custom<T: Into<&'static str>>(msg: T) -> Self;
|
||||||
|
|
||||||
/// Raised when a `Deserialize` type unexpectedly hit the end of the stream.
|
/// Raised when a `Deserialize` type unexpectedly hit the end of the stream.
|
||||||
fn end_of_stream() -> Self;
|
fn end_of_stream() -> Self;
|
||||||
|
|
||||||
@ -558,9 +569,7 @@ pub trait Visitor {
|
|||||||
fn visit_char<E>(&mut self, v: char) -> Result<Self::Value, E>
|
fn visit_char<E>(&mut self, v: char) -> Result<Self::Value, E>
|
||||||
where E: Error,
|
where E: Error,
|
||||||
{
|
{
|
||||||
// FIXME: this allocation is required in order to be compatible with stable rust, which
|
self.visit_str(::core::str::from_utf8(::utils::encode_utf8(v).as_slice()).unwrap())
|
||||||
// doesn't support encoding a `char` into a stack buffer.
|
|
||||||
self.visit_string(v.to_string())
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/// `visit_str` deserializes a `&str` into a `Value`.
|
/// `visit_str` deserializes a `&str` into a `Value`.
|
||||||
@ -574,6 +583,7 @@ pub trait Visitor {
|
|||||||
/// a copy if it is deserializing a string from a `String` type. By default it passes a `&str`
|
/// a copy if it is deserializing a string from a `String` type. By default it passes a `&str`
|
||||||
/// to the `visit_str` method.
|
/// to the `visit_str` method.
|
||||||
#[inline]
|
#[inline]
|
||||||
|
#[cfg(any(feature = "std", feature = "collections"))]
|
||||||
fn visit_string<E>(&mut self, v: String) -> Result<Self::Value, E>
|
fn visit_string<E>(&mut self, v: String) -> Result<Self::Value, E>
|
||||||
where E: Error,
|
where E: Error,
|
||||||
{
|
{
|
||||||
@ -638,6 +648,7 @@ pub trait Visitor {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/// `visit_byte_buf` deserializes a `Vec<u8>` into a `Value`.
|
/// `visit_byte_buf` deserializes a `Vec<u8>` into a `Value`.
|
||||||
|
#[cfg(any(feature = "std", feature = "collections"))]
|
||||||
fn visit_byte_buf<E>(&mut self, v: Vec<u8>) -> Result<Self::Value, E>
|
fn visit_byte_buf<E>(&mut self, v: Vec<u8>) -> Result<Self::Value, E>
|
||||||
where E: Error,
|
where E: Error,
|
||||||
{
|
{
|
||||||
|
@ -1,5 +1,6 @@
|
|||||||
//! This module supports deserializing from primitives with the `ValueDeserializer` trait.
|
//! This module supports deserializing from primitives with the `ValueDeserializer` trait.
|
||||||
|
|
||||||
|
#[cfg(feature = "std")]
|
||||||
use std::collections::{
|
use std::collections::{
|
||||||
BTreeMap,
|
BTreeMap,
|
||||||
BTreeSet,
|
BTreeSet,
|
||||||
@ -10,11 +11,31 @@ use std::collections::{
|
|||||||
hash_map,
|
hash_map,
|
||||||
hash_set,
|
hash_set,
|
||||||
};
|
};
|
||||||
use std::hash::Hash;
|
#[cfg(feature = "std")]
|
||||||
use std::error;
|
|
||||||
use std::fmt;
|
|
||||||
use std::vec;
|
use std::vec;
|
||||||
use std::marker::PhantomData;
|
|
||||||
|
#[cfg(all(feature = "collections", not(feature = "std")))]
|
||||||
|
use collections::{
|
||||||
|
BTreeMap,
|
||||||
|
BTreeSet,
|
||||||
|
Vec,
|
||||||
|
String,
|
||||||
|
btree_map,
|
||||||
|
btree_set,
|
||||||
|
vec,
|
||||||
|
};
|
||||||
|
|
||||||
|
#[cfg(all(feature = "nightly", feature = "collections"))]
|
||||||
|
use collections::borrow::ToOwned;
|
||||||
|
|
||||||
|
use core::hash::Hash;
|
||||||
|
#[cfg(feature = "std")]
|
||||||
|
use std::error;
|
||||||
|
#[cfg(not(feature = "std"))]
|
||||||
|
use error;
|
||||||
|
|
||||||
|
use core::fmt;
|
||||||
|
use core::marker::PhantomData;
|
||||||
|
|
||||||
use de;
|
use de;
|
||||||
use bytes;
|
use bytes;
|
||||||
@ -25,7 +46,11 @@ use bytes;
|
|||||||
#[derive(Clone, Debug, PartialEq)]
|
#[derive(Clone, Debug, PartialEq)]
|
||||||
pub enum Error {
|
pub enum Error {
|
||||||
/// The value had some custom error.
|
/// The value had some custom error.
|
||||||
|
#[cfg(any(feature = "std", feature = "collections"))]
|
||||||
Custom(String),
|
Custom(String),
|
||||||
|
/// The value had some custom error.
|
||||||
|
#[cfg(all(not(feature = "std"), not(feature = "collections")))]
|
||||||
|
Custom(&'static str),
|
||||||
|
|
||||||
/// The value had an incorrect type.
|
/// The value had an incorrect type.
|
||||||
InvalidType(de::Type),
|
InvalidType(de::Type),
|
||||||
@ -34,29 +59,60 @@ pub enum Error {
|
|||||||
InvalidLength(usize),
|
InvalidLength(usize),
|
||||||
|
|
||||||
/// The value is invalid and cannot be deserialized.
|
/// The value is invalid and cannot be deserialized.
|
||||||
|
#[cfg(any(feature = "std", feature = "collections"))]
|
||||||
InvalidValue(String),
|
InvalidValue(String),
|
||||||
|
/// The value is invalid and cannot be deserialized.
|
||||||
|
#[cfg(all(not(feature = "std"), not(feature = "collections")))]
|
||||||
|
InvalidValue(&'static str),
|
||||||
|
|
||||||
/// EOF while deserializing a value.
|
/// EOF while deserializing a value.
|
||||||
EndOfStream,
|
EndOfStream,
|
||||||
|
|
||||||
/// Unknown variant in enum.
|
/// Unknown variant in enum.
|
||||||
|
#[cfg(any(feature = "std", feature = "collections"))]
|
||||||
UnknownVariant(String),
|
UnknownVariant(String),
|
||||||
|
/// Unknown variant in enum.
|
||||||
|
#[cfg(all(not(feature = "std"), not(feature = "collections")))]
|
||||||
|
UnknownVariant(&'static str),
|
||||||
|
|
||||||
/// Unknown field in struct.
|
/// Unknown field in struct.
|
||||||
|
#[cfg(any(feature = "std", feature = "collections"))]
|
||||||
UnknownField(String),
|
UnknownField(String),
|
||||||
|
/// Unknown field in struct.
|
||||||
|
#[cfg(all(not(feature = "std"), not(feature = "collections")))]
|
||||||
|
UnknownField(&'static str),
|
||||||
|
|
||||||
/// Struct is missing a field.
|
/// Struct is missing a field.
|
||||||
MissingField(&'static str),
|
MissingField(&'static str),
|
||||||
}
|
}
|
||||||
|
|
||||||
impl de::Error for Error {
|
impl de::Error for Error {
|
||||||
|
#[cfg(any(feature = "std", feature = "collections"))]
|
||||||
fn custom<T: Into<String>>(msg: T) -> Self { Error::Custom(msg.into()) }
|
fn custom<T: Into<String>>(msg: T) -> Self { Error::Custom(msg.into()) }
|
||||||
|
|
||||||
|
#[cfg(all(not(feature = "std"), not(feature = "collections")))]
|
||||||
|
fn custom<T: Into<&'static str>>(msg: T) -> Self { Error::Custom(msg.into()) }
|
||||||
|
|
||||||
fn end_of_stream() -> Self { Error::EndOfStream }
|
fn end_of_stream() -> Self { Error::EndOfStream }
|
||||||
fn invalid_type(ty: de::Type) -> Self { Error::InvalidType(ty) }
|
fn invalid_type(ty: de::Type) -> Self { Error::InvalidType(ty) }
|
||||||
|
|
||||||
|
#[cfg(any(feature = "std", feature = "collections"))]
|
||||||
fn invalid_value(msg: &str) -> Self { Error::InvalidValue(msg.to_owned()) }
|
fn invalid_value(msg: &str) -> Self { Error::InvalidValue(msg.to_owned()) }
|
||||||
|
|
||||||
|
#[cfg(all(not(feature = "std"), not(feature = "collections")))]
|
||||||
|
fn invalid_value(msg: &str) -> Self { Error::InvalidValue("invalid value") }
|
||||||
|
|
||||||
fn invalid_length(len: usize) -> Self { Error::InvalidLength(len) }
|
fn invalid_length(len: usize) -> Self { Error::InvalidLength(len) }
|
||||||
|
|
||||||
|
#[cfg(any(feature = "std", feature = "collections"))]
|
||||||
fn unknown_variant(variant: &str) -> Self { Error::UnknownVariant(String::from(variant)) }
|
fn unknown_variant(variant: &str) -> Self { Error::UnknownVariant(String::from(variant)) }
|
||||||
|
#[cfg(any(feature = "std", feature = "collections"))]
|
||||||
fn unknown_field(field: &str) -> Self { Error::UnknownField(String::from(field)) }
|
fn unknown_field(field: &str) -> Self { Error::UnknownField(String::from(field)) }
|
||||||
|
|
||||||
|
#[cfg(all(not(feature = "std"), not(feature = "collections")))]
|
||||||
|
fn unknown_variant(variant: &str) -> Self { Error::UnknownVariant("unknown variant") }
|
||||||
|
#[cfg(all(not(feature = "std"), not(feature = "collections")))]
|
||||||
|
fn unknown_field(field: &str) -> Self { Error::UnknownField("unknown field") }
|
||||||
fn missing_field(field: &'static str) -> Self { Error::MissingField(field) }
|
fn missing_field(field: &'static str) -> Self { Error::MissingField(field) }
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -238,8 +294,10 @@ impl<'a, E> de::VariantVisitor for StrDeserializer<'a, E>
|
|||||||
///////////////////////////////////////////////////////////////////////////////
|
///////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
/// A helper deserializer that deserializes a `String`.
|
/// A helper deserializer that deserializes a `String`.
|
||||||
|
#[cfg(any(feature = "std", feature = "collections"))]
|
||||||
pub struct StringDeserializer<E>(Option<String>, PhantomData<E>);
|
pub struct StringDeserializer<E>(Option<String>, PhantomData<E>);
|
||||||
|
|
||||||
|
#[cfg(any(feature = "std", feature = "collections"))]
|
||||||
impl<E> ValueDeserializer<E> for String
|
impl<E> ValueDeserializer<E> for String
|
||||||
where E: de::Error,
|
where E: de::Error,
|
||||||
{
|
{
|
||||||
@ -250,6 +308,7 @@ impl<E> ValueDeserializer<E> for String
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[cfg(any(feature = "std", feature = "collections"))]
|
||||||
impl<E> de::Deserializer for StringDeserializer<E>
|
impl<E> de::Deserializer for StringDeserializer<E>
|
||||||
where E: de::Error,
|
where E: de::Error,
|
||||||
{
|
{
|
||||||
@ -274,6 +333,7 @@ impl<E> de::Deserializer for StringDeserializer<E>
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[cfg(any(feature = "std", feature = "collections"))]
|
||||||
impl<'a, E> de::VariantVisitor for StringDeserializer<E>
|
impl<'a, E> de::VariantVisitor for StringDeserializer<E>
|
||||||
where E: de::Error,
|
where E: de::Error,
|
||||||
{
|
{
|
||||||
@ -361,6 +421,7 @@ impl<I, T, E> de::SeqVisitor for SeqDeserializer<I, E>
|
|||||||
|
|
||||||
///////////////////////////////////////////////////////////////////////////////
|
///////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
|
#[cfg(any(feature = "std", feature = "collections"))]
|
||||||
impl<T, E> ValueDeserializer<E> for Vec<T>
|
impl<T, E> ValueDeserializer<E> for Vec<T>
|
||||||
where T: ValueDeserializer<E>,
|
where T: ValueDeserializer<E>,
|
||||||
E: de::Error,
|
E: de::Error,
|
||||||
@ -373,6 +434,7 @@ impl<T, E> ValueDeserializer<E> for Vec<T>
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[cfg(any(feature = "std", feature = "collections"))]
|
||||||
impl<T, E> ValueDeserializer<E> for BTreeSet<T>
|
impl<T, E> ValueDeserializer<E> for BTreeSet<T>
|
||||||
where T: ValueDeserializer<E> + Eq + Ord,
|
where T: ValueDeserializer<E> + Eq + Ord,
|
||||||
E: de::Error,
|
E: de::Error,
|
||||||
@ -385,6 +447,7 @@ impl<T, E> ValueDeserializer<E> for BTreeSet<T>
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[cfg(feature = "std")]
|
||||||
impl<T, E> ValueDeserializer<E> for HashSet<T>
|
impl<T, E> ValueDeserializer<E> for HashSet<T>
|
||||||
where T: ValueDeserializer<E> + Eq + Hash,
|
where T: ValueDeserializer<E> + Eq + Hash,
|
||||||
E: de::Error,
|
E: de::Error,
|
||||||
@ -527,6 +590,7 @@ impl<I, K, V, E> de::MapVisitor for MapDeserializer<I, K, V, E>
|
|||||||
|
|
||||||
///////////////////////////////////////////////////////////////////////////////
|
///////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
|
#[cfg(any(feature = "std", feature = "collections"))]
|
||||||
impl<K, V, E> ValueDeserializer<E> for BTreeMap<K, V>
|
impl<K, V, E> ValueDeserializer<E> for BTreeMap<K, V>
|
||||||
where K: ValueDeserializer<E> + Eq + Ord,
|
where K: ValueDeserializer<E> + Eq + Ord,
|
||||||
V: ValueDeserializer<E>,
|
V: ValueDeserializer<E>,
|
||||||
@ -540,6 +604,7 @@ impl<K, V, E> ValueDeserializer<E> for BTreeMap<K, V>
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[cfg(feature = "std")]
|
||||||
impl<K, V, E> ValueDeserializer<E> for HashMap<K, V>
|
impl<K, V, E> ValueDeserializer<E> for HashMap<K, V>
|
||||||
where K: ValueDeserializer<E> + Eq + Hash,
|
where K: ValueDeserializer<E> + Eq + Hash,
|
||||||
V: ValueDeserializer<E>,
|
V: ValueDeserializer<E>,
|
||||||
@ -618,6 +683,7 @@ impl<'a, E> de::Deserializer for BytesDeserializer<'a, E>
|
|||||||
|
|
||||||
///////////////////////////////////////////////////////////////////////////////
|
///////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
|
#[cfg(any(feature = "std", feature = "collections"))]
|
||||||
impl<E> ValueDeserializer<E> for bytes::ByteBuf
|
impl<E> ValueDeserializer<E> for bytes::ByteBuf
|
||||||
where E: de::Error,
|
where E: de::Error,
|
||||||
{
|
{
|
||||||
@ -629,8 +695,10 @@ impl<E> ValueDeserializer<E> for bytes::ByteBuf
|
|||||||
}
|
}
|
||||||
|
|
||||||
/// A helper deserializer that deserializes a `Vec<u8>`.
|
/// A helper deserializer that deserializes a `Vec<u8>`.
|
||||||
|
#[cfg(any(feature = "std", feature = "collections"))]
|
||||||
pub struct ByteBufDeserializer<E>(Option<Vec<u8>>, PhantomData<E>);
|
pub struct ByteBufDeserializer<E>(Option<Vec<u8>>, PhantomData<E>);
|
||||||
|
|
||||||
|
#[cfg(any(feature = "std", feature = "collections"))]
|
||||||
impl<E> de::Deserializer for ByteBufDeserializer<E>
|
impl<E> de::Deserializer for ByteBufDeserializer<E>
|
||||||
where E: de::Error,
|
where E: de::Error,
|
||||||
{
|
{
|
||||||
|
44
serde/src/error.rs
Normal file
44
serde/src/error.rs
Normal file
@ -0,0 +1,44 @@
|
|||||||
|
//! A stand-in for `std::error`
|
||||||
|
use core::any::TypeId;
|
||||||
|
use core::fmt::{Debug, Display};
|
||||||
|
|
||||||
|
|
||||||
|
/// A stand-in for `std::error::Error`, which requires no allocation.
|
||||||
|
#[cfg(feature = "nightly")]
|
||||||
|
pub trait Error: Debug + Display + ::core::marker::Reflect {
|
||||||
|
/// A short description of the error.
|
||||||
|
///
|
||||||
|
/// The description should not contain newlines or sentence-ending
|
||||||
|
/// punctuation, to facilitate embedding in larger user-facing
|
||||||
|
/// strings.
|
||||||
|
fn description(&self) -> &str;
|
||||||
|
|
||||||
|
/// The lower-level cause of this error, if any.
|
||||||
|
fn cause(&self) -> Option<&Error> { None }
|
||||||
|
|
||||||
|
/// Get the `TypeId` of `self`
|
||||||
|
#[doc(hidden)]
|
||||||
|
fn type_id(&self) -> TypeId where Self: 'static {
|
||||||
|
TypeId::of::<Self>()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// A stand-in for `std::error::Error`, which requires no allocation.
|
||||||
|
#[cfg(not(feature = "nightly"))]
|
||||||
|
pub trait Error: Debug + Display {
|
||||||
|
/// A short description of the error.
|
||||||
|
///
|
||||||
|
/// The description should not contain newlines or sentence-ending
|
||||||
|
/// punctuation, to facilitate embedding in larger user-facing
|
||||||
|
/// strings.
|
||||||
|
fn description(&self) -> &str;
|
||||||
|
|
||||||
|
/// The lower-level cause of this error, if any.
|
||||||
|
fn cause(&self) -> Option<&Error> { None }
|
||||||
|
|
||||||
|
/// Stubbed! Returns type_id of `()`
|
||||||
|
#[doc(hidden)]
|
||||||
|
fn type_id(&self) -> TypeId where Self: 'static {
|
||||||
|
TypeId::of::<()>()
|
||||||
|
}
|
||||||
|
}
|
@ -10,23 +10,42 @@
|
|||||||
//! [github repository](https://github.com/serde-rs/serde)
|
//! [github repository](https://github.com/serde-rs/serde)
|
||||||
|
|
||||||
#![doc(html_root_url="https://serde-rs.github.io/serde/serde")]
|
#![doc(html_root_url="https://serde-rs.github.io/serde/serde")]
|
||||||
#![cfg_attr(feature = "nightly", feature(collections, enumset, nonzero, plugin, step_trait,
|
#![cfg_attr(not(feature = "std"), no_std)]
|
||||||
zero_one))]
|
#![cfg_attr(feature = "nightly", feature(reflect_marker, unicode, nonzero, plugin, step_trait, zero_one))]
|
||||||
|
#![cfg_attr(feature = "alloc", feature(alloc))]
|
||||||
|
#![cfg_attr(feature = "collections", feature(collections, enumset))]
|
||||||
#![cfg_attr(feature = "nightly-testing", plugin(clippy))]
|
#![cfg_attr(feature = "nightly-testing", plugin(clippy))]
|
||||||
#![cfg_attr(feature = "nightly-testing", allow(linkedlist))]
|
#![cfg_attr(feature = "nightly-testing", allow(linkedlist))]
|
||||||
|
|
||||||
|
#![cfg_attr(any(not(feature = "std"), feature = "nightly"), allow(unused_variables, unused_imports, unused_features, dead_code))]
|
||||||
|
|
||||||
#![deny(missing_docs)]
|
#![deny(missing_docs)]
|
||||||
|
|
||||||
#[cfg(feature = "nightly")]
|
#[cfg(all(feature = "nightly", feature = "collections"))]
|
||||||
extern crate collections;
|
extern crate collections;
|
||||||
|
|
||||||
#[cfg(feature = "nightly")]
|
#[cfg(all(feature = "nightly", feature = "alloc"))]
|
||||||
extern crate core;
|
extern crate alloc;
|
||||||
|
|
||||||
|
#[cfg(feature = "std")]
|
||||||
|
mod core {
|
||||||
|
pub use std::{ops, hash, fmt, cmp, marker, mem, i8, i16, i32, i64, u8, u16, u32, u64, isize,
|
||||||
|
usize, f32, f64, char, str, slice, iter};
|
||||||
|
}
|
||||||
|
|
||||||
pub use ser::{Serialize, Serializer};
|
pub use ser::{Serialize, Serializer};
|
||||||
pub use de::{Deserialize, Deserializer, Error};
|
pub use de::{Deserialize, Deserializer, Error};
|
||||||
|
|
||||||
|
#[cfg(not(feature = "std"))]
|
||||||
|
macro_rules! format {
|
||||||
|
($s:expr, $($rest:tt)*) => ($s)
|
||||||
|
}
|
||||||
|
|
||||||
pub mod bytes;
|
pub mod bytes;
|
||||||
pub mod de;
|
pub mod de;
|
||||||
|
#[cfg(feature = "std")]
|
||||||
pub mod iter;
|
pub mod iter;
|
||||||
pub mod ser;
|
pub mod ser;
|
||||||
|
#[cfg(not(feature = "std"))]
|
||||||
|
pub mod error;
|
||||||
|
mod utils;
|
||||||
|
@ -1,6 +1,11 @@
|
|||||||
//! Implementations for all of Rust's builtin types.
|
//! Implementations for all of Rust's builtin types.
|
||||||
|
|
||||||
|
#[cfg(feature = "std")]
|
||||||
use std::borrow::Cow;
|
use std::borrow::Cow;
|
||||||
|
#[cfg(all(feature = "collections", not(feature = "std")))]
|
||||||
|
use collections::borrow::Cow;
|
||||||
|
|
||||||
|
#[cfg(feature = "std")]
|
||||||
use std::collections::{
|
use std::collections::{
|
||||||
BinaryHeap,
|
BinaryHeap,
|
||||||
BTreeMap,
|
BTreeMap,
|
||||||
@ -10,20 +15,47 @@ use std::collections::{
|
|||||||
HashSet,
|
HashSet,
|
||||||
VecDeque,
|
VecDeque,
|
||||||
};
|
};
|
||||||
#[cfg(feature = "nightly")]
|
#[cfg(all(feature = "collections", not(feature = "std")))]
|
||||||
|
use collections::{
|
||||||
|
BinaryHeap,
|
||||||
|
BTreeMap,
|
||||||
|
BTreeSet,
|
||||||
|
LinkedList,
|
||||||
|
VecDeque,
|
||||||
|
String,
|
||||||
|
Vec,
|
||||||
|
};
|
||||||
|
|
||||||
|
#[cfg(all(feature = "nightly", feature = "collections"))]
|
||||||
use collections::enum_set::{CLike, EnumSet};
|
use collections::enum_set::{CLike, EnumSet};
|
||||||
use std::hash::Hash;
|
#[cfg(all(feature = "nightly", feature = "collections"))]
|
||||||
|
use collections::borrow::ToOwned;
|
||||||
|
|
||||||
|
use core::hash::Hash;
|
||||||
#[cfg(feature = "nightly")]
|
#[cfg(feature = "nightly")]
|
||||||
use std::iter;
|
use core::iter;
|
||||||
|
#[cfg(feature = "std")]
|
||||||
use std::net;
|
use std::net;
|
||||||
#[cfg(feature = "nightly")]
|
#[cfg(feature = "nightly")]
|
||||||
use std::num;
|
use core::num;
|
||||||
#[cfg(feature = "nightly")]
|
#[cfg(feature = "nightly")]
|
||||||
use std::ops;
|
use core::ops;
|
||||||
|
#[cfg(feature = "std")]
|
||||||
use std::path;
|
use std::path;
|
||||||
|
#[cfg(feature = "std")]
|
||||||
use std::rc::Rc;
|
use std::rc::Rc;
|
||||||
|
#[cfg(all(feature = "alloc", not(feature = "std")))]
|
||||||
|
use alloc::rc::Rc;
|
||||||
|
|
||||||
|
#[cfg(feature = "std")]
|
||||||
use std::sync::Arc;
|
use std::sync::Arc;
|
||||||
use std::marker::PhantomData;
|
#[cfg(all(feature = "alloc", not(feature = "std")))]
|
||||||
|
use alloc::arc::Arc;
|
||||||
|
|
||||||
|
#[cfg(all(feature = "alloc", not(feature = "std")))]
|
||||||
|
use alloc::boxed::Box;
|
||||||
|
|
||||||
|
use core::marker::PhantomData;
|
||||||
|
|
||||||
#[cfg(feature = "nightly")]
|
#[cfg(feature = "nightly")]
|
||||||
use core::nonzero::{NonZero, Zeroable};
|
use core::nonzero::{NonZero, Zeroable};
|
||||||
@ -77,6 +109,7 @@ impl Serialize for str {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[cfg(any(feature = "std", feature = "collections"))]
|
||||||
impl Serialize for String {
|
impl Serialize for String {
|
||||||
#[inline]
|
#[inline]
|
||||||
fn serialize<S>(&self, serializer: &mut S) -> Result<(), S::Error>
|
fn serialize<S>(&self, serializer: &mut S) -> Result<(), S::Error>
|
||||||
@ -260,6 +293,7 @@ array_impls!(32);
|
|||||||
|
|
||||||
///////////////////////////////////////////////////////////////////////////////
|
///////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
|
#[cfg(any(feature = "std", feature = "collections"))]
|
||||||
impl<T> Serialize for BinaryHeap<T>
|
impl<T> Serialize for BinaryHeap<T>
|
||||||
where T: Serialize + Ord
|
where T: Serialize + Ord
|
||||||
{
|
{
|
||||||
@ -271,6 +305,7 @@ impl<T> Serialize for BinaryHeap<T>
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[cfg(any(feature = "std", feature = "collections"))]
|
||||||
impl<T> Serialize for BTreeSet<T>
|
impl<T> Serialize for BTreeSet<T>
|
||||||
where T: Serialize + Ord,
|
where T: Serialize + Ord,
|
||||||
{
|
{
|
||||||
@ -282,7 +317,7 @@ impl<T> Serialize for BTreeSet<T>
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[cfg(feature = "nightly")]
|
#[cfg(all(feature = "nightly", feature = "collections"))]
|
||||||
impl<T> Serialize for EnumSet<T>
|
impl<T> Serialize for EnumSet<T>
|
||||||
where T: Serialize + CLike
|
where T: Serialize + CLike
|
||||||
{
|
{
|
||||||
@ -294,6 +329,7 @@ impl<T> Serialize for EnumSet<T>
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[cfg(feature = "std")]
|
||||||
impl<T> Serialize for HashSet<T>
|
impl<T> Serialize for HashSet<T>
|
||||||
where T: Serialize + Eq + Hash,
|
where T: Serialize + Eq + Hash,
|
||||||
{
|
{
|
||||||
@ -305,6 +341,7 @@ impl<T> Serialize for HashSet<T>
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[cfg(any(feature = "std", feature = "collections"))]
|
||||||
impl<T> Serialize for LinkedList<T>
|
impl<T> Serialize for LinkedList<T>
|
||||||
where T: Serialize,
|
where T: Serialize,
|
||||||
{
|
{
|
||||||
@ -330,6 +367,7 @@ impl<A> Serialize for ops::Range<A>
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[cfg(any(feature = "std", feature = "collections"))]
|
||||||
impl<T> Serialize for Vec<T> where T: Serialize {
|
impl<T> Serialize for Vec<T> where T: Serialize {
|
||||||
#[inline]
|
#[inline]
|
||||||
fn serialize<S>(&self, serializer: &mut S) -> Result<(), S::Error>
|
fn serialize<S>(&self, serializer: &mut S) -> Result<(), S::Error>
|
||||||
@ -339,6 +377,7 @@ impl<T> Serialize for Vec<T> where T: Serialize {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[cfg(any(feature = "std", feature = "collections"))]
|
||||||
impl<T> Serialize for VecDeque<T> where T: Serialize {
|
impl<T> Serialize for VecDeque<T> where T: Serialize {
|
||||||
#[inline]
|
#[inline]
|
||||||
fn serialize<S>(&self, serializer: &mut S) -> Result<(), S::Error>
|
fn serialize<S>(&self, serializer: &mut S) -> Result<(), S::Error>
|
||||||
@ -598,6 +637,7 @@ impl<K, V, I> MapVisitor for MapIteratorVisitor<I>
|
|||||||
|
|
||||||
///////////////////////////////////////////////////////////////////////////////
|
///////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
|
#[cfg(any(feature = "std", feature = "collections"))]
|
||||||
impl<K, V> Serialize for BTreeMap<K, V>
|
impl<K, V> Serialize for BTreeMap<K, V>
|
||||||
where K: Serialize + Ord,
|
where K: Serialize + Ord,
|
||||||
V: Serialize,
|
V: Serialize,
|
||||||
@ -610,6 +650,7 @@ impl<K, V> Serialize for BTreeMap<K, V>
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[cfg(feature = "std")]
|
||||||
impl<K, V> Serialize for HashMap<K, V>
|
impl<K, V> Serialize for HashMap<K, V>
|
||||||
where K: Serialize + Eq + Hash,
|
where K: Serialize + Eq + Hash,
|
||||||
V: Serialize,
|
V: Serialize,
|
||||||
@ -642,6 +683,7 @@ impl<'a, T: ?Sized> Serialize for &'a mut T where T: Serialize {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[cfg(any(feature = "std", feature = "alloc"))]
|
||||||
impl<T: ?Sized> Serialize for Box<T> where T: Serialize {
|
impl<T: ?Sized> Serialize for Box<T> where T: Serialize {
|
||||||
#[inline]
|
#[inline]
|
||||||
fn serialize<S>(&self, serializer: &mut S) -> Result<(), S::Error>
|
fn serialize<S>(&self, serializer: &mut S) -> Result<(), S::Error>
|
||||||
@ -651,6 +693,7 @@ impl<T: ?Sized> Serialize for Box<T> where T: Serialize {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[cfg(any(feature = "std", feature = "alloc"))]
|
||||||
impl<T> Serialize for Rc<T> where T: Serialize, {
|
impl<T> Serialize for Rc<T> where T: Serialize, {
|
||||||
#[inline]
|
#[inline]
|
||||||
fn serialize<S>(&self, serializer: &mut S) -> Result<(), S::Error>
|
fn serialize<S>(&self, serializer: &mut S) -> Result<(), S::Error>
|
||||||
@ -660,6 +703,7 @@ impl<T> Serialize for Rc<T> where T: Serialize, {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[cfg(any(feature = "std", feature = "alloc"))]
|
||||||
impl<T> Serialize for Arc<T> where T: Serialize, {
|
impl<T> Serialize for Arc<T> where T: Serialize, {
|
||||||
#[inline]
|
#[inline]
|
||||||
fn serialize<S>(&self, serializer: &mut S) -> Result<(), S::Error>
|
fn serialize<S>(&self, serializer: &mut S) -> Result<(), S::Error>
|
||||||
@ -669,6 +713,7 @@ impl<T> Serialize for Arc<T> where T: Serialize, {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[cfg(any(feature = "std", feature = "collections"))]
|
||||||
impl<'a, T: ?Sized> Serialize for Cow<'a, T> where T: Serialize + ToOwned, {
|
impl<'a, T: ?Sized> Serialize for Cow<'a, T> where T: Serialize + ToOwned, {
|
||||||
#[inline]
|
#[inline]
|
||||||
fn serialize<S>(&self, serializer: &mut S) -> Result<(), S::Error>
|
fn serialize<S>(&self, serializer: &mut S) -> Result<(), S::Error>
|
||||||
@ -695,7 +740,7 @@ impl<T, E> Serialize for Result<T, E> where T: Serialize, E: Serialize {
|
|||||||
|
|
||||||
///////////////////////////////////////////////////////////////////////////////
|
///////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
#[cfg(feature = "nightly")]
|
#[cfg(all(feature = "std", feature = "nightly"))]
|
||||||
impl Serialize for net::IpAddr {
|
impl Serialize for net::IpAddr {
|
||||||
fn serialize<S>(&self, serializer: &mut S) -> Result<(), S::Error>
|
fn serialize<S>(&self, serializer: &mut S) -> Result<(), S::Error>
|
||||||
where S: Serializer,
|
where S: Serializer,
|
||||||
@ -707,6 +752,7 @@ impl Serialize for net::IpAddr {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[cfg(feature = "std")]
|
||||||
impl Serialize for net::Ipv4Addr {
|
impl Serialize for net::Ipv4Addr {
|
||||||
fn serialize<S>(&self, serializer: &mut S) -> Result<(), S::Error>
|
fn serialize<S>(&self, serializer: &mut S) -> Result<(), S::Error>
|
||||||
where S: Serializer,
|
where S: Serializer,
|
||||||
@ -715,6 +761,7 @@ impl Serialize for net::Ipv4Addr {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[cfg(feature = "std")]
|
||||||
impl Serialize for net::Ipv6Addr {
|
impl Serialize for net::Ipv6Addr {
|
||||||
fn serialize<S>(&self, serializer: &mut S) -> Result<(), S::Error>
|
fn serialize<S>(&self, serializer: &mut S) -> Result<(), S::Error>
|
||||||
where S: Serializer,
|
where S: Serializer,
|
||||||
@ -725,6 +772,7 @@ impl Serialize for net::Ipv6Addr {
|
|||||||
|
|
||||||
///////////////////////////////////////////////////////////////////////////////
|
///////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
|
#[cfg(feature = "std")]
|
||||||
impl Serialize for net::SocketAddr {
|
impl Serialize for net::SocketAddr {
|
||||||
fn serialize<S>(&self, serializer: &mut S) -> Result<(), S::Error>
|
fn serialize<S>(&self, serializer: &mut S) -> Result<(), S::Error>
|
||||||
where S: Serializer,
|
where S: Serializer,
|
||||||
@ -736,6 +784,7 @@ impl Serialize for net::SocketAddr {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[cfg(feature = "std")]
|
||||||
impl Serialize for net::SocketAddrV4 {
|
impl Serialize for net::SocketAddrV4 {
|
||||||
fn serialize<S>(&self, serializer: &mut S) -> Result<(), S::Error>
|
fn serialize<S>(&self, serializer: &mut S) -> Result<(), S::Error>
|
||||||
where S: Serializer,
|
where S: Serializer,
|
||||||
@ -744,6 +793,7 @@ impl Serialize for net::SocketAddrV4 {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[cfg(feature = "std")]
|
||||||
impl Serialize for net::SocketAddrV6 {
|
impl Serialize for net::SocketAddrV6 {
|
||||||
fn serialize<S>(&self, serializer: &mut S) -> Result<(), S::Error>
|
fn serialize<S>(&self, serializer: &mut S) -> Result<(), S::Error>
|
||||||
where S: Serializer,
|
where S: Serializer,
|
||||||
@ -754,6 +804,7 @@ impl Serialize for net::SocketAddrV6 {
|
|||||||
|
|
||||||
///////////////////////////////////////////////////////////////////////////////
|
///////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
|
#[cfg(feature = "std")]
|
||||||
impl Serialize for path::Path {
|
impl Serialize for path::Path {
|
||||||
fn serialize<S>(&self, serializer: &mut S) -> Result<(), S::Error>
|
fn serialize<S>(&self, serializer: &mut S) -> Result<(), S::Error>
|
||||||
where S: Serializer,
|
where S: Serializer,
|
||||||
@ -765,6 +816,7 @@ impl Serialize for path::Path {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[cfg(feature = "std")]
|
||||||
impl Serialize for path::PathBuf {
|
impl Serialize for path::PathBuf {
|
||||||
fn serialize<S>(&self, serializer: &mut S) -> Result<(), S::Error>
|
fn serialize<S>(&self, serializer: &mut S) -> Result<(), S::Error>
|
||||||
where S: Serializer,
|
where S: Serializer,
|
||||||
|
@ -1,6 +1,12 @@
|
|||||||
//! Generic serialization framework.
|
//! Generic serialization framework.
|
||||||
|
|
||||||
|
#[cfg(feature = "std")]
|
||||||
use std::error;
|
use std::error;
|
||||||
|
#[cfg(not(feature = "std"))]
|
||||||
|
use error;
|
||||||
|
|
||||||
|
#[cfg(all(feature = "collections", not(feature = "std")))]
|
||||||
|
use collections::String;
|
||||||
|
|
||||||
pub mod impls;
|
pub mod impls;
|
||||||
|
|
||||||
@ -10,8 +16,13 @@ pub mod impls;
|
|||||||
/// `Serializer` error.
|
/// `Serializer` error.
|
||||||
pub trait Error: Sized + error::Error {
|
pub trait Error: Sized + error::Error {
|
||||||
/// Raised when there is general error when deserializing a type.
|
/// Raised when there is general error when deserializing a type.
|
||||||
|
#[cfg(any(feature = "std", feature = "collections"))]
|
||||||
fn custom<T: Into<String>>(msg: T) -> Self;
|
fn custom<T: Into<String>>(msg: T) -> Self;
|
||||||
|
|
||||||
|
/// Raised when there is general error when deserializing a type.
|
||||||
|
#[cfg(all(not(feature = "std"), not(feature = "collections")))]
|
||||||
|
fn custom<T: Into<&'static str>>(msg: T) -> Self;
|
||||||
|
|
||||||
/// Raised when a `Serialize` was passed an incorrect value.
|
/// Raised when a `Serialize` was passed an incorrect value.
|
||||||
fn invalid_value(msg: &str) -> Self {
|
fn invalid_value(msg: &str) -> Self {
|
||||||
Error::custom(format!("invalid value: {}", msg))
|
Error::custom(format!("invalid value: {}", msg))
|
||||||
@ -111,13 +122,10 @@ pub trait Serializer {
|
|||||||
/// Serializes a `f64` value.
|
/// Serializes a `f64` value.
|
||||||
fn serialize_f64(&mut self, v: f64) -> Result<(), Self::Error>;
|
fn serialize_f64(&mut self, v: f64) -> Result<(), Self::Error>;
|
||||||
|
|
||||||
/// Serializes a character. By default it serializes it as a `&str` containing a
|
/// Serializes a character. By default it serializes as bytes containing the UTF-8 encoding
|
||||||
/// single character.
|
/// of the character.
|
||||||
#[inline]
|
|
||||||
fn serialize_char(&mut self, v: char) -> Result<(), Self::Error> {
|
fn serialize_char(&mut self, v: char) -> Result<(), Self::Error> {
|
||||||
// FIXME: this allocation is required in order to be compatible with stable rust, which
|
self.serialize_bytes(::utils::encode_utf8(v).as_slice())
|
||||||
// doesn't support encoding a `char` into a stack buffer.
|
|
||||||
self.serialize_str(&v.to_string())
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Serializes a `&str`.
|
/// Serializes a `&str`.
|
||||||
|
72
serde/src/utils.rs
Normal file
72
serde/src/utils.rs
Normal file
@ -0,0 +1,72 @@
|
|||||||
|
//! Private utility functions
|
||||||
|
|
||||||
|
const TAG_CONT: u8 = 0b1000_0000;
|
||||||
|
const TAG_TWO_B: u8 = 0b1100_0000;
|
||||||
|
const TAG_THREE_B: u8 = 0b1110_0000;
|
||||||
|
const TAG_FOUR_B: u8 = 0b1111_0000;
|
||||||
|
const MAX_ONE_B: u32 = 0x80;
|
||||||
|
const MAX_TWO_B: u32 = 0x800;
|
||||||
|
const MAX_THREE_B: u32 = 0x10000;
|
||||||
|
|
||||||
|
#[inline]
|
||||||
|
pub fn encode_utf8(c: char) -> EncodeUtf8 {
|
||||||
|
let code = c as u32;
|
||||||
|
let mut buf = [0; 4];
|
||||||
|
let pos = if code < MAX_ONE_B {
|
||||||
|
buf[3] = code as u8;
|
||||||
|
3
|
||||||
|
} else if code < MAX_TWO_B {
|
||||||
|
buf[2] = (code >> 6 & 0x1F) as u8 | TAG_TWO_B;
|
||||||
|
buf[3] = (code & 0x3F) as u8 | TAG_CONT;
|
||||||
|
2
|
||||||
|
} else if code < MAX_THREE_B {
|
||||||
|
buf[1] = (code >> 12 & 0x0F) as u8 | TAG_THREE_B;
|
||||||
|
buf[2] = (code >> 6 & 0x3F) as u8 | TAG_CONT;
|
||||||
|
buf[3] = (code & 0x3F) as u8 | TAG_CONT;
|
||||||
|
1
|
||||||
|
} else {
|
||||||
|
buf[0] = (code >> 18 & 0x07) as u8 | TAG_FOUR_B;
|
||||||
|
buf[1] = (code >> 12 & 0x3F) as u8 | TAG_CONT;
|
||||||
|
buf[2] = (code >> 6 & 0x3F) as u8 | TAG_CONT;
|
||||||
|
buf[3] = (code & 0x3F) as u8 | TAG_CONT;
|
||||||
|
0
|
||||||
|
};
|
||||||
|
EncodeUtf8 { buf: buf, pos: pos }
|
||||||
|
}
|
||||||
|
|
||||||
|
pub struct EncodeUtf8 {
|
||||||
|
buf: [u8; 4],
|
||||||
|
pos: usize,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl EncodeUtf8 {
|
||||||
|
/// Returns the remaining bytes of this iterator as a slice.
|
||||||
|
pub fn as_slice(&self) -> &[u8] {
|
||||||
|
&self.buf[self.pos..]
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[allow(non_upper_case_globals)]
|
||||||
|
const Pattern_White_Space_table: &'static [(char, char)] = &[
|
||||||
|
('\u{9}', '\u{d}'), ('\u{20}', '\u{20}'), ('\u{85}', '\u{85}'), ('\u{200e}', '\u{200f}'),
|
||||||
|
('\u{2028}', '\u{2029}')
|
||||||
|
];
|
||||||
|
|
||||||
|
fn bsearch_range_table(c: char, r: &'static [(char, char)]) -> bool {
|
||||||
|
use core::cmp::Ordering::{Equal, Less, Greater};
|
||||||
|
r.binary_search_by(|&(lo, hi)| {
|
||||||
|
if c < lo {
|
||||||
|
Greater
|
||||||
|
} else if hi < c {
|
||||||
|
Less
|
||||||
|
} else {
|
||||||
|
Equal
|
||||||
|
}
|
||||||
|
})
|
||||||
|
.is_ok()
|
||||||
|
}
|
||||||
|
|
||||||
|
#[allow(non_snake_case)]
|
||||||
|
pub fn Pattern_White_Space(c: char) -> bool {
|
||||||
|
bsearch_range_table(c, Pattern_White_Space_table)
|
||||||
|
}
|
Loading…
x
Reference in New Issue
Block a user