зеркало из https://github.com/mozilla/gecko-dev.git
Bug 1341102: Revendor rust dependencies; r=bustage
MozReview-Commit-ID: 7hXRyaLssOZ --HG-- rename : third_party/rust/cssparser/src/macros/match_byte.rs => third_party/rust/cssparser/build/match_byte.rs
This commit is contained in:
Родитель
baba07044d
Коммит
6029c24c9d
|
@ -1 +1 @@
|
|||
{"files":{".cargo-ok":"e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855",".gitignore":"e084df3ce631ce22082bd63f9e421e7f4d7a2408d6520de532f6a649e4d320dd",".travis.yml":"f705a11b487bf71c41ebd8223cc1f3cbde0dfdfeea96a100af55e06e93397a1b","Cargo.toml":"c1d0f68b42bff71b04c8e763f13b0141f30dc849bee5b0ab5b9008e3627aac99","LICENSE.md":"90d7e062634054e6866d3c81e6a2b3058a840e6af733e98e80bdfe1a7dec6912","changelist.org":"90bb4036f90c3792c8294de2e3d52a54cc6230c3e5dc78013a781a9aa468f5f3","examples/basic.rs":"57aeca11d5cc5c3d5bb613e78b2ea43a2e80d66c15a2fffae303b165aa4ab41d","logo.png":"ebc5305aae938c1f834cf35302faa8be0f1b7b8c3c3beef5cf6b2f68b9628c35","readme.dev.md":"43bad3bcc13a5c057344d3ba7f64bd2b313f8c133d6afa068108df73e8e8facd","readme.md":"1fe1bda36327400cfedfcf103d58091c8465067b62706b0a368d287ca0312cd9","src/lib.rs":"04d6e4533f4bbb2ce2126bca414f95610075642b223f4e0c0b8f7a573792d7fd","src/refbox.rs":"fe266cec4f9f36942a1a9a9ad094a4bb1003d0c0f3c070cfb6214790d0f21b69","src/serde/mod.rs":"ef0c0a55936d835ae756d84a6ac38de312687d7c0f2cfc6810ec994413464516","src/serde/reader.rs":"6bfde2e2df9b450f6c07576198e47fdc837bbc4ddc74f447c72875c188c72ddc","src/serde/writer.rs":"eb3b439e8822871d715464ef6aca4b93a73b2b57625f9c586b68007f7386ab12","tests/test.rs":"f009e979fda892ad531ddd0f2003f0a7df607b19bd453a53f87c9041dfd9c745"},"package":"62650bb5651ba8f0580cebf4ef255d791b8b0ef53800322661e1bb5791d42966"}
|
||||
{"files":{".cargo-ok":"e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855",".gitignore":"e084df3ce631ce22082bd63f9e421e7f4d7a2408d6520de532f6a649e4d320dd",".travis.yml":"f705a11b487bf71c41ebd8223cc1f3cbde0dfdfeea96a100af55e06e93397a1b","Cargo.toml":"8988a4300b10f78e0a3affbc4530827766c80c0d9847441e42e12017b09f7854","LICENSE.md":"90d7e062634054e6866d3c81e6a2b3058a840e6af733e98e80bdfe1a7dec6912","changelist.org":"90bb4036f90c3792c8294de2e3d52a54cc6230c3e5dc78013a781a9aa468f5f3","examples/basic.rs":"57aeca11d5cc5c3d5bb613e78b2ea43a2e80d66c15a2fffae303b165aa4ab41d","logo.png":"ebc5305aae938c1f834cf35302faa8be0f1b7b8c3c3beef5cf6b2f68b9628c35","readme.dev.md":"43bad3bcc13a5c057344d3ba7f64bd2b313f8c133d6afa068108df73e8e8facd","readme.md":"a70631b99064d77c968edf1e2f59415ff26c307589fa3767243376db44f00800","src/lib.rs":"84f115fcd9fe9a6fad489341f1134a24f178de46bfba6dab774a13212eac32ba","src/refbox.rs":"fe266cec4f9f36942a1a9a9ad094a4bb1003d0c0f3c070cfb6214790d0f21b69","src/serde/mod.rs":"5b4eaf256ec87f08bec20e0ac46184b3b336e87b2cb22f40bae6213613ae3081","src/serde/reader.rs":"8b223500017eff9eb9b634b74acefb96457db124e64fe594511abf12a4ef4207","src/serde/writer.rs":"5fd74db7389aebfd14c126dad56348ea5ad0d58bbbcc91a0757e9451c6ee977f","tests/test.rs":"8f595d83de63c0ce091626fd5875185fa29040cf77c47f3a27ceba30673d6e67"},"package":"db8831e3eb4e9ae608d826876fa422ffb15b47caa89fc1bcb96bfbe4f5ded8b2"}
|
|
@ -1,6 +1,6 @@
|
|||
[package]
|
||||
name = "bincode"
|
||||
version = "1.0.0-alpha2"
|
||||
version = "1.0.0-alpha4"
|
||||
authors = ["Ty Overby <ty@pre-alpha.com>", "Francesco Mazzoli <f@mazzo.li>", "David Tolnay <dtolnay@gmail.com>", "Daniel Griffen"]
|
||||
|
||||
repository = "https://github.com/TyOverby/bincode"
|
||||
|
|
|
@ -16,7 +16,13 @@ perfectly with other stream-based apis such as rust files, network streams,
|
|||
and the [flate2-rs](https://github.com/alexcrichton/flate2-rs) compression
|
||||
library.
|
||||
|
||||
[Api Documentation](http://tyoverby.github.io/bincode/bincode/)
|
||||
## [Api Documentation](http://tyoverby.github.io/bincode/bincode/)
|
||||
|
||||
## Bincode in the wild
|
||||
|
||||
* [google/tarpc](https://github.com/google/tarpc): Bincode is used to serialize and deserialize networked RPC messages.
|
||||
* [servo/webrender](https://github.com/servo/webrender): Bincode records webrender API calls for record/replay-style graphics debugging.
|
||||
* [servo/icp-channel](https://github.com/servo/ipc-channel): Ipc-Channel uses Bincode to send structs between processes using a channel-like API.
|
||||
|
||||
## Example
|
||||
```rust
|
||||
|
|
|
@ -43,7 +43,63 @@ extern crate serde as serde_crate;
|
|||
pub mod refbox;
|
||||
mod serde;
|
||||
|
||||
pub use serde::*;
|
||||
pub mod endian_choice {
|
||||
pub use super::serde::{serialize, serialize_into, deserialize, deserialize_from};
|
||||
}
|
||||
|
||||
use std::io::{Read, Write};
|
||||
|
||||
pub use serde::{Deserializer, Serializer, ErrorKind, Error, Result, serialized_size, serialized_size_bounded};
|
||||
|
||||
/// Deserializes a slice of bytes into an object.
|
||||
///
|
||||
/// This method does not have a size-limit because if you already have the bytes
|
||||
/// in memory, then you don't gain anything by having a limiter.
|
||||
pub fn deserialize<T>(bytes: &[u8]) -> serde::Result<T>
|
||||
where T: serde_crate::Deserialize,
|
||||
{
|
||||
serde::deserialize::<_, byteorder::LittleEndian>(bytes)
|
||||
}
|
||||
|
||||
/// Deserializes an object directly from a `Buffer`ed Reader.
|
||||
///
|
||||
/// If the provided `SizeLimit` is reached, the deserialization will bail immediately.
|
||||
/// A SizeLimit can help prevent an attacker from flooding your server with
|
||||
/// a neverending stream of values that runs your server out of memory.
|
||||
///
|
||||
/// If this returns an `Error`, assume that the buffer that you passed
|
||||
/// in is in an invalid state, as the error could be returned during any point
|
||||
/// in the reading.
|
||||
pub fn deserialize_from<R: ?Sized, T>(reader: &mut R, size_limit: SizeLimit) -> serde::Result<T>
|
||||
where R: Read,
|
||||
T: serde_crate::Deserialize,
|
||||
{
|
||||
serde::deserialize_from::<_, _, byteorder::LittleEndian>(reader, size_limit)
|
||||
}
|
||||
|
||||
/// Serializes an object directly into a `Writer`.
|
||||
///
|
||||
/// If the serialization would take more bytes than allowed by `size_limit`, an error
|
||||
/// is returned and *no bytes* will be written into the `Writer`.
|
||||
///
|
||||
/// If this returns an `Error` (other than SizeLimit), assume that the
|
||||
/// writer is in an invalid state, as writing could bail out in the middle of
|
||||
/// serializing.
|
||||
pub fn serialize_into<W: ?Sized, T: ?Sized>(writer: &mut W, value: &T, size_limit: SizeLimit) -> serde::Result<()>
|
||||
where W: Write, T: serde_crate::Serialize
|
||||
{
|
||||
serde::serialize_into::<_, _, byteorder::LittleEndian>(writer, value, size_limit)
|
||||
}
|
||||
|
||||
/// Serializes a serializable object into a `Vec` of bytes.
|
||||
///
|
||||
/// If the serialization would take more bytes than allowed by `size_limit`,
|
||||
/// an error is returned.
|
||||
pub fn serialize<T: ?Sized>(value: &T, size_limit: SizeLimit) -> serde::Result<Vec<u8>>
|
||||
where T: serde_crate::Serialize
|
||||
{
|
||||
serde::serialize::<_, byteorder::LittleEndian>(value, size_limit)
|
||||
}
|
||||
|
||||
/// A limit on the amount of bytes that can be read or written.
|
||||
///
|
||||
|
|
|
@ -6,6 +6,7 @@ use std::io::{Write, Read};
|
|||
use std::io::Error as IoError;
|
||||
use std::{error, fmt, result};
|
||||
use ::SizeLimit;
|
||||
use byteorder::{ByteOrder};
|
||||
|
||||
pub use self::reader::{
|
||||
Deserializer,
|
||||
|
@ -118,9 +119,8 @@ impl serde::ser::Error for Error {
|
|||
/// If this returns an `Error` (other than SizeLimit), assume that the
|
||||
/// writer is in an invalid state, as writing could bail out in the middle of
|
||||
/// serializing.
|
||||
pub fn serialize_into<W: ?Sized, T: ?Sized>(writer: &mut W, value: &T, size_limit: SizeLimit) -> Result<()>
|
||||
where W: Write,
|
||||
T: serde::Serialize,
|
||||
pub fn serialize_into<W: ?Sized, T: ?Sized, E>(writer: &mut W, value: &T, size_limit: SizeLimit) -> Result<()>
|
||||
where W: Write, T: serde::Serialize, E: ByteOrder
|
||||
{
|
||||
match size_limit {
|
||||
SizeLimit::Infinite => { }
|
||||
|
@ -130,7 +130,7 @@ pub fn serialize_into<W: ?Sized, T: ?Sized>(writer: &mut W, value: &T, size_limi
|
|||
}
|
||||
}
|
||||
|
||||
let mut serializer = Serializer::new(writer);
|
||||
let mut serializer = Serializer::<_, E>::new(writer);
|
||||
serde::Serialize::serialize(value, &mut serializer)
|
||||
}
|
||||
|
||||
|
@ -138,7 +138,7 @@ pub fn serialize_into<W: ?Sized, T: ?Sized>(writer: &mut W, value: &T, size_limi
|
|||
///
|
||||
/// If the serialization would take more bytes than allowed by `size_limit`,
|
||||
/// an error is returned.
|
||||
pub fn serialize<T: ?Sized>(value: &T, size_limit: SizeLimit) -> Result<Vec<u8>>
|
||||
pub fn serialize<T: ?Sized, E: ByteOrder>(value: &T, size_limit: SizeLimit) -> Result<Vec<u8>>
|
||||
where T: serde::Serialize
|
||||
{
|
||||
// Since we are putting values directly into a vector, we can do size
|
||||
|
@ -152,7 +152,7 @@ pub fn serialize<T: ?Sized>(value: &T, size_limit: SizeLimit) -> Result<Vec<u8>>
|
|||
SizeLimit::Infinite => Vec::new()
|
||||
};
|
||||
|
||||
try!(serialize_into(&mut writer, value, SizeLimit::Infinite));
|
||||
try!(serialize_into::<_, _, E>(&mut writer, value, SizeLimit::Infinite));
|
||||
Ok(writer)
|
||||
}
|
||||
|
||||
|
@ -190,11 +190,11 @@ pub fn serialized_size_bounded<T: ?Sized>(value: &T, max: u64) -> Option<u64>
|
|||
/// If this returns an `Error`, assume that the buffer that you passed
|
||||
/// in is in an invalid state, as the error could be returned during any point
|
||||
/// in the reading.
|
||||
pub fn deserialize_from<R: ?Sized, T>(reader: &mut R, size_limit: SizeLimit) -> Result<T>
|
||||
pub fn deserialize_from<R: ?Sized, T, E: ByteOrder>(reader: &mut R, size_limit: SizeLimit) -> Result<T>
|
||||
where R: Read,
|
||||
T: serde::Deserialize,
|
||||
{
|
||||
let mut deserializer = Deserializer::new(reader, size_limit);
|
||||
let mut deserializer = Deserializer::<_, E>::new(reader, size_limit);
|
||||
serde::Deserialize::deserialize(&mut deserializer)
|
||||
}
|
||||
|
||||
|
@ -202,9 +202,9 @@ pub fn deserialize_from<R: ?Sized, T>(reader: &mut R, size_limit: SizeLimit) ->
|
|||
///
|
||||
/// This method does not have a size-limit because if you already have the bytes
|
||||
/// in memory, then you don't gain anything by having a limiter.
|
||||
pub fn deserialize<T>(bytes: &[u8]) -> Result<T>
|
||||
pub fn deserialize<T, E: ByteOrder>(bytes: &[u8]) -> Result<T>
|
||||
where T: serde::Deserialize,
|
||||
{
|
||||
let mut reader = bytes;
|
||||
deserialize_from(&mut reader, SizeLimit::Infinite)
|
||||
deserialize_from::<_, _, E>(&mut reader, SizeLimit::Infinite)
|
||||
}
|
||||
|
|
|
@ -1,6 +1,7 @@
|
|||
use std::io::Read;
|
||||
use std::marker::PhantomData;
|
||||
|
||||
use byteorder::{BigEndian, ReadBytesExt};
|
||||
use byteorder::{ReadBytesExt, ByteOrder};
|
||||
use serde_crate as serde;
|
||||
use serde_crate::de::value::ValueDeserializer;
|
||||
use serde_crate::de::Error as DeError;
|
||||
|
@ -17,18 +18,20 @@ use super::{Result, Error, ErrorKind};
|
|||
/// serde::Deserialize::deserialize(&mut deserializer);
|
||||
/// let bytes_read = d.bytes_read();
|
||||
/// ```
|
||||
pub struct Deserializer<R> {
|
||||
pub struct Deserializer<R, E: ByteOrder> {
|
||||
reader: R,
|
||||
size_limit: SizeLimit,
|
||||
read: u64
|
||||
read: u64,
|
||||
_phantom: PhantomData<E>,
|
||||
}
|
||||
|
||||
impl<R: Read> Deserializer<R> {
|
||||
pub fn new(r: R, size_limit: SizeLimit) -> Deserializer<R> {
|
||||
impl<R: Read, E: ByteOrder> Deserializer<R, E> {
|
||||
pub fn new(r: R, size_limit: SizeLimit) -> Deserializer<R, E> {
|
||||
Deserializer {
|
||||
reader: r,
|
||||
size_limit: size_limit,
|
||||
read: 0
|
||||
read: 0,
|
||||
_phantom: PhantomData
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -51,14 +54,19 @@ impl<R: Read> Deserializer<R> {
|
|||
self.read_bytes(size_of::<T>() as u64)
|
||||
}
|
||||
|
||||
fn read_string(&mut self) -> Result<String> {
|
||||
fn read_vec(&mut self) -> Result<Vec<u8>> {
|
||||
let len = try!(serde::Deserialize::deserialize(&mut *self));
|
||||
try!(self.read_bytes(len));
|
||||
|
||||
let mut buffer = Vec::new();
|
||||
try!(self.reader.by_ref().take(len as u64).read_to_end(&mut buffer));
|
||||
let len = len as usize;
|
||||
let mut bytes = Vec::with_capacity(len);
|
||||
unsafe { bytes.set_len(len); }
|
||||
try!(self.reader.read_exact(&mut bytes));
|
||||
Ok(bytes)
|
||||
}
|
||||
|
||||
String::from_utf8(buffer).map_err(|err|
|
||||
fn read_string(&mut self) -> Result<String> {
|
||||
String::from_utf8(try!(self.read_vec())).map_err(|err|
|
||||
ErrorKind::InvalidEncoding{
|
||||
desc: "error while decoding utf8 string",
|
||||
detail: Some(format!("Deserialize error: {}", err))
|
||||
|
@ -73,14 +81,13 @@ macro_rules! impl_nums {
|
|||
where V: serde::de::Visitor,
|
||||
{
|
||||
try!(self.read_type::<$ty>());
|
||||
let value = try!(self.reader.$reader_method::<BigEndian>());
|
||||
let value = try!(self.reader.$reader_method::<E>());
|
||||
visitor.$visitor_method(value)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
impl<'a, R: Read> serde::Deserializer for &'a mut Deserializer<R> {
|
||||
impl<'a, R: Read, E: ByteOrder> serde::Deserializer for &'a mut Deserializer<R, E> {
|
||||
type Error = Error;
|
||||
|
||||
#[inline]
|
||||
|
@ -192,13 +199,13 @@ impl<'a, R: Read> serde::Deserializer for &'a mut Deserializer<R> {
|
|||
fn deserialize_bytes<V>(self, visitor: V) -> Result<V::Value>
|
||||
where V: serde::de::Visitor,
|
||||
{
|
||||
self.deserialize_seq(visitor)
|
||||
visitor.visit_bytes(&try!(self.read_vec()))
|
||||
}
|
||||
|
||||
fn deserialize_byte_buf<V>(self, visitor: V) -> Result<V::Value>
|
||||
where V: serde::de::Visitor,
|
||||
{
|
||||
self.deserialize_seq(visitor)
|
||||
visitor.visit_byte_buf(try!(self.read_vec()))
|
||||
}
|
||||
|
||||
fn deserialize_enum<V>(self,
|
||||
|
@ -207,7 +214,7 @@ impl<'a, R: Read> serde::Deserializer for &'a mut Deserializer<R> {
|
|||
visitor: V) -> Result<V::Value>
|
||||
where V: serde::de::Visitor,
|
||||
{
|
||||
impl<'a, R: Read + 'a> serde::de::EnumVisitor for &'a mut Deserializer<R> {
|
||||
impl<'a, R: Read + 'a, E: ByteOrder> serde::de::EnumVisitor for &'a mut Deserializer<R, E> {
|
||||
type Error = Error;
|
||||
type Variant = Self;
|
||||
|
||||
|
@ -228,9 +235,9 @@ impl<'a, R: Read> serde::Deserializer for &'a mut Deserializer<R> {
|
|||
visitor: V) -> Result<V::Value>
|
||||
where V: serde::de::Visitor,
|
||||
{
|
||||
struct TupleVisitor<'a, R: Read + 'a>(&'a mut Deserializer<R>);
|
||||
struct TupleVisitor<'a, R: Read + 'a, E: ByteOrder + 'a>(&'a mut Deserializer<R, E>);
|
||||
|
||||
impl<'a, 'b: 'a, R: Read + 'b> serde::de::SeqVisitor for TupleVisitor<'a, R> {
|
||||
impl<'a, 'b: 'a, R: Read + 'b, E: ByteOrder> serde::de::SeqVisitor for TupleVisitor<'a, R, E> {
|
||||
type Error = Error;
|
||||
|
||||
fn visit_seed<T>(&mut self, seed: T) -> Result<Option<T::Value>>
|
||||
|
@ -249,12 +256,12 @@ impl<'a, R: Read> serde::Deserializer for &'a mut Deserializer<R> {
|
|||
visitor: V) -> Result<V::Value>
|
||||
where V: serde::de::Visitor,
|
||||
{
|
||||
struct SeqVisitor<'a, R: Read + 'a> {
|
||||
deserializer: &'a mut Deserializer<R>,
|
||||
struct SeqVisitor<'a, R: Read + 'a, E: ByteOrder + 'a> {
|
||||
deserializer: &'a mut Deserializer<R, E>,
|
||||
len: usize,
|
||||
}
|
||||
|
||||
impl<'a, 'b: 'a, R: Read + 'b> serde::de::SeqVisitor for SeqVisitor<'a, R> {
|
||||
impl<'a, 'b: 'a, R: Read + 'b, E: ByteOrder> serde::de::SeqVisitor for SeqVisitor<'a, R, E> {
|
||||
type Error = Error;
|
||||
|
||||
fn visit_seed<T>(&mut self, seed: T) -> Result<Option<T::Value>>
|
||||
|
@ -298,12 +305,12 @@ impl<'a, R: Read> serde::Deserializer for &'a mut Deserializer<R> {
|
|||
fn deserialize_map<V>(self, visitor: V) -> Result<V::Value>
|
||||
where V: serde::de::Visitor,
|
||||
{
|
||||
struct MapVisitor<'a, R: Read + 'a> {
|
||||
deserializer: &'a mut Deserializer<R>,
|
||||
struct MapVisitor<'a, R: Read + 'a, E: ByteOrder + 'a> {
|
||||
deserializer: &'a mut Deserializer<R, E>,
|
||||
len: usize,
|
||||
}
|
||||
|
||||
impl<'a, 'b: 'a, R: Read + 'b> serde::de::MapVisitor for MapVisitor<'a, R> {
|
||||
impl<'a, 'b: 'a, R: Read + 'b, E: ByteOrder> serde::de::MapVisitor for MapVisitor<'a, R, E> {
|
||||
type Error = Error;
|
||||
|
||||
fn visit_key_seed<K>(&mut self, seed: K) -> Result<Option<K::Value>>
|
||||
|
@ -382,7 +389,7 @@ impl<'a, R: Read> serde::Deserializer for &'a mut Deserializer<R> {
|
|||
}
|
||||
}
|
||||
|
||||
impl<'a, R: Read> serde::de::VariantVisitor for &'a mut Deserializer<R> {
|
||||
impl<'a, R: Read, E: ByteOrder> serde::de::VariantVisitor for &'a mut Deserializer<R, E> {
|
||||
type Error = Error;
|
||||
|
||||
fn visit_unit(self) -> Result<()> {
|
||||
|
|
|
@ -1,9 +1,10 @@
|
|||
use std::io::Write;
|
||||
use std::u32;
|
||||
use std::marker::PhantomData;
|
||||
|
||||
use serde_crate as serde;
|
||||
|
||||
use byteorder::{BigEndian, WriteBytesExt};
|
||||
use byteorder::{WriteBytesExt, ByteOrder};
|
||||
|
||||
use super::{Result, Error, ErrorKind};
|
||||
|
||||
|
@ -11,14 +12,16 @@ use super::{Result, Error, ErrorKind};
|
|||
///
|
||||
/// This struct should not be used often.
|
||||
/// For most cases, prefer the `encode_into` function.
|
||||
pub struct Serializer<W> {
|
||||
pub struct Serializer<W, E: ByteOrder> {
|
||||
writer: W,
|
||||
_phantom: PhantomData<E>,
|
||||
}
|
||||
|
||||
impl<W: Write> Serializer<W> {
|
||||
pub fn new(w: W) -> Serializer<W> {
|
||||
impl<W: Write, E: ByteOrder> Serializer<W, E> {
|
||||
pub fn new(w: W) -> Serializer<W, E> {
|
||||
Serializer {
|
||||
writer: w,
|
||||
_phantom: PhantomData,
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -31,16 +34,16 @@ impl<W: Write> Serializer<W> {
|
|||
}
|
||||
}
|
||||
|
||||
impl<'a, W: Write> serde::Serializer for &'a mut Serializer<W> {
|
||||
impl<'a, W: Write, E: ByteOrder> serde::Serializer for &'a mut Serializer<W, E> {
|
||||
type Ok = ();
|
||||
type Error = Error;
|
||||
type SerializeSeq = Compound<'a, W>;
|
||||
type SerializeTuple = Compound<'a, W>;
|
||||
type SerializeTupleStruct = Compound<'a, W>;
|
||||
type SerializeTupleVariant = Compound<'a, W>;
|
||||
type SerializeMap = Compound<'a, W>;
|
||||
type SerializeStruct = Compound<'a, W>;
|
||||
type SerializeStructVariant = Compound<'a, W>;
|
||||
type SerializeSeq = Compound<'a, W, E>;
|
||||
type SerializeTuple = Compound<'a, W, E>;
|
||||
type SerializeTupleStruct = Compound<'a, W, E>;
|
||||
type SerializeTupleVariant = Compound<'a, W, E>;
|
||||
type SerializeMap = Compound<'a, W, E>;
|
||||
type SerializeStruct = Compound<'a, W, E>;
|
||||
type SerializeStructVariant = Compound<'a, W, E>;
|
||||
|
||||
fn serialize_unit(self) -> Result<()> { Ok(()) }
|
||||
|
||||
|
@ -55,15 +58,15 @@ impl<'a, W: Write> serde::Serializer for &'a mut Serializer<W> {
|
|||
}
|
||||
|
||||
fn serialize_u16(self, v: u16) -> Result<()> {
|
||||
self.writer.write_u16::<BigEndian>(v).map_err(Into::into)
|
||||
self.writer.write_u16::<E>(v).map_err(Into::into)
|
||||
}
|
||||
|
||||
fn serialize_u32(self, v: u32) -> Result<()> {
|
||||
self.writer.write_u32::<BigEndian>(v).map_err(Into::into)
|
||||
self.writer.write_u32::<E>(v).map_err(Into::into)
|
||||
}
|
||||
|
||||
fn serialize_u64(self, v: u64) -> Result<()> {
|
||||
self.writer.write_u64::<BigEndian>(v).map_err(Into::into)
|
||||
self.writer.write_u64::<E>(v).map_err(Into::into)
|
||||
}
|
||||
|
||||
fn serialize_i8(self, v: i8) -> Result<()> {
|
||||
|
@ -71,23 +74,23 @@ impl<'a, W: Write> serde::Serializer for &'a mut Serializer<W> {
|
|||
}
|
||||
|
||||
fn serialize_i16(self, v: i16) -> Result<()> {
|
||||
self.writer.write_i16::<BigEndian>(v).map_err(Into::into)
|
||||
self.writer.write_i16::<E>(v).map_err(Into::into)
|
||||
}
|
||||
|
||||
fn serialize_i32(self, v: i32) -> Result<()> {
|
||||
self.writer.write_i32::<BigEndian>(v).map_err(Into::into)
|
||||
self.writer.write_i32::<E>(v).map_err(Into::into)
|
||||
}
|
||||
|
||||
fn serialize_i64(self, v: i64) -> Result<()> {
|
||||
self.writer.write_i64::<BigEndian>(v).map_err(Into::into)
|
||||
self.writer.write_i64::<E>(v).map_err(Into::into)
|
||||
}
|
||||
|
||||
fn serialize_f32(self, v: f32) -> Result<()> {
|
||||
self.writer.write_f32::<BigEndian>(v).map_err(Into::into)
|
||||
self.writer.write_f32::<E>(v).map_err(Into::into)
|
||||
}
|
||||
|
||||
fn serialize_f64(self, v: f64) -> Result<()> {
|
||||
self.writer.write_f64::<BigEndian>(v).map_err(Into::into)
|
||||
self.writer.write_f64::<E>(v).map_err(Into::into)
|
||||
}
|
||||
|
||||
fn serialize_str(self, v: &str) -> Result<()> {
|
||||
|
@ -384,12 +387,12 @@ impl<'a> serde::Serializer for &'a mut SizeChecker {
|
|||
}
|
||||
|
||||
#[doc(hidden)]
|
||||
pub struct Compound<'a, W: 'a> {
|
||||
ser: &'a mut Serializer<W>,
|
||||
pub struct Compound<'a, W: 'a, E: ByteOrder + 'a> {
|
||||
ser: &'a mut Serializer<W, E>,
|
||||
}
|
||||
|
||||
impl<'a, W> serde::ser::SerializeSeq for Compound<'a, W>
|
||||
where W: Write
|
||||
impl<'a, W, E> serde::ser::SerializeSeq for Compound<'a, W, E>
|
||||
where W: Write, E: ByteOrder
|
||||
{
|
||||
type Ok = ();
|
||||
type Error = Error;
|
||||
|
@ -407,8 +410,8 @@ impl<'a, W> serde::ser::SerializeSeq for Compound<'a, W>
|
|||
}
|
||||
}
|
||||
|
||||
impl<'a, W> serde::ser::SerializeTuple for Compound<'a, W>
|
||||
where W: Write
|
||||
impl<'a, W, E> serde::ser::SerializeTuple for Compound<'a, W, E>
|
||||
where W: Write, E: ByteOrder
|
||||
{
|
||||
type Ok = ();
|
||||
type Error = Error;
|
||||
|
@ -426,8 +429,8 @@ impl<'a, W> serde::ser::SerializeTuple for Compound<'a, W>
|
|||
}
|
||||
}
|
||||
|
||||
impl<'a, W> serde::ser::SerializeTupleStruct for Compound<'a, W>
|
||||
where W: Write
|
||||
impl<'a, W, E> serde::ser::SerializeTupleStruct for Compound<'a, W, E>
|
||||
where W: Write, E: ByteOrder
|
||||
{
|
||||
type Ok = ();
|
||||
type Error = Error;
|
||||
|
@ -445,8 +448,8 @@ impl<'a, W> serde::ser::SerializeTupleStruct for Compound<'a, W>
|
|||
}
|
||||
}
|
||||
|
||||
impl<'a, W> serde::ser::SerializeTupleVariant for Compound<'a, W>
|
||||
where W: Write
|
||||
impl<'a, W, E> serde::ser::SerializeTupleVariant for Compound<'a, W, E>
|
||||
where W: Write, E: ByteOrder
|
||||
{
|
||||
type Ok = ();
|
||||
type Error = Error;
|
||||
|
@ -464,8 +467,8 @@ impl<'a, W> serde::ser::SerializeTupleVariant for Compound<'a, W>
|
|||
}
|
||||
}
|
||||
|
||||
impl<'a, W> serde::ser::SerializeMap for Compound<'a, W>
|
||||
where W: Write
|
||||
impl<'a, W, E> serde::ser::SerializeMap for Compound<'a, W, E>
|
||||
where W: Write, E: ByteOrder
|
||||
{
|
||||
type Ok = ();
|
||||
type Error = Error;
|
||||
|
@ -490,8 +493,8 @@ impl<'a, W> serde::ser::SerializeMap for Compound<'a, W>
|
|||
}
|
||||
}
|
||||
|
||||
impl<'a, W> serde::ser::SerializeStruct for Compound<'a, W>
|
||||
where W: Write
|
||||
impl<'a, W, E> serde::ser::SerializeStruct for Compound<'a, W, E>
|
||||
where W: Write, E: ByteOrder
|
||||
{
|
||||
type Ok = ();
|
||||
type Error = Error;
|
||||
|
@ -509,8 +512,8 @@ impl<'a, W> serde::ser::SerializeStruct for Compound<'a, W>
|
|||
}
|
||||
}
|
||||
|
||||
impl<'a, W> serde::ser::SerializeStructVariant for Compound<'a, W>
|
||||
where W: Write
|
||||
impl<'a, W, E> serde::ser::SerializeStructVariant for Compound<'a, W, E>
|
||||
where W: Write, E: ByteOrder
|
||||
{
|
||||
type Ok = ();
|
||||
type Error = Error;
|
||||
|
|
|
@ -3,6 +3,7 @@ extern crate serde_derive;
|
|||
|
||||
extern crate bincode;
|
||||
extern crate serde;
|
||||
extern crate byteorder;
|
||||
|
||||
use std::fmt::Debug;
|
||||
use std::collections::HashMap;
|
||||
|
@ -10,29 +11,13 @@ use std::ops::Deref;
|
|||
|
||||
use bincode::refbox::{RefBox, StrBox, SliceBox};
|
||||
|
||||
use bincode::SizeLimit::{self, Infinite, Bounded};
|
||||
use bincode::{serialize, serialized_size, deserialize, deserialize_from, ErrorKind, Result};
|
||||
use bincode::SizeLimit::{Infinite, Bounded};
|
||||
use bincode::{serialized_size, ErrorKind, Result};
|
||||
use bincode::endian_choice::{serialize, deserialize};
|
||||
|
||||
fn proxy_encode<V>(element: &V, size_limit: SizeLimit) -> Vec<u8>
|
||||
where V: serde::Serialize + serde::Deserialize + PartialEq + Debug + 'static
|
||||
{
|
||||
let v2 = serialize(element, size_limit).unwrap();
|
||||
v2
|
||||
}
|
||||
|
||||
fn proxy_decode<V>(slice: &[u8]) -> V
|
||||
where V: serde::Serialize + serde::Deserialize + PartialEq + Debug + 'static
|
||||
{
|
||||
let e2 = deserialize(slice).unwrap();
|
||||
e2
|
||||
}
|
||||
|
||||
fn proxy_encoded_size<V>(element: &V) -> u64
|
||||
where V: serde::Serialize + PartialEq + Debug + 'static
|
||||
{
|
||||
let serde_size = serialized_size(element);
|
||||
serde_size
|
||||
}
|
||||
use bincode::serialize as serialize_little;
|
||||
use bincode::deserialize as deserialize_little;
|
||||
use bincode::deserialize_from as deserialize_from_little;
|
||||
|
||||
fn the_same<V>(element: V)
|
||||
where V: serde::Serialize+serde::Deserialize+PartialEq+Debug+'static
|
||||
|
@ -42,20 +27,35 @@ fn the_same<V>(element: V)
|
|||
where V: serde::Serialize + serde::Deserialize + PartialEq + Debug + 'static
|
||||
{
|
||||
let rf = RefBox::new(v);
|
||||
let encoded = serialize(&rf, Infinite).unwrap();
|
||||
let decoded: RefBox<'static, V> = deserialize(&encoded[..]).unwrap();
|
||||
let encoded = serialize_little(&rf, Infinite).unwrap();
|
||||
let decoded: RefBox<'static, V> = deserialize_little(&encoded[..]).unwrap();
|
||||
|
||||
decoded.take().deref() == v
|
||||
}
|
||||
|
||||
let size = proxy_encoded_size(&element);
|
||||
let size = serialized_size(&element);
|
||||
|
||||
let encoded = proxy_encode(&element, Infinite);
|
||||
let decoded = proxy_decode(&encoded[..]);
|
||||
{
|
||||
let encoded = serialize_little(&element, Infinite);
|
||||
let encoded = encoded.unwrap();
|
||||
let decoded = deserialize_little(&encoded[..]);
|
||||
let decoded = decoded.unwrap();
|
||||
|
||||
assert_eq!(element, decoded);
|
||||
assert_eq!(size, encoded.len() as u64);
|
||||
assert!(ref_box_correct(&element));
|
||||
assert_eq!(element, decoded);
|
||||
assert_eq!(size, encoded.len() as u64);
|
||||
assert!(ref_box_correct(&element));
|
||||
}
|
||||
|
||||
{
|
||||
let encoded = serialize::<_, byteorder::BigEndian>(&element, Infinite);
|
||||
let encoded = encoded.unwrap();
|
||||
let decoded = deserialize::<_, byteorder::BigEndian>(&encoded[..]);
|
||||
let decoded = decoded.unwrap();
|
||||
|
||||
assert_eq!(element, decoded);
|
||||
assert_eq!(size, encoded.len() as u64);
|
||||
assert!(ref_box_correct(&element));
|
||||
}
|
||||
}
|
||||
|
||||
#[test]
|
||||
|
@ -220,26 +220,26 @@ fn deserializing_errors() {
|
|||
}
|
||||
}
|
||||
|
||||
isize_invalid_deserialize(deserialize::<bool>(&vec![0xA][..]));
|
||||
isize_invalid_deserialize(deserialize::<String>(&vec![0, 0, 0, 0, 0, 0, 0, 1, 0xFF][..]));
|
||||
isize_invalid_deserialize(deserialize_little::<bool>(&vec![0xA][..]));
|
||||
isize_invalid_deserialize(deserialize_little::<String>(&vec![1, 0, 0, 0, 0, 0, 0, 0, 0xFF][..]));
|
||||
// Out-of-bounds variant
|
||||
#[derive(Serialize, Deserialize, Debug)]
|
||||
enum Test {
|
||||
One,
|
||||
Two,
|
||||
};
|
||||
isize_invalid_deserialize(deserialize::<Test>(&vec![0, 0, 0, 5][..]));
|
||||
isize_invalid_deserialize(deserialize::<Option<u8>>(&vec![5, 0][..]));
|
||||
isize_invalid_deserialize(deserialize_little::<Test>(&vec![0, 0, 0, 5][..]));
|
||||
isize_invalid_deserialize(deserialize_little::<Option<u8>>(&vec![5, 0][..]));
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn too_big_deserialize() {
|
||||
let serialized = vec![0,0,0,3];
|
||||
let deserialized: Result<u32> = deserialize_from(&mut &serialized[..], Bounded(3));
|
||||
let deserialized: Result<u32> = deserialize_from_little::<_, _>(&mut &serialized[..], Bounded(3));
|
||||
assert!(deserialized.is_err());
|
||||
|
||||
let serialized = vec![0,0,0,3];
|
||||
let deserialized: Result<u32> = deserialize_from(&mut &serialized[..], Bounded(4));
|
||||
let deserialized: Result<u32> = deserialize_from_little::<_, _>(&mut &serialized[..], Bounded(4));
|
||||
assert!(deserialized.is_ok());
|
||||
}
|
||||
|
||||
|
@ -247,8 +247,8 @@ fn too_big_deserialize() {
|
|||
fn char_serialization() {
|
||||
let chars = "Aa\0☺♪";
|
||||
for c in chars.chars() {
|
||||
let encoded = serialize(&c, Bounded(4)).expect("serializing char failed");
|
||||
let decoded: char = deserialize(&encoded).expect("deserializing failed");
|
||||
let encoded = serialize_little(&c, Bounded(4)).expect("serializing char failed");
|
||||
let decoded: char = deserialize_little(&encoded).expect("deserializing failed");
|
||||
assert_eq!(decoded, c);
|
||||
}
|
||||
}
|
||||
|
@ -256,47 +256,47 @@ fn char_serialization() {
|
|||
#[test]
|
||||
fn too_big_char_deserialize() {
|
||||
let serialized = vec![0x41];
|
||||
let deserialized: Result<char> = deserialize_from(&mut &serialized[..], Bounded(1));
|
||||
let deserialized: Result<char> = deserialize_from_little::<_, _>(&mut &serialized[..], Bounded(1));
|
||||
assert!(deserialized.is_ok());
|
||||
assert_eq!(deserialized.unwrap(), 'A');
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn too_big_serialize() {
|
||||
assert!(serialize(&0u32, Bounded(3)).is_err());
|
||||
assert!(serialize(&0u32, Bounded(4)).is_ok());
|
||||
assert!(serialize_little(&0u32, Bounded(3)).is_err());
|
||||
assert!(serialize_little(&0u32, Bounded(4)).is_ok());
|
||||
|
||||
assert!(serialize(&"abcde", Bounded(8 + 4)).is_err());
|
||||
assert!(serialize(&"abcde", Bounded(8 + 5)).is_ok());
|
||||
assert!(serialize_little(&"abcde", Bounded(8 + 4)).is_err());
|
||||
assert!(serialize_little(&"abcde", Bounded(8 + 5)).is_ok());
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_proxy_encoded_size() {
|
||||
assert!(proxy_encoded_size(&0u8) == 1);
|
||||
assert!(proxy_encoded_size(&0u16) == 2);
|
||||
assert!(proxy_encoded_size(&0u32) == 4);
|
||||
assert!(proxy_encoded_size(&0u64) == 8);
|
||||
assert!(serialized_size(&0u8) == 1);
|
||||
assert!(serialized_size(&0u16) == 2);
|
||||
assert!(serialized_size(&0u32) == 4);
|
||||
assert!(serialized_size(&0u64) == 8);
|
||||
|
||||
// length isize stored as u64
|
||||
assert!(proxy_encoded_size(&"") == 8);
|
||||
assert!(proxy_encoded_size(&"a") == 8 + 1);
|
||||
assert!(serialized_size(&"") == 8);
|
||||
assert!(serialized_size(&"a") == 8 + 1);
|
||||
|
||||
assert!(proxy_encoded_size(&vec![0u32, 1u32, 2u32]) == 8 + 3 * (4))
|
||||
assert!(serialized_size(&vec![0u32, 1u32, 2u32]) == 8 + 3 * (4))
|
||||
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_serialized_size() {
|
||||
assert!(proxy_encoded_size(&0u8) == 1);
|
||||
assert!(proxy_encoded_size(&0u16) == 2);
|
||||
assert!(proxy_encoded_size(&0u32) == 4);
|
||||
assert!(proxy_encoded_size(&0u64) == 8);
|
||||
assert!(serialized_size(&0u8) == 1);
|
||||
assert!(serialized_size(&0u16) == 2);
|
||||
assert!(serialized_size(&0u32) == 4);
|
||||
assert!(serialized_size(&0u64) == 8);
|
||||
|
||||
// length isize stored as u64
|
||||
assert!(proxy_encoded_size(&"") == 8);
|
||||
assert!(proxy_encoded_size(&"a") == 8 + 1);
|
||||
assert!(serialized_size(&"") == 8);
|
||||
assert!(serialized_size(&"a") == 8 + 1);
|
||||
|
||||
assert!(proxy_encoded_size(&vec![0u32, 1u32, 2u32]) == 8 + 3 * (4))
|
||||
assert!(serialized_size(&vec![0u32, 1u32, 2u32]) == 8 + 3 * (4))
|
||||
}
|
||||
|
||||
#[test]
|
||||
|
@ -319,8 +319,8 @@ fn test_refbox_serialize() {
|
|||
|
||||
// Test 1
|
||||
{
|
||||
let serialized = serialize(&Message::M1(RefBox::new(&large_object)), Infinite).unwrap();
|
||||
let deserialized: Message<'static> = deserialize_from(&mut &serialized[..], Infinite).unwrap();
|
||||
let serialized = serialize_little(&Message::M1(RefBox::new(&large_object)), Infinite).unwrap();
|
||||
let deserialized: Message<'static> = deserialize_from_little(&mut &serialized[..], Infinite).unwrap();
|
||||
|
||||
match deserialized {
|
||||
Message::M1(b) => assert!(b.take().deref() == &large_object),
|
||||
|
@ -330,8 +330,8 @@ fn test_refbox_serialize() {
|
|||
|
||||
// Test 2
|
||||
{
|
||||
let serialized = serialize(&Message::M2(RefBox::new(&large_map)), Infinite).unwrap();
|
||||
let deserialized: Message<'static> = deserialize_from(&mut &serialized[..], Infinite).unwrap();
|
||||
let serialized = serialize_little(&Message::M2(RefBox::new(&large_map)), Infinite).unwrap();
|
||||
let deserialized: Message<'static> = deserialize_from_little(&mut &serialized[..], Infinite).unwrap();
|
||||
|
||||
match deserialized {
|
||||
Message::M2(b) => assert!(b.take().deref() == &large_map),
|
||||
|
@ -343,8 +343,8 @@ fn test_refbox_serialize() {
|
|||
#[test]
|
||||
fn test_strbox_serialize() {
|
||||
let strx: &'static str = "hello world";
|
||||
let serialized = serialize(&StrBox::new(strx), Infinite).unwrap();
|
||||
let deserialized: StrBox<'static> = deserialize_from(&mut &serialized[..], Infinite).unwrap();
|
||||
let serialized = serialize_little(&StrBox::new(strx), Infinite).unwrap();
|
||||
let deserialized: StrBox<'static> = deserialize_from_little(&mut &serialized[..], Infinite).unwrap();
|
||||
let stringx: String = deserialized.take();
|
||||
assert!(strx == &stringx[..]);
|
||||
}
|
||||
|
@ -352,8 +352,8 @@ fn test_strbox_serialize() {
|
|||
#[test]
|
||||
fn test_slicebox_serialize() {
|
||||
let slice = [1u32, 2, 3 ,4, 5];
|
||||
let serialized = serialize(&SliceBox::new(&slice), Infinite).unwrap();
|
||||
let deserialized: SliceBox<'static, u32> = deserialize_from(&mut &serialized[..], Infinite).unwrap();
|
||||
let serialized = serialize_little(&SliceBox::new(&slice), Infinite).unwrap();
|
||||
let deserialized: SliceBox<'static, u32> = deserialize_from_little(&mut &serialized[..], Infinite).unwrap();
|
||||
{
|
||||
let sb: &[u32] = &deserialized;
|
||||
assert!(slice == sb);
|
||||
|
@ -364,7 +364,7 @@ fn test_slicebox_serialize() {
|
|||
|
||||
#[test]
|
||||
fn test_multi_strings_serialize() {
|
||||
assert!(serialize(&("foo", "bar", "baz"), Infinite).is_ok());
|
||||
assert!(serialize_little(&("foo", "bar", "baz"), Infinite).is_ok());
|
||||
}
|
||||
|
||||
/*
|
||||
|
@ -384,8 +384,8 @@ fn test_oom_protection() {
|
|||
fn path_buf() {
|
||||
use std::path::{Path, PathBuf};
|
||||
let path = Path::new("foo").to_path_buf();
|
||||
let serde_encoded = serialize(&path, Infinite).unwrap();
|
||||
let decoded: PathBuf = deserialize(&serde_encoded).unwrap();
|
||||
let serde_encoded = serialize_little(&path, Infinite).unwrap();
|
||||
let decoded: PathBuf = deserialize_little(&serde_encoded).unwrap();
|
||||
assert!(path.to_str() == decoded.to_str());
|
||||
}
|
||||
|
||||
|
@ -394,8 +394,16 @@ fn bytes() {
|
|||
use serde::bytes::Bytes;
|
||||
|
||||
let data = b"abc\0123";
|
||||
let s = serialize(&data, Infinite).unwrap();
|
||||
let s2 = serialize(&Bytes::new(data), Infinite).unwrap();
|
||||
let s = serialize_little(&data, Infinite).unwrap();
|
||||
let s2 = serialize_little(&Bytes::new(data), Infinite).unwrap();
|
||||
assert_eq!(s[..], s2[8..]);
|
||||
}
|
||||
|
||||
|
||||
#[test]
|
||||
fn endian_difference() {
|
||||
let x = 10u64;
|
||||
let little = serialize_little(&x, Infinite).unwrap();
|
||||
let big = serialize::<_, byteorder::BigEndian>(&x, Infinite).unwrap();
|
||||
assert_ne!(little, big);
|
||||
}
|
||||
|
|
|
@ -1 +1 @@
|
|||
{"files":{".cargo-ok":"e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855",".clog.toml":"f691701bd51b5f311931d0d8f05fa3d78c00dda8d60f3313e21011309c736ff1",".github/CONTRIBUTING.md":"e0db4b38cfc60de0a8d423251fc1f00b794b9754bc1e910fd731bc88edbec068",".github/ISSUE_TEMPLATE.md":"681afbd64b3603e3e82789ceb6841d851eaa7333caec5769173462bab1b5d82b",".gitignore":"57b1cc6deeaf68d35909201e4bb863c7dbec899ceaa17edde7b9fe64ece8c3e9",".travis.yml":"2975b3159624d4ecc4dd29577f378e9d4fa27f1991bfd5042ac3c267fb2cdd38","CHANGELOG.md":"2063be281de14341e47526fb8726000d67b86e2cec63c6d3d0bcb60e0cf8f055","CONTRIBUTORS.md":"62c5e9edb670a0b9315970b1a635a368928cf74b1240bbf1a0dab68d8ca6d598","Cargo.toml":"a38907da1b6af6f34ae4aa196c1d95f56fc16660e28c79cc3ef3604a0261a555","LICENSE-MIT":"6725d1437fc6c77301f2ff0e7d52914cf4f9509213e1078dc77d9356dbe6eac5","README.md":"0385f93d92d48ff5e9ef0522113030b6b8979cc04ff9e98fad827829d6313792","appveyor.yml":"303c64c2cc84c24b3c9ac0b4cd66b98d6bb25dec7d030ed53e5cb6ab3f13ebd1","clap-test.rs":"1021e44ea7981166f988268e619410f8329db8874018f4bc880a4f74b0b8ae76","index.html":"36f9ce4465266f3af9a259444b01c4239200473cabfc848f789f75b322a3ea8f","justfile":"82c20f705bc096a391f4b7232dbf712a0d3f00f9a2229aaa674f035ad0d9650e","rustfmt.toml":"8fd2d63119df515fd5f44e530c709b19d66b09fbc2e22a640bf4b64c57e7d6b3","src/app/help.rs":"f48bfb67331df1ff72da5d404b68a6e2049203ba1a091f701dc212ab0450461b","src/app/macros.rs":"8a8e8fe466da78588affeeadacf5c2a28d00299d387fdb8081ab9314a1d0b4eb","src/app/meta.rs":"81414fb8bfb32fa809eb470f3f3deee6610bfe54205240095371708c3d037933","src/app/mod.rs":"090ed3f2e9e070a06ca910236cecd2d24ab9fc1432bbf46b7cc441469b2dcc8c","src/app/parser.rs":"6d0919580b64dc892d1e4e6c78c7d774972761e092574eac1b7a7a43988733f7","src/app/settings.rs":"52d5482b96e9832af1f06d15f5055cfe4cfb1edca0e2bf8f7c3ac7f72e982ec9","src/args/any_arg.rs":"6b1b480083ae2d31805a7d89ffaac8f452378fa19f0ef13bfc5a198707540f82","src/args/arg.rs":"77f8fd843928b7b963d332657ccaee21258fa9831565d225973579718d010ccc","src/args/arg_builder/base.rs":"70a9882495e2bcec53f5c9a370e5e2ae5d3b06559ef7ebda24c8a842c089df67","src/args/arg_builder/flag.rs":"2c20a751707fa0c5cc24afca3d3f3528eb68d9805ff69830bde66699bbcdd889","src/args/arg_builder/mod.rs":"7a32c8fd85b48f7b60e5f2c13dc70fa9100aa65cd933ba419300d28d682bf722","src/args/arg_builder/option.rs":"1a9473b10e94d09a7345c8c1c845a0380cd5234433ef01e0e62dabc28fa57470","src/args/arg_builder/positional.rs":"a60431c4619333ba0ed6e01cabd2d91f412c51f829c05656cf0f1bbf9b03c7da","src/args/arg_builder/switched.rs":"43b4da391b51a475a8a9bd3a396f507c2ae21bbd5a5a923bb8b1fd6d7829f228","src/args/arg_builder/valued.rs":"bdaa6943254e79c332d45af2e623baf2a99f6418a0d47240d7f666940af33e97","src/args/arg_matcher.rs":"16c4c68c253fa5660586dfa09bfa0f5dbae9cb8cb6de5e5f791ba41839ccc2e5","src/args/arg_matches.rs":"5b948efdc025fc9c39c93a84fbda1c8916c400e3557ae09a422aa29091072414","src/args/group.rs":"93797d3b8ca690d9bd23730ede9c490d49678220c70f8a90bf68914ea9eb8e22","src/args/macros.rs":"0dd7ae4c6e26ed78044c3ef90e21259816e544f724dcb09e6a0d92d4fcbc4b1a","src/args/matched_arg.rs":"ce480cff445964707663886ebbdc7c7bc168ac079ea1dafe928305d387ca07f7","src/args/mod.rs":"e15fc06bd63c3ef09c13c38c801b70c3318350456a3171d0110816eb92e0a0e2","src/args/settings.rs":"f1cdaa80def5760c72efdfddb3c509fa6ebbd83defb746dfc8fbfd57bcd080e3","src/args/subcommand.rs":"e1ad9638c33785f1301675de1795b0a4f4b079452aa11f7526d263c2a1179432","src/completions/bash.rs":"d323396378a5770ea09062fe22a6cade8c5ace74f26678dc992d86268a91c270","src/completions/fish.rs":"737084dc358bc3477477ecb18c0ec00e3ddf1bb8c238374ef017aed9f95d0bed","src/completions/macros.rs":"ebad5037e6e63401b1a54498e09d3bd93d1a3a06f045c2990902d47eb9a73774","src/completions/mod.rs":"5d4a734df6a21e6c1e0831a2f7be50a45d2e7bdaf7475589ea78b978643229cd","src/completions/powershell.rs":"e442d7ee240fb8430ed3ffd8abf7abb69f1523452f8dbe960b4b05047b3523c9","src/completions/shell.rs":"c7995ca229fd0d8671761da0aca0513c4f740165f02d06cd97aa0ae881c22cd4","src/completions/zsh.rs":"8ac4576e1cb3b1403dbb35ce146159aa8b29864e1d8201776200d999052b422d","src/errors.rs":"4da870f2002486b107b6b4b3dc8a5c81525b8416cef9aa1efb6bef495e431c09","src/fmt.rs":"284d4fc8463779241341b779b0a69d24368a21d4798862268036855fd331e18a","src/lib.rs":"78ae21e3fcfa8ffd1b9b2e5a846bd083f03b30b23a9bebc7d24249e3b0599d79","src/macros.rs":"ed6407c433813e8f9be366af42433967db3d43aeebab34530f0e3b36aa5ca33c","src/osstringext.rs":"680869e35af8f4f4b7f57bb7121b6274a9781cc6f7de6ba4c95683d1a71bd848","src/strext.rs":"d4418d396069e9c05804f92c042ba7192a4244e46059e2edc98670b45cd2daee","src/suggestions.rs":"ca35c332646fe9d3f93c6263830eaef77c87522f71794bfc986f90fc34229dec","src/usage_parser.rs":"ac23fdbff8a92eb02d0716685513f765dafe04a3d4ec0f4daf7cf40ed37149f7"},"package":"f89819450aa94325998aa83ce7ea142db11ad24c725d6bc48459845e0d6d9f18"}
|
||||
{"files":{".cargo-ok":"e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855",".clog.toml":"f691701bd51b5f311931d0d8f05fa3d78c00dda8d60f3313e21011309c736ff1",".github/CONTRIBUTING.md":"f7eff737f3aa25294802fefb233e3758a64b248781dbbf3262532d693f340a87",".github/ISSUE_TEMPLATE.md":"681afbd64b3603e3e82789ceb6841d851eaa7333caec5769173462bab1b5d82b",".gitignore":"57b1cc6deeaf68d35909201e4bb863c7dbec899ceaa17edde7b9fe64ece8c3e9",".travis.yml":"2975b3159624d4ecc4dd29577f378e9d4fa27f1991bfd5042ac3c267fb2cdd38","CHANGELOG.md":"a1e86059e19fe5dd7c674d1165d31b77d1ec71d0db2aaa43c2442c3d65301ddd","CONTRIBUTORS.md":"62c5e9edb670a0b9315970b1a635a368928cf74b1240bbf1a0dab68d8ca6d598","Cargo.toml":"166690f9a21d1ea2f0492f10b8974d5ad5238eddea9b35cd3507059abb42ba66","LICENSE-MIT":"6725d1437fc6c77301f2ff0e7d52914cf4f9509213e1078dc77d9356dbe6eac5","README.md":"229557cb90d19e7632ec23820271b4aedad872544190b2477b9b43001c937e13","appveyor.yml":"303c64c2cc84c24b3c9ac0b4cd66b98d6bb25dec7d030ed53e5cb6ab3f13ebd1","clap-test.rs":"1021e44ea7981166f988268e619410f8329db8874018f4bc880a4f74b0b8ae76","index.html":"36f9ce4465266f3af9a259444b01c4239200473cabfc848f789f75b322a3ea8f","justfile":"82c20f705bc096a391f4b7232dbf712a0d3f00f9a2229aaa674f035ad0d9650e","rustfmt.toml":"8fd2d63119df515fd5f44e530c709b19d66b09fbc2e22a640bf4b64c57e7d6b3","src/app/help.rs":"f48bfb67331df1ff72da5d404b68a6e2049203ba1a091f701dc212ab0450461b","src/app/macros.rs":"8a8e8fe466da78588affeeadacf5c2a28d00299d387fdb8081ab9314a1d0b4eb","src/app/meta.rs":"81414fb8bfb32fa809eb470f3f3deee6610bfe54205240095371708c3d037933","src/app/mod.rs":"b36db7c4a404d04e58be00d3a720b87ed071f9234937cac5e77b938ac29d4f3f","src/app/parser.rs":"7aa95d1ddaf2941329668d5bd92c4a0b96ab00b8525207a0fa630e5d633d05e5","src/app/settings.rs":"52d5482b96e9832af1f06d15f5055cfe4cfb1edca0e2bf8f7c3ac7f72e982ec9","src/args/any_arg.rs":"6b1b480083ae2d31805a7d89ffaac8f452378fa19f0ef13bfc5a198707540f82","src/args/arg.rs":"77f8fd843928b7b963d332657ccaee21258fa9831565d225973579718d010ccc","src/args/arg_builder/base.rs":"70a9882495e2bcec53f5c9a370e5e2ae5d3b06559ef7ebda24c8a842c089df67","src/args/arg_builder/flag.rs":"2c20a751707fa0c5cc24afca3d3f3528eb68d9805ff69830bde66699bbcdd889","src/args/arg_builder/mod.rs":"7a32c8fd85b48f7b60e5f2c13dc70fa9100aa65cd933ba419300d28d682bf722","src/args/arg_builder/option.rs":"1a9473b10e94d09a7345c8c1c845a0380cd5234433ef01e0e62dabc28fa57470","src/args/arg_builder/positional.rs":"a60431c4619333ba0ed6e01cabd2d91f412c51f829c05656cf0f1bbf9b03c7da","src/args/arg_builder/switched.rs":"43b4da391b51a475a8a9bd3a396f507c2ae21bbd5a5a923bb8b1fd6d7829f228","src/args/arg_builder/valued.rs":"bdaa6943254e79c332d45af2e623baf2a99f6418a0d47240d7f666940af33e97","src/args/arg_matcher.rs":"16c4c68c253fa5660586dfa09bfa0f5dbae9cb8cb6de5e5f791ba41839ccc2e5","src/args/arg_matches.rs":"5b948efdc025fc9c39c93a84fbda1c8916c400e3557ae09a422aa29091072414","src/args/group.rs":"93797d3b8ca690d9bd23730ede9c490d49678220c70f8a90bf68914ea9eb8e22","src/args/macros.rs":"0dd7ae4c6e26ed78044c3ef90e21259816e544f724dcb09e6a0d92d4fcbc4b1a","src/args/matched_arg.rs":"ce480cff445964707663886ebbdc7c7bc168ac079ea1dafe928305d387ca07f7","src/args/mod.rs":"e15fc06bd63c3ef09c13c38c801b70c3318350456a3171d0110816eb92e0a0e2","src/args/settings.rs":"f1cdaa80def5760c72efdfddb3c509fa6ebbd83defb746dfc8fbfd57bcd080e3","src/args/subcommand.rs":"e1ad9638c33785f1301675de1795b0a4f4b079452aa11f7526d263c2a1179432","src/completions/bash.rs":"d323396378a5770ea09062fe22a6cade8c5ace74f26678dc992d86268a91c270","src/completions/fish.rs":"737084dc358bc3477477ecb18c0ec00e3ddf1bb8c238374ef017aed9f95d0bed","src/completions/macros.rs":"ebad5037e6e63401b1a54498e09d3bd93d1a3a06f045c2990902d47eb9a73774","src/completions/mod.rs":"5d4a734df6a21e6c1e0831a2f7be50a45d2e7bdaf7475589ea78b978643229cd","src/completions/powershell.rs":"e442d7ee240fb8430ed3ffd8abf7abb69f1523452f8dbe960b4b05047b3523c9","src/completions/shell.rs":"c7995ca229fd0d8671761da0aca0513c4f740165f02d06cd97aa0ae881c22cd4","src/completions/zsh.rs":"8ac4576e1cb3b1403dbb35ce146159aa8b29864e1d8201776200d999052b422d","src/errors.rs":"4da870f2002486b107b6b4b3dc8a5c81525b8416cef9aa1efb6bef495e431c09","src/fmt.rs":"284d4fc8463779241341b779b0a69d24368a21d4798862268036855fd331e18a","src/lib.rs":"78ae21e3fcfa8ffd1b9b2e5a846bd083f03b30b23a9bebc7d24249e3b0599d79","src/macros.rs":"50bf5bb36a4ca5511d3e1959aedb8d234bd84ff3d4eef0918fe9a269ef050a35","src/osstringext.rs":"680869e35af8f4f4b7f57bb7121b6274a9781cc6f7de6ba4c95683d1a71bd848","src/strext.rs":"d4418d396069e9c05804f92c042ba7192a4244e46059e2edc98670b45cd2daee","src/suggestions.rs":"ca35c332646fe9d3f93c6263830eaef77c87522f71794bfc986f90fc34229dec","src/usage_parser.rs":"ac23fdbff8a92eb02d0716685513f765dafe04a3d4ec0f4daf7cf40ed37149f7"},"package":"7db281b0520e97fbd15cd615dcd8f8bcad0c26f5f7d5effe705f090f39e9a758"}
|
|
@ -52,5 +52,5 @@ I use a [conventional](https://github.com/ajoslin/conventional-changelog/blob/a5
|
|||
|
||||
### Other ways to contribute
|
||||
|
||||
Another really great way to help is if you find an interesting, or helpful way in which to use `clap`. You can either add it to the [examples/](examples) directory, or file an issue and tell me. I'm all about giving credit where credit is due :)
|
||||
Another really great way to help is if you find an interesting, or helpful way in which to use `clap`. You can either add it to the [examples/](../examples) directory, or file an issue and tell me. I'm all about giving credit where credit is due :)
|
||||
|
||||
|
|
|
@ -1,3 +1,25 @@
|
|||
<a name="v2.20.5"></a>
|
||||
### v2.20.5 (2017-02-18)
|
||||
|
||||
|
||||
#### Bug Fixes
|
||||
|
||||
* **clap_app!:** fixes a critical bug of a missing fragment specifier when using `!property` style tags. ([5635c1f94](https://github.com/kbknapp/clap-rs/commit/5e9b9cf4dd80fa66a624374fd04e6545635c1f94))
|
||||
|
||||
|
||||
<a name="v2.20.4"></a>
|
||||
### v2.20.4 (2017-02-15)
|
||||
|
||||
|
||||
#### Bug Fixes
|
||||
|
||||
* **Completions:** fixes a bug that tried to propogate global args multiple times when generating multiple completion scripts ([5e9b9cf4](https://github.com/kbknapp/clap-rs/commit/5e9b9cf4dd80fa66a624374fd04e6545635c1f94), closes [#846](https://github.com/kbknapp/clap-rs/issues/846))
|
||||
|
||||
#### Documentation
|
||||
|
||||
* Fix examples link in CONTRIBUTING.md ([60cf875d](https://github.com/kbknapp/clap-rs/commit/60cf875d67a252e19bb85054be57696fac2c57a1))
|
||||
|
||||
|
||||
<a name="v2.20.3"></a>
|
||||
### v2.20.3 (2017-02-03)
|
||||
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
[package]
|
||||
|
||||
name = "clap"
|
||||
version = "2.20.3"
|
||||
version = "2.20.5"
|
||||
authors = ["Kevin K. <kbknapp@gmail.com>"]
|
||||
exclude = ["examples/*", "clap-test/*", "tests/*", "benches/*", "*.png", "clap-perf/*", "*.dot"]
|
||||
repository = "https://github.com/kbknapp/clap-rs.git"
|
||||
|
@ -10,7 +10,7 @@ homepage = "https://clap.rs/"
|
|||
readme = "README.md"
|
||||
license = "MIT"
|
||||
keywords = ["argument", "command", "arg", "parser", "parse"]
|
||||
categories = ["command-line interface"]
|
||||
categories = ["command-line-interface"]
|
||||
description = """
|
||||
A simple to use, efficient, and full featured Command Line Argument Parser
|
||||
"""
|
||||
|
|
|
@ -45,19 +45,22 @@ Created by [gh-md-toc](https://github.com/ekalinin/github-markdown-toc)
|
|||
|
||||
## What's New
|
||||
|
||||
Here's the highlights for v2.20.2
|
||||
Here's the highlights for v2.20.5
|
||||
|
||||
* fixes a println->debugln typo
|
||||
* **Completions**: fixes bash completions for commands that have an underscore in the name
|
||||
* **Completions**: fixes a bug where ZSH completions would panic if the binary name had an underscore in it
|
||||
* allow final word to be wrapped in wrap_help
|
||||
* **Completions**: fixes a bug where global args weren't included in the generated completion scripts
|
||||
* **Macros Documentation:** adds a warning about changing values in Cargo.toml not triggering a rebuild automatically
|
||||
* Fixes a critical bug in the `clap_app!` macro of a missing fragment specifier when using `!property` style tags.
|
||||
|
||||
Here's the highlights from v2.0.0 to v2.20.2
|
||||
|
||||
* Fixes a critical bug where subcommand settings were being propogated too far
|
||||
* Adds ArgGroup::multiple to the supported YAML fields for building ArgGroups from YAML
|
||||
Here's the highlights from v2.0.0 to v2.20.4
|
||||
|
||||
* Fixes a bug that tried to propogate global args multiple times when generating multiple completion scripts
|
||||
* Fix examples link in CONTRIBUTING.md
|
||||
* **Completions**: fixes bash completions for commands that have an underscore in the name
|
||||
* **Completions**: fixes a bug where ZSH completions would panic if the binary name had an underscore in it
|
||||
* allow final word to be wrapped in wrap_help
|
||||
* **Completions**: fixes a bug where global args weren't included in the generated completion scripts
|
||||
* **Macros Documentation:** adds a warning about changing values in Cargo.toml not triggering a rebuild automatically
|
||||
* Fixes a critical bug where subcommand settings were being propogated too far
|
||||
* Adds ArgGroup::multiple to the supported YAML fields for building ArgGroups from YAML
|
||||
* Fixes a bug where the final word wasn't wrapped in help messages
|
||||
* Fixes finding required arguments in group arguments
|
||||
* **ArgsNegateSubcommands:** disables args being allowed between subcommands
|
||||
|
|
|
@ -400,6 +400,7 @@ impl<'a, 'b> App<'a, 'b> {
|
|||
/// * `{bin}` - Binary name.
|
||||
/// * `{version}` - Version number.
|
||||
/// * `{author}` - Author information.
|
||||
/// * `{about}` - General description (from [`App::about`])
|
||||
/// * `{usage}` - Automatically generated or given usage string.
|
||||
/// * `{all-args}` - Help for all arguments (options, flags, positionals arguments,
|
||||
/// and subcommands) including titles.
|
||||
|
@ -408,7 +409,8 @@ impl<'a, 'b> App<'a, 'b> {
|
|||
/// * `{options}` - Help for options.
|
||||
/// * `{positionals}` - Help for positionals arguments.
|
||||
/// * `{subcommands}` - Help for subcommands.
|
||||
/// * `{after-help}` - Help for flags.
|
||||
/// * `{after-help}` - Help from [`App::after_help`]
|
||||
/// * `{before-help}` - Help from [`App::before_help`]
|
||||
///
|
||||
/// # Examples
|
||||
///
|
||||
|
@ -421,6 +423,9 @@ impl<'a, 'b> App<'a, 'b> {
|
|||
/// ```
|
||||
/// **NOTE:**The template system is, on purpose, very simple. Therefore the tags have to writen
|
||||
/// in the lowercase and without spacing.
|
||||
/// [`App::about`]: ./struct.App.html#method.about
|
||||
/// [`App::after_help`]: ./struct.App.html#method.after_help
|
||||
/// [`App::before_help`]: ./struct.App.html#method.before_help
|
||||
pub fn template<S: Into<&'b str>>(mut self, s: S) -> Self {
|
||||
self.p.meta.template = Some(s.into());
|
||||
self
|
||||
|
|
|
@ -37,6 +37,7 @@ use suggestions;
|
|||
pub struct Parser<'a, 'b>
|
||||
where 'a: 'b
|
||||
{
|
||||
propogated: bool,
|
||||
required: Vec<&'a str>,
|
||||
r_ifs: Vec<(&'a str, &'b str, &'a str)>,
|
||||
pub short_list: Vec<char>,
|
||||
|
@ -69,6 +70,7 @@ pub struct Parser<'a, 'b>
|
|||
impl<'a, 'b> Default for Parser<'a, 'b> {
|
||||
fn default() -> Self {
|
||||
Parser {
|
||||
propogated: false,
|
||||
flags: vec![],
|
||||
opts: vec![],
|
||||
positionals: VecMap::new(),
|
||||
|
@ -114,11 +116,13 @@ impl<'a, 'b> Parser<'a, 'b>
|
|||
}
|
||||
|
||||
pub fn gen_completions_to<W: Write>(&mut self, for_shell: Shell, buf: &mut W) {
|
||||
|
||||
self.propogate_help_version();
|
||||
self.build_bin_names();
|
||||
self.propogate_globals();
|
||||
self.propogate_settings();
|
||||
if !self.propogated {
|
||||
self.propogate_help_version();
|
||||
self.build_bin_names();
|
||||
self.propogate_globals();
|
||||
self.propogate_settings();
|
||||
self.propogated = true;
|
||||
}
|
||||
|
||||
ComplGen::new(self).generate(for_shell, buf)
|
||||
}
|
||||
|
@ -2210,6 +2214,7 @@ impl<'a, 'b> Clone for Parser<'a, 'b>
|
|||
{
|
||||
fn clone(&self) -> Self {
|
||||
Parser {
|
||||
propogated: self.propogated,
|
||||
required: self.required.clone(),
|
||||
short_list: self.short_list.clone(),
|
||||
long_list: self.long_list.clone(),
|
||||
|
|
|
@ -532,7 +532,66 @@ macro_rules! app_from_crate {
|
|||
}
|
||||
|
||||
/// Build `App`, `Arg`s, `SubCommand`s and `Group`s with Usage-string like input
|
||||
/// but without the parsing.
|
||||
/// but without the associated parsing runtime cost.
|
||||
///
|
||||
/// `clap_app!` also supports several shorthand syntaxes.
|
||||
///
|
||||
/// # Examples
|
||||
///
|
||||
/// ```no_run
|
||||
/// # #[macro_use]
|
||||
/// # extern crate clap;
|
||||
/// # fn main() {
|
||||
/// let matches = clap_app!(myapp =>
|
||||
/// (version: "1.0")
|
||||
/// (author: "Kevin K. <kbknapp@gmail.com>")
|
||||
/// (about: "Does awesome things")
|
||||
/// (@arg CONFIG: -c --config +takes_value "Sets a custom config file")
|
||||
/// (@arg INPUT: +required "Sets the input file to use")
|
||||
/// (@arg debug: -d ... "Sets the level of debugging information")
|
||||
/// (@subcommand test =>
|
||||
/// (about: "controls testing features")
|
||||
/// (version: "1.3")
|
||||
/// (author: "Someone E. <someone_else@other.com>")
|
||||
/// (@arg verbose: -v --verbose "Print test information verbosely")
|
||||
/// )
|
||||
/// );
|
||||
/// # }
|
||||
/// ```
|
||||
/// # Shorthand Syntax for Args
|
||||
///
|
||||
/// * A single hyphen followed by a character (such as `-c`) sets the [`Arg::short`]
|
||||
/// * A double hyphen followed by a character or word (such as `--config`) sets [`Arg::long`]
|
||||
/// * Three dots (`...`) sets [`Arg::multiple(true)`]
|
||||
/// * Angled brackets after either a short or long will set [`Arg::value_name`] and
|
||||
/// `Arg::required(true)` such as `--config <FILE>` = `Arg::value_name("FILE")` and
|
||||
/// `Arg::required(true)
|
||||
/// * Square brackets after either a short or long will set [`Arg::value_name`] and
|
||||
/// `Arg::required(false)` such as `--config [FILE]` = `Arg::value_name("FILE")` and
|
||||
/// `Arg::required(false)
|
||||
/// * There are short hand syntaxes for Arg methods that accept booleans
|
||||
/// * A plus sign will set that method to `true` such as `+required` = `Arg::required(true)`
|
||||
/// * An exclamation will set that method to `false` such as `!required` = `Arg::required(false)`
|
||||
/// * A `#{min, max}` will set [`Arg::min_values(min)`] and [`Arg::max_values(max)`]
|
||||
/// * An asterisk (`*`) will set `Arg::required(true)`
|
||||
/// * Curly brackets around a `fn` will set [`Arg::validator`] as in `{fn}` = `Arg::validator(fn)`
|
||||
/// * An Arg method that accepts a string followed by square brackets will set that method such as
|
||||
/// `conflicts_with[FOO]` will set `Arg::conflicts_with("FOO")` (note the lack of quotes around
|
||||
/// `FOO` in the macro)
|
||||
/// * An Arg method that takes a string and can be set multiple times (such as
|
||||
/// [`Arg::conflicts_with`]) followed by square brackets and a list of values separated by spaces
|
||||
/// will set that method such as `conflicts_with[FOO BAR BAZ]` will set
|
||||
/// `Arg::conflicts_with("FOO")`, `Arg::conflicts_with("BAR")`, and `Arg::conflicts_with("BAZ")`
|
||||
/// (note the lack of quotes around the values in the macro)
|
||||
///
|
||||
/// [`Arg::short`]: ./struct.Arg.html#method.short
|
||||
/// [`Arg::long`]: ./struct.Arg.html#method.long
|
||||
/// [`Arg::multiple(true)`]: ./struct.Arg.html#method.multiple
|
||||
/// [`Arg::value_name`]: ./struct.Arg.html#method.value_name
|
||||
/// [`Arg::min_values(min)`]: ./struct.Arg.html#method.min_values
|
||||
/// [`Arg::max_values(max)`]: ./struct.Arg.html#method.max_values
|
||||
/// [`Arg::validator`]: ./struct.Arg.html#method.validator
|
||||
/// [`Arg::conflicts_with`]: ./struct.Arg.html#method.conflicts_with
|
||||
#[macro_export]
|
||||
macro_rules! clap_app {
|
||||
(@app ($builder:expr)) => { $builder };
|
||||
|
@ -625,10 +684,10 @@ macro_rules! clap_app {
|
|||
clap_app!{ @arg ($arg) $modes +required $($tail)* }
|
||||
};
|
||||
// !foo -> .foo(false)
|
||||
(@arg ($arg:expr) $modes:tt !$ident $($tail:tt)*) => {
|
||||
(@arg ($arg:expr) $modes:tt !$ident:ident $($tail:tt)*) => {
|
||||
clap_app!{ @arg ($arg.$ident(false)) $modes $($tail)* }
|
||||
};
|
||||
// foo -> .foo(true)
|
||||
// +foo -> .foo(true)
|
||||
(@arg ($arg:expr) $modes:tt +$ident:ident $($tail:tt)*) => {
|
||||
clap_app!{ @arg ($arg.$ident(true)) $modes $($tail)* }
|
||||
};
|
||||
|
|
|
@ -1 +1 @@
|
|||
{"files":{".cargo-ok":"e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855","Cargo.toml":"ebe4110b0c97747210ec48a874d3b128531f59868f3ee1e169023854413cc948","lib.rs":"f7219b22e9cccc53a02f5a5e40f38d50640042727566913d4b2b579517667983"},"package":"a85e1452f40a50777c8424fa7fcaa7dd7074c7bc5419014fbffe7ea3d750dee8"}
|
||||
{"files":{".cargo-ok":"e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855","Cargo.toml":"e740a473ab5e2339d639a86f1996b1ecc72f25b25f23b2789c836bff1455cf5a","lib.rs":"2b54cf96da2049eb03e4b30a223124e7f5a9c067975d54ec0ecf92f0245777a1"},"package":"b8f0415de0bdbce823c0db204e00a62c8240fa2d3e04cd13ff7c6396e4446b95"}
|
|
@ -1,6 +1,6 @@
|
|||
[package]
|
||||
name = "cssparser-macros"
|
||||
version = "0.1.0"
|
||||
version = "0.2.0"
|
||||
authors = ["Simon Sapin <simon.sapin@exyr.org>"]
|
||||
description = "Procedural macros for cssparser"
|
||||
documentation = "https://docs.rs/cssparser-macros/"
|
||||
|
@ -12,7 +12,7 @@ path = "lib.rs"
|
|||
proc-macro = true
|
||||
|
||||
[dependencies]
|
||||
procedural-masquerade = {path = "../procedural-masquerade", version = "0.1"}
|
||||
phf_codegen = "0.7"
|
||||
quote = "0.3"
|
||||
syn = "0.11"
|
||||
|
||||
quote = "0.3.14"
|
||||
syn = {version = "0.11.8", features = ["full"]}
|
||||
|
|
|
@ -2,6 +2,7 @@
|
|||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||
|
||||
#[macro_use] extern crate procedural_masquerade;
|
||||
extern crate phf_codegen;
|
||||
extern crate proc_macro;
|
||||
#[macro_use] extern crate quote;
|
||||
|
@ -9,115 +10,96 @@ extern crate syn;
|
|||
|
||||
use std::ascii::AsciiExt;
|
||||
|
||||
/// Find a `#[cssparser__assert_ascii_lowercase__data(string = "…", string = "…")]` attribute,
|
||||
/// and panic if any string contains ASCII uppercase letters.
|
||||
#[proc_macro_derive(cssparser__assert_ascii_lowercase,
|
||||
attributes(cssparser__assert_ascii_lowercase__data))]
|
||||
pub fn assert_ascii_lowercase(input: proc_macro::TokenStream) -> proc_macro::TokenStream {
|
||||
let input = syn::parse_macro_input(&input.to_string()).unwrap();
|
||||
let data = list_attr(&input, "cssparser__assert_ascii_lowercase__data");
|
||||
|
||||
for sub_attr in data {
|
||||
let string = sub_attr_value(sub_attr, "string");
|
||||
assert_eq!(*string, string.to_ascii_lowercase(),
|
||||
"the expected strings must be given in ASCII lowercase");
|
||||
define_proc_macros! {
|
||||
/// Input: the arms of a `match` expression.
|
||||
///
|
||||
/// Output: a `MAX_LENGTH` constant with the length of the longest string pattern.
|
||||
///
|
||||
/// Panic if the arms contain non-string patterns,
|
||||
/// or string patterns that contains ASCII uppercase letters.
|
||||
#[allow(non_snake_case)]
|
||||
pub fn cssparser_internal__assert_ascii_lowercase__max_len(input: &str) -> String {
|
||||
let expr = syn::parse_expr(&format!("match x {{ {} }}", input)).unwrap();
|
||||
let arms = match expr {
|
||||
syn::Expr { node: syn::ExprKind::Match(_, ref arms), .. } => arms,
|
||||
_ => panic!("expected a match expression, got {:?}", expr)
|
||||
};
|
||||
max_len(arms.iter().flat_map(|arm| &arm.pats).filter_map(|pattern| {
|
||||
let expr = match *pattern {
|
||||
syn::Pat::Lit(ref expr) => expr,
|
||||
syn::Pat::Wild |
|
||||
syn::Pat::Ident(_, _, None) => return None,
|
||||
syn::Pat::Ident(_, _, Some(ref sub_pattern)) => {
|
||||
match **sub_pattern {
|
||||
syn::Pat::Lit(ref expr) => expr,
|
||||
syn::Pat::Wild => return None,
|
||||
_ => panic!("expected string or wildcard pattern, got {:?}", pattern)
|
||||
}
|
||||
}
|
||||
_ => panic!("expected string or wildcard pattern, got {:?}", pattern)
|
||||
};
|
||||
match **expr {
|
||||
syn::Expr { node: syn::ExprKind::Lit(syn::Lit::Str(ref string, _)), .. } => {
|
||||
assert_eq!(*string, string.to_ascii_lowercase(),
|
||||
"string patterns must be given in ASCII lowercase");
|
||||
Some(string.len())
|
||||
}
|
||||
_ => panic!("expected string pattern, got {:?}", expr)
|
||||
}
|
||||
}))
|
||||
}
|
||||
|
||||
"".parse().unwrap()
|
||||
/// Input: string literals with no separator
|
||||
///
|
||||
/// Output: a `MAX_LENGTH` constant with the length of the longest string.
|
||||
#[allow(non_snake_case)]
|
||||
pub fn cssparser_internal__max_len(input: &str) -> String {
|
||||
max_len(syn::parse_token_trees(input).unwrap().iter().map(|tt| string_literal(tt).len()))
|
||||
}
|
||||
|
||||
/// Input: parsed as token trees. The first TT is a type. (Can be wrapped in parens.)
|
||||
/// following TTs are grouped in pairs, each pair being a key as a string literal
|
||||
/// and the corresponding value as a const expression.
|
||||
///
|
||||
/// Output: a rust-phf map, with keys ASCII-lowercased:
|
||||
/// ```
|
||||
/// static MAP: &'static ::cssparser::phf::Map<&'static str, $ValueType> = …;
|
||||
/// ```
|
||||
#[allow(non_snake_case)]
|
||||
pub fn cssparser_internal__phf_map(input: &str) -> String {
|
||||
let token_trees = syn::parse_token_trees(input).unwrap();
|
||||
let value_type = &token_trees[0];
|
||||
let pairs: Vec<_> = token_trees[1..].chunks(2).map(|chunk| {
|
||||
let key = string_literal(&chunk[0]);
|
||||
let value = &chunk[1];
|
||||
(key.to_ascii_lowercase(), quote!(#value).to_string())
|
||||
}).collect();
|
||||
|
||||
let mut map = phf_codegen::Map::new();
|
||||
map.phf_path("::cssparser::_internal__phf");
|
||||
for &(ref key, ref value) in &pairs {
|
||||
map.entry(&**key, &**value);
|
||||
}
|
||||
|
||||
let mut tokens = quote! {
|
||||
static MAP: ::cssparser::_internal__phf::Map<&'static str, #value_type> =
|
||||
};
|
||||
let mut initializer_bytes = Vec::new();
|
||||
map.build(&mut initializer_bytes).unwrap();
|
||||
tokens.append(::std::str::from_utf8(&initializer_bytes).unwrap());
|
||||
tokens.append(";");
|
||||
tokens.into_string()
|
||||
}
|
||||
}
|
||||
|
||||
/// Find a `#[cssparser__max_len__data(string = "…", string = "…")]` attribute,
|
||||
/// panic if any string contains ASCII uppercase letters,
|
||||
/// emit a `MAX_LENGTH` constant with the length of the longest string.
|
||||
#[proc_macro_derive(cssparser__max_len,
|
||||
attributes(cssparser__max_len__data))]
|
||||
pub fn max_len(input: proc_macro::TokenStream) -> proc_macro::TokenStream {
|
||||
let input = syn::parse_macro_input(&input.to_string()).unwrap();
|
||||
let data = list_attr(&input, "cssparser__max_len__data");
|
||||
|
||||
let lengths = data.iter().map(|sub_attr| sub_attr_value(sub_attr, "string").len());
|
||||
fn max_len<I: Iterator<Item=usize>>(lengths: I) -> String {
|
||||
let max_length = lengths.max().expect("expected at least one string");
|
||||
|
||||
let tokens = quote! {
|
||||
const MAX_LENGTH: usize = #max_length;
|
||||
};
|
||||
|
||||
tokens.as_str().parse().unwrap()
|
||||
quote!( const MAX_LENGTH: usize = #max_length; ).into_string()
|
||||
}
|
||||
|
||||
/// On `struct $Name($ValueType)`, add a new static method
|
||||
/// `fn map() -> &'static ::phf::Map<&'static str, $ValueType>`.
|
||||
/// The map’s content is given as:
|
||||
/// `#[cssparser__phf_map__kv_pairs(key = "…", value = "…", key = "…", value = "…")]`.
|
||||
/// Keys are ASCII-lowercased.
|
||||
#[proc_macro_derive(cssparser__phf_map,
|
||||
attributes(cssparser__phf_map__kv_pairs))]
|
||||
pub fn phf_map(input: proc_macro::TokenStream) -> proc_macro::TokenStream {
|
||||
let input = syn::parse_macro_input(&input.to_string()).unwrap();
|
||||
let name = &input.ident;
|
||||
let value_type = match input.body {
|
||||
syn::Body::Struct(syn::VariantData::Tuple(ref fields)) if fields.len() == 1 => {
|
||||
&fields[0].ty
|
||||
}
|
||||
_ => panic!("expected tuple struct newtype, got {:?}", input.body)
|
||||
};
|
||||
|
||||
let pairs: Vec<_> = list_attr(&input, "cssparser__phf_map__kv_pairs").chunks(2).map(|chunk| {
|
||||
let key = sub_attr_value(&chunk[0], "key");
|
||||
let value = sub_attr_value(&chunk[1], "value");
|
||||
(key.to_ascii_lowercase(), value)
|
||||
}).collect();
|
||||
|
||||
let mut map = phf_codegen::Map::new();
|
||||
for &(ref key, value) in &pairs {
|
||||
map.entry(&**key, value);
|
||||
}
|
||||
|
||||
let mut initializer_bytes = Vec::<u8>::new();
|
||||
let mut initializer_tokens = quote::Tokens::new();
|
||||
map.build(&mut initializer_bytes).unwrap();
|
||||
initializer_tokens.append(::std::str::from_utf8(&initializer_bytes).unwrap());
|
||||
|
||||
let tokens = quote! {
|
||||
impl #name {
|
||||
#[inline]
|
||||
fn map() -> &'static ::phf::Map<&'static str, #value_type> {
|
||||
static MAP: ::phf::Map<&'static str, #value_type> = #initializer_tokens;
|
||||
&MAP
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
tokens.as_str().parse().unwrap()
|
||||
}
|
||||
|
||||
/// Panic if the first attribute isn’t `#[foo(…)]` with the given name,
|
||||
/// or return the parameters.
|
||||
fn list_attr<'a>(input: &'a syn::DeriveInput, expected_name: &str) -> &'a [syn::NestedMetaItem] {
|
||||
for attr in &input.attrs {
|
||||
match attr.value {
|
||||
syn::MetaItem::List(ref name, ref nested) if name == expected_name => {
|
||||
return nested
|
||||
}
|
||||
_ => {}
|
||||
}
|
||||
}
|
||||
panic!("expected a {} attribute", expected_name)
|
||||
}
|
||||
|
||||
/// Panic if `sub_attr` is not a name-value like `foo = "…"` with the given name,
|
||||
/// or return the value.
|
||||
fn sub_attr_value<'a>(sub_attr: &'a syn::NestedMetaItem, expected_name: &str) -> &'a str {
|
||||
match *sub_attr {
|
||||
syn::NestedMetaItem::MetaItem(
|
||||
syn::MetaItem::NameValue(ref name, syn::Lit::Str(ref value, _))
|
||||
)
|
||||
if name == expected_name => {
|
||||
value
|
||||
}
|
||||
_ => {
|
||||
panic!("expected a `{} = \"…\"` parameter to the attribute, got {:?}",
|
||||
expected_name, sub_attr)
|
||||
}
|
||||
fn string_literal(token: &syn::TokenTree) -> &str {
|
||||
match *token {
|
||||
syn::TokenTree::Token(syn::Token::Literal(syn::Lit::Str(ref string, _))) => string,
|
||||
_ => panic!("expected string literal, got {:?}", token)
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1 +1 @@
|
|||
{"files":{".cargo-ok":"e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855",".gitignore":"e32812a8f09b0c5b0b972e2e090f8929eb5b600a37ca7aac2ed07ba10c30291e",".travis.yml":"f1fb4b65964c81bc1240544267ea334f554ca38ae7a74d57066f4d47d2b5d568","Cargo.toml":"b8bd480e473642bfe3a7075661ea5f9ddff03b703dddaddb796cfd0d82ee73f3","LICENSE":"fab3dd6bdab226f1c08630b1dd917e11fcb4ec5e1e020e2c16f83a0a13863e85","README.md":"9afe084d70a5d9396674a2624012d6ac749df35f81e322d2d75b042bf208f523","build.rs":"56bfa720a5982d724661a8029315e801258e67245354aabaf2120b73f853cf3c","docs/.nojekyll":"e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855","docs/404.html":"025861f76f8d1f6d67c20ab624c6e418f4f824385e2dd8ad8732c4ea563c6a2e","docs/index.html":"025861f76f8d1f6d67c20ab624c6e418f4f824385e2dd8ad8732c4ea563c6a2e","src/big-data-url.css":"04a8f6197ea1181123bca48bd1ebd016268e1da40f01b8f21055814e44bf62b8","src/color.rs":"4941bb291e3be9537c70bac16cedb57b338daded2a801b19201302bacae2dca5","src/css-parsing-tests/An+B.json":"d24559c1dad55d3da9d1fca29383edefdfc6046988435d6388a9bc0f28850257","src/css-parsing-tests/LICENSE":"5f9019a92f4aa8917aadc8e035aa673c2c1bf08d5ca2e535a0564106599f44eb","src/css-parsing-tests/README.rst":"775c5f957dd1d46d3ce954aaad219c821d2b64b4a9fb93c42e9737a11131ca44","src/css-parsing-tests/color3.json":"008f080f6f2dbae5ee403ff46aaa40a9a16e68a2b8923446ac6374f04da9e868","src/css-parsing-tests/color3_hsl.json":"09a4a1e51fb78276cdbf2e834cc9234f5b97c35426ddc879e35b2b09990327b5","src/css-parsing-tests/color3_keywords.json":"95609bf9fe762c316878a30f371fa375a2e51c21a6fda24fa188a95cd9118f5c","src/css-parsing-tests/component_value_list.json":"dda7244eb3a4fcf6d296762e285f7031028837d987065a09e584e8d973edc7f3","src/css-parsing-tests/declaration_list.json":"0b85cc3f19e945f838432acbfb9edb003abea13debc4ea27bcdcef25d117eac5","src/css-parsing-tests/make_color3_hsl.py":"df6f4c154c098641aab81d030de53c65d75d9bde429e9d1ff7069cc5b1827031","src/css-parsing-tests/make_color3_keywords.py":"66bccab3f1dea18698fcfd854be79b1fd1cd724dd487e25b1f057b522163aad2","src/css-parsing-tests/one_component_value.json":"8798017709002e14cf11e203c9d716f82d308ce6ba0f6e64ee4eea331b8485c6","src/css-parsing-tests/one_declaration.json":"a34c9da56edfff9e2e21615f059e141b0e878e90f794dc8fa58d65b47cd193ed","src/css-parsing-tests/one_rule.json":"88f7b1b6049be88e1e2827673b75fc9261986b216e8ee6bf09621fecbe274e3c","src/css-parsing-tests/rule_list.json":"97c45e80fb83abef149a4016c5625a74f053e7ad70a2ce5a95c02fce1c195686","src/css-parsing-tests/stylesheet.json":"05f1e10fc486bfbda2c059c313a74ff78c0063c0768b99737cab41969c0c87ce","src/css-parsing-tests/stylesheet_bytes.json":"890fd856a596e61f82cf7ed77920ffe95df89209fdb5ee0afe0b26bdfdb80a42","src/css-parsing-tests/urange.json":"7ce494811fcb64f20597bd11c88dc99bd72445290582e280bf7774f5d15e1ed3","src/from_bytes.rs":"331fe63af2123ae3675b61928a69461b5ac77799fff3ce9978c55cf2c558f4ff","src/lib.rs":"718d9ecd62b66ad0b2337f5f4aa89421ef25bfe12a8a98d0f882059fb3e321b0","src/macros/match_byte.rs":"89e8b941af74df2c204abf808672d3ff278bdec75abc918c41a843260b924677","src/macros/mod.rs":"99ffb7c3dbb5a09c7363db84a6ea439ab848439615b37a2e420710c5be3fbde2","src/nth.rs":"0a5e68bd8a597403e184ebf34e69230ae1e955f92b16b99b3f67cf8730a180a9","src/parser.rs":"99739b79e0829d868fc9d3ded5a20d54023dd4ff4bd71f2d0bf8e20df4f395ac","src/rules_and_declarations.rs":"6b66a986e411a56998546ab0e64de5285df3368d7c4018c7230a1b6cf6bcc532","src/serializer.rs":"4521b58389bd57acced55c3c6130831b7f80eff48ef873c48c5363e0eca0a15c","src/tests.rs":"10e2f5358b4bbbb58ef4ee5fcff5e86db1bbc3462ee892de2171f63cb46125c3","src/tokenizer.rs":"ef1f220224365d46299160191facd2d9e0534e10ef362129cf56cd3dbb87106a","src/unicode_range.rs":"a3accaf00b8e0e93ba9af0863024507b97ddc2646e65c5f7421597a269317ac0"},"package":"d8352ccd22c5ebab558d179e32f6d3dd26eed30252f8420d636bfae5052eb50e"}
|
||||
{"files":{".cargo-ok":"e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855",".gitignore":"e32812a8f09b0c5b0b972e2e090f8929eb5b600a37ca7aac2ed07ba10c30291e",".travis.yml":"f1fb4b65964c81bc1240544267ea334f554ca38ae7a74d57066f4d47d2b5d568","Cargo.toml":"ef633aeb8f29bb5577a87178daaae3dbeb37ca792696be08cce3d48ce5a0f5f4","LICENSE":"fab3dd6bdab226f1c08630b1dd917e11fcb4ec5e1e020e2c16f83a0a13863e85","README.md":"9afe084d70a5d9396674a2624012d6ac749df35f81e322d2d75b042bf208f523","build.rs":"950bcc47a196f07f99f59637c28cc65e02a885130011f90a2b2608248b4724a2","build/match_byte.rs":"89e8b941af74df2c204abf808672d3ff278bdec75abc918c41a843260b924677","docs/.nojekyll":"e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855","docs/404.html":"025861f76f8d1f6d67c20ab624c6e418f4f824385e2dd8ad8732c4ea563c6a2e","docs/index.html":"025861f76f8d1f6d67c20ab624c6e418f4f824385e2dd8ad8732c4ea563c6a2e","src/big-data-url.css":"04a8f6197ea1181123bca48bd1ebd016268e1da40f01b8f21055814e44bf62b8","src/color.rs":"1534825f7462378ad830954168b8d257d82b95709c140ba8e463a6ada05727b7","src/css-parsing-tests/An+B.json":"d24559c1dad55d3da9d1fca29383edefdfc6046988435d6388a9bc0f28850257","src/css-parsing-tests/LICENSE":"5f9019a92f4aa8917aadc8e035aa673c2c1bf08d5ca2e535a0564106599f44eb","src/css-parsing-tests/README.rst":"775c5f957dd1d46d3ce954aaad219c821d2b64b4a9fb93c42e9737a11131ca44","src/css-parsing-tests/color3.json":"008f080f6f2dbae5ee403ff46aaa40a9a16e68a2b8923446ac6374f04da9e868","src/css-parsing-tests/color3_hsl.json":"09a4a1e51fb78276cdbf2e834cc9234f5b97c35426ddc879e35b2b09990327b5","src/css-parsing-tests/color3_keywords.json":"95609bf9fe762c316878a30f371fa375a2e51c21a6fda24fa188a95cd9118f5c","src/css-parsing-tests/component_value_list.json":"dda7244eb3a4fcf6d296762e285f7031028837d987065a09e584e8d973edc7f3","src/css-parsing-tests/declaration_list.json":"0b85cc3f19e945f838432acbfb9edb003abea13debc4ea27bcdcef25d117eac5","src/css-parsing-tests/make_color3_hsl.py":"df6f4c154c098641aab81d030de53c65d75d9bde429e9d1ff7069cc5b1827031","src/css-parsing-tests/make_color3_keywords.py":"66bccab3f1dea18698fcfd854be79b1fd1cd724dd487e25b1f057b522163aad2","src/css-parsing-tests/one_component_value.json":"8798017709002e14cf11e203c9d716f82d308ce6ba0f6e64ee4eea331b8485c6","src/css-parsing-tests/one_declaration.json":"a34c9da56edfff9e2e21615f059e141b0e878e90f794dc8fa58d65b47cd193ed","src/css-parsing-tests/one_rule.json":"88f7b1b6049be88e1e2827673b75fc9261986b216e8ee6bf09621fecbe274e3c","src/css-parsing-tests/rule_list.json":"97c45e80fb83abef149a4016c5625a74f053e7ad70a2ce5a95c02fce1c195686","src/css-parsing-tests/stylesheet.json":"05f1e10fc486bfbda2c059c313a74ff78c0063c0768b99737cab41969c0c87ce","src/css-parsing-tests/stylesheet_bytes.json":"890fd856a596e61f82cf7ed77920ffe95df89209fdb5ee0afe0b26bdfdb80a42","src/css-parsing-tests/urange.json":"7ce494811fcb64f20597bd11c88dc99bd72445290582e280bf7774f5d15e1ed3","src/from_bytes.rs":"331fe63af2123ae3675b61928a69461b5ac77799fff3ce9978c55cf2c558f4ff","src/lib.rs":"517ed8dc4520a1294ecd103b0ffa249550e51f8410124166dddaa2b5488f55af","src/macros.rs":"bd492479eee8c65850bdfc2c9de100eddc224e5d6629cd583219058901cd0ca7","src/nth.rs":"0a5e68bd8a597403e184ebf34e69230ae1e955f92b16b99b3f67cf8730a180a9","src/parser.rs":"99739b79e0829d868fc9d3ded5a20d54023dd4ff4bd71f2d0bf8e20df4f395ac","src/rules_and_declarations.rs":"6b66a986e411a56998546ab0e64de5285df3368d7c4018c7230a1b6cf6bcc532","src/serializer.rs":"4521b58389bd57acced55c3c6130831b7f80eff48ef873c48c5363e0eca0a15c","src/tests.rs":"bfaa3fd5892c6fd32a747d48251eb3262d514dc2b82329086e8c75febed98e95","src/tokenizer.rs":"ef1f220224365d46299160191facd2d9e0534e10ef362129cf56cd3dbb87106a","src/unicode_range.rs":"a3accaf00b8e0e93ba9af0863024507b97ddc2646e65c5f7421597a269317ac0"},"package":"112b0e846ce6b441564c908a2e74d98a2c6f2cbe838b0f32d037d5bfb9e982ca"}
|
|
@ -1,7 +1,7 @@
|
|||
[package]
|
||||
|
||||
name = "cssparser"
|
||||
version = "0.11.0"
|
||||
version = "0.12.0"
|
||||
authors = [ "Simon Sapin <simon.sapin@exyr.org>" ]
|
||||
|
||||
description = "Rust implementation of CSS Syntax Level 3"
|
||||
|
@ -20,10 +20,11 @@ tempdir = "0.3"
|
|||
encoding_rs = "0.5"
|
||||
|
||||
[dependencies]
|
||||
cssparser-macros = {path = "./macros", version = "0.1"}
|
||||
cssparser-macros = {path = "./macros", version = "0.2"}
|
||||
heapsize = {version = "0.3", optional = true}
|
||||
matches = "0.1"
|
||||
phf = "0.7"
|
||||
procedural-masquerade = {path = "./procedural-masquerade", version = "0.1"}
|
||||
serde = {version = "0.9", optional = true}
|
||||
|
||||
[build-dependencies]
|
||||
|
@ -35,4 +36,4 @@ bench = []
|
|||
dummy_match_byte = []
|
||||
|
||||
[workspace]
|
||||
members = [".", "./macros"]
|
||||
members = [".", "./macros", "./procedural-masquerade"]
|
||||
|
|
|
@ -16,18 +16,18 @@ mod codegen {
|
|||
}
|
||||
|
||||
#[cfg(not(feature = "dummy_match_byte"))]
|
||||
#[path = "src/macros/mod.rs"]
|
||||
mod macros;
|
||||
#[path = "build/match_byte.rs"]
|
||||
mod match_byte;
|
||||
|
||||
#[cfg(not(feature = "dummy_match_byte"))]
|
||||
mod codegen {
|
||||
use macros;
|
||||
use match_byte;
|
||||
use std::env;
|
||||
use std::path::Path;
|
||||
|
||||
pub fn main(tokenizer_rs: &Path) {
|
||||
macros::match_byte::expand(tokenizer_rs,
|
||||
&Path::new(&env::var("OUT_DIR").unwrap()).join("tokenizer.rs"));
|
||||
match_byte::expand(tokenizer_rs,
|
||||
&Path::new(&env::var("OUT_DIR").unwrap()).join("tokenizer.rs"));
|
||||
|
||||
}
|
||||
}
|
||||
|
|
|
@ -180,162 +180,162 @@ pub fn parse_color_keyword(ident: &str) -> Result<Color, ()> {
|
|||
}
|
||||
}
|
||||
ascii_case_insensitive_phf_map! {
|
||||
KEYWORDS: Map<Color> = {
|
||||
"black" => "rgb!(0, 0, 0)",
|
||||
"silver" => "rgb!(192, 192, 192)",
|
||||
"gray" => "rgb!(128, 128, 128)",
|
||||
"white" => "rgb!(255, 255, 255)",
|
||||
"maroon" => "rgb!(128, 0, 0)",
|
||||
"red" => "rgb!(255, 0, 0)",
|
||||
"purple" => "rgb!(128, 0, 128)",
|
||||
"fuchsia" => "rgb!(255, 0, 255)",
|
||||
"green" => "rgb!(0, 128, 0)",
|
||||
"lime" => "rgb!(0, 255, 0)",
|
||||
"olive" => "rgb!(128, 128, 0)",
|
||||
"yellow" => "rgb!(255, 255, 0)",
|
||||
"navy" => "rgb!(0, 0, 128)",
|
||||
"blue" => "rgb!(0, 0, 255)",
|
||||
"teal" => "rgb!(0, 128, 128)",
|
||||
"aqua" => "rgb!(0, 255, 255)",
|
||||
keyword -> Color = {
|
||||
"black" => rgb!(0, 0, 0),
|
||||
"silver" => rgb!(192, 192, 192),
|
||||
"gray" => rgb!(128, 128, 128),
|
||||
"white" => rgb!(255, 255, 255),
|
||||
"maroon" => rgb!(128, 0, 0),
|
||||
"red" => rgb!(255, 0, 0),
|
||||
"purple" => rgb!(128, 0, 128),
|
||||
"fuchsia" => rgb!(255, 0, 255),
|
||||
"green" => rgb!(0, 128, 0),
|
||||
"lime" => rgb!(0, 255, 0),
|
||||
"olive" => rgb!(128, 128, 0),
|
||||
"yellow" => rgb!(255, 255, 0),
|
||||
"navy" => rgb!(0, 0, 128),
|
||||
"blue" => rgb!(0, 0, 255),
|
||||
"teal" => rgb!(0, 128, 128),
|
||||
"aqua" => rgb!(0, 255, 255),
|
||||
|
||||
"aliceblue" => "rgb!(240, 248, 255)",
|
||||
"antiquewhite" => "rgb!(250, 235, 215)",
|
||||
"aquamarine" => "rgb!(127, 255, 212)",
|
||||
"azure" => "rgb!(240, 255, 255)",
|
||||
"beige" => "rgb!(245, 245, 220)",
|
||||
"bisque" => "rgb!(255, 228, 196)",
|
||||
"blanchedalmond" => "rgb!(255, 235, 205)",
|
||||
"blueviolet" => "rgb!(138, 43, 226)",
|
||||
"brown" => "rgb!(165, 42, 42)",
|
||||
"burlywood" => "rgb!(222, 184, 135)",
|
||||
"cadetblue" => "rgb!(95, 158, 160)",
|
||||
"chartreuse" => "rgb!(127, 255, 0)",
|
||||
"chocolate" => "rgb!(210, 105, 30)",
|
||||
"coral" => "rgb!(255, 127, 80)",
|
||||
"cornflowerblue" => "rgb!(100, 149, 237)",
|
||||
"cornsilk" => "rgb!(255, 248, 220)",
|
||||
"crimson" => "rgb!(220, 20, 60)",
|
||||
"cyan" => "rgb!(0, 255, 255)",
|
||||
"darkblue" => "rgb!(0, 0, 139)",
|
||||
"darkcyan" => "rgb!(0, 139, 139)",
|
||||
"darkgoldenrod" => "rgb!(184, 134, 11)",
|
||||
"darkgray" => "rgb!(169, 169, 169)",
|
||||
"darkgreen" => "rgb!(0, 100, 0)",
|
||||
"darkgrey" => "rgb!(169, 169, 169)",
|
||||
"darkkhaki" => "rgb!(189, 183, 107)",
|
||||
"darkmagenta" => "rgb!(139, 0, 139)",
|
||||
"darkolivegreen" => "rgb!(85, 107, 47)",
|
||||
"darkorange" => "rgb!(255, 140, 0)",
|
||||
"darkorchid" => "rgb!(153, 50, 204)",
|
||||
"darkred" => "rgb!(139, 0, 0)",
|
||||
"darksalmon" => "rgb!(233, 150, 122)",
|
||||
"darkseagreen" => "rgb!(143, 188, 143)",
|
||||
"darkslateblue" => "rgb!(72, 61, 139)",
|
||||
"darkslategray" => "rgb!(47, 79, 79)",
|
||||
"darkslategrey" => "rgb!(47, 79, 79)",
|
||||
"darkturquoise" => "rgb!(0, 206, 209)",
|
||||
"darkviolet" => "rgb!(148, 0, 211)",
|
||||
"deeppink" => "rgb!(255, 20, 147)",
|
||||
"deepskyblue" => "rgb!(0, 191, 255)",
|
||||
"dimgray" => "rgb!(105, 105, 105)",
|
||||
"dimgrey" => "rgb!(105, 105, 105)",
|
||||
"dodgerblue" => "rgb!(30, 144, 255)",
|
||||
"firebrick" => "rgb!(178, 34, 34)",
|
||||
"floralwhite" => "rgb!(255, 250, 240)",
|
||||
"forestgreen" => "rgb!(34, 139, 34)",
|
||||
"gainsboro" => "rgb!(220, 220, 220)",
|
||||
"ghostwhite" => "rgb!(248, 248, 255)",
|
||||
"gold" => "rgb!(255, 215, 0)",
|
||||
"goldenrod" => "rgb!(218, 165, 32)",
|
||||
"greenyellow" => "rgb!(173, 255, 47)",
|
||||
"grey" => "rgb!(128, 128, 128)",
|
||||
"honeydew" => "rgb!(240, 255, 240)",
|
||||
"hotpink" => "rgb!(255, 105, 180)",
|
||||
"indianred" => "rgb!(205, 92, 92)",
|
||||
"indigo" => "rgb!(75, 0, 130)",
|
||||
"ivory" => "rgb!(255, 255, 240)",
|
||||
"khaki" => "rgb!(240, 230, 140)",
|
||||
"lavender" => "rgb!(230, 230, 250)",
|
||||
"lavenderblush" => "rgb!(255, 240, 245)",
|
||||
"lawngreen" => "rgb!(124, 252, 0)",
|
||||
"lemonchiffon" => "rgb!(255, 250, 205)",
|
||||
"lightblue" => "rgb!(173, 216, 230)",
|
||||
"lightcoral" => "rgb!(240, 128, 128)",
|
||||
"lightcyan" => "rgb!(224, 255, 255)",
|
||||
"lightgoldenrodyellow" => "rgb!(250, 250, 210)",
|
||||
"lightgray" => "rgb!(211, 211, 211)",
|
||||
"lightgreen" => "rgb!(144, 238, 144)",
|
||||
"lightgrey" => "rgb!(211, 211, 211)",
|
||||
"lightpink" => "rgb!(255, 182, 193)",
|
||||
"lightsalmon" => "rgb!(255, 160, 122)",
|
||||
"lightseagreen" => "rgb!(32, 178, 170)",
|
||||
"lightskyblue" => "rgb!(135, 206, 250)",
|
||||
"lightslategray" => "rgb!(119, 136, 153)",
|
||||
"lightslategrey" => "rgb!(119, 136, 153)",
|
||||
"lightsteelblue" => "rgb!(176, 196, 222)",
|
||||
"lightyellow" => "rgb!(255, 255, 224)",
|
||||
"limegreen" => "rgb!(50, 205, 50)",
|
||||
"linen" => "rgb!(250, 240, 230)",
|
||||
"magenta" => "rgb!(255, 0, 255)",
|
||||
"mediumaquamarine" => "rgb!(102, 205, 170)",
|
||||
"mediumblue" => "rgb!(0, 0, 205)",
|
||||
"mediumorchid" => "rgb!(186, 85, 211)",
|
||||
"mediumpurple" => "rgb!(147, 112, 219)",
|
||||
"mediumseagreen" => "rgb!(60, 179, 113)",
|
||||
"mediumslateblue" => "rgb!(123, 104, 238)",
|
||||
"mediumspringgreen" => "rgb!(0, 250, 154)",
|
||||
"mediumturquoise" => "rgb!(72, 209, 204)",
|
||||
"mediumvioletred" => "rgb!(199, 21, 133)",
|
||||
"midnightblue" => "rgb!(25, 25, 112)",
|
||||
"mintcream" => "rgb!(245, 255, 250)",
|
||||
"mistyrose" => "rgb!(255, 228, 225)",
|
||||
"moccasin" => "rgb!(255, 228, 181)",
|
||||
"navajowhite" => "rgb!(255, 222, 173)",
|
||||
"oldlace" => "rgb!(253, 245, 230)",
|
||||
"olivedrab" => "rgb!(107, 142, 35)",
|
||||
"orange" => "rgb!(255, 165, 0)",
|
||||
"orangered" => "rgb!(255, 69, 0)",
|
||||
"orchid" => "rgb!(218, 112, 214)",
|
||||
"palegoldenrod" => "rgb!(238, 232, 170)",
|
||||
"palegreen" => "rgb!(152, 251, 152)",
|
||||
"paleturquoise" => "rgb!(175, 238, 238)",
|
||||
"palevioletred" => "rgb!(219, 112, 147)",
|
||||
"papayawhip" => "rgb!(255, 239, 213)",
|
||||
"peachpuff" => "rgb!(255, 218, 185)",
|
||||
"peru" => "rgb!(205, 133, 63)",
|
||||
"pink" => "rgb!(255, 192, 203)",
|
||||
"plum" => "rgb!(221, 160, 221)",
|
||||
"powderblue" => "rgb!(176, 224, 230)",
|
||||
"rebeccapurple" => "rgb!(102, 51, 153)",
|
||||
"rosybrown" => "rgb!(188, 143, 143)",
|
||||
"royalblue" => "rgb!(65, 105, 225)",
|
||||
"saddlebrown" => "rgb!(139, 69, 19)",
|
||||
"salmon" => "rgb!(250, 128, 114)",
|
||||
"sandybrown" => "rgb!(244, 164, 96)",
|
||||
"seagreen" => "rgb!(46, 139, 87)",
|
||||
"seashell" => "rgb!(255, 245, 238)",
|
||||
"sienna" => "rgb!(160, 82, 45)",
|
||||
"skyblue" => "rgb!(135, 206, 235)",
|
||||
"slateblue" => "rgb!(106, 90, 205)",
|
||||
"slategray" => "rgb!(112, 128, 144)",
|
||||
"slategrey" => "rgb!(112, 128, 144)",
|
||||
"snow" => "rgb!(255, 250, 250)",
|
||||
"springgreen" => "rgb!(0, 255, 127)",
|
||||
"steelblue" => "rgb!(70, 130, 180)",
|
||||
"tan" => "rgb!(210, 180, 140)",
|
||||
"thistle" => "rgb!(216, 191, 216)",
|
||||
"tomato" => "rgb!(255, 99, 71)",
|
||||
"turquoise" => "rgb!(64, 224, 208)",
|
||||
"violet" => "rgb!(238, 130, 238)",
|
||||
"wheat" => "rgb!(245, 222, 179)",
|
||||
"whitesmoke" => "rgb!(245, 245, 245)",
|
||||
"yellowgreen" => "rgb!(154, 205, 50)",
|
||||
"aliceblue" => rgb!(240, 248, 255),
|
||||
"antiquewhite" => rgb!(250, 235, 215),
|
||||
"aquamarine" => rgb!(127, 255, 212),
|
||||
"azure" => rgb!(240, 255, 255),
|
||||
"beige" => rgb!(245, 245, 220),
|
||||
"bisque" => rgb!(255, 228, 196),
|
||||
"blanchedalmond" => rgb!(255, 235, 205),
|
||||
"blueviolet" => rgb!(138, 43, 226),
|
||||
"brown" => rgb!(165, 42, 42),
|
||||
"burlywood" => rgb!(222, 184, 135),
|
||||
"cadetblue" => rgb!(95, 158, 160),
|
||||
"chartreuse" => rgb!(127, 255, 0),
|
||||
"chocolate" => rgb!(210, 105, 30),
|
||||
"coral" => rgb!(255, 127, 80),
|
||||
"cornflowerblue" => rgb!(100, 149, 237),
|
||||
"cornsilk" => rgb!(255, 248, 220),
|
||||
"crimson" => rgb!(220, 20, 60),
|
||||
"cyan" => rgb!(0, 255, 255),
|
||||
"darkblue" => rgb!(0, 0, 139),
|
||||
"darkcyan" => rgb!(0, 139, 139),
|
||||
"darkgoldenrod" => rgb!(184, 134, 11),
|
||||
"darkgray" => rgb!(169, 169, 169),
|
||||
"darkgreen" => rgb!(0, 100, 0),
|
||||
"darkgrey" => rgb!(169, 169, 169),
|
||||
"darkkhaki" => rgb!(189, 183, 107),
|
||||
"darkmagenta" => rgb!(139, 0, 139),
|
||||
"darkolivegreen" => rgb!(85, 107, 47),
|
||||
"darkorange" => rgb!(255, 140, 0),
|
||||
"darkorchid" => rgb!(153, 50, 204),
|
||||
"darkred" => rgb!(139, 0, 0),
|
||||
"darksalmon" => rgb!(233, 150, 122),
|
||||
"darkseagreen" => rgb!(143, 188, 143),
|
||||
"darkslateblue" => rgb!(72, 61, 139),
|
||||
"darkslategray" => rgb!(47, 79, 79),
|
||||
"darkslategrey" => rgb!(47, 79, 79),
|
||||
"darkturquoise" => rgb!(0, 206, 209),
|
||||
"darkviolet" => rgb!(148, 0, 211),
|
||||
"deeppink" => rgb!(255, 20, 147),
|
||||
"deepskyblue" => rgb!(0, 191, 255),
|
||||
"dimgray" => rgb!(105, 105, 105),
|
||||
"dimgrey" => rgb!(105, 105, 105),
|
||||
"dodgerblue" => rgb!(30, 144, 255),
|
||||
"firebrick" => rgb!(178, 34, 34),
|
||||
"floralwhite" => rgb!(255, 250, 240),
|
||||
"forestgreen" => rgb!(34, 139, 34),
|
||||
"gainsboro" => rgb!(220, 220, 220),
|
||||
"ghostwhite" => rgb!(248, 248, 255),
|
||||
"gold" => rgb!(255, 215, 0),
|
||||
"goldenrod" => rgb!(218, 165, 32),
|
||||
"greenyellow" => rgb!(173, 255, 47),
|
||||
"grey" => rgb!(128, 128, 128),
|
||||
"honeydew" => rgb!(240, 255, 240),
|
||||
"hotpink" => rgb!(255, 105, 180),
|
||||
"indianred" => rgb!(205, 92, 92),
|
||||
"indigo" => rgb!(75, 0, 130),
|
||||
"ivory" => rgb!(255, 255, 240),
|
||||
"khaki" => rgb!(240, 230, 140),
|
||||
"lavender" => rgb!(230, 230, 250),
|
||||
"lavenderblush" => rgb!(255, 240, 245),
|
||||
"lawngreen" => rgb!(124, 252, 0),
|
||||
"lemonchiffon" => rgb!(255, 250, 205),
|
||||
"lightblue" => rgb!(173, 216, 230),
|
||||
"lightcoral" => rgb!(240, 128, 128),
|
||||
"lightcyan" => rgb!(224, 255, 255),
|
||||
"lightgoldenrodyellow" => rgb!(250, 250, 210),
|
||||
"lightgray" => rgb!(211, 211, 211),
|
||||
"lightgreen" => rgb!(144, 238, 144),
|
||||
"lightgrey" => rgb!(211, 211, 211),
|
||||
"lightpink" => rgb!(255, 182, 193),
|
||||
"lightsalmon" => rgb!(255, 160, 122),
|
||||
"lightseagreen" => rgb!(32, 178, 170),
|
||||
"lightskyblue" => rgb!(135, 206, 250),
|
||||
"lightslategray" => rgb!(119, 136, 153),
|
||||
"lightslategrey" => rgb!(119, 136, 153),
|
||||
"lightsteelblue" => rgb!(176, 196, 222),
|
||||
"lightyellow" => rgb!(255, 255, 224),
|
||||
"limegreen" => rgb!(50, 205, 50),
|
||||
"linen" => rgb!(250, 240, 230),
|
||||
"magenta" => rgb!(255, 0, 255),
|
||||
"mediumaquamarine" => rgb!(102, 205, 170),
|
||||
"mediumblue" => rgb!(0, 0, 205),
|
||||
"mediumorchid" => rgb!(186, 85, 211),
|
||||
"mediumpurple" => rgb!(147, 112, 219),
|
||||
"mediumseagreen" => rgb!(60, 179, 113),
|
||||
"mediumslateblue" => rgb!(123, 104, 238),
|
||||
"mediumspringgreen" => rgb!(0, 250, 154),
|
||||
"mediumturquoise" => rgb!(72, 209, 204),
|
||||
"mediumvioletred" => rgb!(199, 21, 133),
|
||||
"midnightblue" => rgb!(25, 25, 112),
|
||||
"mintcream" => rgb!(245, 255, 250),
|
||||
"mistyrose" => rgb!(255, 228, 225),
|
||||
"moccasin" => rgb!(255, 228, 181),
|
||||
"navajowhite" => rgb!(255, 222, 173),
|
||||
"oldlace" => rgb!(253, 245, 230),
|
||||
"olivedrab" => rgb!(107, 142, 35),
|
||||
"orange" => rgb!(255, 165, 0),
|
||||
"orangered" => rgb!(255, 69, 0),
|
||||
"orchid" => rgb!(218, 112, 214),
|
||||
"palegoldenrod" => rgb!(238, 232, 170),
|
||||
"palegreen" => rgb!(152, 251, 152),
|
||||
"paleturquoise" => rgb!(175, 238, 238),
|
||||
"palevioletred" => rgb!(219, 112, 147),
|
||||
"papayawhip" => rgb!(255, 239, 213),
|
||||
"peachpuff" => rgb!(255, 218, 185),
|
||||
"peru" => rgb!(205, 133, 63),
|
||||
"pink" => rgb!(255, 192, 203),
|
||||
"plum" => rgb!(221, 160, 221),
|
||||
"powderblue" => rgb!(176, 224, 230),
|
||||
"rebeccapurple" => rgb!(102, 51, 153),
|
||||
"rosybrown" => rgb!(188, 143, 143),
|
||||
"royalblue" => rgb!(65, 105, 225),
|
||||
"saddlebrown" => rgb!(139, 69, 19),
|
||||
"salmon" => rgb!(250, 128, 114),
|
||||
"sandybrown" => rgb!(244, 164, 96),
|
||||
"seagreen" => rgb!(46, 139, 87),
|
||||
"seashell" => rgb!(255, 245, 238),
|
||||
"sienna" => rgb!(160, 82, 45),
|
||||
"skyblue" => rgb!(135, 206, 235),
|
||||
"slateblue" => rgb!(106, 90, 205),
|
||||
"slategray" => rgb!(112, 128, 144),
|
||||
"slategrey" => rgb!(112, 128, 144),
|
||||
"snow" => rgb!(255, 250, 250),
|
||||
"springgreen" => rgb!(0, 255, 127),
|
||||
"steelblue" => rgb!(70, 130, 180),
|
||||
"tan" => rgb!(210, 180, 140),
|
||||
"thistle" => rgb!(216, 191, 216),
|
||||
"tomato" => rgb!(255, 99, 71),
|
||||
"turquoise" => rgb!(64, 224, 208),
|
||||
"violet" => rgb!(238, 130, 238),
|
||||
"wheat" => rgb!(245, 222, 179),
|
||||
"whitesmoke" => rgb!(245, 245, 245),
|
||||
"yellowgreen" => rgb!(154, 205, 50),
|
||||
|
||||
"transparent" => "Color::RGBA(RGBA { red: 0, green: 0, blue: 0, alpha: 0 })",
|
||||
"currentcolor" => "Color::CurrentColor",
|
||||
"transparent" => Color::RGBA(RGBA { red: 0, green: 0, blue: 0, alpha: 0 }),
|
||||
"currentcolor" => Color::CurrentColor,
|
||||
}
|
||||
}
|
||||
KEYWORDS::get(ident).cloned().ok_or(())
|
||||
keyword(ident).cloned().ok_or(())
|
||||
}
|
||||
|
||||
|
||||
|
|
|
@ -70,13 +70,16 @@ fn parse_border_spacing(_context: &ParserContext, input: &mut Parser)
|
|||
|
||||
#[macro_use] extern crate cssparser_macros;
|
||||
#[macro_use] extern crate matches;
|
||||
extern crate phf;
|
||||
#[macro_use] extern crate procedural_masquerade;
|
||||
#[doc(hidden)] pub extern crate phf as _internal__phf;
|
||||
#[cfg(test)] extern crate encoding_rs;
|
||||
#[cfg(test)] extern crate tempdir;
|
||||
#[cfg(test)] extern crate rustc_serialize;
|
||||
#[cfg(feature = "serde")] extern crate serde;
|
||||
#[cfg(feature = "heapsize")] #[macro_use] extern crate heapsize;
|
||||
|
||||
pub use cssparser_macros::*;
|
||||
|
||||
pub use tokenizer::{Token, NumericValue, PercentageValue, SourceLocation};
|
||||
pub use rules_and_declarations::{parse_important};
|
||||
pub use rules_and_declarations::{DeclarationParser, DeclarationListParser, parse_one_declaration};
|
||||
|
@ -89,199 +92,17 @@ pub use serializer::{ToCss, CssStringWriter, serialize_identifier, serialize_str
|
|||
pub use parser::{Parser, Delimiter, Delimiters, SourcePosition};
|
||||
pub use unicode_range::UnicodeRange;
|
||||
|
||||
/// Expands to an expression equivalent to a `match` with string patterns,
|
||||
/// but matching is case-insensitive in the ASCII range.
|
||||
///
|
||||
/// Requirements:
|
||||
///
|
||||
/// * The `cssparser_macros` crate must also be imported at the crate root
|
||||
/// * The patterns must not contain ASCII upper case letters. (They must be already be lower-cased.)
|
||||
///
|
||||
/// # Example
|
||||
///
|
||||
/// ```rust
|
||||
/// #[macro_use] extern crate cssparser;
|
||||
/// #[macro_use] extern crate cssparser_macros;
|
||||
///
|
||||
/// # fn main() {} // Make doctest not wrap everythig in its own main
|
||||
/// # fn dummy(function_name: &String) { let _ =
|
||||
/// match_ignore_ascii_case! { &function_name,
|
||||
/// "rgb" => parse_rgb(..),
|
||||
/// "rgba" => parse_rgba(..),
|
||||
/// "hsl" => parse_hsl(..),
|
||||
/// "hsla" => parse_hsla(..),
|
||||
/// _ => Err("unknown function")
|
||||
/// }
|
||||
/// # ;}
|
||||
/// # use std::ops::RangeFull;
|
||||
/// # fn parse_rgb(_: RangeFull) -> Result<(), &'static str> { Err("") }
|
||||
/// # fn parse_rgba(_: RangeFull) -> Result<(), &'static str> { Err("") }
|
||||
/// # fn parse_hsl(_: RangeFull) -> Result<(), &'static str> { Err("") }
|
||||
/// # fn parse_hsla(_: RangeFull) -> Result<(), &'static str> { Err("") }
|
||||
/// ```
|
||||
#[macro_export]
|
||||
macro_rules! match_ignore_ascii_case {
|
||||
// parse the last case plus the fallback
|
||||
(@inner $value:expr, ($string:expr => $result:expr, _ => $fallback:expr) -> ($($parsed:tt)*) ) => {
|
||||
match_ignore_ascii_case!(@inner $value, () -> ($($parsed)* ($string => $result)) $fallback)
|
||||
};
|
||||
// For macros
|
||||
#[doc(hidden)] pub use macros::_internal__to_lowercase;
|
||||
|
||||
// parse a case (not the last one)
|
||||
(@inner $value:expr, ($string:expr => $result:expr, $($rest:tt)*) -> ($($parsed:tt)*) ) => {
|
||||
match_ignore_ascii_case!(@inner $value, ($($rest)*) -> ($($parsed)* ($string => $result)))
|
||||
};
|
||||
// For macros when used in this crate. Unsure how $crate works with procedural-masquerade.
|
||||
mod cssparser { pub use _internal__phf; }
|
||||
|
||||
// finished parsing
|
||||
(@inner $value:expr, () -> ($(($string:expr => $result:expr))*) $fallback:expr ) => {
|
||||
{
|
||||
#[derive(cssparser__assert_ascii_lowercase)]
|
||||
#[cssparser__assert_ascii_lowercase__data($(string = $string),+)]
|
||||
#[allow(dead_code)]
|
||||
struct Dummy;
|
||||
|
||||
_cssparser_internal__to_lowercase!($value => lowercase, $($string),+);
|
||||
match lowercase {
|
||||
$(
|
||||
Some($string) => $result,
|
||||
)+
|
||||
_ => $fallback
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
// entry point, start parsing
|
||||
( $value:expr, $($rest:tt)* ) => {
|
||||
match_ignore_ascii_case!(@inner $value, ($($rest)*) -> ())
|
||||
};
|
||||
}
|
||||
|
||||
/// Define a placeholder type `$Name`
|
||||
/// with a method `fn get(input: &str) -> Option<&'static $ValueType>`.
|
||||
///
|
||||
/// This method uses finds a match for the input string
|
||||
/// in a [`phf` map](https://github.com/sfackler/rust-phf).
|
||||
/// Matching is case-insensitive in the ASCII range.
|
||||
///
|
||||
/// Requirements:
|
||||
///
|
||||
/// * The `phf` and `cssparser_macros` crates must also be imported at the crate root
|
||||
/// * The values must be given a strings that contain Rust syntax for a constant expression.
|
||||
///
|
||||
/// ## Example:
|
||||
///
|
||||
/// ```rust
|
||||
/// extern crate phf;
|
||||
/// #[macro_use] extern crate cssparser;
|
||||
/// #[macro_use] extern crate cssparser_macros;
|
||||
///
|
||||
/// # fn main() {} // Make doctest not wrap everythig in its own main
|
||||
///
|
||||
/// fn color_rgb(input: &str) -> Option<(u8, u8, u8)> {
|
||||
/// ascii_case_insensitive_phf_map! {
|
||||
/// KEYWORDS: Map<(u8, u8, u8)> = {
|
||||
/// "red" => "(255, 0, 0)",
|
||||
/// "green" => "(0, 255, 0)",
|
||||
/// "blue" => "(0, 0, 255)",
|
||||
/// }
|
||||
/// }
|
||||
/// KEYWORDS::get(input).cloned()
|
||||
/// }
|
||||
#[macro_export]
|
||||
macro_rules! ascii_case_insensitive_phf_map {
|
||||
($Name: ident : Map<$ValueType: ty> = {
|
||||
$( $key: expr => $value: expr, )*
|
||||
}) => {
|
||||
#[derive(cssparser__phf_map)]
|
||||
#[cssparser__phf_map__kv_pairs(
|
||||
$(
|
||||
key = $key,
|
||||
value = $value
|
||||
),+
|
||||
)]
|
||||
struct $Name($ValueType);
|
||||
|
||||
impl $Name {
|
||||
#[inline]
|
||||
fn get(input: &str) -> Option<&'static $ValueType> {
|
||||
_cssparser_internal__to_lowercase!(input => lowercase, $($key),+);
|
||||
lowercase.and_then(|string| $Name::map().get(string))
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// Implementation detail of match_ignore_ascii_case! and ascii_case_insensitive_phf_map! macros.
|
||||
///
|
||||
/// **This macro is not part of the public API. It can change or be removed between any versions.**
|
||||
///
|
||||
/// * Check at compile-time that none of the `$string`s contain ASCII uppercase letters
|
||||
/// * Define a local variable named `$output` to the result of calling `_internal__to_lowercase`
|
||||
/// with a stack-allocated buffer as long as the longest `$string`.
|
||||
#[macro_export]
|
||||
#[doc(hidden)]
|
||||
macro_rules! _cssparser_internal__to_lowercase {
|
||||
($input: expr => $output: ident, $($string: expr),+) => {
|
||||
#[derive(cssparser__max_len)]
|
||||
#[cssparser__max_len__data($(string = $string),+)]
|
||||
#[allow(dead_code)]
|
||||
struct Dummy2;
|
||||
|
||||
// mem::uninitialized() is ok because `buffer` is only used in `_internal__to_lowercase`,
|
||||
// which initializes with `copy_from_slice` the part of the buffer it uses,
|
||||
// before it uses it.
|
||||
#[allow(unsafe_code)]
|
||||
// MAX_LENGTH is generated by cssparser__max_len
|
||||
let mut buffer: [u8; MAX_LENGTH] = unsafe {
|
||||
::std::mem::uninitialized()
|
||||
};
|
||||
let input: &str = $input;
|
||||
let $output = $crate::_internal__to_lowercase(&mut buffer, input);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/// Implementation detail of match_ignore_ascii_case! and ascii_case_insensitive_phf_map! macros.
|
||||
///
|
||||
/// **This function is not part of the public API. It can change or be removed between any verisons.**
|
||||
///
|
||||
/// Return `input`, lower-cased, unless larger than `buffer`
|
||||
/// which is used temporary space for lower-casing a copy of `input` if necessary.
|
||||
#[doc(hidden)]
|
||||
#[allow(non_snake_case)]
|
||||
pub fn _internal__to_lowercase<'a>(buffer: &'a mut [u8], input: &'a str) -> Option<&'a str> {
|
||||
if let Some(buffer) = buffer.get_mut(..input.len()) {
|
||||
if let Some(first_uppercase) = input.bytes().position(|byte| matches!(byte, b'A'...b'Z')) {
|
||||
buffer.copy_from_slice(input.as_bytes());
|
||||
std::ascii::AsciiExt::make_ascii_lowercase(&mut buffer[first_uppercase..]);
|
||||
// `buffer` was initialized to a copy of `input` (which is &str so well-formed UTF-8)
|
||||
// then lowercased (which preserves UTF-8 well-formedness)
|
||||
unsafe {
|
||||
Some(::std::str::from_utf8_unchecked(buffer))
|
||||
}
|
||||
} else {
|
||||
// Input is already lower-case
|
||||
Some(input)
|
||||
}
|
||||
} else {
|
||||
// Input is longer than buffer, which has the length of the longest expected string:
|
||||
// none of the expected strings would match.
|
||||
None
|
||||
}
|
||||
}
|
||||
#[macro_use]
|
||||
mod macros;
|
||||
|
||||
mod rules_and_declarations;
|
||||
|
||||
#[cfg(feature = "dummy_match_byte")]
|
||||
macro_rules! match_byte {
|
||||
($value:expr, $($rest:tt)* ) => {
|
||||
match $value {
|
||||
$(
|
||||
$rest
|
||||
)+
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
#[cfg(feature = "dummy_match_byte")]
|
||||
mod tokenizer;
|
||||
|
||||
|
|
|
@ -0,0 +1,163 @@
|
|||
/* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||
|
||||
/// See docs of the `procedural-masquerade` crate.
|
||||
define_invoke_proc_macro!(cssparser_internal__invoke_proc_macro);
|
||||
|
||||
/// Expands to a `match` expression with string patterns,
|
||||
/// matching case-insensitively in the ASCII range.
|
||||
///
|
||||
/// The patterns must not contain ASCII upper case letters. (They must be already be lower-cased.)
|
||||
///
|
||||
/// # Example
|
||||
///
|
||||
/// ```rust
|
||||
/// #[macro_use] extern crate cssparser;
|
||||
///
|
||||
/// # fn main() {} // Make doctest not wrap everythig in its own main
|
||||
/// # fn dummy(function_name: &String) { let _ =
|
||||
/// match_ignore_ascii_case! { &function_name,
|
||||
/// "rgb" => parse_rgb(..),
|
||||
/// "rgba" => parse_rgba(..),
|
||||
/// "hsl" => parse_hsl(..),
|
||||
/// "hsla" => parse_hsla(..),
|
||||
/// name @ _ => Err(format!("unknown function: {}", name))
|
||||
/// }
|
||||
/// # ;}
|
||||
/// # use std::ops::RangeFull;
|
||||
/// # fn parse_rgb(_: RangeFull) -> Result<(), String> { Ok(()) }
|
||||
/// # fn parse_rgba(_: RangeFull) -> Result<(), String> { Ok(()) }
|
||||
/// # fn parse_hsl(_: RangeFull) -> Result<(), String> { Ok(()) }
|
||||
/// # fn parse_hsla(_: RangeFull) -> Result<(), String> { Ok(()) }
|
||||
/// ```
|
||||
#[macro_export]
|
||||
macro_rules! match_ignore_ascii_case {
|
||||
( $input:expr, $( $match_body:tt )* ) => {
|
||||
{
|
||||
cssparser_internal__invoke_proc_macro! {
|
||||
cssparser_internal__assert_ascii_lowercase__max_len!( $( $match_body )* )
|
||||
}
|
||||
|
||||
{
|
||||
// MAX_LENGTH is generated by cssparser_internal__assert_ascii_lowercase__max_len
|
||||
cssparser_internal__to_lowercase!($input, MAX_LENGTH => lowercase);
|
||||
// "A" is a short string that we know is different for every string pattern,
|
||||
// since we’ve verified that none of them include ASCII upper case letters.
|
||||
match lowercase.unwrap_or("A") {
|
||||
$( $match_body )*
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
/// Define a function `$name(&str) -> Option<&'static $ValueType>`
|
||||
///
|
||||
/// The function finds a match for the input string
|
||||
/// in a [`phf` map](https://github.com/sfackler/rust-phf)
|
||||
/// and returns a reference to the corresponding value.
|
||||
/// Matching is case-insensitive in the ASCII range.
|
||||
///
|
||||
/// ## Example:
|
||||
///
|
||||
/// ```rust
|
||||
/// #[macro_use] extern crate cssparser;
|
||||
///
|
||||
/// # fn main() {} // Make doctest not wrap everything in its own main
|
||||
///
|
||||
/// fn color_rgb(input: &str) -> Option<(u8, u8, u8)> {
|
||||
/// ascii_case_insensitive_phf_map! {
|
||||
/// keyword -> (u8, u8, u8) = {
|
||||
/// "red" => (255, 0, 0),
|
||||
/// "green" => (0, 255, 0),
|
||||
/// "blue" => (0, 0, 255),
|
||||
/// }
|
||||
/// }
|
||||
/// keyword(input).cloned()
|
||||
/// }
|
||||
#[macro_export]
|
||||
macro_rules! ascii_case_insensitive_phf_map {
|
||||
($name: ident -> $ValueType: ty = { $( $key: expr => $value: expr ),* }) => {
|
||||
ascii_case_insensitive_phf_map!($name -> $ValueType = { $( $key => $value, )* })
|
||||
};
|
||||
($name: ident -> $ValueType: ty = { $( $key: expr => $value: expr, )* }) => {
|
||||
fn $name(input: &str) -> Option<&'static $ValueType> {
|
||||
cssparser_internal__invoke_proc_macro! {
|
||||
cssparser_internal__phf_map!( ($ValueType) $( $key ($value) )+ )
|
||||
}
|
||||
|
||||
{
|
||||
cssparser_internal__invoke_proc_macro! {
|
||||
cssparser_internal__max_len!( $( $key )+ )
|
||||
}
|
||||
// MAX_LENGTH is generated by cssparser_internal__max_len
|
||||
cssparser_internal__to_lowercase!(input, MAX_LENGTH => lowercase);
|
||||
lowercase.and_then(|s| MAP.get(s))
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// Implementation detail of match_ignore_ascii_case! and ascii_case_insensitive_phf_map! macros.
|
||||
///
|
||||
/// **This macro is not part of the public API. It can change or be removed between any versions.**
|
||||
///
|
||||
/// Define a local variable named `$output`
|
||||
/// and assign it the result of calling `_internal__to_lowercase`
|
||||
/// with a stack-allocated buffer of length `$BUFFER_SIZE`.
|
||||
#[macro_export]
|
||||
#[doc(hidden)]
|
||||
macro_rules! cssparser_internal__to_lowercase {
|
||||
($input: expr, $BUFFER_SIZE: expr => $output: ident) => {
|
||||
// mem::uninitialized() is ok because `buffer` is only used in `_internal__to_lowercase`,
|
||||
// which initializes with `copy_from_slice` the part of the buffer it uses,
|
||||
// before it uses it.
|
||||
#[allow(unsafe_code)]
|
||||
let mut buffer: [u8; $BUFFER_SIZE] = unsafe {
|
||||
::std::mem::uninitialized()
|
||||
};
|
||||
let input: &str = $input;
|
||||
let $output = $crate::_internal__to_lowercase(&mut buffer, input);
|
||||
}
|
||||
}
|
||||
|
||||
/// Implementation detail of match_ignore_ascii_case! and ascii_case_insensitive_phf_map! macros.
|
||||
///
|
||||
/// **This function is not part of the public API. It can change or be removed between any verisons.**
|
||||
///
|
||||
/// If `input` is larger than buffer, return `None`.
|
||||
/// Otherwise, return `input` ASCII-lowercased, using `buffer` as temporary space if necessary.
|
||||
#[doc(hidden)]
|
||||
#[allow(non_snake_case)]
|
||||
pub fn _internal__to_lowercase<'a>(buffer: &'a mut [u8], input: &'a str) -> Option<&'a str> {
|
||||
if let Some(buffer) = buffer.get_mut(..input.len()) {
|
||||
if let Some(first_uppercase) = input.bytes().position(|byte| matches!(byte, b'A'...b'Z')) {
|
||||
buffer.copy_from_slice(input.as_bytes());
|
||||
::std::ascii::AsciiExt::make_ascii_lowercase(&mut buffer[first_uppercase..]);
|
||||
// `buffer` was initialized to a copy of `input` (which is &str so well-formed UTF-8)
|
||||
// then lowercased (which preserves UTF-8 well-formedness)
|
||||
unsafe {
|
||||
Some(::std::str::from_utf8_unchecked(buffer))
|
||||
}
|
||||
} else {
|
||||
// Input is already lower-case
|
||||
Some(input)
|
||||
}
|
||||
} else {
|
||||
// Input is longer than buffer, which has the length of the longest expected string:
|
||||
// none of the expected strings would match.
|
||||
None
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(feature = "dummy_match_byte")]
|
||||
macro_rules! match_byte {
|
||||
($value:expr, $($rest:tt)* ) => {
|
||||
match $value {
|
||||
$(
|
||||
$rest
|
||||
)+
|
||||
}
|
||||
};
|
||||
}
|
|
@ -1,5 +0,0 @@
|
|||
/* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||
|
||||
pub mod match_byte;
|
|
@ -817,3 +817,29 @@ fn one_component_value_to_json(token: Token, input: &mut Parser) -> Json {
|
|||
Token::CloseCurlyBracket => JArray!["error", "}"],
|
||||
}
|
||||
}
|
||||
|
||||
/// A previous version of procedural-masquerade had a bug where it
|
||||
/// would normalize consecutive whitespace to a single space,
|
||||
/// including in string literals.
|
||||
#[test]
|
||||
fn procedural_masquerade_whitespace() {
|
||||
ascii_case_insensitive_phf_map! {
|
||||
map -> () = {
|
||||
" \t\n" => ()
|
||||
}
|
||||
}
|
||||
assert_eq!(map(" \t\n"), Some(&()));
|
||||
assert_eq!(map(" "), None);
|
||||
|
||||
match_ignore_ascii_case! { " \t\n",
|
||||
" " => panic!("1"),
|
||||
" \t\n" => {},
|
||||
_ => panic!("2"),
|
||||
}
|
||||
|
||||
match_ignore_ascii_case! { " ",
|
||||
" \t\n" => panic!("3"),
|
||||
" " => {},
|
||||
_ => panic!("4"),
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1 +1 @@
|
|||
{"files":{".cargo-ok":"e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855","Cargo.toml":"909cbbdd1eb19266cfdb4074e02dbefde878656aa2ebfc8c65c58fba4b02c376","src/lib.rs":"484cec14a5f18a25b71d7b1842f7b184f0530165021b71b36dde9fc57b7fc15a","src/regex.rs":"d8e2a6958d4ed8084867063aae4b5c77ffc5d271dc2e17909d56c5a5e1552034","src/string.rs":"26ede9ab41a2673c3ad6001bc1802c005ce9a4f190f55860a24aa66b6b71bbc7","tests/regexp_filter.rs":"a3f9c01623e90e54b247a62c53b25caf5f502d054f28c0bdf92abbea486a95b5"},"package":"99971fb1b635fe7a0ee3c4d065845bb93cca80a23b5613b5613391ece5de4144"}
|
||||
{"files":{".cargo-ok":"e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855","Cargo.toml":"7e71042ee2dbb7e40f1f821cee50d83426eaf875fab8435315f60cf7d46cae75","LICENSE-APACHE":"a60eea817514531668d7e00765731449fe14d059d3249e0bc93b36de45f759f2","LICENSE-MIT":"6485b8ed310d3f0340bf1ad1f47645069ce4069dcc6bb46c7d5c6faf41de1fdb","src/lib.rs":"484cec14a5f18a25b71d7b1842f7b184f0530165021b71b36dde9fc57b7fc15a","src/regex.rs":"d8e2a6958d4ed8084867063aae4b5c77ffc5d271dc2e17909d56c5a5e1552034","src/string.rs":"26ede9ab41a2673c3ad6001bc1802c005ce9a4f190f55860a24aa66b6b71bbc7","tests/regexp_filter.rs":"a3f9c01623e90e54b247a62c53b25caf5f502d054f28c0bdf92abbea486a95b5"},"package":"ed39959122ea027670b704fb70539f4286ddf4a49eefede23bf0b4b2a069ec03"}
|
|
@ -1,6 +1,6 @@
|
|||
[package]
|
||||
name = "env_logger"
|
||||
version = "0.4.0"
|
||||
version = "0.4.1"
|
||||
authors = ["The Rust Project Developers"]
|
||||
license = "MIT/Apache-2.0"
|
||||
repository = "https://github.com/rust-lang/log"
|
||||
|
|
|
@ -0,0 +1,201 @@
|
|||
Apache License
|
||||
Version 2.0, January 2004
|
||||
http://www.apache.org/licenses/
|
||||
|
||||
TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
|
||||
|
||||
1. Definitions.
|
||||
|
||||
"License" shall mean the terms and conditions for use, reproduction,
|
||||
and distribution as defined by Sections 1 through 9 of this document.
|
||||
|
||||
"Licensor" shall mean the copyright owner or entity authorized by
|
||||
the copyright owner that is granting the License.
|
||||
|
||||
"Legal Entity" shall mean the union of the acting entity and all
|
||||
other entities that control, are controlled by, or are under common
|
||||
control with that entity. For the purposes of this definition,
|
||||
"control" means (i) the power, direct or indirect, to cause the
|
||||
direction or management of such entity, whether by contract or
|
||||
otherwise, or (ii) ownership of fifty percent (50%) or more of the
|
||||
outstanding shares, or (iii) beneficial ownership of such entity.
|
||||
|
||||
"You" (or "Your") shall mean an individual or Legal Entity
|
||||
exercising permissions granted by this License.
|
||||
|
||||
"Source" form shall mean the preferred form for making modifications,
|
||||
including but not limited to software source code, documentation
|
||||
source, and configuration files.
|
||||
|
||||
"Object" form shall mean any form resulting from mechanical
|
||||
transformation or translation of a Source form, including but
|
||||
not limited to compiled object code, generated documentation,
|
||||
and conversions to other media types.
|
||||
|
||||
"Work" shall mean the work of authorship, whether in Source or
|
||||
Object form, made available under the License, as indicated by a
|
||||
copyright notice that is included in or attached to the work
|
||||
(an example is provided in the Appendix below).
|
||||
|
||||
"Derivative Works" shall mean any work, whether in Source or Object
|
||||
form, that is based on (or derived from) the Work and for which the
|
||||
editorial revisions, annotations, elaborations, or other modifications
|
||||
represent, as a whole, an original work of authorship. For the purposes
|
||||
of this License, Derivative Works shall not include works that remain
|
||||
separable from, or merely link (or bind by name) to the interfaces of,
|
||||
the Work and Derivative Works thereof.
|
||||
|
||||
"Contribution" shall mean any work of authorship, including
|
||||
the original version of the Work and any modifications or additions
|
||||
to that Work or Derivative Works thereof, that is intentionally
|
||||
submitted to Licensor for inclusion in the Work by the copyright owner
|
||||
or by an individual or Legal Entity authorized to submit on behalf of
|
||||
the copyright owner. For the purposes of this definition, "submitted"
|
||||
means any form of electronic, verbal, or written communication sent
|
||||
to the Licensor or its representatives, including but not limited to
|
||||
communication on electronic mailing lists, source code control systems,
|
||||
and issue tracking systems that are managed by, or on behalf of, the
|
||||
Licensor for the purpose of discussing and improving the Work, but
|
||||
excluding communication that is conspicuously marked or otherwise
|
||||
designated in writing by the copyright owner as "Not a Contribution."
|
||||
|
||||
"Contributor" shall mean Licensor and any individual or Legal Entity
|
||||
on behalf of whom a Contribution has been received by Licensor and
|
||||
subsequently incorporated within the Work.
|
||||
|
||||
2. Grant of Copyright License. Subject to the terms and conditions of
|
||||
this License, each Contributor hereby grants to You a perpetual,
|
||||
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
|
||||
copyright license to reproduce, prepare Derivative Works of,
|
||||
publicly display, publicly perform, sublicense, and distribute the
|
||||
Work and such Derivative Works in Source or Object form.
|
||||
|
||||
3. Grant of Patent License. Subject to the terms and conditions of
|
||||
this License, each Contributor hereby grants to You a perpetual,
|
||||
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
|
||||
(except as stated in this section) patent license to make, have made,
|
||||
use, offer to sell, sell, import, and otherwise transfer the Work,
|
||||
where such license applies only to those patent claims licensable
|
||||
by such Contributor that are necessarily infringed by their
|
||||
Contribution(s) alone or by combination of their Contribution(s)
|
||||
with the Work to which such Contribution(s) was submitted. If You
|
||||
institute patent litigation against any entity (including a
|
||||
cross-claim or counterclaim in a lawsuit) alleging that the Work
|
||||
or a Contribution incorporated within the Work constitutes direct
|
||||
or contributory patent infringement, then any patent licenses
|
||||
granted to You under this License for that Work shall terminate
|
||||
as of the date such litigation is filed.
|
||||
|
||||
4. Redistribution. You may reproduce and distribute copies of the
|
||||
Work or Derivative Works thereof in any medium, with or without
|
||||
modifications, and in Source or Object form, provided that You
|
||||
meet the following conditions:
|
||||
|
||||
(a) You must give any other recipients of the Work or
|
||||
Derivative Works a copy of this License; and
|
||||
|
||||
(b) You must cause any modified files to carry prominent notices
|
||||
stating that You changed the files; and
|
||||
|
||||
(c) You must retain, in the Source form of any Derivative Works
|
||||
that You distribute, all copyright, patent, trademark, and
|
||||
attribution notices from the Source form of the Work,
|
||||
excluding those notices that do not pertain to any part of
|
||||
the Derivative Works; and
|
||||
|
||||
(d) If the Work includes a "NOTICE" text file as part of its
|
||||
distribution, then any Derivative Works that You distribute must
|
||||
include a readable copy of the attribution notices contained
|
||||
within such NOTICE file, excluding those notices that do not
|
||||
pertain to any part of the Derivative Works, in at least one
|
||||
of the following places: within a NOTICE text file distributed
|
||||
as part of the Derivative Works; within the Source form or
|
||||
documentation, if provided along with the Derivative Works; or,
|
||||
within a display generated by the Derivative Works, if and
|
||||
wherever such third-party notices normally appear. The contents
|
||||
of the NOTICE file are for informational purposes only and
|
||||
do not modify the License. You may add Your own attribution
|
||||
notices within Derivative Works that You distribute, alongside
|
||||
or as an addendum to the NOTICE text from the Work, provided
|
||||
that such additional attribution notices cannot be construed
|
||||
as modifying the License.
|
||||
|
||||
You may add Your own copyright statement to Your modifications and
|
||||
may provide additional or different license terms and conditions
|
||||
for use, reproduction, or distribution of Your modifications, or
|
||||
for any such Derivative Works as a whole, provided Your use,
|
||||
reproduction, and distribution of the Work otherwise complies with
|
||||
the conditions stated in this License.
|
||||
|
||||
5. Submission of Contributions. Unless You explicitly state otherwise,
|
||||
any Contribution intentionally submitted for inclusion in the Work
|
||||
by You to the Licensor shall be under the terms and conditions of
|
||||
this License, without any additional terms or conditions.
|
||||
Notwithstanding the above, nothing herein shall supersede or modify
|
||||
the terms of any separate license agreement you may have executed
|
||||
with Licensor regarding such Contributions.
|
||||
|
||||
6. Trademarks. This License does not grant permission to use the trade
|
||||
names, trademarks, service marks, or product names of the Licensor,
|
||||
except as required for reasonable and customary use in describing the
|
||||
origin of the Work and reproducing the content of the NOTICE file.
|
||||
|
||||
7. Disclaimer of Warranty. Unless required by applicable law or
|
||||
agreed to in writing, Licensor provides the Work (and each
|
||||
Contributor provides its Contributions) on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
|
||||
implied, including, without limitation, any warranties or conditions
|
||||
of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
|
||||
PARTICULAR PURPOSE. You are solely responsible for determining the
|
||||
appropriateness of using or redistributing the Work and assume any
|
||||
risks associated with Your exercise of permissions under this License.
|
||||
|
||||
8. Limitation of Liability. In no event and under no legal theory,
|
||||
whether in tort (including negligence), contract, or otherwise,
|
||||
unless required by applicable law (such as deliberate and grossly
|
||||
negligent acts) or agreed to in writing, shall any Contributor be
|
||||
liable to You for damages, including any direct, indirect, special,
|
||||
incidental, or consequential damages of any character arising as a
|
||||
result of this License or out of the use or inability to use the
|
||||
Work (including but not limited to damages for loss of goodwill,
|
||||
work stoppage, computer failure or malfunction, or any and all
|
||||
other commercial damages or losses), even if such Contributor
|
||||
has been advised of the possibility of such damages.
|
||||
|
||||
9. Accepting Warranty or Additional Liability. While redistributing
|
||||
the Work or Derivative Works thereof, You may choose to offer,
|
||||
and charge a fee for, acceptance of support, warranty, indemnity,
|
||||
or other liability obligations and/or rights consistent with this
|
||||
License. However, in accepting such obligations, You may act only
|
||||
on Your own behalf and on Your sole responsibility, not on behalf
|
||||
of any other Contributor, and only if You agree to indemnify,
|
||||
defend, and hold each Contributor harmless for any liability
|
||||
incurred by, or claims asserted against, such Contributor by reason
|
||||
of your accepting any such warranty or additional liability.
|
||||
|
||||
END OF TERMS AND CONDITIONS
|
||||
|
||||
APPENDIX: How to apply the Apache License to your work.
|
||||
|
||||
To apply the Apache License to your work, attach the following
|
||||
boilerplate notice, with the fields enclosed by brackets "[]"
|
||||
replaced with your own identifying information. (Don't include
|
||||
the brackets!) The text should be enclosed in the appropriate
|
||||
comment syntax for the file format. We also recommend that a
|
||||
file or class name and description of purpose be included on the
|
||||
same "printed page" as the copyright notice for easier
|
||||
identification within third-party archives.
|
||||
|
||||
Copyright [yyyy] [name of copyright owner]
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
|
@ -0,0 +1,25 @@
|
|||
Copyright (c) 2014 The Rust Project Developers
|
||||
|
||||
Permission is hereby granted, free of charge, to any
|
||||
person obtaining a copy of this software and associated
|
||||
documentation files (the "Software"), to deal in the
|
||||
Software without restriction, including without
|
||||
limitation the rights to use, copy, modify, merge,
|
||||
publish, distribute, sublicense, and/or sell copies of
|
||||
the Software, and to permit persons to whom the Software
|
||||
is furnished to do so, subject to the following
|
||||
conditions:
|
||||
|
||||
The above copyright notice and this permission notice
|
||||
shall be included in all copies or substantial portions
|
||||
of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF
|
||||
ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED
|
||||
TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A
|
||||
PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT
|
||||
SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
|
||||
CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
|
||||
OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR
|
||||
IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
|
||||
DEALINGS IN THE SOFTWARE.
|
|
@ -1 +1 @@
|
|||
{"files":{".cargo-ok":"e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855","Cargo.toml":"be0aaf0c998d1913f40d901850f561ace784587152bfa23ebb14ed781774307a","src/lib.rs":"0bc63c3c812abf24179b104306a2a5b87329752269cc4d76570ed3c273f1baa7"},"package":"fb24d9bfb3f222010df27995441ded1e954f8f69cd35021f6bef02ca9552fb92"}
|
||||
{"files":{".cargo-ok":"e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855","Cargo.toml":"69c84ad73d7c646a1ef4672b6d8f958c5f18d43e43c17b902f1198f9fed4ae5e","LICENSE-APACHE":"a60eea817514531668d7e00765731449fe14d059d3249e0bc93b36de45f759f2","LICENSE-MIT":"6485b8ed310d3f0340bf1ad1f47645069ce4069dcc6bb46c7d5c6faf41de1fdb","src/lib.rs":"c49cb1f2c2c5b414d28556ba7076d0243fe73378dd3a3ae97d29b3b4dc060a58"},"package":"21e4df1098d1d797d27ef0c69c178c3fab64941559b290fcae198e0825c9c8b5"}
|
|
@ -7,7 +7,7 @@ keywords = ["mathematics", "numerics"]
|
|||
license = "MIT/Apache-2.0"
|
||||
repository = "https://github.com/rust-num/num"
|
||||
name = "num-integer"
|
||||
version = "0.1.32"
|
||||
version = "0.1.33"
|
||||
|
||||
[dependencies.num-traits]
|
||||
path = "../traits"
|
||||
|
|
|
@ -0,0 +1,201 @@
|
|||
Apache License
|
||||
Version 2.0, January 2004
|
||||
http://www.apache.org/licenses/
|
||||
|
||||
TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
|
||||
|
||||
1. Definitions.
|
||||
|
||||
"License" shall mean the terms and conditions for use, reproduction,
|
||||
and distribution as defined by Sections 1 through 9 of this document.
|
||||
|
||||
"Licensor" shall mean the copyright owner or entity authorized by
|
||||
the copyright owner that is granting the License.
|
||||
|
||||
"Legal Entity" shall mean the union of the acting entity and all
|
||||
other entities that control, are controlled by, or are under common
|
||||
control with that entity. For the purposes of this definition,
|
||||
"control" means (i) the power, direct or indirect, to cause the
|
||||
direction or management of such entity, whether by contract or
|
||||
otherwise, or (ii) ownership of fifty percent (50%) or more of the
|
||||
outstanding shares, or (iii) beneficial ownership of such entity.
|
||||
|
||||
"You" (or "Your") shall mean an individual or Legal Entity
|
||||
exercising permissions granted by this License.
|
||||
|
||||
"Source" form shall mean the preferred form for making modifications,
|
||||
including but not limited to software source code, documentation
|
||||
source, and configuration files.
|
||||
|
||||
"Object" form shall mean any form resulting from mechanical
|
||||
transformation or translation of a Source form, including but
|
||||
not limited to compiled object code, generated documentation,
|
||||
and conversions to other media types.
|
||||
|
||||
"Work" shall mean the work of authorship, whether in Source or
|
||||
Object form, made available under the License, as indicated by a
|
||||
copyright notice that is included in or attached to the work
|
||||
(an example is provided in the Appendix below).
|
||||
|
||||
"Derivative Works" shall mean any work, whether in Source or Object
|
||||
form, that is based on (or derived from) the Work and for which the
|
||||
editorial revisions, annotations, elaborations, or other modifications
|
||||
represent, as a whole, an original work of authorship. For the purposes
|
||||
of this License, Derivative Works shall not include works that remain
|
||||
separable from, or merely link (or bind by name) to the interfaces of,
|
||||
the Work and Derivative Works thereof.
|
||||
|
||||
"Contribution" shall mean any work of authorship, including
|
||||
the original version of the Work and any modifications or additions
|
||||
to that Work or Derivative Works thereof, that is intentionally
|
||||
submitted to Licensor for inclusion in the Work by the copyright owner
|
||||
or by an individual or Legal Entity authorized to submit on behalf of
|
||||
the copyright owner. For the purposes of this definition, "submitted"
|
||||
means any form of electronic, verbal, or written communication sent
|
||||
to the Licensor or its representatives, including but not limited to
|
||||
communication on electronic mailing lists, source code control systems,
|
||||
and issue tracking systems that are managed by, or on behalf of, the
|
||||
Licensor for the purpose of discussing and improving the Work, but
|
||||
excluding communication that is conspicuously marked or otherwise
|
||||
designated in writing by the copyright owner as "Not a Contribution."
|
||||
|
||||
"Contributor" shall mean Licensor and any individual or Legal Entity
|
||||
on behalf of whom a Contribution has been received by Licensor and
|
||||
subsequently incorporated within the Work.
|
||||
|
||||
2. Grant of Copyright License. Subject to the terms and conditions of
|
||||
this License, each Contributor hereby grants to You a perpetual,
|
||||
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
|
||||
copyright license to reproduce, prepare Derivative Works of,
|
||||
publicly display, publicly perform, sublicense, and distribute the
|
||||
Work and such Derivative Works in Source or Object form.
|
||||
|
||||
3. Grant of Patent License. Subject to the terms and conditions of
|
||||
this License, each Contributor hereby grants to You a perpetual,
|
||||
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
|
||||
(except as stated in this section) patent license to make, have made,
|
||||
use, offer to sell, sell, import, and otherwise transfer the Work,
|
||||
where such license applies only to those patent claims licensable
|
||||
by such Contributor that are necessarily infringed by their
|
||||
Contribution(s) alone or by combination of their Contribution(s)
|
||||
with the Work to which such Contribution(s) was submitted. If You
|
||||
institute patent litigation against any entity (including a
|
||||
cross-claim or counterclaim in a lawsuit) alleging that the Work
|
||||
or a Contribution incorporated within the Work constitutes direct
|
||||
or contributory patent infringement, then any patent licenses
|
||||
granted to You under this License for that Work shall terminate
|
||||
as of the date such litigation is filed.
|
||||
|
||||
4. Redistribution. You may reproduce and distribute copies of the
|
||||
Work or Derivative Works thereof in any medium, with or without
|
||||
modifications, and in Source or Object form, provided that You
|
||||
meet the following conditions:
|
||||
|
||||
(a) You must give any other recipients of the Work or
|
||||
Derivative Works a copy of this License; and
|
||||
|
||||
(b) You must cause any modified files to carry prominent notices
|
||||
stating that You changed the files; and
|
||||
|
||||
(c) You must retain, in the Source form of any Derivative Works
|
||||
that You distribute, all copyright, patent, trademark, and
|
||||
attribution notices from the Source form of the Work,
|
||||
excluding those notices that do not pertain to any part of
|
||||
the Derivative Works; and
|
||||
|
||||
(d) If the Work includes a "NOTICE" text file as part of its
|
||||
distribution, then any Derivative Works that You distribute must
|
||||
include a readable copy of the attribution notices contained
|
||||
within such NOTICE file, excluding those notices that do not
|
||||
pertain to any part of the Derivative Works, in at least one
|
||||
of the following places: within a NOTICE text file distributed
|
||||
as part of the Derivative Works; within the Source form or
|
||||
documentation, if provided along with the Derivative Works; or,
|
||||
within a display generated by the Derivative Works, if and
|
||||
wherever such third-party notices normally appear. The contents
|
||||
of the NOTICE file are for informational purposes only and
|
||||
do not modify the License. You may add Your own attribution
|
||||
notices within Derivative Works that You distribute, alongside
|
||||
or as an addendum to the NOTICE text from the Work, provided
|
||||
that such additional attribution notices cannot be construed
|
||||
as modifying the License.
|
||||
|
||||
You may add Your own copyright statement to Your modifications and
|
||||
may provide additional or different license terms and conditions
|
||||
for use, reproduction, or distribution of Your modifications, or
|
||||
for any such Derivative Works as a whole, provided Your use,
|
||||
reproduction, and distribution of the Work otherwise complies with
|
||||
the conditions stated in this License.
|
||||
|
||||
5. Submission of Contributions. Unless You explicitly state otherwise,
|
||||
any Contribution intentionally submitted for inclusion in the Work
|
||||
by You to the Licensor shall be under the terms and conditions of
|
||||
this License, without any additional terms or conditions.
|
||||
Notwithstanding the above, nothing herein shall supersede or modify
|
||||
the terms of any separate license agreement you may have executed
|
||||
with Licensor regarding such Contributions.
|
||||
|
||||
6. Trademarks. This License does not grant permission to use the trade
|
||||
names, trademarks, service marks, or product names of the Licensor,
|
||||
except as required for reasonable and customary use in describing the
|
||||
origin of the Work and reproducing the content of the NOTICE file.
|
||||
|
||||
7. Disclaimer of Warranty. Unless required by applicable law or
|
||||
agreed to in writing, Licensor provides the Work (and each
|
||||
Contributor provides its Contributions) on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
|
||||
implied, including, without limitation, any warranties or conditions
|
||||
of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
|
||||
PARTICULAR PURPOSE. You are solely responsible for determining the
|
||||
appropriateness of using or redistributing the Work and assume any
|
||||
risks associated with Your exercise of permissions under this License.
|
||||
|
||||
8. Limitation of Liability. In no event and under no legal theory,
|
||||
whether in tort (including negligence), contract, or otherwise,
|
||||
unless required by applicable law (such as deliberate and grossly
|
||||
negligent acts) or agreed to in writing, shall any Contributor be
|
||||
liable to You for damages, including any direct, indirect, special,
|
||||
incidental, or consequential damages of any character arising as a
|
||||
result of this License or out of the use or inability to use the
|
||||
Work (including but not limited to damages for loss of goodwill,
|
||||
work stoppage, computer failure or malfunction, or any and all
|
||||
other commercial damages or losses), even if such Contributor
|
||||
has been advised of the possibility of such damages.
|
||||
|
||||
9. Accepting Warranty or Additional Liability. While redistributing
|
||||
the Work or Derivative Works thereof, You may choose to offer,
|
||||
and charge a fee for, acceptance of support, warranty, indemnity,
|
||||
or other liability obligations and/or rights consistent with this
|
||||
License. However, in accepting such obligations, You may act only
|
||||
on Your own behalf and on Your sole responsibility, not on behalf
|
||||
of any other Contributor, and only if You agree to indemnify,
|
||||
defend, and hold each Contributor harmless for any liability
|
||||
incurred by, or claims asserted against, such Contributor by reason
|
||||
of your accepting any such warranty or additional liability.
|
||||
|
||||
END OF TERMS AND CONDITIONS
|
||||
|
||||
APPENDIX: How to apply the Apache License to your work.
|
||||
|
||||
To apply the Apache License to your work, attach the following
|
||||
boilerplate notice, with the fields enclosed by brackets "[]"
|
||||
replaced with your own identifying information. (Don't include
|
||||
the brackets!) The text should be enclosed in the appropriate
|
||||
comment syntax for the file format. We also recommend that a
|
||||
file or class name and description of purpose be included on the
|
||||
same "printed page" as the copyright notice for easier
|
||||
identification within third-party archives.
|
||||
|
||||
Copyright [yyyy] [name of copyright owner]
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
|
@ -0,0 +1,25 @@
|
|||
Copyright (c) 2014 The Rust Project Developers
|
||||
|
||||
Permission is hereby granted, free of charge, to any
|
||||
person obtaining a copy of this software and associated
|
||||
documentation files (the "Software"), to deal in the
|
||||
Software without restriction, including without
|
||||
limitation the rights to use, copy, modify, merge,
|
||||
publish, distribute, sublicense, and/or sell copies of
|
||||
the Software, and to permit persons to whom the Software
|
||||
is furnished to do so, subject to the following
|
||||
conditions:
|
||||
|
||||
The above copyright notice and this permission notice
|
||||
shall be included in all copies or substantial portions
|
||||
of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF
|
||||
ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED
|
||||
TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A
|
||||
PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT
|
||||
SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
|
||||
CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
|
||||
OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR
|
||||
IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
|
||||
DEALINGS IN THE SOFTWARE.
|
|
@ -9,6 +9,10 @@
|
|||
// except according to those terms.
|
||||
|
||||
//! Integer trait and functions.
|
||||
#![doc(html_logo_url = "https://rust-num.github.io/num/rust-logo-128x128-blk-v2.png",
|
||||
html_favicon_url = "https://rust-num.github.io/num/favicon.ico",
|
||||
html_root_url = "https://rust-num.github.io/num/",
|
||||
html_playground_url = "http://play.integer32.com/")]
|
||||
|
||||
extern crate num_traits as traits;
|
||||
|
||||
|
|
|
@ -1 +1 @@
|
|||
{"files":{".cargo-ok":"e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855","Cargo.toml":"3befa332314f31a68e226930e393fd79b0215fab661519f3163b04ef6fbccaac","src/bounds.rs":"32f69f86640520478eff7978951a6d2dc0d51fe263782970185fb31ffcc4a9e1","src/cast.rs":"d76053ff336eadb80a18725c174226b4be147b876c6aa70d7aa81a16d85e9f25","src/float.rs":"1f9d571bd3946d1d93dc7f4f4ae344bfabf5fd871243145aad120e242599c2e4","src/identities.rs":"188c63de57997fb8468732251a3a8d7f665b8f61d512222c2553baefe1c827bb","src/int.rs":"8ef622da766cb69586981e5eb5bd6c608ce9db0e345aeb34347023730561cb87","src/lib.rs":"3e56bafef9c32e10ff8d70241f64a0d811cd6dfc8f57924c094d1735f32fc3b2","src/ops/checked.rs":"f02fd815b99edf079043d3621c1566e0ab3e755fe284d0b8fdf5d7ca56d546e7","src/ops/mod.rs":"2ed0ec81f58958665f251348fa670375ab863a628182a2dec20308b249a8087a","src/ops/saturating.rs":"46821d815c90c16b2f6bec0b94b4d7ebdbddf3ea42edc0467de738c56abf6436","src/pow.rs":"73b611ad8d595ef917871ba859ff0c25efc2382220d30568e5fbb930bf6b4daa","src/sign.rs":"c08ad1647d393571cc73344b174b1764d7d7d5fb57170cc8f1d26e7ab9527e7c"},"package":"a16a42856a256b39c6d3484f097f6713e14feacd9bfb02290917904fae46c81c"}
|
||||
{"files":{".cargo-ok":"e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855","Cargo.toml":"c1f571e6884f2643c11053465800afe4056253687fd332e7a9c2d32fb30704ed","LICENSE-APACHE":"a60eea817514531668d7e00765731449fe14d059d3249e0bc93b36de45f759f2","LICENSE-MIT":"6485b8ed310d3f0340bf1ad1f47645069ce4069dcc6bb46c7d5c6faf41de1fdb","src/bounds.rs":"32f69f86640520478eff7978951a6d2dc0d51fe263782970185fb31ffcc4a9e1","src/cast.rs":"d76053ff336eadb80a18725c174226b4be147b876c6aa70d7aa81a16d85e9f25","src/float.rs":"1f9d571bd3946d1d93dc7f4f4ae344bfabf5fd871243145aad120e242599c2e4","src/identities.rs":"188c63de57997fb8468732251a3a8d7f665b8f61d512222c2553baefe1c827bb","src/int.rs":"b7b42dfa10423308f858216ac63fa52e26c49a7bc8900cd98de210992efc3f5f","src/lib.rs":"f99d825e652698d9b39b1e26132139542e12e968d87cf804d46e95ec0c21f14f","src/ops/checked.rs":"f02fd815b99edf079043d3621c1566e0ab3e755fe284d0b8fdf5d7ca56d546e7","src/ops/mod.rs":"668ea4d117bc1fdf7eaf0fe16692fa40dfbdfcbc7a2010237fe395ce0086e02e","src/ops/saturating.rs":"46821d815c90c16b2f6bec0b94b4d7ebdbddf3ea42edc0467de738c56abf6436","src/ops/wrapping.rs":"aa750486640063fad24175fd3b622eba2d4453d4de5a3d8bc93e1c3f50ced485","src/pow.rs":"73b611ad8d595ef917871ba859ff0c25efc2382220d30568e5fbb930bf6b4daa","src/sign.rs":"c08ad1647d393571cc73344b174b1764d7d7d5fb57170cc8f1d26e7ab9527e7c"},"package":"e1cbfa3781f3fe73dc05321bed52a06d2d491eaa764c52335cf4399f046ece99"}
|
|
@ -7,6 +7,6 @@ keywords = ["mathematics", "numerics"]
|
|||
license = "MIT/Apache-2.0"
|
||||
repository = "https://github.com/rust-num/num"
|
||||
name = "num-traits"
|
||||
version = "0.1.36"
|
||||
version = "0.1.37"
|
||||
|
||||
[dependencies]
|
||||
|
|
|
@ -0,0 +1,201 @@
|
|||
Apache License
|
||||
Version 2.0, January 2004
|
||||
http://www.apache.org/licenses/
|
||||
|
||||
TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
|
||||
|
||||
1. Definitions.
|
||||
|
||||
"License" shall mean the terms and conditions for use, reproduction,
|
||||
and distribution as defined by Sections 1 through 9 of this document.
|
||||
|
||||
"Licensor" shall mean the copyright owner or entity authorized by
|
||||
the copyright owner that is granting the License.
|
||||
|
||||
"Legal Entity" shall mean the union of the acting entity and all
|
||||
other entities that control, are controlled by, or are under common
|
||||
control with that entity. For the purposes of this definition,
|
||||
"control" means (i) the power, direct or indirect, to cause the
|
||||
direction or management of such entity, whether by contract or
|
||||
otherwise, or (ii) ownership of fifty percent (50%) or more of the
|
||||
outstanding shares, or (iii) beneficial ownership of such entity.
|
||||
|
||||
"You" (or "Your") shall mean an individual or Legal Entity
|
||||
exercising permissions granted by this License.
|
||||
|
||||
"Source" form shall mean the preferred form for making modifications,
|
||||
including but not limited to software source code, documentation
|
||||
source, and configuration files.
|
||||
|
||||
"Object" form shall mean any form resulting from mechanical
|
||||
transformation or translation of a Source form, including but
|
||||
not limited to compiled object code, generated documentation,
|
||||
and conversions to other media types.
|
||||
|
||||
"Work" shall mean the work of authorship, whether in Source or
|
||||
Object form, made available under the License, as indicated by a
|
||||
copyright notice that is included in or attached to the work
|
||||
(an example is provided in the Appendix below).
|
||||
|
||||
"Derivative Works" shall mean any work, whether in Source or Object
|
||||
form, that is based on (or derived from) the Work and for which the
|
||||
editorial revisions, annotations, elaborations, or other modifications
|
||||
represent, as a whole, an original work of authorship. For the purposes
|
||||
of this License, Derivative Works shall not include works that remain
|
||||
separable from, or merely link (or bind by name) to the interfaces of,
|
||||
the Work and Derivative Works thereof.
|
||||
|
||||
"Contribution" shall mean any work of authorship, including
|
||||
the original version of the Work and any modifications or additions
|
||||
to that Work or Derivative Works thereof, that is intentionally
|
||||
submitted to Licensor for inclusion in the Work by the copyright owner
|
||||
or by an individual or Legal Entity authorized to submit on behalf of
|
||||
the copyright owner. For the purposes of this definition, "submitted"
|
||||
means any form of electronic, verbal, or written communication sent
|
||||
to the Licensor or its representatives, including but not limited to
|
||||
communication on electronic mailing lists, source code control systems,
|
||||
and issue tracking systems that are managed by, or on behalf of, the
|
||||
Licensor for the purpose of discussing and improving the Work, but
|
||||
excluding communication that is conspicuously marked or otherwise
|
||||
designated in writing by the copyright owner as "Not a Contribution."
|
||||
|
||||
"Contributor" shall mean Licensor and any individual or Legal Entity
|
||||
on behalf of whom a Contribution has been received by Licensor and
|
||||
subsequently incorporated within the Work.
|
||||
|
||||
2. Grant of Copyright License. Subject to the terms and conditions of
|
||||
this License, each Contributor hereby grants to You a perpetual,
|
||||
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
|
||||
copyright license to reproduce, prepare Derivative Works of,
|
||||
publicly display, publicly perform, sublicense, and distribute the
|
||||
Work and such Derivative Works in Source or Object form.
|
||||
|
||||
3. Grant of Patent License. Subject to the terms and conditions of
|
||||
this License, each Contributor hereby grants to You a perpetual,
|
||||
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
|
||||
(except as stated in this section) patent license to make, have made,
|
||||
use, offer to sell, sell, import, and otherwise transfer the Work,
|
||||
where such license applies only to those patent claims licensable
|
||||
by such Contributor that are necessarily infringed by their
|
||||
Contribution(s) alone or by combination of their Contribution(s)
|
||||
with the Work to which such Contribution(s) was submitted. If You
|
||||
institute patent litigation against any entity (including a
|
||||
cross-claim or counterclaim in a lawsuit) alleging that the Work
|
||||
or a Contribution incorporated within the Work constitutes direct
|
||||
or contributory patent infringement, then any patent licenses
|
||||
granted to You under this License for that Work shall terminate
|
||||
as of the date such litigation is filed.
|
||||
|
||||
4. Redistribution. You may reproduce and distribute copies of the
|
||||
Work or Derivative Works thereof in any medium, with or without
|
||||
modifications, and in Source or Object form, provided that You
|
||||
meet the following conditions:
|
||||
|
||||
(a) You must give any other recipients of the Work or
|
||||
Derivative Works a copy of this License; and
|
||||
|
||||
(b) You must cause any modified files to carry prominent notices
|
||||
stating that You changed the files; and
|
||||
|
||||
(c) You must retain, in the Source form of any Derivative Works
|
||||
that You distribute, all copyright, patent, trademark, and
|
||||
attribution notices from the Source form of the Work,
|
||||
excluding those notices that do not pertain to any part of
|
||||
the Derivative Works; and
|
||||
|
||||
(d) If the Work includes a "NOTICE" text file as part of its
|
||||
distribution, then any Derivative Works that You distribute must
|
||||
include a readable copy of the attribution notices contained
|
||||
within such NOTICE file, excluding those notices that do not
|
||||
pertain to any part of the Derivative Works, in at least one
|
||||
of the following places: within a NOTICE text file distributed
|
||||
as part of the Derivative Works; within the Source form or
|
||||
documentation, if provided along with the Derivative Works; or,
|
||||
within a display generated by the Derivative Works, if and
|
||||
wherever such third-party notices normally appear. The contents
|
||||
of the NOTICE file are for informational purposes only and
|
||||
do not modify the License. You may add Your own attribution
|
||||
notices within Derivative Works that You distribute, alongside
|
||||
or as an addendum to the NOTICE text from the Work, provided
|
||||
that such additional attribution notices cannot be construed
|
||||
as modifying the License.
|
||||
|
||||
You may add Your own copyright statement to Your modifications and
|
||||
may provide additional or different license terms and conditions
|
||||
for use, reproduction, or distribution of Your modifications, or
|
||||
for any such Derivative Works as a whole, provided Your use,
|
||||
reproduction, and distribution of the Work otherwise complies with
|
||||
the conditions stated in this License.
|
||||
|
||||
5. Submission of Contributions. Unless You explicitly state otherwise,
|
||||
any Contribution intentionally submitted for inclusion in the Work
|
||||
by You to the Licensor shall be under the terms and conditions of
|
||||
this License, without any additional terms or conditions.
|
||||
Notwithstanding the above, nothing herein shall supersede or modify
|
||||
the terms of any separate license agreement you may have executed
|
||||
with Licensor regarding such Contributions.
|
||||
|
||||
6. Trademarks. This License does not grant permission to use the trade
|
||||
names, trademarks, service marks, or product names of the Licensor,
|
||||
except as required for reasonable and customary use in describing the
|
||||
origin of the Work and reproducing the content of the NOTICE file.
|
||||
|
||||
7. Disclaimer of Warranty. Unless required by applicable law or
|
||||
agreed to in writing, Licensor provides the Work (and each
|
||||
Contributor provides its Contributions) on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
|
||||
implied, including, without limitation, any warranties or conditions
|
||||
of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
|
||||
PARTICULAR PURPOSE. You are solely responsible for determining the
|
||||
appropriateness of using or redistributing the Work and assume any
|
||||
risks associated with Your exercise of permissions under this License.
|
||||
|
||||
8. Limitation of Liability. In no event and under no legal theory,
|
||||
whether in tort (including negligence), contract, or otherwise,
|
||||
unless required by applicable law (such as deliberate and grossly
|
||||
negligent acts) or agreed to in writing, shall any Contributor be
|
||||
liable to You for damages, including any direct, indirect, special,
|
||||
incidental, or consequential damages of any character arising as a
|
||||
result of this License or out of the use or inability to use the
|
||||
Work (including but not limited to damages for loss of goodwill,
|
||||
work stoppage, computer failure or malfunction, or any and all
|
||||
other commercial damages or losses), even if such Contributor
|
||||
has been advised of the possibility of such damages.
|
||||
|
||||
9. Accepting Warranty or Additional Liability. While redistributing
|
||||
the Work or Derivative Works thereof, You may choose to offer,
|
||||
and charge a fee for, acceptance of support, warranty, indemnity,
|
||||
or other liability obligations and/or rights consistent with this
|
||||
License. However, in accepting such obligations, You may act only
|
||||
on Your own behalf and on Your sole responsibility, not on behalf
|
||||
of any other Contributor, and only if You agree to indemnify,
|
||||
defend, and hold each Contributor harmless for any liability
|
||||
incurred by, or claims asserted against, such Contributor by reason
|
||||
of your accepting any such warranty or additional liability.
|
||||
|
||||
END OF TERMS AND CONDITIONS
|
||||
|
||||
APPENDIX: How to apply the Apache License to your work.
|
||||
|
||||
To apply the Apache License to your work, attach the following
|
||||
boilerplate notice, with the fields enclosed by brackets "[]"
|
||||
replaced with your own identifying information. (Don't include
|
||||
the brackets!) The text should be enclosed in the appropriate
|
||||
comment syntax for the file format. We also recommend that a
|
||||
file or class name and description of purpose be included on the
|
||||
same "printed page" as the copyright notice for easier
|
||||
identification within third-party archives.
|
||||
|
||||
Copyright [yyyy] [name of copyright owner]
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
|
@ -0,0 +1,25 @@
|
|||
Copyright (c) 2014 The Rust Project Developers
|
||||
|
||||
Permission is hereby granted, free of charge, to any
|
||||
person obtaining a copy of this software and associated
|
||||
documentation files (the "Software"), to deal in the
|
||||
Software without restriction, including without
|
||||
limitation the rights to use, copy, modify, merge,
|
||||
publish, distribute, sublicense, and/or sell copies of
|
||||
the Software, and to permit persons to whom the Software
|
||||
is furnished to do so, subject to the following
|
||||
conditions:
|
||||
|
||||
The above copyright notice and this permission notice
|
||||
shall be included in all copies or substantial portions
|
||||
of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF
|
||||
ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED
|
||||
TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A
|
||||
PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT
|
||||
SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
|
||||
CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
|
||||
OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR
|
||||
IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
|
||||
DEALINGS IN THE SOFTWARE.
|
|
@ -274,7 +274,7 @@ pub trait PrimInt
|
|||
///
|
||||
/// assert_eq!(2i32.pow(4), 16);
|
||||
/// ```
|
||||
fn pow(self, mut exp: u32) -> Self;
|
||||
fn pow(self, exp: u32) -> Self;
|
||||
}
|
||||
|
||||
macro_rules! prim_int_impl {
|
||||
|
|
|
@ -9,6 +9,10 @@
|
|||
// except according to those terms.
|
||||
|
||||
//! Numeric traits for generic mathematics
|
||||
#![doc(html_logo_url = "https://rust-num.github.io/num/rust-logo-128x128-blk-v2.png",
|
||||
html_favicon_url = "https://rust-num.github.io/num/favicon.ico",
|
||||
html_root_url = "https://rust-num.github.io/num/",
|
||||
html_playground_url = "http://play.integer32.com/")]
|
||||
|
||||
use std::ops::{Add, Sub, Mul, Div, Rem};
|
||||
|
||||
|
@ -16,6 +20,7 @@ pub use bounds::Bounded;
|
|||
pub use float::{Float, FloatConst};
|
||||
pub use identities::{Zero, One, zero, one};
|
||||
pub use ops::checked::*;
|
||||
pub use ops::wrapping::*;
|
||||
pub use ops::saturating::Saturating;
|
||||
pub use sign::{Signed, Unsigned, abs, abs_sub, signum};
|
||||
pub use cast::*;
|
||||
|
@ -39,6 +44,18 @@ pub trait Num: PartialEq + Zero + One
|
|||
type FromStrRadixErr;
|
||||
|
||||
/// Convert from a string and radix <= 36.
|
||||
///
|
||||
/// # Examples
|
||||
///
|
||||
/// ```rust
|
||||
/// use num_traits::Num;
|
||||
///
|
||||
/// let result = <i32 as Num>::from_str_radix("27", 10);
|
||||
/// assert_eq!(result, Ok(27));
|
||||
///
|
||||
/// let result = <i32 as Num>::from_str_radix("foo", 10);
|
||||
/// assert!(result.is_err());
|
||||
/// ```
|
||||
fn from_str_radix(str: &str, radix: u32) -> Result<Self, Self::FromStrRadixErr>;
|
||||
}
|
||||
|
||||
|
@ -224,6 +241,36 @@ macro_rules! float_trait_impl {
|
|||
}
|
||||
float_trait_impl!(Num for f32 f64);
|
||||
|
||||
/// A value bounded by a minimum and a maximum
|
||||
///
|
||||
/// If input is less than min then this returns min.
|
||||
/// If input is greater than max then this returns max.
|
||||
/// Otherwise this returns input.
|
||||
#[inline]
|
||||
pub fn clamp<T: PartialOrd>(input: T, min: T, max: T) -> T {
|
||||
debug_assert!(min <= max, "min must be less than or equal to max");
|
||||
if input < min {
|
||||
min
|
||||
} else if input > max {
|
||||
max
|
||||
} else {
|
||||
input
|
||||
}
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn clamp_test() {
|
||||
// Int test
|
||||
assert_eq!(1, clamp(1, -1, 2));
|
||||
assert_eq!(-1, clamp(-2, -1, 2));
|
||||
assert_eq!(2, clamp(3, -1, 2));
|
||||
|
||||
// Float test
|
||||
assert_eq!(1.0, clamp(1.0, -1.0, 2.0));
|
||||
assert_eq!(-1.0, clamp(-2.0, -1.0, 2.0));
|
||||
assert_eq!(2.0, clamp(3.0, -1.0, 2.0));
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn from_str_radix_unwrap() {
|
||||
// The Result error must impl Debug to allow unwrap()
|
||||
|
|
|
@ -1,2 +1,3 @@
|
|||
pub mod saturating;
|
||||
pub mod checked;
|
||||
pub mod wrapping;
|
||||
|
|
|
@ -0,0 +1,88 @@
|
|||
use std::ops::{Add, Sub, Mul};
|
||||
|
||||
macro_rules! wrapping_impl {
|
||||
($trait_name:ident, $method:ident, $t:ty) => {
|
||||
impl $trait_name for $t {
|
||||
#[inline]
|
||||
fn $method(&self, v: &Self) -> Self {
|
||||
<$t>::$method(*self, *v)
|
||||
}
|
||||
}
|
||||
};
|
||||
($trait_name:ident, $method:ident, $t:ty, $rhs:ty) => {
|
||||
impl $trait_name<$rhs> for $t {
|
||||
#[inline]
|
||||
fn $method(&self, v: &$rhs) -> Self {
|
||||
<$t>::$method(*self, *v)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// Performs addition that wraps around on overflow.
|
||||
pub trait WrappingAdd: Sized + Add<Self, Output=Self> {
|
||||
/// Wrapping (modular) addition. Computes `self + other`, wrapping around at the boundary of
|
||||
/// the type.
|
||||
fn wrapping_add(&self, v: &Self) -> Self;
|
||||
}
|
||||
|
||||
wrapping_impl!(WrappingAdd, wrapping_add, u8);
|
||||
wrapping_impl!(WrappingAdd, wrapping_add, u16);
|
||||
wrapping_impl!(WrappingAdd, wrapping_add, u32);
|
||||
wrapping_impl!(WrappingAdd, wrapping_add, u64);
|
||||
wrapping_impl!(WrappingAdd, wrapping_add, usize);
|
||||
|
||||
wrapping_impl!(WrappingAdd, wrapping_add, i8);
|
||||
wrapping_impl!(WrappingAdd, wrapping_add, i16);
|
||||
wrapping_impl!(WrappingAdd, wrapping_add, i32);
|
||||
wrapping_impl!(WrappingAdd, wrapping_add, i64);
|
||||
wrapping_impl!(WrappingAdd, wrapping_add, isize);
|
||||
|
||||
/// Performs subtraction that wraps around on overflow.
|
||||
pub trait WrappingSub: Sized + Sub<Self, Output=Self> {
|
||||
/// Wrapping (modular) subtraction. Computes `self - other`, wrapping around at the boundary
|
||||
/// of the type.
|
||||
fn wrapping_sub(&self, v: &Self) -> Self;
|
||||
}
|
||||
|
||||
wrapping_impl!(WrappingSub, wrapping_sub, u8);
|
||||
wrapping_impl!(WrappingSub, wrapping_sub, u16);
|
||||
wrapping_impl!(WrappingSub, wrapping_sub, u32);
|
||||
wrapping_impl!(WrappingSub, wrapping_sub, u64);
|
||||
wrapping_impl!(WrappingSub, wrapping_sub, usize);
|
||||
|
||||
wrapping_impl!(WrappingSub, wrapping_sub, i8);
|
||||
wrapping_impl!(WrappingSub, wrapping_sub, i16);
|
||||
wrapping_impl!(WrappingSub, wrapping_sub, i32);
|
||||
wrapping_impl!(WrappingSub, wrapping_sub, i64);
|
||||
wrapping_impl!(WrappingSub, wrapping_sub, isize);
|
||||
|
||||
/// Performs multiplication that wraps around on overflow.
|
||||
pub trait WrappingMul: Sized + Mul<Self, Output=Self> {
|
||||
/// Wrapping (modular) multiplication. Computes `self * other`, wrapping around at the boundary
|
||||
/// of the type.
|
||||
fn wrapping_mul(&self, v: &Self) -> Self;
|
||||
}
|
||||
|
||||
wrapping_impl!(WrappingMul, wrapping_mul, u8);
|
||||
wrapping_impl!(WrappingMul, wrapping_mul, u16);
|
||||
wrapping_impl!(WrappingMul, wrapping_mul, u32);
|
||||
wrapping_impl!(WrappingMul, wrapping_mul, u64);
|
||||
wrapping_impl!(WrappingMul, wrapping_mul, usize);
|
||||
|
||||
wrapping_impl!(WrappingMul, wrapping_mul, i8);
|
||||
wrapping_impl!(WrappingMul, wrapping_mul, i16);
|
||||
wrapping_impl!(WrappingMul, wrapping_mul, i32);
|
||||
wrapping_impl!(WrappingMul, wrapping_mul, i64);
|
||||
wrapping_impl!(WrappingMul, wrapping_mul, isize);
|
||||
|
||||
|
||||
#[test]
|
||||
fn test_wrapping_traits() {
|
||||
fn wrapping_add<T: WrappingAdd>(a: T, b: T) -> T { a.wrapping_add(&b) }
|
||||
fn wrapping_sub<T: WrappingSub>(a: T, b: T) -> T { a.wrapping_sub(&b) }
|
||||
fn wrapping_mul<T: WrappingMul>(a: T, b: T) -> T { a.wrapping_mul(&b) }
|
||||
assert_eq!(wrapping_add(255, 1), 0u8);
|
||||
assert_eq!(wrapping_sub(0, 1), 255u8);
|
||||
assert_eq!(wrapping_mul(255, 2), 254u8);
|
||||
}
|
|
@ -1 +1 @@
|
|||
{"files":{".cargo-ok":"e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855",".gitignore":"f9b1ca6ae27d1c18215265024629a8960c31379f206d9ed20f64e0b2dcf79805",".travis.yml":"9b39b9d42d077d028d5742450256c9f11f3456ff185ce2a987f4606b152bf440","Cargo.toml":"3324e491e6872435e4131dbe8312c3ffeff4a1c7c29814da3de796a8d34025e5","LICENSE-APACHE":"a60eea817514531668d7e00765731449fe14d059d3249e0bc93b36de45f759f2","LICENSE-MIT":"c9a75f18b9ab2927829a208fc6aa2cf4e63b8420887ba29cdb265d6619ae82d5","README.md":"d7bb9d24f29da05ef02c232f6354c01a93a8205f55d137f8b7d7a74f88163994","appveyor.yml":"1181ecde6a5df38051107a3ef4051751499f5a462ed761c1eafd6d4c62fde73e","src/condvar.rs":"227cd171d14ee54b115a5d1bff38ac4a01460ca2d85a40773b08035b6f39e94e","src/elision.rs":"0fef04d2991afeabafb041e81afeec74e89095d0eca49e5516bdcd5bc90c086f","src/lib.rs":"50951210148941266ce3a7d4017c339f8ad4419a9a8db6f915023890ed27d638","src/mutex.rs":"956b58465f78ac97d8ecf4dda7bbd973998cb29c4057f51cc3d8c8bdfa47f460","src/once.rs":"dee225c5472d152ed820eb90a3dcb96f7af409d8315f006b2179fa3f350de4ed","src/raw_mutex.rs":"225cbf0ef951be062866da674e5eea8245fcc43ecd8a26da7097dea03b770bf5","src/raw_remutex.rs":"a451cc3ce7bf11bc94777148b81d39b07b5a2a2fc698f6db2ca2fc765b158fa8","src/raw_rwlock.rs":"f7a206d0d401dae475d42f06d8a8fe6d8f2ca986b60633aaa4d3d588a997793e","src/remutex.rs":"a5cefa1a97e4669e3b2dffa9007988e6a6088500472d9eefea1a28ed1443e1b0","src/rwlock.rs":"9bdafa8eabc0b6720deed380799db1c1219f5344933437196f67332a6d9e1740","src/stable.rs":"cc18c58404dc6017924d88fb9f4ed94e5320b8cb0a36985162b23130b8cd7480","src/util.rs":"2d07c0c010a857790ae2ed6a1215eeed8af76859e076797ea1ba8dec82169e84"},"package":"3771b463ebf30418ef54378e647d01cc33123b2e7a4958b1cec284edc71054f6"}
|
||||
{"files":{".cargo-ok":"e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855",".gitignore":"f9b1ca6ae27d1c18215265024629a8960c31379f206d9ed20f64e0b2dcf79805",".travis.yml":"9b39b9d42d077d028d5742450256c9f11f3456ff185ce2a987f4606b152bf440","Cargo.toml":"8a0938f1fd49ceae700f27333cdacd754d7b2205664265de4bd67be3d37a9525","LICENSE-APACHE":"a60eea817514531668d7e00765731449fe14d059d3249e0bc93b36de45f759f2","LICENSE-MIT":"c9a75f18b9ab2927829a208fc6aa2cf4e63b8420887ba29cdb265d6619ae82d5","README.md":"d7bb9d24f29da05ef02c232f6354c01a93a8205f55d137f8b7d7a74f88163994","appveyor.yml":"1181ecde6a5df38051107a3ef4051751499f5a462ed761c1eafd6d4c62fde73e","src/condvar.rs":"227cd171d14ee54b115a5d1bff38ac4a01460ca2d85a40773b08035b6f39e94e","src/elision.rs":"0fef04d2991afeabafb041e81afeec74e89095d0eca49e5516bdcd5bc90c086f","src/lib.rs":"50951210148941266ce3a7d4017c339f8ad4419a9a8db6f915023890ed27d638","src/mutex.rs":"956b58465f78ac97d8ecf4dda7bbd973998cb29c4057f51cc3d8c8bdfa47f460","src/once.rs":"dee225c5472d152ed820eb90a3dcb96f7af409d8315f006b2179fa3f350de4ed","src/raw_mutex.rs":"225cbf0ef951be062866da674e5eea8245fcc43ecd8a26da7097dea03b770bf5","src/raw_remutex.rs":"a451cc3ce7bf11bc94777148b81d39b07b5a2a2fc698f6db2ca2fc765b158fa8","src/raw_rwlock.rs":"f7a206d0d401dae475d42f06d8a8fe6d8f2ca986b60633aaa4d3d588a997793e","src/remutex.rs":"a5cefa1a97e4669e3b2dffa9007988e6a6088500472d9eefea1a28ed1443e1b0","src/rwlock.rs":"3de0dded88f3dd339e962aba1cc778a03d5a10ac743325a81859617c455c31d3","src/stable.rs":"cc18c58404dc6017924d88fb9f4ed94e5320b8cb0a36985162b23130b8cd7480","src/util.rs":"2d07c0c010a857790ae2ed6a1215eeed8af76859e076797ea1ba8dec82169e84"},"package":"fa12d706797d42551663426a45e2db2e0364bd1dbf6aeada87e89c5f981f43e9"}
|
|
@ -1,6 +1,6 @@
|
|||
[package]
|
||||
name = "parking_lot"
|
||||
version = "0.3.7"
|
||||
version = "0.3.8"
|
||||
authors = ["Amanieu d'Antras <amanieu@gmail.com>"]
|
||||
description = "More compact and efficient implementations of the standard synchronization primitives."
|
||||
documentation = "https://amanieu.github.io/parking_lot/parking_lot/index.html"
|
||||
|
|
|
@ -378,6 +378,22 @@ impl<T: ?Sized> RwLock<T> {
|
|||
pub unsafe fn raw_unlock_write_fair(&self) {
|
||||
self.raw.unlock_exclusive(true);
|
||||
}
|
||||
|
||||
/// Atomically downgrades a write lock into a read lock without allowing any
|
||||
/// writers to take exclusive access of the lock in the meantime.
|
||||
///
|
||||
/// See `RwLockWriteGuard::downgrade`.
|
||||
///
|
||||
/// # Safety
|
||||
///
|
||||
/// This function must only be called if the rwlock was locked using
|
||||
/// `raw_write` or `raw_try_write`, or if an `RwLockWriteGuard` from this
|
||||
/// rwlock was leaked (e.g. with `mem::forget`). The rwlock must be locked
|
||||
/// with exclusive write access.
|
||||
#[inline]
|
||||
pub unsafe fn raw_downgrade(&self) {
|
||||
self.raw.downgrade();
|
||||
}
|
||||
}
|
||||
|
||||
impl RwLock<()> {
|
||||
|
|
|
@ -1 +1 @@
|
|||
{"files":{".cargo-ok":"e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855",".gitignore":"f9b1ca6ae27d1c18215265024629a8960c31379f206d9ed20f64e0b2dcf79805",".travis.yml":"85e71e3082a4d00de52505b07957cca71718d9a1cc531f66d77ad8f54dd190a2","Cargo.toml":"40c50f26b3d9369da246b6f7be656afe86cbc80940bb8ba1f16fd5971bd20213","LICENSE-APACHE":"a60eea817514531668d7e00765731449fe14d059d3249e0bc93b36de45f759f2","LICENSE-MIT":"0621878e61f0d0fda054bcbe02df75192c28bde1ecc8289cbd86aeba2dd72720","README.md":"1f81d0b3d68ae7fde22059e956541697e053dc335177013fe8c367210fff77d0","benches/bench.rs":"11adfc56ff91ddaf780a46ef45ed359c06d4086ce7787951bbb8dbfd9b11898f","src/lib.rs":"abc5f8a647f046f3d002901be4d2f365549a603a5f218bc374184a5ca26c109c"},"package":"9b488405652f1d330f26e3112a477b12b49a70589372cb50aea2e29ebeb5ba54"}
|
||||
{"files":{".cargo-ok":"e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855",".gitignore":"f9b1ca6ae27d1c18215265024629a8960c31379f206d9ed20f64e0b2dcf79805",".travis.yml":"85e71e3082a4d00de52505b07957cca71718d9a1cc531f66d77ad8f54dd190a2","Cargo.toml":"72b56d640b72470dedf71dead0d4ceda51ec82ac048dea9a97ab6be440eb41a9","LICENSE-APACHE":"a60eea817514531668d7e00765731449fe14d059d3249e0bc93b36de45f759f2","LICENSE-MIT":"0621878e61f0d0fda054bcbe02df75192c28bde1ecc8289cbd86aeba2dd72720","README.md":"795851777c3d915da30f2b11b21f478fb46f793170321b1ffa64b6eb27d93127","benches/bench.rs":"4e5e084d25ce4fe5824e653438249206278f3f428c4c2bfb96f98ad8622dfa5e","src/lib.rs":"c3a7cff009a399f1d180b23daaf483798021a117a352c81704dd8ff470ba9f16"},"package":"ceca1642c89148ca05611cc775a0c383abef355fc4907c4e95f49f7b09d6287c"}
|
|
@ -1,6 +1,6 @@
|
|||
[package]
|
||||
name = "pdqsort"
|
||||
version = "0.1.1"
|
||||
version = "0.1.2"
|
||||
authors = ["Stjepan Glavina <stjepang@gmail.com>"]
|
||||
description = "Pattern-defeating quicksort"
|
||||
repository = "https://github.com/stjepang/pdqsort"
|
||||
|
|
|
@ -6,10 +6,10 @@
|
|||
[![Documentation](https://docs.rs/pdqsort/badge.svg)](https://docs.rs/pdqsort)
|
||||
|
||||
This sort is significantly faster than the standard sort in Rust. In particular, it sorts
|
||||
random arrays of integers approximately 40% faster. The key drawback is that it is an unstable
|
||||
random arrays of integers approximately 45% faster. The key drawback is that it is an unstable
|
||||
sort (i.e. may reorder equal elements). However, in most cases stability doesn't matter anyway.
|
||||
|
||||
The algorithm was designed by Orson Peters and first published at: https://github.com/orlp/pdqsort
|
||||
The algorithm is based on pdqsort by Orson Peters, published at: https://github.com/orlp/pdqsort
|
||||
|
||||
#### Properties
|
||||
|
||||
|
@ -42,7 +42,7 @@ Sorting 10 million random numbers of type `u64`:
|
|||
|
||||
| Sort | Time |
|
||||
|-------------------|-----------:|
|
||||
| pdqsort | **396 ms** |
|
||||
| pdqsort | **370 ms** |
|
||||
| slice::sort | 668 ms |
|
||||
| [quickersort][qs] | 777 ms |
|
||||
| [dmsort][ds] | 728 ms |
|
||||
|
@ -50,9 +50,11 @@ Sorting 10 million random numbers of type `u64`:
|
|||
|
||||
#### Extensive benchmarks
|
||||
|
||||
The benchmarks that follow are [used in Rust][bench] for testing the performance of slice::sort.
|
||||
The following benchmarks are [used in Rust][bench] for testing the performance of slice::sort.
|
||||
|
||||
| Benchmark | pdqsort | slice::sort | [quickersort][qs] | [dmsort][ds] | [rdxsort][rs] |
|
||||
*Note: The numbers for dmsort are outdated.*
|
||||
|
||||
| Benchmark | pdqsort | slice::sort | [quickersort][qs] | ~~[dmsort][ds]~~ | [rdxsort][rs] |
|
||||
|-------------------------|--------------:|--------------:|------------------:|-------------:|--------------:|
|
||||
| large_ascending | 11 us | **9 us** | 12 us | 22 us | 358 us |
|
||||
| large_descending | **14 us** | **14 us** | 46 us | 144 us | 347 us |
|
||||
|
|
|
@ -92,17 +92,15 @@ sort_bench!(sort_large_big_descending, gen_big_descending, 10000);
|
|||
fn sort_large_random_expensive(b: &mut Bencher) {
|
||||
let len = 10000;
|
||||
b.iter(|| {
|
||||
let mut v = gen_random(len);
|
||||
let mut count = 0;
|
||||
let mut cmp = move |a: &u64, b: &u64| {
|
||||
pdqsort::sort_by(&mut v, |a: &u64, b: &u64| {
|
||||
count += 1;
|
||||
if count % 1_000_000_000 == 0 {
|
||||
panic!("should not happen");
|
||||
}
|
||||
(*a as f64).cos().partial_cmp(&(*b as f64).cos()).unwrap()
|
||||
};
|
||||
|
||||
let mut v = gen_random(len);
|
||||
pdqsort::sort_by(&mut v, &mut cmp);
|
||||
});
|
||||
test::black_box(count);
|
||||
});
|
||||
b.bytes = len as u64 * mem::size_of::<u64>() as u64;
|
||||
|
|
|
@ -1,16 +1,10 @@
|
|||
//! Pattern-defeating quicksort.
|
||||
//!
|
||||
//! This sort is significantly faster than the standard sort in Rust. In particular, it sorts
|
||||
//! random arrays of integers approximately 40% faster. The key drawback is that it is an unstable
|
||||
//! random arrays of integers approximately 45% faster. The key drawback is that it is an unstable
|
||||
//! sort (i.e. may reorder equal elements). However, in most cases stability doesn't matter anyway.
|
||||
//!
|
||||
//! The algorithm was designed by Orson Peters and first published at:
|
||||
//! https://github.com/orlp/pdqsort
|
||||
//!
|
||||
//! Quoting it's designer: "Pattern-defeating quicksort (pdqsort) is a novel sorting algorithm
|
||||
//! that combines the fast average case of randomized quicksort with the fast worst case of
|
||||
//! heapsort, while achieving linear time on inputs with certain patterns. pdqsort is an extension
|
||||
//! and improvement of David Musser's introsort."
|
||||
//! The algorithm is based on pdqsort by Orson Peters, published at: https://github.com/orlp/pdqsort
|
||||
//!
|
||||
//! # Properties
|
||||
//!
|
||||
|
@ -43,7 +37,7 @@ use core::cmp::{self, Ordering};
|
|||
use core::mem;
|
||||
use core::ptr;
|
||||
|
||||
/// On drop, takes the value out of `Option` and writes it into `dest`.
|
||||
/// When dropped, takes the value out of `Option` and writes it into `dest`.
|
||||
///
|
||||
/// This allows us to safely read the pivot into a stack-allocated variable for efficiency, and
|
||||
/// write it back into the slice after partitioning. This way we ensure that the write happens
|
||||
|
@ -61,55 +55,58 @@ impl<T> Drop for WriteOnDrop<T> {
|
|||
}
|
||||
}
|
||||
|
||||
/// Inserts `v[0]` into pre-sorted sequence `v[1..]` so that whole `v[..]` becomes sorted.
|
||||
///
|
||||
/// This is the integral subroutine of insertion sort.
|
||||
fn insert_head<T, F>(v: &mut [T], is_less: &mut F)
|
||||
/// Sorts a slice using insertion sort, which is `O(n^2)` worst-case.
|
||||
fn insertion_sort<T, F>(v: &mut [T], is_less: &mut F)
|
||||
where F: FnMut(&T, &T) -> bool
|
||||
{
|
||||
if v.len() >= 2 && is_less(&v[1], &v[0]) {
|
||||
let len = v.len();
|
||||
|
||||
for i in 1..len {
|
||||
unsafe {
|
||||
// There are three ways to implement insertion here:
|
||||
//
|
||||
// 1. Swap adjacent elements until the first one gets to its final destination.
|
||||
// However, this way we copy data around more than is necessary. If elements are big
|
||||
// structures (costly to copy), this method will be slow.
|
||||
//
|
||||
// 2. Iterate until the right place for the first element is found. Then shift the
|
||||
// elements succeeding it to make room for it and finally place it into the
|
||||
// remaining hole. This is a good method.
|
||||
//
|
||||
// 3. Copy the first element into a temporary variable. Iterate until the right place
|
||||
// for it is found. As we go along, copy every traversed element into the slot
|
||||
// preceding it. Finally, copy data from the temporary variable into the remaining
|
||||
// hole. This method is very good. Benchmarks demonstrated slightly better
|
||||
// performance than with the 2nd method.
|
||||
//
|
||||
// All methods were benchmarked, and the 3rd showed best results. So we chose that one.
|
||||
let mut tmp = NoDrop { value: Some(ptr::read(&v[0])) };
|
||||
if is_less(v.get_unchecked(i), v.get_unchecked(i - 1)) {
|
||||
// There are three ways to implement insertion here:
|
||||
//
|
||||
// 1. Swap adjacent elements until the first one gets to its final destination.
|
||||
// However, this way we copy data around more than is necessary. If elements are
|
||||
// big structures (costly to copy), this method will be slow.
|
||||
//
|
||||
// 2. Iterate until the right place for the first element is found. Then shift the
|
||||
// elements succeeding it to make room for it and finally place it into the
|
||||
// remaining hole. This is a good method.
|
||||
//
|
||||
// 3. Copy the first element into a temporary variable. Iterate until the right
|
||||
// place for it is found. As we go along, copy every traversed element into the
|
||||
// slot preceding it. Finally, copy data from the temporary variable into the
|
||||
// remaining hole. This method is very good. Benchmarks demonstrated slightly
|
||||
// better performance than with the 2nd method.
|
||||
//
|
||||
// All methods were benchmarked, and the 3rd showed best results. So we chose that
|
||||
// one.
|
||||
let mut tmp = NoDrop { value: Some(ptr::read(v.get_unchecked(i))) };
|
||||
|
||||
// Intermediate state of the insertion process is always tracked by `hole`, which
|
||||
// serves two purposes:
|
||||
// 1. Protects integrity of `v` from panics in `is_less`.
|
||||
// 2. Fills the remaining hole in `v` in the end.
|
||||
//
|
||||
// Panic safety:
|
||||
//
|
||||
// If `is_less` panics at any point during the process, `hole` will get dropped and
|
||||
// fill the hole in `v` with `tmp`, thus ensuring that `v` still holds every object it
|
||||
// initially held exactly once.
|
||||
let mut hole = InsertionHole {
|
||||
src: tmp.value.as_mut().unwrap(),
|
||||
dest: &mut v[1],
|
||||
};
|
||||
ptr::copy_nonoverlapping(&v[1], &mut v[0], 1);
|
||||
// Intermediate state of the insertion process is always tracked by `hole`, which
|
||||
// serves two purposes:
|
||||
// 1. Protects integrity of `v` from panics in `is_less`.
|
||||
// 2. Fills the remaining hole in `v` in the end.
|
||||
//
|
||||
// Panic safety:
|
||||
//
|
||||
// If `is_less` panics at any point during the process, `hole` will get dropped and
|
||||
// fill the hole in `v` with `tmp`, thus ensuring that `v` still holds every object
|
||||
// it initially held exactly once.
|
||||
let mut hole = InsertionHole {
|
||||
src: tmp.value.as_mut().unwrap(),
|
||||
dest: v.get_unchecked_mut(i - 1),
|
||||
};
|
||||
ptr::copy_nonoverlapping(v.get_unchecked(i - 1), v.get_unchecked_mut(i), 1);
|
||||
|
||||
for i in 2..v.len() {
|
||||
if !is_less(&v[i], &tmp.value.as_ref().unwrap()) {
|
||||
break;
|
||||
for j in (0..i-1).rev() {
|
||||
if !is_less(&tmp.value.as_ref().unwrap(), v.get_unchecked(j)) {
|
||||
break;
|
||||
}
|
||||
ptr::copy_nonoverlapping(v.get_unchecked(j), v.get_unchecked_mut(j + 1), 1);
|
||||
hole.dest = v.get_unchecked_mut(j);
|
||||
}
|
||||
ptr::copy_nonoverlapping(&v[i], &mut v[i - 1], 1);
|
||||
hole.dest = &mut v[i];
|
||||
}
|
||||
// `hole` gets dropped and thus copies `tmp` into the remaining hole in `v`.
|
||||
}
|
||||
|
@ -139,18 +136,6 @@ fn insert_head<T, F>(v: &mut [T], is_less: &mut F)
|
|||
}
|
||||
}
|
||||
|
||||
/// Sorts a slice using insertion sort, which is `O(n^2)` worst-case.
|
||||
fn insertion_sort<T, F>(v: &mut [T], is_less: &mut F)
|
||||
where F: FnMut(&T, &T) -> bool
|
||||
{
|
||||
let len = v.len();
|
||||
if len >= 2 {
|
||||
for i in (0..len-1).rev() {
|
||||
insert_head(&mut v[i..], is_less);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// Sorts `v` using heapsort, which guarantees `O(n log n)` worst-case.
|
||||
#[cold]
|
||||
fn heapsort<T, F>(v: &mut [T], is_less: &mut F)
|
||||
|
@ -203,7 +188,7 @@ fn heapsort<T, F>(v: &mut [T], is_less: &mut F)
|
|||
fn partition_in_blocks<T, F>(v: &mut [T], pivot: &T, is_less: &mut F) -> usize
|
||||
where F: FnMut(&T, &T) -> bool
|
||||
{
|
||||
const BLOCK: usize = 64;
|
||||
const BLOCK: usize = 128;
|
||||
|
||||
// State on the left side.
|
||||
let mut l = v.as_mut_ptr();
|
||||
|
@ -221,6 +206,7 @@ fn partition_in_blocks<T, F>(v: &mut [T], pivot: &T, is_less: &mut F) -> usize
|
|||
|
||||
// Returns the number of elements between pointers `l` (inclusive) and `r` (exclusive).
|
||||
fn width<T>(l: *mut T, r: *mut T) -> usize {
|
||||
assert!(mem::size_of::<T>() > 0);
|
||||
(r as usize - l as usize) / mem::size_of::<T>()
|
||||
}
|
||||
|
||||
|
@ -283,7 +269,7 @@ fn partition_in_blocks<T, F>(v: &mut [T], pivot: &T, is_less: &mut F) -> usize
|
|||
}
|
||||
}
|
||||
|
||||
// Number of displaced elements to swap between the left and right side.
|
||||
// Number of out-of-order elements to swap between the left and right side.
|
||||
let count = cmp::min(width(start_l, end_l), width(start_r, end_r));
|
||||
|
||||
if count > 0 {
|
||||
|
@ -371,7 +357,7 @@ fn partition<T, F>(v: &mut [T], pivot: usize, is_less: &mut F) -> (usize, bool)
|
|||
};
|
||||
let pivot = write_on_drop.value.as_ref().unwrap();
|
||||
|
||||
// Find the first pair of displaced elements.
|
||||
// Find the first pair of out-of-order elements.
|
||||
let mut l = 0;
|
||||
let mut r = v.len();
|
||||
unsafe {
|
||||
|
@ -469,7 +455,7 @@ fn choose_pivot<T, F>(v: &mut [T], is_less: &mut F) -> usize
|
|||
let mut c = len / 4 * 3;
|
||||
let mut swaps = 0;
|
||||
|
||||
if len >= 4 {
|
||||
if len >= 8 {
|
||||
let mut sort2 = |a: &mut usize, b: &mut usize| unsafe {
|
||||
if is_less(v.get_unchecked(*b), v.get_unchecked(*a)) {
|
||||
ptr::swap(a, b);
|
||||
|
@ -510,7 +496,7 @@ fn choose_pivot<T, F>(v: &mut [T], is_less: &mut F) -> usize
|
|||
///
|
||||
/// `limit` is the number of allowed imbalanced partitions before switching to `heapsort`. If zero,
|
||||
/// this function will immediately switch to heapsort.
|
||||
fn recurse<T, F>(v: &mut [T], is_less: &mut F, pred: Option<&T>, mut limit: usize)
|
||||
fn recurse<'a, T, F>(mut v: &'a mut [T], is_less: &mut F, mut pred: Option<&'a T>, mut limit: usize)
|
||||
where F: FnMut(&T, &T) -> bool
|
||||
{
|
||||
// If `v` has length up to `insertion_len`, simply switch to insertion sort because it is going
|
||||
|
@ -521,53 +507,64 @@ fn recurse<T, F>(v: &mut [T], is_less: &mut F, pred: Option<&T>, mut limit: usiz
|
|||
16
|
||||
};
|
||||
|
||||
let len = v.len();
|
||||
// This is `true` if the last partitioning was balanced.
|
||||
let mut was_balanced = true;
|
||||
|
||||
if len <= max_insertion {
|
||||
insertion_sort(v, is_less);
|
||||
return;
|
||||
}
|
||||
|
||||
if limit == 0 {
|
||||
heapsort(v, is_less);
|
||||
return;
|
||||
}
|
||||
|
||||
let pivot = choose_pivot(v, is_less);
|
||||
|
||||
// If the chosen pivot is equal to the predecessor, then it's the smallest element in the
|
||||
// slice. Partition the slice into elements equal to and elements greater than the pivot.
|
||||
// This case is often hit when the slice contains many duplicate elements.
|
||||
if let Some(p) = pred {
|
||||
if !is_less(p, &v[pivot]) {
|
||||
let mid = partition_equal(v, pivot, is_less);
|
||||
recurse(&mut v[mid..], is_less, pred, limit);
|
||||
loop {
|
||||
let len = v.len();
|
||||
if len <= max_insertion {
|
||||
insertion_sort(v, is_less);
|
||||
return;
|
||||
}
|
||||
|
||||
if limit == 0 {
|
||||
heapsort(v, is_less);
|
||||
return;
|
||||
}
|
||||
|
||||
// If the last partitioning was imbalanced, try breaking patterns in the slice by shuffling
|
||||
// some elements around. Hopefully we'll choose a better pivot this time.
|
||||
if !was_balanced {
|
||||
break_patterns(v);
|
||||
limit -= 1;
|
||||
}
|
||||
|
||||
let pivot = choose_pivot(v, is_less);
|
||||
|
||||
// If the chosen pivot is equal to the predecessor, then it's the smallest element in the
|
||||
// slice. Partition the slice into elements equal to and elements greater than the pivot.
|
||||
// This case is usually hit when the slice contains many duplicate elements.
|
||||
if let Some(p) = pred {
|
||||
if !is_less(p, &v[pivot]) {
|
||||
let mid = partition_equal(v, pivot, is_less);
|
||||
v = &mut {v}[mid..];
|
||||
continue;
|
||||
}
|
||||
}
|
||||
|
||||
let (mid, was_partitioned) = partition(v, pivot, is_less);
|
||||
was_balanced = cmp::min(mid, len - mid) >= len / 8;
|
||||
|
||||
// If the partitioning is decently balanced and the slice was already partitioned, there
|
||||
// are good chances it is also completely sorted. If so, we're done.
|
||||
if was_balanced && was_partitioned && v.windows(2).all(|w| !is_less(&w[1], &w[0])) {
|
||||
return;
|
||||
}
|
||||
|
||||
let (left, right) = {v}.split_at_mut(mid);
|
||||
let (pivot, right) = right.split_at_mut(1);
|
||||
|
||||
// Recurse into the smaller side only, in order to minimize the total number of recursive
|
||||
// calls and consume less stack space.
|
||||
if left.len() < right.len() {
|
||||
recurse(left, is_less, pred, limit);
|
||||
v = right;
|
||||
pred = Some(&pivot[0]);
|
||||
} else {
|
||||
recurse(right, is_less, Some(&pivot[0]), limit);
|
||||
v = left;
|
||||
}
|
||||
}
|
||||
|
||||
let (mid, was_partitioned) = partition(v, pivot, is_less);
|
||||
let is_balanced = cmp::min(mid, len - mid) >= len / 8;
|
||||
|
||||
// If the partitioning is decently balanced and the slice was already partitioned, there are
|
||||
// good chances it is also completely sorted. If so, we're done.
|
||||
if is_balanced && was_partitioned && v.windows(2).all(|w| !is_less(&w[1], &w[0])) {
|
||||
return;
|
||||
}
|
||||
|
||||
let (left, right) = v.split_at_mut(mid);
|
||||
let (pivot, right) = right.split_at_mut(1);
|
||||
|
||||
// If the partitioning is imbalanced, try breaking patterns in the slice by shuffling
|
||||
// potential future pivots around.
|
||||
if !is_balanced {
|
||||
break_patterns(left);
|
||||
break_patterns(right);
|
||||
limit -= 1;
|
||||
}
|
||||
|
||||
recurse(left, is_less, pred, limit);
|
||||
recurse(right, is_less, Some(&pivot[0]), limit);
|
||||
}
|
||||
|
||||
/// Sorts `v` using quicksort.
|
||||
|
|
|
@ -0,0 +1 @@
|
|||
{"files":{".cargo-ok":"e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855","Cargo.toml":"3aad5ce464f7224e4b86fc0a70d89c354635ed624bf4bb12cf4ca597c45879b7","lib.rs":"f0f2793a21bc85ae3ee3e040ef703da87b558a1ce524873ef872bf44de795931"},"package":"9f566249236c6ca4340f7ca78968271f0ed2b0f234007a61b66f9ecd0af09260"}
|
|
@ -0,0 +1,12 @@
|
|||
[package]
|
||||
name = "procedural-masquerade"
|
||||
version = "0.1.1"
|
||||
authors = ["Simon Sapin <simon.sapin@exyr.org>"]
|
||||
description = "macro_rules for making proc_macro_derive pretending to be proc_macro"
|
||||
documentation = "https://docs.rs/procedural-masquerade/"
|
||||
repository = "https://github.com/servo/rust-cssparser"
|
||||
license = "MIT/Apache-2.0"
|
||||
|
||||
[lib]
|
||||
path = "lib.rs"
|
||||
doctest = false
|
|
@ -0,0 +1,250 @@
|
|||
//! # Custom `derive` pretending to be functional procedural macros on Rust 1.15
|
||||
//!
|
||||
//! This crate enables creating function-like macros (invoked as `foo!(...)`)
|
||||
//! with a procedural component,
|
||||
//! based on both custom `derive` (a.k.a. *Macros 1.1*) and `macro_rules!`.
|
||||
//!
|
||||
//! This convoluted mechanism enables such macros to run on stable Rust 1.15,
|
||||
//! even though functional procedural macros (a.k.a. *Macros 2.0*) are not available yet.
|
||||
//!
|
||||
//! A library defining such a macro needs two crates: a “normal” one, and a `proc-macro` one.
|
||||
//! In the example below we’ll call them `libfoo` and `libfoo-macros`, respectively.
|
||||
//!
|
||||
//! # Credits
|
||||
//!
|
||||
//! The trick that makes this crate work
|
||||
//! is based on an idea from [David Tolnay](https://github.com/dtolnay).
|
||||
//! Many thanks!
|
||||
//!
|
||||
//! # Example
|
||||
//!
|
||||
//! As a simple example, we’re going to re-implement the `stringify!` macro.
|
||||
//! This is useless since `stringify!` already exists in the standard library,
|
||||
//! and a bit absurd since this crate uses `stringify!` internally.
|
||||
//!
|
||||
//! Nevertheless, it serves as a simple example to demonstrate the use of this crate.
|
||||
//!
|
||||
//! ## The `proc-macro` crate
|
||||
//!
|
||||
//! The minimal `Cargo.toml` file is typical for Macros 1.1:
|
||||
//!
|
||||
//! ```toml
|
||||
//! [package]
|
||||
//! name = "libfoo-macros"
|
||||
//! version = "1.0.0"
|
||||
//!
|
||||
//! [lib]
|
||||
//! proc-macro = true
|
||||
//! ```
|
||||
//!
|
||||
//! In the code, we define the procedural part of our macro in a function.
|
||||
//! This function will not be used directly by end users,
|
||||
//! but it still needs to be re-exported to them
|
||||
//! (because of limitations in `macro_rules!`).
|
||||
//!
|
||||
//! To avoid name collisions, we and a long and explicit prefix in the function’s name.
|
||||
//!
|
||||
//! The function takes a string containing arbitrary Rust tokens,
|
||||
//! and returns a string that is parsed as *items*.
|
||||
//! The returned string can contain constants, statics, functions, `impl`s, etc.,
|
||||
//! but not expressions directly.
|
||||
//!
|
||||
//! ```rust
|
||||
//! #[macro_use] extern crate procedural_masquerade;
|
||||
//! extern crate proc_macro;
|
||||
//!
|
||||
//! define_proc_macros! {
|
||||
//! #[allow(non_snake_case)]
|
||||
//! pub fn foo_internal__stringify_const(input: &str) -> String {
|
||||
//! format!("const STRINGIFIED: &'static str = {:?};", input)
|
||||
//! }
|
||||
//! }
|
||||
//! ```
|
||||
//!
|
||||
//! A less trivial macro would probably use
|
||||
//! the [`syn`](https://github.com/dtolnay/syn/) crate to parse its input
|
||||
//! and the [`quote`](https://github.com/dtolnay/quote) crate to generate its output.
|
||||
//!
|
||||
//! ## The library crate
|
||||
//!
|
||||
//! ```toml
|
||||
//! [package]
|
||||
//! name = "libfoo"
|
||||
//! version = "1.0.0"
|
||||
//!
|
||||
//! [dependencies]
|
||||
//! cssparser-macros = {path = "./macros", version = "1.0"}
|
||||
//! ```
|
||||
//!
|
||||
//! ```rust
|
||||
//! #[macro_use] extern crate libfoo_macros; // (1)
|
||||
//!
|
||||
//! pub use libfoo_macros::*; // (2)
|
||||
//!
|
||||
//! define_invoke_proc_macro!(libfoo__invoke_proc_macro); // (3)
|
||||
//!
|
||||
//! #[macro_export]
|
||||
//! macro_rules! foo_stringify { // (4)
|
||||
//! ( $( $tts: tt ) ) => {
|
||||
//! { // (5)
|
||||
//! libfoo__invoke_proc_macro! { // (6)
|
||||
//! foo_internal__stringify_const!( $( $tts ) ) // (7)
|
||||
//! }
|
||||
//! STRINGIFIED // (8)
|
||||
//! }
|
||||
//! }
|
||||
//! }
|
||||
//! ```
|
||||
//!
|
||||
//! Let’s go trough the numbered lines one by one:
|
||||
//!
|
||||
//! 1. `libfoo` depends on the other `libfoo-macros`, and imports its macros.
|
||||
//! 2. Everything exported by `libfoo-macros` (which is one custom `derive`)
|
||||
//! is re-exported to users of `libfoo`.
|
||||
//! They’re not expected to use it directly,
|
||||
//! but expansion of the `foo_stringify` macro needs it.
|
||||
//! 3. This macro invocation defines yet another macro, called `libfoo__invoke_proc_macro`,
|
||||
//! which is also exported.
|
||||
//! This indirection is necessary
|
||||
//! because re-exporting `macro_rules!` macros doesn’t work currently,
|
||||
//! and once again it is used by the expansion of `foo_stringify`.
|
||||
//! Again, we use a long prefix to avoid name collisions.
|
||||
//! 4. Finally, we define the macro that we really want.
|
||||
//! This one has a name that users will use.
|
||||
//! 5. The expansion of this macro will define some items,
|
||||
//! whose names are not hygienic in `macro_rules`.
|
||||
//! So we wrap everything in an extra `{…}` block to prevent these names for leaking.
|
||||
//! 6. Here we use the macro defined in (3),
|
||||
//! which allows us to write something that look like invoking a functional procedural macro,
|
||||
//! but really uses a custom `derive`.
|
||||
//! This will define a type called `ProceduralMasqueradeDummyType`,
|
||||
//! as a placeholder to use `derive`.
|
||||
//! If `libfoo__invoke_proc_macro!` is to be used more than once,
|
||||
//! each use needs to be nested in another block
|
||||
//! so that the names of multiple dummy types don’t collide.
|
||||
//! 7. In addition to the dummy type,
|
||||
//! the items returned by our procedural component are inserted here.
|
||||
//! (In this case the `STRINGIFIED` constant.)
|
||||
//! 8. Finally, we write the expression that we want the macro to evaluate to.
|
||||
//! This expression can use parts of `foo_stringify`’s input,
|
||||
//! it can contain control-flow statements like `return` or `continue`,
|
||||
//! and of course refer to procedurally-defined items.
|
||||
//!
|
||||
//! This macro can be used in an expression context.
|
||||
//! It expands to a block-expression that contains some items (as an implementation detail)
|
||||
//! and ends with another expression.
|
||||
//!
|
||||
//! ## For users
|
||||
//!
|
||||
//! Users of `libfoo` don’t need to worry about any of these implementation details.
|
||||
//! They can use the `foo_stringify` macro as if it were a simle `macro_rules` macro:
|
||||
//!
|
||||
//! ```rust
|
||||
//! #[macro_use] extern crate libfoo;
|
||||
//!
|
||||
//! fn main() {
|
||||
//! do_something(foo_stringify!(1 + 2));
|
||||
//! }
|
||||
//!
|
||||
//! fn do_something(_: &str) { /* ... */ }
|
||||
//! ```
|
||||
//!
|
||||
//! # More
|
||||
//!
|
||||
//! To see a more complex example, look at
|
||||
//! [`cssparser`’s `src/macros.rs](https://github.com/servo/rust-cssparser/blob/master/src/macros.rs)
|
||||
//! and
|
||||
//! [`cssparser-macros`’s `macros/lib.rs](https://github.com/servo/rust-cssparser/blob/master/macros/lib.rs).
|
||||
|
||||
/// This macro wraps `&str -> String` functions
|
||||
/// in custom `derive` implementations with `#[proc_macro_derive]`.
|
||||
///
|
||||
/// See crate documentation for details.
|
||||
#[macro_export]
|
||||
macro_rules! define_proc_macros {
|
||||
(
|
||||
$(
|
||||
$( #[$attr:meta] )*
|
||||
pub fn $proc_macro_name: ident ($input: ident : &str) -> String
|
||||
$body: block
|
||||
)+
|
||||
) => {
|
||||
$(
|
||||
$( #[$attr] )*
|
||||
#[proc_macro_derive($proc_macro_name)]
|
||||
pub fn $proc_macro_name(derive_input: ::proc_macro::TokenStream)
|
||||
-> ::proc_macro::TokenStream {
|
||||
let $input = derive_input.to_string();
|
||||
let $input = $crate::_extract_input(&$input);
|
||||
$body.parse().unwrap()
|
||||
}
|
||||
)+
|
||||
}
|
||||
}
|
||||
|
||||
/// Implementation detail of `define_proc_macros!`.
|
||||
///
|
||||
/// **This function is not part of the public API. It can change or be removed between any versions.**
|
||||
#[doc(hidden)]
|
||||
pub fn _extract_input(derive_input: &str) -> &str {
|
||||
let mut input = derive_input;
|
||||
|
||||
for expected in &["#[allow(unused)]", "enum", "ProceduralMasqueradeDummyType", "{",
|
||||
"Input", "=", "(0,", "stringify!", "("] {
|
||||
input = input.trim_left();
|
||||
assert!(input.starts_with(expected),
|
||||
"expected prefix {:?} not found in {:?}", expected, derive_input);
|
||||
input = &input[expected.len()..];
|
||||
}
|
||||
|
||||
for expected in [")", ").0,", "}"].iter().rev() {
|
||||
input = input.trim_right();
|
||||
assert!(input.ends_with(expected),
|
||||
"expected suffix {:?} not found in {:?}", expected, derive_input);
|
||||
let end = input.len() - expected.len();
|
||||
input = &input[..end];
|
||||
}
|
||||
|
||||
input
|
||||
}
|
||||
|
||||
/// This macro expands to the definition of another macro (whose name is given as a parameter).
|
||||
///
|
||||
/// See crate documentation for details.
|
||||
#[macro_export]
|
||||
macro_rules! define_invoke_proc_macro {
|
||||
($macro_name: ident) => {
|
||||
/// Implementation detail of other macros in this crate.
|
||||
#[doc(hidden)]
|
||||
#[macro_export]
|
||||
macro_rules! $macro_name {
|
||||
($proc_macro_name: ident ! $paren: tt) => {
|
||||
#[derive($proc_macro_name)]
|
||||
#[allow(unused)]
|
||||
enum ProceduralMasqueradeDummyType {
|
||||
// The magic happens here.
|
||||
//
|
||||
// We use an `enum` with an explicit discriminant
|
||||
// because that is the only case where a type definition
|
||||
// can contain a (const) expression.
|
||||
//
|
||||
// `(0, "foo").0` evalutes to 0, with the `"foo"` part ignored.
|
||||
//
|
||||
// By the time the `#[proc_macro_derive]` function
|
||||
// implementing `#[derive($proc_macro_name)]` is called,
|
||||
// `$paren` has already been replaced with the input of this inner macro,
|
||||
// but `stringify!` has not been expanded yet.
|
||||
//
|
||||
// This how arbitrary tokens can be inserted
|
||||
// in the input to the `#[proc_macro_derive]` function.
|
||||
//
|
||||
// Later, `stringify!(...)` is expanded into a string literal
|
||||
// which is then ignored.
|
||||
// Using `stringify!` enables passing arbitrary tokens
|
||||
// rather than only what can be parsed as a const expression.
|
||||
Input = (0, stringify! $paren ).0
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
|
@ -1 +1 @@
|
|||
{"files":{".cargo-ok":"e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855","Cargo.toml":"a5da41e07bf2d8af3fda684c7adb912e98047e9fe12a8288be3d9e3a494388ca","src/ident.rs":"830077b64dce8c8ede1fb6ab664cae72f5496f4ab6be21a5b4e3b5e4e57ec425","src/lib.rs":"f799c898057a4e8e1620b32c70e13d3fee7af3a0352a5a4a1da6393942d21cc7","src/to_tokens.rs":"a871cb84506fa9e0783ac29617d686327ce5d05a9711a3a10833430b00345ccc","src/tokens.rs":"a559a56905debae32a0e7852114812cca7173341a62b277894517264a759dfa6"},"package":"e7b44fd83db28b83c1c58187159934906e5e955c812e211df413b76b03c909a5"}
|
||||
{"files":{".cargo-ok":"e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855","Cargo.toml":"9e488340fc68d310f52d8b7d68fc305e0a8b76261d450f34b1ecb9772d42617a","LICENSE-APACHE":"a60eea817514531668d7e00765731449fe14d059d3249e0bc93b36de45f759f2","LICENSE-MIT":"c9a75f18b9ab2927829a208fc6aa2cf4e63b8420887ba29cdb265d6619ae82d5","README.md":"3390fa1362c73052a268ae97a4777c5bcd8e991f866f9cce88ddde8d0963fd4d","src/ident.rs":"830077b64dce8c8ede1fb6ab664cae72f5496f4ab6be21a5b4e3b5e4e57ec425","src/lib.rs":"f799c898057a4e8e1620b32c70e13d3fee7af3a0352a5a4a1da6393942d21cc7","src/to_tokens.rs":"a871cb84506fa9e0783ac29617d686327ce5d05a9711a3a10833430b00345ccc","src/tokens.rs":"ecf42295d45982ba63c9eb51dd1b3abb5498e14a880c607fd11cf78e51f99035","tests/test.rs":"823f836751f89d98ddee52c99194ab9d686583b365328425f56831c480e8a21b"},"package":"7375cf7ad34a92e8fd18dd9c42f58b9a11def59ab48bec955bf359a788335592"}
|
|
@ -1,10 +1,10 @@
|
|||
[package]
|
||||
name = "quote"
|
||||
version = "0.3.12" # don't forget to update version in readme for breaking changes
|
||||
version = "0.3.14" # don't forget to update version in readme for breaking changes
|
||||
authors = ["David Tolnay <dtolnay@gmail.com>"]
|
||||
license = "MIT/Apache-2.0"
|
||||
description = "Quasi-quoting macro quote!(...)"
|
||||
repository = "https://github.com/dtolnay/quote"
|
||||
documentation = "https://docs.rs/quote/"
|
||||
keywords = ["syn"]
|
||||
include = ["Cargo.toml", "src/**/*.rs"]
|
||||
include = ["Cargo.toml", "src/**/*.rs", "tests/**/*.rs", "README.md", "LICENSE-APACHE", "LICENSE-MIT"]
|
||||
|
|
|
@ -0,0 +1,201 @@
|
|||
Apache License
|
||||
Version 2.0, January 2004
|
||||
http://www.apache.org/licenses/
|
||||
|
||||
TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
|
||||
|
||||
1. Definitions.
|
||||
|
||||
"License" shall mean the terms and conditions for use, reproduction,
|
||||
and distribution as defined by Sections 1 through 9 of this document.
|
||||
|
||||
"Licensor" shall mean the copyright owner or entity authorized by
|
||||
the copyright owner that is granting the License.
|
||||
|
||||
"Legal Entity" shall mean the union of the acting entity and all
|
||||
other entities that control, are controlled by, or are under common
|
||||
control with that entity. For the purposes of this definition,
|
||||
"control" means (i) the power, direct or indirect, to cause the
|
||||
direction or management of such entity, whether by contract or
|
||||
otherwise, or (ii) ownership of fifty percent (50%) or more of the
|
||||
outstanding shares, or (iii) beneficial ownership of such entity.
|
||||
|
||||
"You" (or "Your") shall mean an individual or Legal Entity
|
||||
exercising permissions granted by this License.
|
||||
|
||||
"Source" form shall mean the preferred form for making modifications,
|
||||
including but not limited to software source code, documentation
|
||||
source, and configuration files.
|
||||
|
||||
"Object" form shall mean any form resulting from mechanical
|
||||
transformation or translation of a Source form, including but
|
||||
not limited to compiled object code, generated documentation,
|
||||
and conversions to other media types.
|
||||
|
||||
"Work" shall mean the work of authorship, whether in Source or
|
||||
Object form, made available under the License, as indicated by a
|
||||
copyright notice that is included in or attached to the work
|
||||
(an example is provided in the Appendix below).
|
||||
|
||||
"Derivative Works" shall mean any work, whether in Source or Object
|
||||
form, that is based on (or derived from) the Work and for which the
|
||||
editorial revisions, annotations, elaborations, or other modifications
|
||||
represent, as a whole, an original work of authorship. For the purposes
|
||||
of this License, Derivative Works shall not include works that remain
|
||||
separable from, or merely link (or bind by name) to the interfaces of,
|
||||
the Work and Derivative Works thereof.
|
||||
|
||||
"Contribution" shall mean any work of authorship, including
|
||||
the original version of the Work and any modifications or additions
|
||||
to that Work or Derivative Works thereof, that is intentionally
|
||||
submitted to Licensor for inclusion in the Work by the copyright owner
|
||||
or by an individual or Legal Entity authorized to submit on behalf of
|
||||
the copyright owner. For the purposes of this definition, "submitted"
|
||||
means any form of electronic, verbal, or written communication sent
|
||||
to the Licensor or its representatives, including but not limited to
|
||||
communication on electronic mailing lists, source code control systems,
|
||||
and issue tracking systems that are managed by, or on behalf of, the
|
||||
Licensor for the purpose of discussing and improving the Work, but
|
||||
excluding communication that is conspicuously marked or otherwise
|
||||
designated in writing by the copyright owner as "Not a Contribution."
|
||||
|
||||
"Contributor" shall mean Licensor and any individual or Legal Entity
|
||||
on behalf of whom a Contribution has been received by Licensor and
|
||||
subsequently incorporated within the Work.
|
||||
|
||||
2. Grant of Copyright License. Subject to the terms and conditions of
|
||||
this License, each Contributor hereby grants to You a perpetual,
|
||||
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
|
||||
copyright license to reproduce, prepare Derivative Works of,
|
||||
publicly display, publicly perform, sublicense, and distribute the
|
||||
Work and such Derivative Works in Source or Object form.
|
||||
|
||||
3. Grant of Patent License. Subject to the terms and conditions of
|
||||
this License, each Contributor hereby grants to You a perpetual,
|
||||
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
|
||||
(except as stated in this section) patent license to make, have made,
|
||||
use, offer to sell, sell, import, and otherwise transfer the Work,
|
||||
where such license applies only to those patent claims licensable
|
||||
by such Contributor that are necessarily infringed by their
|
||||
Contribution(s) alone or by combination of their Contribution(s)
|
||||
with the Work to which such Contribution(s) was submitted. If You
|
||||
institute patent litigation against any entity (including a
|
||||
cross-claim or counterclaim in a lawsuit) alleging that the Work
|
||||
or a Contribution incorporated within the Work constitutes direct
|
||||
or contributory patent infringement, then any patent licenses
|
||||
granted to You under this License for that Work shall terminate
|
||||
as of the date such litigation is filed.
|
||||
|
||||
4. Redistribution. You may reproduce and distribute copies of the
|
||||
Work or Derivative Works thereof in any medium, with or without
|
||||
modifications, and in Source or Object form, provided that You
|
||||
meet the following conditions:
|
||||
|
||||
(a) You must give any other recipients of the Work or
|
||||
Derivative Works a copy of this License; and
|
||||
|
||||
(b) You must cause any modified files to carry prominent notices
|
||||
stating that You changed the files; and
|
||||
|
||||
(c) You must retain, in the Source form of any Derivative Works
|
||||
that You distribute, all copyright, patent, trademark, and
|
||||
attribution notices from the Source form of the Work,
|
||||
excluding those notices that do not pertain to any part of
|
||||
the Derivative Works; and
|
||||
|
||||
(d) If the Work includes a "NOTICE" text file as part of its
|
||||
distribution, then any Derivative Works that You distribute must
|
||||
include a readable copy of the attribution notices contained
|
||||
within such NOTICE file, excluding those notices that do not
|
||||
pertain to any part of the Derivative Works, in at least one
|
||||
of the following places: within a NOTICE text file distributed
|
||||
as part of the Derivative Works; within the Source form or
|
||||
documentation, if provided along with the Derivative Works; or,
|
||||
within a display generated by the Derivative Works, if and
|
||||
wherever such third-party notices normally appear. The contents
|
||||
of the NOTICE file are for informational purposes only and
|
||||
do not modify the License. You may add Your own attribution
|
||||
notices within Derivative Works that You distribute, alongside
|
||||
or as an addendum to the NOTICE text from the Work, provided
|
||||
that such additional attribution notices cannot be construed
|
||||
as modifying the License.
|
||||
|
||||
You may add Your own copyright statement to Your modifications and
|
||||
may provide additional or different license terms and conditions
|
||||
for use, reproduction, or distribution of Your modifications, or
|
||||
for any such Derivative Works as a whole, provided Your use,
|
||||
reproduction, and distribution of the Work otherwise complies with
|
||||
the conditions stated in this License.
|
||||
|
||||
5. Submission of Contributions. Unless You explicitly state otherwise,
|
||||
any Contribution intentionally submitted for inclusion in the Work
|
||||
by You to the Licensor shall be under the terms and conditions of
|
||||
this License, without any additional terms or conditions.
|
||||
Notwithstanding the above, nothing herein shall supersede or modify
|
||||
the terms of any separate license agreement you may have executed
|
||||
with Licensor regarding such Contributions.
|
||||
|
||||
6. Trademarks. This License does not grant permission to use the trade
|
||||
names, trademarks, service marks, or product names of the Licensor,
|
||||
except as required for reasonable and customary use in describing the
|
||||
origin of the Work and reproducing the content of the NOTICE file.
|
||||
|
||||
7. Disclaimer of Warranty. Unless required by applicable law or
|
||||
agreed to in writing, Licensor provides the Work (and each
|
||||
Contributor provides its Contributions) on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
|
||||
implied, including, without limitation, any warranties or conditions
|
||||
of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
|
||||
PARTICULAR PURPOSE. You are solely responsible for determining the
|
||||
appropriateness of using or redistributing the Work and assume any
|
||||
risks associated with Your exercise of permissions under this License.
|
||||
|
||||
8. Limitation of Liability. In no event and under no legal theory,
|
||||
whether in tort (including negligence), contract, or otherwise,
|
||||
unless required by applicable law (such as deliberate and grossly
|
||||
negligent acts) or agreed to in writing, shall any Contributor be
|
||||
liable to You for damages, including any direct, indirect, special,
|
||||
incidental, or consequential damages of any character arising as a
|
||||
result of this License or out of the use or inability to use the
|
||||
Work (including but not limited to damages for loss of goodwill,
|
||||
work stoppage, computer failure or malfunction, or any and all
|
||||
other commercial damages or losses), even if such Contributor
|
||||
has been advised of the possibility of such damages.
|
||||
|
||||
9. Accepting Warranty or Additional Liability. While redistributing
|
||||
the Work or Derivative Works thereof, You may choose to offer,
|
||||
and charge a fee for, acceptance of support, warranty, indemnity,
|
||||
or other liability obligations and/or rights consistent with this
|
||||
License. However, in accepting such obligations, You may act only
|
||||
on Your own behalf and on Your sole responsibility, not on behalf
|
||||
of any other Contributor, and only if You agree to indemnify,
|
||||
defend, and hold each Contributor harmless for any liability
|
||||
incurred by, or claims asserted against, such Contributor by reason
|
||||
of your accepting any such warranty or additional liability.
|
||||
|
||||
END OF TERMS AND CONDITIONS
|
||||
|
||||
APPENDIX: How to apply the Apache License to your work.
|
||||
|
||||
To apply the Apache License to your work, attach the following
|
||||
boilerplate notice, with the fields enclosed by brackets "[]"
|
||||
replaced with your own identifying information. (Don't include
|
||||
the brackets!) The text should be enclosed in the appropriate
|
||||
comment syntax for the file format. We also recommend that a
|
||||
file or class name and description of purpose be included on the
|
||||
same "printed page" as the copyright notice for easier
|
||||
identification within third-party archives.
|
||||
|
||||
Copyright [yyyy] [name of copyright owner]
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
|
@ -0,0 +1,25 @@
|
|||
Copyright (c) 2016 The Rust Project Developers
|
||||
|
||||
Permission is hereby granted, free of charge, to any
|
||||
person obtaining a copy of this software and associated
|
||||
documentation files (the "Software"), to deal in the
|
||||
Software without restriction, including without
|
||||
limitation the rights to use, copy, modify, merge,
|
||||
publish, distribute, sublicense, and/or sell copies of
|
||||
the Software, and to permit persons to whom the Software
|
||||
is furnished to do so, subject to the following
|
||||
conditions:
|
||||
|
||||
The above copyright notice and this permission notice
|
||||
shall be included in all copies or substantial portions
|
||||
of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF
|
||||
ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED
|
||||
TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A
|
||||
PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT
|
||||
SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
|
||||
CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
|
||||
OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR
|
||||
IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
|
||||
DEALINGS IN THE SOFTWARE.
|
|
@ -0,0 +1,104 @@
|
|||
Rust Quasi-Quoting
|
||||
==================
|
||||
|
||||
[![Build Status](https://api.travis-ci.org/dtolnay/quote.svg?branch=master)](https://travis-ci.org/dtolnay/quote)
|
||||
[![Latest Version](https://img.shields.io/crates/v/quote.svg)](https://crates.io/crates/quote)
|
||||
[![Rust Documentation](https://img.shields.io/badge/api-rustdoc-blue.svg)](https://docs.rs/quote/)
|
||||
|
||||
Quasi-quoting without a Syntex dependency, intended for use with [Macros
|
||||
1.1](https://github.com/rust-lang/rfcs/blob/master/text/1681-macros-1.1.md).
|
||||
|
||||
```toml
|
||||
[dependencies]
|
||||
quote = "0.3"
|
||||
```
|
||||
|
||||
```rust
|
||||
#[macro_use]
|
||||
extern crate quote;
|
||||
```
|
||||
|
||||
## What is quasi-quoting?
|
||||
|
||||
Quasi-quoting is a way of writing code and treating it as data, similar to
|
||||
writing code inside of a double-quoted string literal except more friendly to
|
||||
your text editor or IDE. It does not get in the way of syntax highlighting,
|
||||
brace matching, indentation, or autocompletion, all of which you would lose by
|
||||
writing code inside of double quotes.
|
||||
|
||||
Check out
|
||||
[my meetup talk](https://air.mozilla.org/rust-meetup-december-2016-12-15/)
|
||||
on the topic to learn more about the use case. Start the video at 3:00.
|
||||
|
||||
This crate is motivated by the Macros 1.1 use case, but is a general-purpose
|
||||
Rust quasi-quoting library and is not specific to procedural macros.
|
||||
|
||||
## Syntax
|
||||
|
||||
The quote crate provides a `quote!` macro within which you can write Rust code
|
||||
that gets packaged into a `quote::Tokens` and can be treated as data. You should
|
||||
think of `quote::Tokens` as representing a fragment of Rust source code. Call
|
||||
`to_string()` or `as_str()` on a Tokens to get back the fragment of source code
|
||||
as a string.
|
||||
|
||||
Within the `quote!` macro, interpolation is done with `#var`. Any type
|
||||
implementing the `quote::ToTokens` trait can be interpolated. This includes most
|
||||
Rust primitive types as well as most of the syntax tree types from
|
||||
[`syn`](https://github.com/dtolnay/syn).
|
||||
|
||||
```rust
|
||||
let tokens = quote! {
|
||||
struct SerializeWith #generics #where_clause {
|
||||
value: &'a #field_ty,
|
||||
phantom: ::std::marker::PhantomData<#item_ty>,
|
||||
}
|
||||
|
||||
impl #generics serde::Serialize for SerializeWith #generics #where_clause {
|
||||
fn serialize<S>(&self, s: &mut S) -> Result<(), S::Error>
|
||||
where S: serde::Serializer
|
||||
{
|
||||
#path(self.value, s)
|
||||
}
|
||||
}
|
||||
|
||||
SerializeWith {
|
||||
value: #value,
|
||||
phantom: ::std::marker::PhantomData::<#item_ty>,
|
||||
}
|
||||
};
|
||||
```
|
||||
|
||||
Repetition is done using `#(...)*` or `#(...),*` very similar to `macro_rules!`:
|
||||
|
||||
- `#(#var)*` - no separators
|
||||
- `#(#var),*` - the character before the asterisk is used as a separator
|
||||
- `#( struct #var; )*` - the repetition can contain other things
|
||||
- `#( #k => println!("{}", #v), )*` - even multiple interpolations
|
||||
|
||||
Tokens can be interpolated into other quotes:
|
||||
|
||||
```rust
|
||||
let t = quote! { /* ... */ };
|
||||
return quote! { /* ... */ #t /* ... */ };
|
||||
```
|
||||
|
||||
The `quote!` macro relies on deep recursion so some large invocations may fail
|
||||
with "recursion limit reached" when you compile. If it fails, bump up the
|
||||
recursion limit by adding `#![recursion_limit = "128"]` to your crate. An even
|
||||
higher limit may be necessary for especially large invocations. You don't need
|
||||
this unless the compiler tells you that you need it.
|
||||
|
||||
## License
|
||||
|
||||
Licensed under either of
|
||||
|
||||
* Apache License, Version 2.0 ([LICENSE-APACHE](LICENSE-APACHE) or http://www.apache.org/licenses/LICENSE-2.0)
|
||||
* MIT license ([LICENSE-MIT](LICENSE-MIT) or http://opensource.org/licenses/MIT)
|
||||
|
||||
at your option.
|
||||
|
||||
### Contribution
|
||||
|
||||
Unless you explicitly state otherwise, any contribution intentionally submitted
|
||||
for inclusion in this crate by you, as defined in the Apache-2.0 license, shall
|
||||
be dual licensed as above, without any additional terms or conditions.
|
|
@ -132,6 +132,10 @@ impl Tokens {
|
|||
&self.0
|
||||
}
|
||||
|
||||
pub fn into_string(self) -> String {
|
||||
self.0
|
||||
}
|
||||
|
||||
pub fn parse<T: FromStr>(&self) -> Result<T, T::Err> {
|
||||
FromStr::from_str(&self.0)
|
||||
}
|
||||
|
|
|
@ -0,0 +1,350 @@
|
|||
use std::{f32, f64};
|
||||
use std::borrow::Cow;
|
||||
|
||||
#[macro_use]
|
||||
extern crate quote;
|
||||
|
||||
struct X;
|
||||
|
||||
impl quote::ToTokens for X {
|
||||
fn to_tokens(&self, tokens: &mut quote::Tokens) {
|
||||
tokens.append("X");
|
||||
}
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_quote_impl() {
|
||||
let tokens = quote!(
|
||||
impl<'a, T: ToTokens> ToTokens for &'a T {
|
||||
fn to_tokens(&self, tokens: &mut Tokens) {
|
||||
(**self).to_tokens(tokens)
|
||||
}
|
||||
}
|
||||
);
|
||||
|
||||
let expected = concat!(
|
||||
"impl < 'a , T : ToTokens > ToTokens for & 'a T { ",
|
||||
"fn to_tokens ( & self , tokens : & mut Tokens ) { ",
|
||||
"( * * self ) . to_tokens ( tokens ) ",
|
||||
"} ",
|
||||
"}"
|
||||
);
|
||||
|
||||
assert_eq!(expected, tokens.as_str());
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_substitution() {
|
||||
let x = X;
|
||||
let tokens = quote!(#x <#x> (#x) [#x] {#x});
|
||||
|
||||
let expected = "X < X > ( X ) [ X ] { X }";
|
||||
|
||||
assert_eq!(expected, tokens.as_str());
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_iter() {
|
||||
let primes = &[X, X, X, X];
|
||||
|
||||
assert_eq!("X X X X", quote!(#(#primes)*).as_str());
|
||||
|
||||
assert_eq!("X , X , X , X ,", quote!(#(#primes,)*).as_str());
|
||||
|
||||
assert_eq!("X , X , X , X", quote!(#(#primes),*).as_str());
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_advanced() {
|
||||
let generics = quote!( <'a, T> );
|
||||
|
||||
let where_clause = quote!( where T: Serialize );
|
||||
|
||||
let field_ty = quote!( String );
|
||||
|
||||
let item_ty = quote!( Cow<'a, str> );
|
||||
|
||||
let path = quote!( SomeTrait::serialize_with );
|
||||
|
||||
let value = quote!( self.x );
|
||||
|
||||
let tokens = quote! {
|
||||
struct SerializeWith #generics #where_clause {
|
||||
value: &'a #field_ty,
|
||||
phantom: ::std::marker::PhantomData<#item_ty>,
|
||||
}
|
||||
|
||||
impl #generics ::serde::Serialize for SerializeWith #generics #where_clause {
|
||||
fn serialize<S>(&self, s: &mut S) -> Result<(), S::Error>
|
||||
where S: ::serde::Serializer
|
||||
{
|
||||
#path(self.value, s)
|
||||
}
|
||||
}
|
||||
|
||||
SerializeWith {
|
||||
value: #value,
|
||||
phantom: ::std::marker::PhantomData::<#item_ty>,
|
||||
}
|
||||
};
|
||||
|
||||
let expected = concat!(
|
||||
"struct SerializeWith < 'a , T > where T : Serialize { ",
|
||||
"value : & 'a String , ",
|
||||
"phantom : :: std :: marker :: PhantomData < Cow < 'a , str > > , ",
|
||||
"} ",
|
||||
"impl < 'a , T > :: serde :: Serialize for SerializeWith < 'a , T > where T : Serialize { ",
|
||||
"fn serialize < S > ( & self , s : & mut S ) -> Result < ( ) , S :: Error > ",
|
||||
"where S : :: serde :: Serializer ",
|
||||
"{ ",
|
||||
"SomeTrait :: serialize_with ( self . value , s ) ",
|
||||
"} ",
|
||||
"} ",
|
||||
"SerializeWith { ",
|
||||
"value : self . x , ",
|
||||
"phantom : :: std :: marker :: PhantomData :: < Cow < 'a , str > > , ",
|
||||
"}"
|
||||
);
|
||||
|
||||
assert_eq!(expected, tokens.as_str());
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_unit() {
|
||||
let x = ();
|
||||
let tokens = quote!(#x);
|
||||
let expected = "( )";
|
||||
assert_eq!(expected, tokens.as_str());
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_tuple() {
|
||||
let x = ("foo", 4_u32);
|
||||
let tokens = quote!(#x);
|
||||
let expected = "( \"foo\" , 4u32 , )";
|
||||
assert_eq!(expected, tokens.as_str());
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_array() {
|
||||
let x: [u32; 3] = [1, 2, 3];
|
||||
let tokens = quote!(#x);
|
||||
let expected = "[ 1u32 , 2u32 , 3u32 , ]";
|
||||
assert_eq!(expected, tokens.as_str());
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_slice() {
|
||||
let x: &[u32] = &[1, 2, 3];
|
||||
let tokens = quote!(&#x); // Note: explicit `&`
|
||||
let expected = "& [ 1u32 , 2u32 , 3u32 , ]";
|
||||
assert_eq!(expected, tokens.as_str());
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_vec() {
|
||||
let x: Vec<u32> = vec![1, 2, 3];
|
||||
let tokens = quote!(vec!#x); // Note: explicit `vec!`
|
||||
let expected = "vec ! [ 1u32 , 2u32 , 3u32 , ]";
|
||||
assert_eq!(expected, tokens.as_str());
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_integer() {
|
||||
let ii8 = -1i8;
|
||||
let ii16 = -1i16;
|
||||
let ii32 = -1i32;
|
||||
let ii64 = -1i64;
|
||||
let iisize = -1isize;
|
||||
let uu8 = 1u8;
|
||||
let uu16 = 1u16;
|
||||
let uu32 = 1u32;
|
||||
let uu64 = 1u64;
|
||||
let uusize = 1usize;
|
||||
|
||||
let tokens = quote! {
|
||||
#ii8 #ii16 #ii32 #ii64 #iisize
|
||||
#uu8 #uu16 #uu32 #uu64 #uusize
|
||||
};
|
||||
let expected = "-1i8 -1i16 -1i32 -1i64 -1isize 1u8 1u16 1u32 1u64 1usize";
|
||||
assert_eq!(expected, tokens.as_str());
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_hex() {
|
||||
let hex = quote::Hex(0xFFFF_0000_u32);
|
||||
let tokens = quote!(#hex);
|
||||
let expected = "0xFFFF0000u32";
|
||||
assert_eq!(expected, tokens.as_str());
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_floating() {
|
||||
let e32 = 2.71828f32;
|
||||
let nan32 = f32::NAN;
|
||||
let inf32 = f32::INFINITY;
|
||||
let neginf32 = f32::NEG_INFINITY;
|
||||
|
||||
let e64 = 2.71828f64;
|
||||
let nan64 = f64::NAN;
|
||||
let inf64 = f64::INFINITY;
|
||||
let neginf64 = f64::NEG_INFINITY;
|
||||
|
||||
let tokens = quote! {
|
||||
#e32 @ #nan32 @ #inf32 @ #neginf32
|
||||
#e64 @ #nan64 @ #inf64 @ #neginf64
|
||||
};
|
||||
let expected = concat!(
|
||||
"2.71828f32 @ :: std :: f32 :: NAN @ :: std :: f32 :: INFINITY @ :: std :: f32 :: NEG_INFINITY ",
|
||||
"2.71828f64 @ :: std :: f64 :: NAN @ :: std :: f64 :: INFINITY @ :: std :: f64 :: NEG_INFINITY",
|
||||
);
|
||||
assert_eq!(expected, tokens.as_str());
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_char() {
|
||||
let zero = '\0';
|
||||
let pound = '#';
|
||||
let quote = '"';
|
||||
let apost = '\'';
|
||||
let newline = '\n';
|
||||
let heart = '\u{2764}';
|
||||
|
||||
let tokens = quote! {
|
||||
#zero #pound #quote #apost #newline #heart
|
||||
};
|
||||
let expected = "'\\0' '#' '\"' '\\'' '\\n' '\u{2764}'";
|
||||
assert_eq!(expected, tokens.as_str());
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_str() {
|
||||
let s = "\0 a 'b \" c";
|
||||
let tokens = quote!(#s);
|
||||
let expected = "\"\\0 a 'b \\\" c\"";
|
||||
assert_eq!(expected, tokens.as_str());
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_string() {
|
||||
let s = "\0 a 'b \" c".to_string();
|
||||
let tokens = quote!(#s);
|
||||
let expected = "\"\\0 a 'b \\\" c\"";
|
||||
assert_eq!(expected, tokens.as_str());
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_byte_str() {
|
||||
let s = quote::ByteStr("\0 a 'b \" c");
|
||||
let tokens = quote!(#s);
|
||||
let expected = "b\"\\0 a 'b \\\" c\"";
|
||||
assert_eq!(expected, tokens.as_str());
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_byte_str_escape() {
|
||||
let s = quote::ByteStr("\u{3c3} \\ \" \n");
|
||||
let tokens = quote!(#s);
|
||||
let expected = "b\"\\xCF\\x83 \\\\ \\\" \\n\"";
|
||||
assert_eq!(expected, tokens.as_str());
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_ident() {
|
||||
let foo = quote::Ident::from("Foo");
|
||||
let bar = quote::Ident::from(format!("Bar{}", 7));
|
||||
let tokens = quote!(struct #foo; enum #bar {});
|
||||
let expected = "struct Foo ; enum Bar7 { }";
|
||||
assert_eq!(expected, tokens.as_str());
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_duplicate() {
|
||||
let ch = 'x';
|
||||
|
||||
let tokens = quote!(#ch #ch);
|
||||
|
||||
let expected = "'x' 'x'";
|
||||
assert_eq!(expected, tokens.as_str());
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_fancy_repetition() {
|
||||
let foo = vec!["a", "b"];
|
||||
let bar = vec![true, false];
|
||||
|
||||
let tokens = quote! {
|
||||
#(#foo: #bar),*
|
||||
};
|
||||
|
||||
let expected = r#""a" : true , "b" : false"#;
|
||||
assert_eq!(expected, tokens.as_str());
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_nested_fancy_repetition() {
|
||||
let nested = vec![vec!['a', 'b', 'c'], vec!['x', 'y', 'z']];
|
||||
|
||||
let tokens = quote! {
|
||||
#(
|
||||
#(#nested)*
|
||||
),*
|
||||
};
|
||||
|
||||
let expected = "'a' 'b' 'c' , 'x' 'y' 'z'";
|
||||
assert_eq!(expected, tokens.as_str());
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_empty_repetition() {
|
||||
let tokens = quote!(#(a b)* #(c d),*);
|
||||
assert_eq!("", tokens.as_str());
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_variable_name_conflict() {
|
||||
// The implementation of `#(...),*` uses the variable `_i` but it should be
|
||||
// fine, if a little confusing when debugging.
|
||||
let _i = vec!['a', 'b'];
|
||||
let tokens = quote! { #(#_i),* };
|
||||
let expected = "'a' , 'b'";
|
||||
assert_eq!(expected, tokens.as_str());
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_empty_quote() {
|
||||
let tokens = quote!();
|
||||
assert_eq!("", tokens.as_str());
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_box_str() {
|
||||
let b = "str".to_owned().into_boxed_str();
|
||||
let tokens = quote! { #b };
|
||||
assert_eq!("\"str\"", tokens.as_str());
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_cow() {
|
||||
let owned: Cow<quote::Ident> = Cow::Owned(quote::Ident::from("owned"));
|
||||
|
||||
let ident = quote::Ident::from("borrowed");
|
||||
let borrowed = Cow::Borrowed(&ident);
|
||||
|
||||
let tokens = quote! { #owned #borrowed };
|
||||
assert_eq!("owned borrowed", tokens.as_str());
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_closure() {
|
||||
fn field_i(i: usize) -> quote::Ident {
|
||||
quote::Ident::new(format!("__field{}", i))
|
||||
}
|
||||
|
||||
let fields = (0usize..3)
|
||||
.map(field_i as fn(_) -> _)
|
||||
.map(|var| quote! { #var });
|
||||
|
||||
let tokens = quote! { #(#fields)* };
|
||||
assert_eq!("__field0 __field1 __field2", tokens.as_str());
|
||||
}
|
|
@ -1 +1 @@
|
|||
{"files":{".cargo-ok":"e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855","Cargo.toml":"52cbed9713eaf849002a7aa53e0ead1deeb665c342b19c12ae36fe912cd0a40f","src/bytes.rs":"1f7846e870cf00b06a927896309b8b32457f2fe7d9944783eb1b715ce0459bd1","src/de/content.rs":"1887e6d7ff6bf15d9f74d4a88f7f21c5263a179cbc5ba0a7151f37c1b1a72345","src/de/from_primitive.rs":"b1bd165e343a4380965551709119ef9ed895e4b025045a810dabd671511ba3ab","src/de/impls.rs":"399dd33fbb9d66aae720b2ac1cbaa528aaace6a714dd26fd76307985bcd20798","src/de/mod.rs":"0f68ba1dcc40954b4f8283561fe73d7df3449d35e02817d056b260eacb953834","src/de/private.rs":"818364e2750fa09a2e9baa8be9fcbf44f4eac15f7ab29daf563d96fd18c481b0","src/de/value.rs":"948b4d8f0c2fdfd82699dbbba6c4b1175fbfc89e4cc8522bb78d34e76aa1f00f","src/error.rs":"7e8d8f3d09527598574d3d12a110bd34e1b835bb9b702fd7ac0b758fa55a1011","src/export.rs":"0b8e6b642010ad6a71f13f5facfd91e9da1d7c99d479dba020dec10e88fb6b0f","src/iter.rs":"30090fe6ab49bb1d8c7fec362cace52981b2c4e1a1a8e3fad4117eab558cdde6","src/lib.rs":"1471f32b6ffb8e049ab5177327420a72499fff79b9f58636412d36ce592ff517","src/macros.rs":"6c1ab6568717a882c7ed619319cf00c9966803474c3f45be5cb1dc496ba474a5","src/ser/impls.rs":"c27bb83e3ff78a6038f551db584322910dd97b1a988cf5c533aefb27b98298ca","src/ser/impossible.rs":"8700bd05e21e4ce20187e0c0d8e1c08df78d68ccceaaec8cc6b900e46a6b83f0","src/ser/mod.rs":"eeb43ee845375c815b247d2ee1c024ac5221584299359c1dc94ad85118dbd391","src/ser/private.rs":"9e7805dbb79516e297fa00432b6ae75d268ad9cd0b8857a302dea44fd8991fe8","src/utils.rs":"b0d1a54af90e3620abd66479d757a2eb442449788c4ece93161916da0838affa"},"package":"1e0ed773960f90a78567fcfbe935284adf50c5d7cf119aa2cf43bb0b4afa69bb"}
|
||||
{"files":{".cargo-ok":"e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855","Cargo.toml":"e2817af66db5f058a55b5f126ca9a663925bfeb36a592a4121e7e9a44d3a3453","LICENSE-APACHE":"a60eea817514531668d7e00765731449fe14d059d3249e0bc93b36de45f759f2","LICENSE-MIT":"6485b8ed310d3f0340bf1ad1f47645069ce4069dcc6bb46c7d5c6faf41de1fdb","README.md":"ebe318a04cf4e547e0f3ab97f1345ecb553358ee13ea81f99e3323e37d70ccdf","src/bytes.rs":"2b6a9c2c3d6eabe8633adee6655a3b94f0d1e931e740e72699b6965bee21e226","src/de/content.rs":"469d3298d4109d514a8cd630273a288a361544979e2ab23aaa325b2201f9361f","src/de/from_primitive.rs":"b1bd165e343a4380965551709119ef9ed895e4b025045a810dabd671511ba3ab","src/de/impls.rs":"762c3f32627d12555ccd08fcdf3dfb621403c35cde8a5af7866e2ad74c95a4c8","src/de/mod.rs":"365ee7038c53e88cddd451afd11d459f65185fd04523bd000a6b424ac4f71db7","src/de/private.rs":"2578dbc89c2f2a852caed3fdc40f710d4828d085c4e954dd96789d678583424e","src/de/value.rs":"67a34c03fda6521c082548984b0116494e5fbff7e60e30e06f0dda62d9d3e083","src/error.rs":"3af5286c1daad9bfd504693f8a8587f7044c9b9520e23e072549c43a72e4821d","src/export.rs":"0b8e6b642010ad6a71f13f5facfd91e9da1d7c99d479dba020dec10e88fb6b0f","src/iter.rs":"af3c43712c240b3a06870e0b0b6e837b142d5a65c62742fa358fe36a9d9319a7","src/lib.rs":"75df159c150e62c99887c0a4f23ed1271c9eb910ebc79a2d4bd279b0e11ce7e3","src/macros.rs":"af1f75bb34460b814e44f7bc67bdd1dc1bba97f1f2a31744c22e1bfcdc29499a","src/ser/content.rs":"f1cd3724e5ddeacb75b3585b2fd2be7c42fc764444b1f764e31ed9fe49f62025","src/ser/impls.rs":"51d4036b8309381af8267375778bf80c3a9114577c03a04da9a679462077efac","src/ser/impossible.rs":"f1332a1250f9c1d85d679653ade502cf99bdff0344b9f864e6cf1a1789d7c597","src/ser/mod.rs":"d1d821488453651a986bb4e4608f72868c09a71a8dbf693584758b25603ae8bf","src/ser/private.rs":"3999dc19d61d43a64d5d1bdda61f80ea16405a926b074b5441b39d87318be73b","src/utils.rs":"ed271c0825c01d7b24968bf47ce9e2475ca219faf733eb33831d6e19bf07aaf1"},"package":"05a67b8a53f885f4b6e3ed183806035819f9862474e747fe4488a6d63bcbfcb7"}
|
|
@ -1,16 +1,16 @@
|
|||
[package]
|
||||
name = "serde"
|
||||
version = "0.9.7"
|
||||
version = "0.9.9"
|
||||
authors = ["Erick Tryzelaar <erick.tryzelaar@gmail.com>"]
|
||||
license = "MIT/Apache-2.0"
|
||||
description = "A generic serialization/deserialization framework"
|
||||
homepage = "https://serde.rs"
|
||||
repository = "https://github.com/serde-rs/serde"
|
||||
documentation = "https://docs.serde.rs/serde/"
|
||||
readme = "../README.md"
|
||||
keywords = ["serde", "serialization", "no_std"]
|
||||
categories = ["encoding"]
|
||||
include = ["Cargo.toml", "src/**/*.rs"]
|
||||
readme = "../README.md"
|
||||
include = ["Cargo.toml", "src/**/*.rs", "README.md", "LICENSE-APACHE", "LICENSE-MIT"]
|
||||
|
||||
[badges]
|
||||
travis-ci = { repository = "serde-rs/serde" }
|
||||
|
|
|
@ -0,0 +1,201 @@
|
|||
Apache License
|
||||
Version 2.0, January 2004
|
||||
http://www.apache.org/licenses/
|
||||
|
||||
TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
|
||||
|
||||
1. Definitions.
|
||||
|
||||
"License" shall mean the terms and conditions for use, reproduction,
|
||||
and distribution as defined by Sections 1 through 9 of this document.
|
||||
|
||||
"Licensor" shall mean the copyright owner or entity authorized by
|
||||
the copyright owner that is granting the License.
|
||||
|
||||
"Legal Entity" shall mean the union of the acting entity and all
|
||||
other entities that control, are controlled by, or are under common
|
||||
control with that entity. For the purposes of this definition,
|
||||
"control" means (i) the power, direct or indirect, to cause the
|
||||
direction or management of such entity, whether by contract or
|
||||
otherwise, or (ii) ownership of fifty percent (50%) or more of the
|
||||
outstanding shares, or (iii) beneficial ownership of such entity.
|
||||
|
||||
"You" (or "Your") shall mean an individual or Legal Entity
|
||||
exercising permissions granted by this License.
|
||||
|
||||
"Source" form shall mean the preferred form for making modifications,
|
||||
including but not limited to software source code, documentation
|
||||
source, and configuration files.
|
||||
|
||||
"Object" form shall mean any form resulting from mechanical
|
||||
transformation or translation of a Source form, including but
|
||||
not limited to compiled object code, generated documentation,
|
||||
and conversions to other media types.
|
||||
|
||||
"Work" shall mean the work of authorship, whether in Source or
|
||||
Object form, made available under the License, as indicated by a
|
||||
copyright notice that is included in or attached to the work
|
||||
(an example is provided in the Appendix below).
|
||||
|
||||
"Derivative Works" shall mean any work, whether in Source or Object
|
||||
form, that is based on (or derived from) the Work and for which the
|
||||
editorial revisions, annotations, elaborations, or other modifications
|
||||
represent, as a whole, an original work of authorship. For the purposes
|
||||
of this License, Derivative Works shall not include works that remain
|
||||
separable from, or merely link (or bind by name) to the interfaces of,
|
||||
the Work and Derivative Works thereof.
|
||||
|
||||
"Contribution" shall mean any work of authorship, including
|
||||
the original version of the Work and any modifications or additions
|
||||
to that Work or Derivative Works thereof, that is intentionally
|
||||
submitted to Licensor for inclusion in the Work by the copyright owner
|
||||
or by an individual or Legal Entity authorized to submit on behalf of
|
||||
the copyright owner. For the purposes of this definition, "submitted"
|
||||
means any form of electronic, verbal, or written communication sent
|
||||
to the Licensor or its representatives, including but not limited to
|
||||
communication on electronic mailing lists, source code control systems,
|
||||
and issue tracking systems that are managed by, or on behalf of, the
|
||||
Licensor for the purpose of discussing and improving the Work, but
|
||||
excluding communication that is conspicuously marked or otherwise
|
||||
designated in writing by the copyright owner as "Not a Contribution."
|
||||
|
||||
"Contributor" shall mean Licensor and any individual or Legal Entity
|
||||
on behalf of whom a Contribution has been received by Licensor and
|
||||
subsequently incorporated within the Work.
|
||||
|
||||
2. Grant of Copyright License. Subject to the terms and conditions of
|
||||
this License, each Contributor hereby grants to You a perpetual,
|
||||
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
|
||||
copyright license to reproduce, prepare Derivative Works of,
|
||||
publicly display, publicly perform, sublicense, and distribute the
|
||||
Work and such Derivative Works in Source or Object form.
|
||||
|
||||
3. Grant of Patent License. Subject to the terms and conditions of
|
||||
this License, each Contributor hereby grants to You a perpetual,
|
||||
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
|
||||
(except as stated in this section) patent license to make, have made,
|
||||
use, offer to sell, sell, import, and otherwise transfer the Work,
|
||||
where such license applies only to those patent claims licensable
|
||||
by such Contributor that are necessarily infringed by their
|
||||
Contribution(s) alone or by combination of their Contribution(s)
|
||||
with the Work to which such Contribution(s) was submitted. If You
|
||||
institute patent litigation against any entity (including a
|
||||
cross-claim or counterclaim in a lawsuit) alleging that the Work
|
||||
or a Contribution incorporated within the Work constitutes direct
|
||||
or contributory patent infringement, then any patent licenses
|
||||
granted to You under this License for that Work shall terminate
|
||||
as of the date such litigation is filed.
|
||||
|
||||
4. Redistribution. You may reproduce and distribute copies of the
|
||||
Work or Derivative Works thereof in any medium, with or without
|
||||
modifications, and in Source or Object form, provided that You
|
||||
meet the following conditions:
|
||||
|
||||
(a) You must give any other recipients of the Work or
|
||||
Derivative Works a copy of this License; and
|
||||
|
||||
(b) You must cause any modified files to carry prominent notices
|
||||
stating that You changed the files; and
|
||||
|
||||
(c) You must retain, in the Source form of any Derivative Works
|
||||
that You distribute, all copyright, patent, trademark, and
|
||||
attribution notices from the Source form of the Work,
|
||||
excluding those notices that do not pertain to any part of
|
||||
the Derivative Works; and
|
||||
|
||||
(d) If the Work includes a "NOTICE" text file as part of its
|
||||
distribution, then any Derivative Works that You distribute must
|
||||
include a readable copy of the attribution notices contained
|
||||
within such NOTICE file, excluding those notices that do not
|
||||
pertain to any part of the Derivative Works, in at least one
|
||||
of the following places: within a NOTICE text file distributed
|
||||
as part of the Derivative Works; within the Source form or
|
||||
documentation, if provided along with the Derivative Works; or,
|
||||
within a display generated by the Derivative Works, if and
|
||||
wherever such third-party notices normally appear. The contents
|
||||
of the NOTICE file are for informational purposes only and
|
||||
do not modify the License. You may add Your own attribution
|
||||
notices within Derivative Works that You distribute, alongside
|
||||
or as an addendum to the NOTICE text from the Work, provided
|
||||
that such additional attribution notices cannot be construed
|
||||
as modifying the License.
|
||||
|
||||
You may add Your own copyright statement to Your modifications and
|
||||
may provide additional or different license terms and conditions
|
||||
for use, reproduction, or distribution of Your modifications, or
|
||||
for any such Derivative Works as a whole, provided Your use,
|
||||
reproduction, and distribution of the Work otherwise complies with
|
||||
the conditions stated in this License.
|
||||
|
||||
5. Submission of Contributions. Unless You explicitly state otherwise,
|
||||
any Contribution intentionally submitted for inclusion in the Work
|
||||
by You to the Licensor shall be under the terms and conditions of
|
||||
this License, without any additional terms or conditions.
|
||||
Notwithstanding the above, nothing herein shall supersede or modify
|
||||
the terms of any separate license agreement you may have executed
|
||||
with Licensor regarding such Contributions.
|
||||
|
||||
6. Trademarks. This License does not grant permission to use the trade
|
||||
names, trademarks, service marks, or product names of the Licensor,
|
||||
except as required for reasonable and customary use in describing the
|
||||
origin of the Work and reproducing the content of the NOTICE file.
|
||||
|
||||
7. Disclaimer of Warranty. Unless required by applicable law or
|
||||
agreed to in writing, Licensor provides the Work (and each
|
||||
Contributor provides its Contributions) on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
|
||||
implied, including, without limitation, any warranties or conditions
|
||||
of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
|
||||
PARTICULAR PURPOSE. You are solely responsible for determining the
|
||||
appropriateness of using or redistributing the Work and assume any
|
||||
risks associated with Your exercise of permissions under this License.
|
||||
|
||||
8. Limitation of Liability. In no event and under no legal theory,
|
||||
whether in tort (including negligence), contract, or otherwise,
|
||||
unless required by applicable law (such as deliberate and grossly
|
||||
negligent acts) or agreed to in writing, shall any Contributor be
|
||||
liable to You for damages, including any direct, indirect, special,
|
||||
incidental, or consequential damages of any character arising as a
|
||||
result of this License or out of the use or inability to use the
|
||||
Work (including but not limited to damages for loss of goodwill,
|
||||
work stoppage, computer failure or malfunction, or any and all
|
||||
other commercial damages or losses), even if such Contributor
|
||||
has been advised of the possibility of such damages.
|
||||
|
||||
9. Accepting Warranty or Additional Liability. While redistributing
|
||||
the Work or Derivative Works thereof, You may choose to offer,
|
||||
and charge a fee for, acceptance of support, warranty, indemnity,
|
||||
or other liability obligations and/or rights consistent with this
|
||||
License. However, in accepting such obligations, You may act only
|
||||
on Your own behalf and on Your sole responsibility, not on behalf
|
||||
of any other Contributor, and only if You agree to indemnify,
|
||||
defend, and hold each Contributor harmless for any liability
|
||||
incurred by, or claims asserted against, such Contributor by reason
|
||||
of your accepting any such warranty or additional liability.
|
||||
|
||||
END OF TERMS AND CONDITIONS
|
||||
|
||||
APPENDIX: How to apply the Apache License to your work.
|
||||
|
||||
To apply the Apache License to your work, attach the following
|
||||
boilerplate notice, with the fields enclosed by brackets "[]"
|
||||
replaced with your own identifying information. (Don't include
|
||||
the brackets!) The text should be enclosed in the appropriate
|
||||
comment syntax for the file format. We also recommend that a
|
||||
file or class name and description of purpose be included on the
|
||||
same "printed page" as the copyright notice for easier
|
||||
identification within third-party archives.
|
||||
|
||||
Copyright [yyyy] [name of copyright owner]
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
|
@ -0,0 +1,25 @@
|
|||
Copyright (c) 2014 The Rust Project Developers
|
||||
|
||||
Permission is hereby granted, free of charge, to any
|
||||
person obtaining a copy of this software and associated
|
||||
documentation files (the "Software"), to deal in the
|
||||
Software without restriction, including without
|
||||
limitation the rights to use, copy, modify, merge,
|
||||
publish, distribute, sublicense, and/or sell copies of
|
||||
the Software, and to permit persons to whom the Software
|
||||
is furnished to do so, subject to the following
|
||||
conditions:
|
||||
|
||||
The above copyright notice and this permission notice
|
||||
shall be included in all copies or substantial portions
|
||||
of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF
|
||||
ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED
|
||||
TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A
|
||||
PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT
|
||||
SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
|
||||
CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
|
||||
OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR
|
||||
IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
|
||||
DEALINGS IN THE SOFTWARE.
|
|
@ -0,0 +1,71 @@
|
|||
# Serde   [![Build Status](https://api.travis-ci.org/serde-rs/serde.svg?branch=master)](https://travis-ci.org/serde-rs/serde) [![Latest Version](https://img.shields.io/crates/v/serde.svg)](https://crates.io/crates/serde)
|
||||
|
||||
**Serde is a framework for *ser*ializing and *de*serializing Rust data structures efficiently and generically.**
|
||||
|
||||
---
|
||||
|
||||
You may be looking for:
|
||||
|
||||
- [An overview of Serde](https://serde.rs/)
|
||||
- [Data formats supported by Serde](https://serde.rs/#data-formats)
|
||||
- [Setting up `#[derive(Serialize, Deserialize)]`](https://serde.rs/codegen.html)
|
||||
- [Examples](https://serde.rs/examples.html)
|
||||
- [API documentation](https://docs.serde.rs/serde/)
|
||||
- [Release notes](https://github.com/serde-rs/serde/releases)
|
||||
|
||||
## Serde in action
|
||||
|
||||
```rust
|
||||
#[macro_use]
|
||||
extern crate serde_derive;
|
||||
|
||||
extern crate serde_json;
|
||||
|
||||
#[derive(Serialize, Deserialize, Debug)]
|
||||
struct Point {
|
||||
x: i32,
|
||||
y: i32,
|
||||
}
|
||||
|
||||
fn main() {
|
||||
let point = Point { x: 1, y: 2 };
|
||||
|
||||
// Convert the Point to a JSON string.
|
||||
let serialized = serde_json::to_string(&point).unwrap();
|
||||
|
||||
// Prints serialized = {"x":1,"y":2}
|
||||
println!("serialized = {}", serialized);
|
||||
|
||||
// Convert the JSON string back to a Point.
|
||||
let deserialized: Point = serde_json::from_str(&serialized).unwrap();
|
||||
|
||||
// Prints deserialized = Point { x: 1, y: 2 }
|
||||
println!("deserialized = {:?}", deserialized);
|
||||
}
|
||||
```
|
||||
|
||||
## Getting help
|
||||
|
||||
Serde developers live in the #serde channel on
|
||||
[`irc.mozilla.org`](https://wiki.mozilla.org/IRC). The #rust channel is also a
|
||||
good resource with generally faster response time but less specific knowledge
|
||||
about Serde. If IRC is not your thing or you don't get a good response, we are
|
||||
happy to respond to [GitHub issues](https://github.com/serde-rs/serde/issues/new)
|
||||
as well.
|
||||
|
||||
## License
|
||||
|
||||
Serde is licensed under either of
|
||||
|
||||
* Apache License, Version 2.0, ([LICENSE-APACHE](LICENSE-APACHE) or
|
||||
http://www.apache.org/licenses/LICENSE-2.0)
|
||||
* MIT license ([LICENSE-MIT](LICENSE-MIT) or
|
||||
http://opensource.org/licenses/MIT)
|
||||
|
||||
at your option.
|
||||
|
||||
### Contribution
|
||||
|
||||
Unless you explicitly state otherwise, any contribution intentionally submitted
|
||||
for inclusion in Serde by you, as defined in the Apache-2.0 license, shall be
|
||||
dual licensed as above, without any additional terms or conditions.
|
|
@ -60,9 +60,7 @@ pub struct Bytes<'a> {
|
|||
impl<'a> Bytes<'a> {
|
||||
/// Wrap an existing `&[u8]`.
|
||||
pub fn new(bytes: &'a [u8]) -> Self {
|
||||
Bytes {
|
||||
bytes: bytes,
|
||||
}
|
||||
Bytes { bytes: bytes }
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -98,7 +96,9 @@ impl<'a> Into<&'a [u8]> for Bytes<'a> {
|
|||
impl<'a> ops::Deref for Bytes<'a> {
|
||||
type Target = [u8];
|
||||
|
||||
fn deref(&self) -> &[u8] { self.bytes }
|
||||
fn deref(&self) -> &[u8] {
|
||||
self.bytes
|
||||
}
|
||||
}
|
||||
|
||||
impl<'a> ser::Serialize for Bytes<'a> {
|
||||
|
@ -114,6 +114,7 @@ impl<'a> ser::Serialize for Bytes<'a> {
|
|||
|
||||
#[cfg(any(feature = "std", feature = "collections"))]
|
||||
mod bytebuf {
|
||||
use core::cmp;
|
||||
use core::ops;
|
||||
use core::fmt;
|
||||
use core::fmt::Write;
|
||||
|
@ -161,9 +162,7 @@ mod bytebuf {
|
|||
|
||||
/// Wrap existing bytes in a `ByteBuf`.
|
||||
pub fn from<T: Into<Vec<u8>>>(bytes: T) -> Self {
|
||||
ByteBuf {
|
||||
bytes: bytes.into(),
|
||||
}
|
||||
ByteBuf { bytes: bytes.into() }
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -216,11 +215,15 @@ mod bytebuf {
|
|||
impl ops::Deref for ByteBuf {
|
||||
type Target = [u8];
|
||||
|
||||
fn deref(&self) -> &[u8] { &self.bytes[..] }
|
||||
fn deref(&self) -> &[u8] {
|
||||
&self.bytes[..]
|
||||
}
|
||||
}
|
||||
|
||||
impl ops::DerefMut for ByteBuf {
|
||||
fn deref_mut(&mut self) -> &mut [u8] { &mut self.bytes[..] }
|
||||
fn deref_mut(&mut self) -> &mut [u8] {
|
||||
&mut self.bytes[..]
|
||||
}
|
||||
}
|
||||
|
||||
impl ser::Serialize for ByteBuf {
|
||||
|
@ -243,16 +246,16 @@ mod bytebuf {
|
|||
|
||||
#[inline]
|
||||
fn visit_unit<E>(self) -> Result<ByteBuf, E>
|
||||
where E: de::Error,
|
||||
where E: de::Error
|
||||
{
|
||||
Ok(ByteBuf::new())
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn visit_seq<V>(self, mut visitor: V) -> Result<ByteBuf, V::Error>
|
||||
where V: de::SeqVisitor,
|
||||
where V: de::SeqVisitor
|
||||
{
|
||||
let (len, _) = visitor.size_hint();
|
||||
let len = cmp::min(visitor.size_hint().0, 4096);
|
||||
let mut values = Vec::with_capacity(len);
|
||||
|
||||
while let Some(value) = try!(visitor.visit()) {
|
||||
|
@ -264,26 +267,26 @@ mod bytebuf {
|
|||
|
||||
#[inline]
|
||||
fn visit_bytes<E>(self, v: &[u8]) -> Result<ByteBuf, E>
|
||||
where E: de::Error,
|
||||
where E: de::Error
|
||||
{
|
||||
Ok(ByteBuf::from(v))
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn visit_byte_buf<E>(self, v: Vec<u8>) -> Result<ByteBuf, E>
|
||||
where E: de::Error,
|
||||
where E: de::Error
|
||||
{
|
||||
Ok(ByteBuf::from(v))
|
||||
}
|
||||
|
||||
fn visit_str<E>(self, v: &str) -> Result<ByteBuf, E>
|
||||
where E: de::Error,
|
||||
where E: de::Error
|
||||
{
|
||||
Ok(ByteBuf::from(v))
|
||||
}
|
||||
|
||||
fn visit_string<E>(self, v: String) -> Result<ByteBuf, E>
|
||||
where E: de::Error,
|
||||
where E: de::Error
|
||||
{
|
||||
Ok(ByteBuf::from(v))
|
||||
}
|
||||
|
@ -302,7 +305,9 @@ mod bytebuf {
|
|||
///////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
#[inline]
|
||||
fn escape_bytestring<'a>(bytes: &'a [u8]) -> iter::FlatMap<slice::Iter<'a, u8>, char::EscapeDefault, fn(&u8) -> char::EscapeDefault> {
|
||||
fn escape_bytestring<'a>
|
||||
(bytes: &'a [u8])
|
||||
-> iter::FlatMap<slice::Iter<'a, u8>, char::EscapeDefault, fn(&u8) -> char::EscapeDefault> {
|
||||
fn f(b: &u8) -> char::EscapeDefault {
|
||||
char::from_u32(*b as u32).unwrap().escape_default()
|
||||
}
|
||||
|
|
|
@ -10,6 +10,7 @@
|
|||
|
||||
#![doc(hidden)]
|
||||
|
||||
use core::cmp;
|
||||
use core::fmt;
|
||||
use core::marker::PhantomData;
|
||||
|
||||
|
@ -19,16 +20,8 @@ use collections::{String, Vec};
|
|||
#[cfg(all(feature = "alloc", not(feature = "std")))]
|
||||
use alloc::boxed::Box;
|
||||
|
||||
use de::{
|
||||
self,
|
||||
Deserialize,
|
||||
DeserializeSeed,
|
||||
Deserializer,
|
||||
Visitor,
|
||||
SeqVisitor,
|
||||
MapVisitor,
|
||||
EnumVisitor,
|
||||
};
|
||||
use de::{self, Deserialize, DeserializeSeed, Deserializer, Visitor, SeqVisitor, MapVisitor,
|
||||
EnumVisitor, Unexpected};
|
||||
|
||||
/// Used from generated code to buffer the contents of the Deserializer when
|
||||
/// deserializing untagged enums and internally tagged enums.
|
||||
|
@ -36,7 +29,6 @@ use de::{
|
|||
/// Not public API. Use serde-value instead.
|
||||
#[derive(Debug)]
|
||||
pub enum Content {
|
||||
// Don't mind the PhantomData, just need to use E somewhere.
|
||||
Bool(bool),
|
||||
|
||||
U8(u8),
|
||||
|
@ -65,6 +57,32 @@ pub enum Content {
|
|||
Map(Vec<(Content, Content)>),
|
||||
}
|
||||
|
||||
impl Content {
|
||||
fn unexpected(&self) -> Unexpected {
|
||||
match *self {
|
||||
Content::Bool(b) => Unexpected::Bool(b),
|
||||
Content::U8(n) => Unexpected::Unsigned(n as u64),
|
||||
Content::U16(n) => Unexpected::Unsigned(n as u64),
|
||||
Content::U32(n) => Unexpected::Unsigned(n as u64),
|
||||
Content::U64(n) => Unexpected::Unsigned(n),
|
||||
Content::I8(n) => Unexpected::Signed(n as i64),
|
||||
Content::I16(n) => Unexpected::Signed(n as i64),
|
||||
Content::I32(n) => Unexpected::Signed(n as i64),
|
||||
Content::I64(n) => Unexpected::Signed(n),
|
||||
Content::F32(f) => Unexpected::Float(f as f64),
|
||||
Content::F64(f) => Unexpected::Float(f),
|
||||
Content::Char(c) => Unexpected::Char(c),
|
||||
Content::String(ref s) => Unexpected::Str(s),
|
||||
Content::Bytes(ref b) => Unexpected::Bytes(b),
|
||||
Content::None | Content::Some(_) => Unexpected::Option,
|
||||
Content::Unit => Unexpected::Unit,
|
||||
Content::Newtype(_) => Unexpected::NewtypeStruct,
|
||||
Content::Seq(_) => Unexpected::Seq,
|
||||
Content::Map(_) => Unexpected::Map,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl Deserialize for Content {
|
||||
fn deserialize<D: Deserializer>(deserializer: D) -> Result<Self, D::Error> {
|
||||
// Untagged and internally tagged enums are only supported in
|
||||
|
@ -205,7 +223,7 @@ impl Visitor for ContentVisitor {
|
|||
fn visit_seq<V>(self, mut visitor: V) -> Result<Self::Value, V::Error>
|
||||
where V: SeqVisitor
|
||||
{
|
||||
let mut vec = Vec::with_capacity(visitor.size_hint().0);
|
||||
let mut vec = Vec::with_capacity(cmp::min(visitor.size_hint().0, 4096));
|
||||
while let Some(e) = try!(visitor.visit()) {
|
||||
vec.push(e);
|
||||
}
|
||||
|
@ -215,7 +233,7 @@ impl Visitor for ContentVisitor {
|
|||
fn visit_map<V>(self, mut visitor: V) -> Result<Self::Value, V::Error>
|
||||
where V: MapVisitor
|
||||
{
|
||||
let mut vec = Vec::with_capacity(visitor.size_hint().0);
|
||||
let mut vec = Vec::with_capacity(cmp::min(visitor.size_hint().0, 4096));
|
||||
while let Some(kv) = try!(visitor.visit()) {
|
||||
vec.push(kv);
|
||||
}
|
||||
|
@ -243,9 +261,7 @@ struct TagOrContentVisitor {
|
|||
|
||||
impl TagOrContentVisitor {
|
||||
fn new(name: &'static str) -> Self {
|
||||
TagOrContentVisitor {
|
||||
name: name,
|
||||
}
|
||||
TagOrContentVisitor { name: name }
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -475,7 +491,7 @@ impl<T> Visitor for TaggedContentVisitor<T>
|
|||
where V: MapVisitor
|
||||
{
|
||||
let mut tag = None;
|
||||
let mut vec = Vec::with_capacity(visitor.size_hint().0);
|
||||
let mut vec = Vec::with_capacity(cmp::min(visitor.size_hint().0, 4096));
|
||||
while let Some(k) = try!(visitor.visit_key_seed(TagOrContentVisitor::new(self.tag_name))) {
|
||||
match k {
|
||||
TagOrContent::Tag => {
|
||||
|
@ -491,9 +507,7 @@ impl<T> Visitor for TaggedContentVisitor<T>
|
|||
}
|
||||
}
|
||||
match tag {
|
||||
None => {
|
||||
Err(de::Error::missing_field(self.tag_name))
|
||||
}
|
||||
None => Err(de::Error::missing_field(self.tag_name)),
|
||||
Some(tag) => {
|
||||
Ok(TaggedContent {
|
||||
tag: tag,
|
||||
|
@ -504,6 +518,50 @@ impl<T> Visitor for TaggedContentVisitor<T>
|
|||
}
|
||||
}
|
||||
|
||||
/// Used by generated code to deserialize an adjacently tagged enum.
|
||||
///
|
||||
/// Not public API.
|
||||
pub enum TagOrContentField {
|
||||
Tag,
|
||||
Content,
|
||||
}
|
||||
|
||||
/// Not public API.
|
||||
pub struct TagOrContentFieldVisitor {
|
||||
pub tag: &'static str,
|
||||
pub content: &'static str,
|
||||
}
|
||||
|
||||
impl DeserializeSeed for TagOrContentFieldVisitor {
|
||||
type Value = TagOrContentField;
|
||||
|
||||
fn deserialize<D>(self, deserializer: D) -> Result<Self::Value, D::Error>
|
||||
where D: Deserializer
|
||||
{
|
||||
deserializer.deserialize_str(self)
|
||||
}
|
||||
}
|
||||
|
||||
impl Visitor for TagOrContentFieldVisitor {
|
||||
type Value = TagOrContentField;
|
||||
|
||||
fn expecting(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
|
||||
write!(formatter, "{:?} or {:?}", self.tag, self.content)
|
||||
}
|
||||
|
||||
fn visit_str<E>(self, field: &str) -> Result<Self::Value, E>
|
||||
where E: de::Error
|
||||
{
|
||||
if field == self.tag {
|
||||
Ok(TagOrContentField::Tag)
|
||||
} else if field == self.content {
|
||||
Ok(TagOrContentField::Content)
|
||||
} else {
|
||||
Err(de::Error::invalid_value(Unexpected::Str(field), &self))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// Not public API
|
||||
pub struct ContentDeserializer<E> {
|
||||
content: Content,
|
||||
|
@ -544,14 +602,15 @@ impl<E> Deserializer for ContentDeserializer<E>
|
|||
let value = try!(visitor.visit_seq(&mut seq_visitor));
|
||||
try!(seq_visitor.end());
|
||||
Ok(value)
|
||||
},
|
||||
}
|
||||
Content::Map(v) => {
|
||||
let map = v.into_iter().map(|(k, v)| (ContentDeserializer::new(k), ContentDeserializer::new(v)));
|
||||
let map = v.into_iter()
|
||||
.map(|(k, v)| (ContentDeserializer::new(k), ContentDeserializer::new(v)));
|
||||
let mut map_visitor = de::value::MapDeserializer::new(map);
|
||||
let value = try!(visitor.visit_map(&mut map_visitor));
|
||||
try!(map_visitor.end());
|
||||
Ok(value)
|
||||
},
|
||||
}
|
||||
Content::Bytes(v) => visitor.visit_byte_buf(v),
|
||||
}
|
||||
}
|
||||
|
@ -563,7 +622,7 @@ impl<E> Deserializer for ContentDeserializer<E>
|
|||
Content::None => visitor.visit_none(),
|
||||
Content::Some(v) => visitor.visit_some(ContentDeserializer::new(*v)),
|
||||
Content::Unit => visitor.visit_unit(),
|
||||
_ => visitor.visit_some(self)
|
||||
_ => visitor.visit_some(self),
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -573,10 +632,41 @@ impl<E> Deserializer for ContentDeserializer<E>
|
|||
visitor.visit_newtype_struct(self)
|
||||
}
|
||||
|
||||
fn deserialize_enum<V>(self, _name: &str, _variants: &'static [&'static str], visitor: V) -> Result<V::Value, Self::Error>
|
||||
where V: Visitor,
|
||||
{
|
||||
let (variant, value) = match self.content {
|
||||
Content::Map(value) => {
|
||||
let mut iter = value.into_iter();
|
||||
let (variant, value) = match iter.next() {
|
||||
Some(v) => v,
|
||||
None => {
|
||||
return Err(de::Error::invalid_value(de::Unexpected::Map, &"map with a single key"));
|
||||
}
|
||||
};
|
||||
// enums are encoded in json as maps with a single key:value pair
|
||||
if iter.next().is_some() {
|
||||
return Err(de::Error::invalid_value(de::Unexpected::Map, &"map with a single key"));
|
||||
}
|
||||
(variant, Some(value))
|
||||
}
|
||||
Content::String(variant) => (Content::String(variant), None),
|
||||
other => {
|
||||
return Err(de::Error::invalid_type(other.unexpected(), &"string or map"));
|
||||
}
|
||||
};
|
||||
|
||||
visitor.visit_enum(EnumDeserializer {
|
||||
variant: variant,
|
||||
value: value,
|
||||
err: PhantomData,
|
||||
})
|
||||
}
|
||||
|
||||
forward_to_deserialize! {
|
||||
bool u8 u16 u32 u64 i8 i16 i32 i64 f32 f64 char str string unit seq
|
||||
seq_fixed_size bytes byte_buf map unit_struct tuple_struct struct
|
||||
struct_field tuple enum ignored_any
|
||||
struct_field tuple ignored_any
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -590,6 +680,203 @@ impl<E> ContentDeserializer<E> {
|
|||
}
|
||||
}
|
||||
|
||||
struct EnumDeserializer<E> where E: de::Error {
|
||||
variant: Content,
|
||||
value: Option<Content>,
|
||||
err: PhantomData<E>,
|
||||
}
|
||||
|
||||
impl<E> de::EnumVisitor for EnumDeserializer<E> where E: de::Error {
|
||||
type Error = E;
|
||||
type Variant = VariantDeserializer<Self::Error>;
|
||||
|
||||
fn visit_variant_seed<V>(self, seed: V) -> Result<(V::Value, VariantDeserializer<E>), Self::Error>
|
||||
where V: de::DeserializeSeed,
|
||||
{
|
||||
let visitor = VariantDeserializer { value: self.value, err: PhantomData, };
|
||||
seed.deserialize(ContentDeserializer::new(self.variant)).map(|v| (v, visitor))
|
||||
}
|
||||
}
|
||||
|
||||
struct VariantDeserializer<E> where E: de::Error {
|
||||
value: Option<Content>,
|
||||
err: PhantomData<E>,
|
||||
}
|
||||
|
||||
impl<E> de::VariantVisitor for VariantDeserializer<E> where E: de::Error {
|
||||
type Error = E;
|
||||
|
||||
fn visit_unit(self) -> Result<(), E> {
|
||||
match self.value {
|
||||
Some(value) => de::Deserialize::deserialize(ContentDeserializer::new(value)),
|
||||
None => Ok(()),
|
||||
}
|
||||
}
|
||||
|
||||
fn visit_newtype_seed<T>(self, seed: T) -> Result<T::Value, E>
|
||||
where T: de::DeserializeSeed
|
||||
{
|
||||
match self.value {
|
||||
Some(value) => seed.deserialize(ContentDeserializer::new(value)),
|
||||
None => Err(de::Error::invalid_type(de::Unexpected::UnitVariant, &"newtype variant")),
|
||||
}
|
||||
}
|
||||
|
||||
fn visit_tuple<V>(
|
||||
self,
|
||||
_len: usize,
|
||||
visitor: V
|
||||
) -> Result<V::Value, Self::Error>
|
||||
where V: de::Visitor
|
||||
{
|
||||
match self.value {
|
||||
Some(Content::Seq(v)) => {
|
||||
de::Deserializer::deserialize(SeqDeserializer::new(v), visitor)
|
||||
}
|
||||
Some(other) => Err(de::Error::invalid_type(other.unexpected(), &"tuple variant")),
|
||||
None => Err(de::Error::invalid_type(de::Unexpected::UnitVariant, &"tuple variant"))
|
||||
}
|
||||
}
|
||||
|
||||
fn visit_struct<V>(
|
||||
self,
|
||||
_fields: &'static [&'static str],
|
||||
visitor: V
|
||||
) -> Result<V::Value, Self::Error>
|
||||
where V: de::Visitor
|
||||
{
|
||||
match self.value {
|
||||
Some(Content::Map(v)) => {
|
||||
de::Deserializer::deserialize(MapDeserializer::new(v), visitor)
|
||||
}
|
||||
Some(other) => Err(de::Error::invalid_type(other.unexpected(), &"struct variant")),
|
||||
_ => Err(de::Error::invalid_type(de::Unexpected::UnitVariant, &"struct variant"))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
struct SeqDeserializer<E> where E: de::Error {
|
||||
iter: <Vec<Content> as IntoIterator>::IntoIter,
|
||||
err: PhantomData<E>,
|
||||
}
|
||||
|
||||
impl<E> SeqDeserializer<E> where E: de::Error {
|
||||
fn new(vec: Vec<Content>) -> Self {
|
||||
SeqDeserializer {
|
||||
iter: vec.into_iter(),
|
||||
err: PhantomData,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl<E> de::Deserializer for SeqDeserializer<E> where E: de::Error {
|
||||
type Error = E;
|
||||
|
||||
#[inline]
|
||||
fn deserialize<V>(mut self, visitor: V) -> Result<V::Value, Self::Error>
|
||||
where V: de::Visitor,
|
||||
{
|
||||
let len = self.iter.len();
|
||||
if len == 0 {
|
||||
visitor.visit_unit()
|
||||
} else {
|
||||
let ret = try!(visitor.visit_seq(&mut self));
|
||||
let remaining = self.iter.len();
|
||||
if remaining == 0 {
|
||||
Ok(ret)
|
||||
} else {
|
||||
Err(de::Error::invalid_length(len, &"fewer elements in array"))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
forward_to_deserialize! {
|
||||
bool u8 u16 u32 u64 i8 i16 i32 i64 f32 f64 char str string unit option
|
||||
seq seq_fixed_size bytes byte_buf map unit_struct newtype_struct
|
||||
tuple_struct struct struct_field tuple enum ignored_any
|
||||
}
|
||||
}
|
||||
|
||||
impl<E> de::SeqVisitor for SeqDeserializer<E> where E: de::Error {
|
||||
type Error = E;
|
||||
|
||||
fn visit_seed<T>(&mut self, seed: T) -> Result<Option<T::Value>, Self::Error>
|
||||
where T: de::DeserializeSeed,
|
||||
{
|
||||
match self.iter.next() {
|
||||
Some(value) => seed.deserialize(ContentDeserializer::new(value)).map(Some),
|
||||
None => Ok(None),
|
||||
}
|
||||
}
|
||||
|
||||
fn size_hint(&self) -> (usize, Option<usize>) {
|
||||
self.iter.size_hint()
|
||||
}
|
||||
}
|
||||
|
||||
struct MapDeserializer<E> where E: de::Error {
|
||||
iter: <Vec<(Content, Content)> as IntoIterator>::IntoIter,
|
||||
value: Option<Content>,
|
||||
err: PhantomData<E>,
|
||||
}
|
||||
|
||||
impl<E> MapDeserializer<E> where E: de::Error {
|
||||
fn new(map: Vec<(Content, Content)>) -> Self {
|
||||
MapDeserializer {
|
||||
iter: map.into_iter(),
|
||||
value: None,
|
||||
err: PhantomData,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl<E> de::MapVisitor for MapDeserializer<E> where E: de::Error {
|
||||
type Error = E;
|
||||
|
||||
fn visit_key_seed<T>(&mut self, seed: T) -> Result<Option<T::Value>, Self::Error>
|
||||
where T: de::DeserializeSeed,
|
||||
{
|
||||
match self.iter.next() {
|
||||
Some((key, value)) => {
|
||||
self.value = Some(value);
|
||||
seed.deserialize(ContentDeserializer::new(key)).map(Some)
|
||||
}
|
||||
None => Ok(None),
|
||||
}
|
||||
}
|
||||
|
||||
fn visit_value_seed<T>(&mut self, seed: T) -> Result<T::Value, Self::Error>
|
||||
where T: de::DeserializeSeed,
|
||||
{
|
||||
match self.value.take() {
|
||||
Some(value) => seed.deserialize(ContentDeserializer::new(value)),
|
||||
None => Err(de::Error::custom("value is missing")),
|
||||
}
|
||||
}
|
||||
|
||||
fn size_hint(&self) -> (usize, Option<usize>) {
|
||||
self.iter.size_hint()
|
||||
}
|
||||
}
|
||||
|
||||
impl<E> de::Deserializer for MapDeserializer<E> where E: de::Error {
|
||||
type Error = E;
|
||||
|
||||
#[inline]
|
||||
fn deserialize<V>(self, visitor: V) -> Result<V::Value, Self::Error>
|
||||
where V: de::Visitor,
|
||||
{
|
||||
visitor.visit_map(self)
|
||||
}
|
||||
|
||||
forward_to_deserialize! {
|
||||
bool u8 u16 u32 u64 i8 i16 i32 i64 f32 f64 char str string unit option
|
||||
seq seq_fixed_size bytes byte_buf map unit_struct newtype_struct
|
||||
tuple_struct struct struct_field tuple enum ignored_any
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/// Not public API.
|
||||
pub struct ContentRefDeserializer<'a, E> {
|
||||
content: &'a Content,
|
||||
|
@ -603,7 +890,7 @@ impl<'a, E> Deserializer for ContentRefDeserializer<'a, E>
|
|||
{
|
||||
type Error = E;
|
||||
|
||||
fn deserialize<V>(self, visitor: V) -> Result<V::Value, Self::Error>
|
||||
fn deserialize<V>(self, visitor: V) -> Result<V::Value, E>
|
||||
where V: Visitor
|
||||
{
|
||||
match *self.content {
|
||||
|
@ -630,39 +917,72 @@ impl<'a, E> Deserializer for ContentRefDeserializer<'a, E>
|
|||
let value = try!(visitor.visit_seq(&mut seq_visitor));
|
||||
try!(seq_visitor.end());
|
||||
Ok(value)
|
||||
},
|
||||
}
|
||||
Content::Map(ref v) => {
|
||||
let map = v.into_iter().map(|&(ref k, ref v)| (ContentRefDeserializer::new(k), ContentRefDeserializer::new(v)));
|
||||
let map = v.into_iter().map(|&(ref k, ref v)| {
|
||||
(ContentRefDeserializer::new(k), ContentRefDeserializer::new(v))
|
||||
});
|
||||
let mut map_visitor = de::value::MapDeserializer::new(map);
|
||||
let value = try!(visitor.visit_map(&mut map_visitor));
|
||||
try!(map_visitor.end());
|
||||
Ok(value)
|
||||
},
|
||||
}
|
||||
Content::Bytes(ref v) => visitor.visit_bytes(v),
|
||||
}
|
||||
}
|
||||
|
||||
fn deserialize_option<V>(self, visitor: V) -> Result<V::Value, Self::Error>
|
||||
fn deserialize_option<V>(self, visitor: V) -> Result<V::Value, E>
|
||||
where V: Visitor
|
||||
{
|
||||
match *self.content {
|
||||
Content::None => visitor.visit_none(),
|
||||
Content::Some(ref v) => visitor.visit_some(ContentRefDeserializer::new(v)),
|
||||
Content::Unit => visitor.visit_unit(),
|
||||
_ => visitor.visit_some(self)
|
||||
_ => visitor.visit_some(self),
|
||||
}
|
||||
}
|
||||
|
||||
fn deserialize_newtype_struct<V>(self, _name: &str, visitor: V) -> Result<V::Value, Self::Error>
|
||||
fn deserialize_newtype_struct<V>(self, _name: &str, visitor: V) -> Result<V::Value, E>
|
||||
where V: Visitor
|
||||
{
|
||||
visitor.visit_newtype_struct(self)
|
||||
}
|
||||
|
||||
fn deserialize_enum<V>(self, _name: &str, _variants: &'static [&'static str], visitor: V) -> Result<V::Value, Self::Error>
|
||||
where V: Visitor,
|
||||
{
|
||||
let (variant, value) = match *self.content {
|
||||
Content::Map(ref value) => {
|
||||
let mut iter = value.into_iter();
|
||||
let &(ref variant, ref value) = match iter.next() {
|
||||
Some(v) => v,
|
||||
None => {
|
||||
return Err(de::Error::invalid_value(de::Unexpected::Map, &"map with a single key"));
|
||||
}
|
||||
};
|
||||
// enums are encoded in json as maps with a single key:value pair
|
||||
if iter.next().is_some() {
|
||||
return Err(de::Error::invalid_value(de::Unexpected::Map, &"map with a single key"));
|
||||
}
|
||||
(variant, Some(value))
|
||||
}
|
||||
ref s @ Content::String(_) => (s, None),
|
||||
ref other => {
|
||||
return Err(de::Error::invalid_type(other.unexpected(), &"string or map"));
|
||||
}
|
||||
};
|
||||
|
||||
visitor.visit_enum(EnumRefDeserializer {
|
||||
variant: variant,
|
||||
value: value,
|
||||
err: PhantomData,
|
||||
})
|
||||
}
|
||||
|
||||
forward_to_deserialize! {
|
||||
bool u8 u16 u32 u64 i8 i16 i32 i64 f32 f64 char str string unit seq
|
||||
seq_fixed_size bytes byte_buf map unit_struct tuple_struct struct
|
||||
struct_field tuple enum ignored_any
|
||||
struct_field tuple ignored_any
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -676,6 +996,202 @@ impl<'a, E> ContentRefDeserializer<'a, E> {
|
|||
}
|
||||
}
|
||||
|
||||
struct EnumRefDeserializer<'a, E> where E: de::Error {
|
||||
variant: &'a Content,
|
||||
value: Option<&'a Content>,
|
||||
err: PhantomData<E>,
|
||||
}
|
||||
|
||||
impl<'a, E> de::EnumVisitor for EnumRefDeserializer<'a, E> where E: de::Error {
|
||||
type Error = E;
|
||||
type Variant = VariantRefDeserializer<'a, Self::Error>;
|
||||
|
||||
fn visit_variant_seed<V>(self, seed: V) -> Result<(V::Value, Self::Variant), Self::Error>
|
||||
where V: de::DeserializeSeed,
|
||||
{
|
||||
let visitor = VariantRefDeserializer { value: self.value, err: PhantomData, };
|
||||
seed.deserialize(ContentRefDeserializer::new(self.variant)).map(|v| (v, visitor))
|
||||
}
|
||||
}
|
||||
|
||||
struct VariantRefDeserializer<'a, E> where E: de::Error {
|
||||
value: Option<&'a Content>,
|
||||
err: PhantomData<E>,
|
||||
}
|
||||
|
||||
impl<'a, E> de::VariantVisitor for VariantRefDeserializer<'a, E> where E: de::Error {
|
||||
type Error = E;
|
||||
|
||||
fn visit_unit(self) -> Result<(), E> {
|
||||
match self.value {
|
||||
Some(value) => de::Deserialize::deserialize(ContentRefDeserializer::new(value)),
|
||||
None => Ok(()),
|
||||
}
|
||||
}
|
||||
|
||||
fn visit_newtype_seed<T>(self, seed: T) -> Result<T::Value, E>
|
||||
where T: de::DeserializeSeed
|
||||
{
|
||||
match self.value {
|
||||
Some(value) => seed.deserialize(ContentRefDeserializer::new(value)),
|
||||
None => Err(de::Error::invalid_type(de::Unexpected::UnitVariant, &"newtype variant")),
|
||||
}
|
||||
}
|
||||
|
||||
fn visit_tuple<V>(
|
||||
self,
|
||||
_len: usize,
|
||||
visitor: V
|
||||
) -> Result<V::Value, Self::Error>
|
||||
where V: de::Visitor
|
||||
{
|
||||
match self.value {
|
||||
Some(&Content::Seq(ref v)) => {
|
||||
de::Deserializer::deserialize(SeqRefDeserializer::new(v), visitor)
|
||||
}
|
||||
Some(other) => Err(de::Error::invalid_type(other.unexpected(), &"tuple variant")),
|
||||
None => Err(de::Error::invalid_type(de::Unexpected::UnitVariant, &"tuple variant"))
|
||||
}
|
||||
}
|
||||
|
||||
fn visit_struct<V>(
|
||||
self,
|
||||
_fields: &'static [&'static str],
|
||||
visitor: V
|
||||
) -> Result<V::Value, Self::Error>
|
||||
where V: de::Visitor
|
||||
{
|
||||
match self.value {
|
||||
Some(&Content::Map(ref v)) => {
|
||||
de::Deserializer::deserialize(MapRefDeserializer::new(v), visitor)
|
||||
}
|
||||
Some(other) => Err(de::Error::invalid_type(other.unexpected(), &"struct variant")),
|
||||
_ => Err(de::Error::invalid_type(de::Unexpected::UnitVariant, &"struct variant"))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
struct SeqRefDeserializer<'a, E> where E: de::Error {
|
||||
iter: <&'a [Content] as IntoIterator>::IntoIter,
|
||||
err: PhantomData<E>,
|
||||
}
|
||||
|
||||
impl<'a, E> SeqRefDeserializer<'a, E> where E: de::Error {
|
||||
fn new(vec: &'a [Content]) -> Self {
|
||||
SeqRefDeserializer {
|
||||
iter: vec.into_iter(),
|
||||
err: PhantomData,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl<'a, E> de::Deserializer for SeqRefDeserializer<'a, E> where E: de::Error {
|
||||
type Error = E;
|
||||
|
||||
#[inline]
|
||||
fn deserialize<V>(mut self, visitor: V) -> Result<V::Value, Self::Error>
|
||||
where V: de::Visitor,
|
||||
{
|
||||
let len = self.iter.len();
|
||||
if len == 0 {
|
||||
visitor.visit_unit()
|
||||
} else {
|
||||
let ret = try!(visitor.visit_seq(&mut self));
|
||||
let remaining = self.iter.len();
|
||||
if remaining == 0 {
|
||||
Ok(ret)
|
||||
} else {
|
||||
Err(de::Error::invalid_length(len, &"fewer elements in array"))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
forward_to_deserialize! {
|
||||
bool u8 u16 u32 u64 i8 i16 i32 i64 f32 f64 char str string unit option
|
||||
seq seq_fixed_size bytes byte_buf map unit_struct newtype_struct
|
||||
tuple_struct struct struct_field tuple enum ignored_any
|
||||
}
|
||||
}
|
||||
|
||||
impl<'a, E> de::SeqVisitor for SeqRefDeserializer<'a, E> where E: de::Error {
|
||||
type Error = E;
|
||||
|
||||
fn visit_seed<T>(&mut self, seed: T) -> Result<Option<T::Value>, Self::Error>
|
||||
where T: de::DeserializeSeed,
|
||||
{
|
||||
match self.iter.next() {
|
||||
Some(value) => seed.deserialize(ContentRefDeserializer::new(value)).map(Some),
|
||||
None => Ok(None),
|
||||
}
|
||||
}
|
||||
|
||||
fn size_hint(&self) -> (usize, Option<usize>) {
|
||||
self.iter.size_hint()
|
||||
}
|
||||
}
|
||||
|
||||
struct MapRefDeserializer<'a, E> where E: de::Error {
|
||||
iter: <&'a [(Content, Content)] as IntoIterator>::IntoIter,
|
||||
value: Option<&'a Content>,
|
||||
err: PhantomData<E>,
|
||||
}
|
||||
|
||||
impl<'a, E> MapRefDeserializer<'a, E> where E: de::Error {
|
||||
fn new(map: &'a [(Content, Content)]) -> Self {
|
||||
MapRefDeserializer {
|
||||
iter: map.into_iter(),
|
||||
value: None,
|
||||
err: PhantomData,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl<'a, E> de::MapVisitor for MapRefDeserializer<'a, E> where E: de::Error {
|
||||
type Error = E;
|
||||
|
||||
fn visit_key_seed<T>(&mut self, seed: T) -> Result<Option<T::Value>, Self::Error>
|
||||
where T: de::DeserializeSeed,
|
||||
{
|
||||
match self.iter.next() {
|
||||
Some(&(ref key, ref value)) => {
|
||||
self.value = Some(value);
|
||||
seed.deserialize(ContentRefDeserializer::new(key)).map(Some)
|
||||
}
|
||||
None => Ok(None),
|
||||
}
|
||||
}
|
||||
|
||||
fn visit_value_seed<T>(&mut self, seed: T) -> Result<T::Value, Self::Error>
|
||||
where T: de::DeserializeSeed,
|
||||
{
|
||||
match self.value.take() {
|
||||
Some(value) => seed.deserialize(ContentRefDeserializer::new(value)),
|
||||
None => Err(de::Error::custom("value is missing")),
|
||||
}
|
||||
}
|
||||
|
||||
fn size_hint(&self) -> (usize, Option<usize>) {
|
||||
self.iter.size_hint()
|
||||
}
|
||||
}
|
||||
|
||||
impl<'a, E> de::Deserializer for MapRefDeserializer<'a, E> where E: de::Error {
|
||||
type Error = E;
|
||||
|
||||
#[inline]
|
||||
fn deserialize<V>(self, visitor: V) -> Result<V::Value, Self::Error>
|
||||
where V: de::Visitor,
|
||||
{
|
||||
visitor.visit_map(self)
|
||||
}
|
||||
|
||||
forward_to_deserialize! {
|
||||
bool u8 u16 u32 u64 i8 i16 i32 i64 f32 f64 char str string unit option
|
||||
seq seq_fixed_size bytes byte_buf map unit_struct newtype_struct
|
||||
tuple_struct struct struct_field tuple enum ignored_any
|
||||
}
|
||||
}
|
||||
|
||||
impl<E> de::value::ValueDeserializer<E> for ContentDeserializer<E>
|
||||
where E: de::Error
|
||||
{
|
||||
|
|
|
@ -6,30 +6,16 @@ use std::borrow::Cow;
|
|||
use collections::borrow::Cow;
|
||||
|
||||
#[cfg(all(feature = "collections", not(feature = "std")))]
|
||||
use collections::{
|
||||
BinaryHeap,
|
||||
BTreeMap,
|
||||
BTreeSet,
|
||||
LinkedList,
|
||||
VecDeque,
|
||||
Vec,
|
||||
String,
|
||||
};
|
||||
use collections::{BinaryHeap, BTreeMap, BTreeSet, LinkedList, VecDeque, Vec, String};
|
||||
|
||||
#[cfg(feature = "std")]
|
||||
use std::collections::{
|
||||
HashMap,
|
||||
HashSet,
|
||||
BinaryHeap,
|
||||
BTreeMap,
|
||||
BTreeSet,
|
||||
LinkedList,
|
||||
VecDeque,
|
||||
};
|
||||
use std::collections::{HashMap, HashSet, BinaryHeap, BTreeMap, BTreeSet, LinkedList, VecDeque};
|
||||
|
||||
#[cfg(feature = "collections")]
|
||||
use collections::borrow::ToOwned;
|
||||
|
||||
#[cfg(any(feature = "std", feature = "collections"))]
|
||||
use core::cmp;
|
||||
use core::fmt;
|
||||
#[cfg(feature = "std")]
|
||||
use core::hash::{Hash, BuildHasher};
|
||||
|
@ -63,17 +49,8 @@ use core::nonzero::{NonZero, Zeroable};
|
|||
#[allow(deprecated)] // required for impl Deserialize for NonZero<T>
|
||||
use core::num::Zero;
|
||||
|
||||
use de::{
|
||||
Deserialize,
|
||||
Deserializer,
|
||||
EnumVisitor,
|
||||
Error,
|
||||
MapVisitor,
|
||||
SeqVisitor,
|
||||
Unexpected,
|
||||
VariantVisitor,
|
||||
Visitor,
|
||||
};
|
||||
use de::{Deserialize, Deserializer, EnumVisitor, Error, MapVisitor, SeqVisitor, Unexpected,
|
||||
VariantVisitor, Visitor};
|
||||
use de::from_primitive::FromPrimitive;
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
|
@ -89,13 +66,13 @@ impl Visitor for UnitVisitor {
|
|||
}
|
||||
|
||||
fn visit_unit<E>(self) -> Result<(), E>
|
||||
where E: Error,
|
||||
where E: Error
|
||||
{
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn visit_seq<V>(self, _: V) -> Result<(), V::Error>
|
||||
where V: SeqVisitor,
|
||||
where V: SeqVisitor
|
||||
{
|
||||
Ok(())
|
||||
}
|
||||
|
@ -103,7 +80,7 @@ impl Visitor for UnitVisitor {
|
|||
|
||||
impl Deserialize for () {
|
||||
fn deserialize<D>(deserializer: D) -> Result<(), D::Error>
|
||||
where D: Deserializer,
|
||||
where D: Deserializer
|
||||
{
|
||||
deserializer.deserialize_unit(UnitVisitor)
|
||||
}
|
||||
|
@ -122,13 +99,13 @@ impl Visitor for BoolVisitor {
|
|||
}
|
||||
|
||||
fn visit_bool<E>(self, v: bool) -> Result<bool, E>
|
||||
where E: Error,
|
||||
where E: Error
|
||||
{
|
||||
Ok(v)
|
||||
}
|
||||
|
||||
fn visit_str<E>(self, s: &str) -> Result<bool, E>
|
||||
where E: Error,
|
||||
where E: Error
|
||||
{
|
||||
match s.trim_matches(::utils::Pattern_White_Space) {
|
||||
"true" => Ok(true),
|
||||
|
@ -140,7 +117,7 @@ impl Visitor for BoolVisitor {
|
|||
|
||||
impl Deserialize for bool {
|
||||
fn deserialize<D>(deserializer: D) -> Result<bool, D::Error>
|
||||
where D: Deserializer,
|
||||
where D: Deserializer
|
||||
{
|
||||
deserializer.deserialize_bool(BoolVisitor)
|
||||
}
|
||||
|
@ -231,14 +208,14 @@ impl Visitor for CharVisitor {
|
|||
|
||||
#[inline]
|
||||
fn visit_char<E>(self, v: char) -> Result<char, E>
|
||||
where E: Error,
|
||||
where E: Error
|
||||
{
|
||||
Ok(v)
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn visit_str<E>(self, v: &str) -> Result<char, E>
|
||||
where E: Error,
|
||||
where E: Error
|
||||
{
|
||||
let mut iter = v.chars();
|
||||
match (iter.next(), iter.next()) {
|
||||
|
@ -251,7 +228,7 @@ impl Visitor for CharVisitor {
|
|||
impl Deserialize for char {
|
||||
#[inline]
|
||||
fn deserialize<D>(deserializer: D) -> Result<char, D::Error>
|
||||
where D: Deserializer,
|
||||
where D: Deserializer
|
||||
{
|
||||
deserializer.deserialize_char(CharVisitor)
|
||||
}
|
||||
|
@ -271,25 +248,25 @@ impl Visitor for StringVisitor {
|
|||
}
|
||||
|
||||
fn visit_str<E>(self, v: &str) -> Result<String, E>
|
||||
where E: Error,
|
||||
where E: Error
|
||||
{
|
||||
Ok(v.to_owned())
|
||||
}
|
||||
|
||||
fn visit_string<E>(self, v: String) -> Result<String, E>
|
||||
where E: Error,
|
||||
where E: Error
|
||||
{
|
||||
Ok(v)
|
||||
}
|
||||
|
||||
fn visit_unit<E>(self) -> Result<String, E>
|
||||
where E: Error,
|
||||
where E: Error
|
||||
{
|
||||
Ok(String::new())
|
||||
}
|
||||
|
||||
fn visit_bytes<E>(self, v: &[u8]) -> Result<String, E>
|
||||
where E: Error,
|
||||
where E: Error
|
||||
{
|
||||
match str::from_utf8(v) {
|
||||
Ok(s) => Ok(s.to_owned()),
|
||||
|
@ -298,7 +275,7 @@ impl Visitor for StringVisitor {
|
|||
}
|
||||
|
||||
fn visit_byte_buf<E>(self, v: Vec<u8>) -> Result<String, E>
|
||||
where E: Error,
|
||||
where E: Error
|
||||
{
|
||||
match String::from_utf8(v) {
|
||||
Ok(s) => Ok(s),
|
||||
|
@ -310,7 +287,7 @@ impl Visitor for StringVisitor {
|
|||
#[cfg(any(feature = "std", feature = "collections"))]
|
||||
impl Deserialize for String {
|
||||
fn deserialize<D>(deserializer: D) -> Result<String, D::Error>
|
||||
where D: Deserializer,
|
||||
where D: Deserializer
|
||||
{
|
||||
deserializer.deserialize_string(StringVisitor)
|
||||
}
|
||||
|
@ -322,9 +299,7 @@ struct OptionVisitor<T> {
|
|||
marker: PhantomData<T>,
|
||||
}
|
||||
|
||||
impl<
|
||||
T: Deserialize,
|
||||
> Visitor for OptionVisitor<T> {
|
||||
impl<T: Deserialize> Visitor for OptionVisitor<T> {
|
||||
type Value = Option<T>;
|
||||
|
||||
fn expecting(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
|
||||
|
@ -333,29 +308,31 @@ impl<
|
|||
|
||||
#[inline]
|
||||
fn visit_unit<E>(self) -> Result<Option<T>, E>
|
||||
where E: Error,
|
||||
where E: Error
|
||||
{
|
||||
Ok(None)
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn visit_none<E>(self) -> Result<Option<T>, E>
|
||||
where E: Error,
|
||||
where E: Error
|
||||
{
|
||||
Ok(None)
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn visit_some<D>(self, deserializer: D) -> Result<Option<T>, D::Error>
|
||||
where D: Deserializer,
|
||||
where D: Deserializer
|
||||
{
|
||||
Ok(Some(try!(Deserialize::deserialize(deserializer))))
|
||||
}
|
||||
}
|
||||
|
||||
impl<T> Deserialize for Option<T> where T: Deserialize {
|
||||
impl<T> Deserialize for Option<T>
|
||||
where T: Deserialize
|
||||
{
|
||||
fn deserialize<D>(deserializer: D) -> Result<Option<T>, D::Error>
|
||||
where D: Deserializer,
|
||||
where D: Deserializer
|
||||
{
|
||||
deserializer.deserialize_option(OptionVisitor { marker: PhantomData })
|
||||
}
|
||||
|
@ -377,7 +354,7 @@ impl<T> Visitor for PhantomDataVisitor<T> {
|
|||
|
||||
#[inline]
|
||||
fn visit_unit<E>(self) -> Result<PhantomData<T>, E>
|
||||
where E: Error,
|
||||
where E: Error
|
||||
{
|
||||
Ok(PhantomData)
|
||||
}
|
||||
|
@ -385,7 +362,7 @@ impl<T> Visitor for PhantomDataVisitor<T> {
|
|||
|
||||
impl<T> Deserialize for PhantomData<T> {
|
||||
fn deserialize<D>(deserializer: D) -> Result<PhantomData<T>, D::Error>
|
||||
where D: Deserializer,
|
||||
where D: Deserializer
|
||||
{
|
||||
let visitor = PhantomDataVisitor { marker: PhantomData };
|
||||
deserializer.deserialize_unit_struct("PhantomData", visitor)
|
||||
|
@ -467,7 +444,7 @@ seq_impl!(
|
|||
BinaryHeapVisitor<T: Deserialize + Ord>,
|
||||
visitor,
|
||||
BinaryHeap::new(),
|
||||
BinaryHeap::with_capacity(visitor.size_hint().0),
|
||||
BinaryHeap::with_capacity(cmp::min(visitor.size_hint().0, 4096)),
|
||||
BinaryHeap::push);
|
||||
|
||||
#[cfg(any(feature = "std", feature = "collections"))]
|
||||
|
@ -495,7 +472,7 @@ seq_impl!(
|
|||
S: BuildHasher + Default>,
|
||||
visitor,
|
||||
HashSet::with_hasher(S::default()),
|
||||
HashSet::with_capacity_and_hasher(visitor.size_hint().0, S::default()),
|
||||
HashSet::with_capacity_and_hasher(cmp::min(visitor.size_hint().0, 4096), S::default()),
|
||||
HashSet::insert);
|
||||
|
||||
#[cfg(any(feature = "std", feature = "collections"))]
|
||||
|
@ -504,7 +481,7 @@ seq_impl!(
|
|||
VecVisitor<T: Deserialize>,
|
||||
visitor,
|
||||
Vec::new(),
|
||||
Vec::with_capacity(visitor.size_hint().0),
|
||||
Vec::with_capacity(cmp::min(visitor.size_hint().0, 4096)),
|
||||
Vec::push);
|
||||
|
||||
#[cfg(any(feature = "std", feature = "collections"))]
|
||||
|
@ -513,7 +490,7 @@ seq_impl!(
|
|||
VecDequeVisitor<T: Deserialize>,
|
||||
visitor,
|
||||
VecDeque::new(),
|
||||
VecDeque::with_capacity(visitor.size_hint().0),
|
||||
VecDeque::with_capacity(cmp::min(visitor.size_hint().0, 4096)),
|
||||
VecDeque::push_back);
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
|
@ -524,13 +501,13 @@ struct ArrayVisitor<A> {
|
|||
|
||||
impl<A> ArrayVisitor<A> {
|
||||
pub fn new() -> Self {
|
||||
ArrayVisitor {
|
||||
marker: PhantomData,
|
||||
}
|
||||
ArrayVisitor { marker: PhantomData }
|
||||
}
|
||||
}
|
||||
|
||||
impl<T> Visitor for ArrayVisitor<[T; 0]> where T: Deserialize {
|
||||
impl<T> Visitor for ArrayVisitor<[T; 0]>
|
||||
where T: Deserialize
|
||||
{
|
||||
type Value = [T; 0];
|
||||
|
||||
fn expecting(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
|
||||
|
@ -539,14 +516,14 @@ impl<T> Visitor for ArrayVisitor<[T; 0]> where T: Deserialize {
|
|||
|
||||
#[inline]
|
||||
fn visit_unit<E>(self) -> Result<[T; 0], E>
|
||||
where E: Error,
|
||||
where E: Error
|
||||
{
|
||||
Ok([])
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn visit_seq<V>(self, _: V) -> Result<[T; 0], V::Error>
|
||||
where V: SeqVisitor,
|
||||
where V: SeqVisitor
|
||||
{
|
||||
Ok([])
|
||||
}
|
||||
|
@ -556,7 +533,7 @@ impl<T> Deserialize for [T; 0]
|
|||
where T: Deserialize
|
||||
{
|
||||
fn deserialize<D>(deserializer: D) -> Result<[T; 0], D::Error>
|
||||
where D: Deserializer,
|
||||
where D: Deserializer
|
||||
{
|
||||
deserializer.deserialize_seq_fixed_size(0, ArrayVisitor::<[T; 0]>::new())
|
||||
}
|
||||
|
@ -791,14 +768,14 @@ map_impl!(
|
|||
S: BuildHasher + Default>,
|
||||
visitor,
|
||||
HashMap::with_hasher(S::default()),
|
||||
HashMap::with_capacity_and_hasher(visitor.size_hint().0, S::default()));
|
||||
HashMap::with_capacity_and_hasher(cmp::min(visitor.size_hint().0, 4096), S::default()));
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
#[cfg(feature = "std")]
|
||||
impl Deserialize for net::IpAddr {
|
||||
fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
|
||||
where D: Deserializer,
|
||||
where D: Deserializer
|
||||
{
|
||||
let s = try!(String::deserialize(deserializer));
|
||||
match s.parse() {
|
||||
|
@ -811,7 +788,7 @@ impl Deserialize for net::IpAddr {
|
|||
#[cfg(feature = "std")]
|
||||
impl Deserialize for net::Ipv4Addr {
|
||||
fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
|
||||
where D: Deserializer,
|
||||
where D: Deserializer
|
||||
{
|
||||
let s = try!(String::deserialize(deserializer));
|
||||
match s.parse() {
|
||||
|
@ -824,7 +801,7 @@ impl Deserialize for net::Ipv4Addr {
|
|||
#[cfg(feature = "std")]
|
||||
impl Deserialize for net::Ipv6Addr {
|
||||
fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
|
||||
where D: Deserializer,
|
||||
where D: Deserializer
|
||||
{
|
||||
let s = try!(String::deserialize(deserializer));
|
||||
match s.parse() {
|
||||
|
@ -839,7 +816,7 @@ impl Deserialize for net::Ipv6Addr {
|
|||
#[cfg(feature = "std")]
|
||||
impl Deserialize for net::SocketAddr {
|
||||
fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
|
||||
where D: Deserializer,
|
||||
where D: Deserializer
|
||||
{
|
||||
let s = try!(String::deserialize(deserializer));
|
||||
match s.parse() {
|
||||
|
@ -852,7 +829,7 @@ impl Deserialize for net::SocketAddr {
|
|||
#[cfg(feature = "std")]
|
||||
impl Deserialize for net::SocketAddrV4 {
|
||||
fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
|
||||
where D: Deserializer,
|
||||
where D: Deserializer
|
||||
{
|
||||
let s = try!(String::deserialize(deserializer));
|
||||
match s.parse() {
|
||||
|
@ -865,7 +842,7 @@ impl Deserialize for net::SocketAddrV4 {
|
|||
#[cfg(feature = "std")]
|
||||
impl Deserialize for net::SocketAddrV6 {
|
||||
fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
|
||||
where D: Deserializer,
|
||||
where D: Deserializer
|
||||
{
|
||||
let s = try!(String::deserialize(deserializer));
|
||||
match s.parse() {
|
||||
|
@ -889,13 +866,13 @@ impl Visitor for PathBufVisitor {
|
|||
}
|
||||
|
||||
fn visit_str<E>(self, v: &str) -> Result<path::PathBuf, E>
|
||||
where E: Error,
|
||||
where E: Error
|
||||
{
|
||||
Ok(From::from(v))
|
||||
}
|
||||
|
||||
fn visit_string<E>(self, v: String) -> Result<path::PathBuf, E>
|
||||
where E: Error,
|
||||
where E: Error
|
||||
{
|
||||
Ok(From::from(v))
|
||||
}
|
||||
|
@ -904,7 +881,7 @@ impl Visitor for PathBufVisitor {
|
|||
#[cfg(feature = "std")]
|
||||
impl Deserialize for path::PathBuf {
|
||||
fn deserialize<D>(deserializer: D) -> Result<path::PathBuf, D::Error>
|
||||
where D: Deserializer,
|
||||
where D: Deserializer
|
||||
{
|
||||
deserializer.deserialize_string(PathBufVisitor)
|
||||
}
|
||||
|
@ -915,7 +892,7 @@ impl Deserialize for path::PathBuf {
|
|||
#[cfg(any(feature = "std", feature = "alloc"))]
|
||||
impl<T: Deserialize> Deserialize for Box<T> {
|
||||
fn deserialize<D>(deserializer: D) -> Result<Box<T>, D::Error>
|
||||
where D: Deserializer,
|
||||
where D: Deserializer
|
||||
{
|
||||
let val = try!(Deserialize::deserialize(deserializer));
|
||||
Ok(Box::new(val))
|
||||
|
@ -925,7 +902,7 @@ impl<T: Deserialize> Deserialize for Box<T> {
|
|||
#[cfg(any(feature = "std", feature = "collections"))]
|
||||
impl<T: Deserialize> Deserialize for Box<[T]> {
|
||||
fn deserialize<D>(deserializer: D) -> Result<Box<[T]>, D::Error>
|
||||
where D: Deserializer,
|
||||
where D: Deserializer
|
||||
{
|
||||
let v: Vec<T> = try!(Deserialize::deserialize(deserializer));
|
||||
Ok(v.into_boxed_slice())
|
||||
|
@ -945,7 +922,7 @@ impl Deserialize for Box<str> {
|
|||
#[cfg(any(feature = "std", feature = "alloc"))]
|
||||
impl<T: Deserialize> Deserialize for Arc<T> {
|
||||
fn deserialize<D>(deserializer: D) -> Result<Arc<T>, D::Error>
|
||||
where D: Deserializer,
|
||||
where D: Deserializer
|
||||
{
|
||||
let val = try!(Deserialize::deserialize(deserializer));
|
||||
Ok(Arc::new(val))
|
||||
|
@ -955,7 +932,7 @@ impl<T: Deserialize> Deserialize for Arc<T> {
|
|||
#[cfg(any(feature = "std", feature = "alloc"))]
|
||||
impl<T: Deserialize> Deserialize for Rc<T> {
|
||||
fn deserialize<D>(deserializer: D) -> Result<Rc<T>, D::Error>
|
||||
where D: Deserializer,
|
||||
where D: Deserializer
|
||||
{
|
||||
let val = try!(Deserialize::deserialize(deserializer));
|
||||
Ok(Rc::new(val))
|
||||
|
@ -963,10 +940,13 @@ 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]
|
||||
fn deserialize<D>(deserializer: D) -> Result<Cow<'a, T>, D::Error>
|
||||
where D: Deserializer,
|
||||
where D: Deserializer
|
||||
{
|
||||
let val = try!(Deserialize::deserialize(deserializer));
|
||||
Ok(Cow::Owned(val))
|
||||
|
@ -986,13 +966,16 @@ impl<'a, T: ?Sized> Deserialize for Cow<'a, T> where T: ToOwned, T::Owned: Deser
|
|||
#[cfg(feature = "std")]
|
||||
impl Deserialize for Duration {
|
||||
fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
|
||||
where D: Deserializer,
|
||||
where D: Deserializer
|
||||
{
|
||||
enum Field { Secs, Nanos };
|
||||
enum Field {
|
||||
Secs,
|
||||
Nanos,
|
||||
};
|
||||
|
||||
impl Deserialize for Field {
|
||||
fn deserialize<D>(deserializer: D) -> Result<Field, D::Error>
|
||||
where D: Deserializer,
|
||||
where D: Deserializer
|
||||
{
|
||||
struct FieldVisitor;
|
||||
|
||||
|
@ -1004,7 +987,7 @@ impl Deserialize for Duration {
|
|||
}
|
||||
|
||||
fn visit_str<E>(self, value: &str) -> Result<Field, E>
|
||||
where E: Error,
|
||||
where E: Error
|
||||
{
|
||||
match value {
|
||||
"secs" => Ok(Field::Secs),
|
||||
|
@ -1014,7 +997,7 @@ impl Deserialize for Duration {
|
|||
}
|
||||
|
||||
fn visit_bytes<E>(self, value: &[u8]) -> Result<Field, E>
|
||||
where E: Error,
|
||||
where E: Error
|
||||
{
|
||||
match value {
|
||||
b"secs" => Ok(Field::Secs),
|
||||
|
@ -1041,7 +1024,7 @@ impl Deserialize for Duration {
|
|||
}
|
||||
|
||||
fn visit_seq<V>(self, mut visitor: V) -> Result<Duration, V::Error>
|
||||
where V: SeqVisitor,
|
||||
where V: SeqVisitor
|
||||
{
|
||||
let secs: u64 = match try!(visitor.visit()) {
|
||||
Some(value) => value,
|
||||
|
@ -1059,7 +1042,7 @@ impl Deserialize for Duration {
|
|||
}
|
||||
|
||||
fn visit_map<V>(self, mut visitor: V) -> Result<Duration, V::Error>
|
||||
where V: MapVisitor,
|
||||
where V: MapVisitor
|
||||
{
|
||||
let mut secs: Option<u64> = None;
|
||||
let mut nanos: Option<u32> = None;
|
||||
|
@ -1100,24 +1083,30 @@ impl Deserialize for Duration {
|
|||
|
||||
#[cfg(feature = "unstable")]
|
||||
#[allow(deprecated)] // num::Zero is deprecated but there is no replacement
|
||||
impl<T> Deserialize for NonZero<T> where T: Deserialize + PartialEq + Zeroable + Zero {
|
||||
fn deserialize<D>(deserializer: D) -> Result<NonZero<T>, D::Error> where D: Deserializer {
|
||||
impl<T> Deserialize for NonZero<T>
|
||||
where T: Deserialize + PartialEq + Zeroable + Zero
|
||||
{
|
||||
fn deserialize<D>(deserializer: D) -> Result<NonZero<T>, D::Error>
|
||||
where D: Deserializer
|
||||
{
|
||||
let value = try!(Deserialize::deserialize(deserializer));
|
||||
if value == Zero::zero() {
|
||||
return Err(Error::custom("expected a non-zero value"))
|
||||
}
|
||||
unsafe {
|
||||
Ok(NonZero::new(value))
|
||||
return Err(Error::custom("expected a non-zero value"));
|
||||
}
|
||||
unsafe { Ok(NonZero::new(value)) }
|
||||
}
|
||||
}
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
|
||||
impl<T, E> Deserialize for Result<T, E> where T: Deserialize, E: Deserialize {
|
||||
impl<T, E> Deserialize for Result<T, E>
|
||||
where T: Deserialize,
|
||||
E: Deserialize
|
||||
{
|
||||
fn deserialize<D>(deserializer: D) -> Result<Result<T, E>, D::Error>
|
||||
where D: Deserializer {
|
||||
where D: Deserializer
|
||||
{
|
||||
enum Field {
|
||||
Ok,
|
||||
Err,
|
||||
|
@ -1137,15 +1126,21 @@ impl<T, E> Deserialize for Result<T, E> where T: Deserialize, E: Deserialize {
|
|||
formatter.write_str("`Ok` or `Err`")
|
||||
}
|
||||
|
||||
fn visit_u32<E>(self, value: u32) -> Result<Field, E> where E: Error {
|
||||
fn visit_u32<E>(self, value: u32) -> Result<Field, E>
|
||||
where E: Error
|
||||
{
|
||||
match value {
|
||||
0 => Ok(Field::Ok),
|
||||
1 => Ok(Field::Err),
|
||||
_ => Err(Error::invalid_value(Unexpected::Unsigned(value as u64), &self)),
|
||||
_ => {
|
||||
Err(Error::invalid_value(Unexpected::Unsigned(value as u64), &self))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fn visit_str<E>(self, value: &str) -> Result<Field, E> where E: Error {
|
||||
fn visit_str<E>(self, value: &str) -> Result<Field, E>
|
||||
where E: Error
|
||||
{
|
||||
match value {
|
||||
"Ok" => Ok(Field::Ok),
|
||||
"Err" => Ok(Field::Err),
|
||||
|
@ -1153,14 +1148,18 @@ impl<T, E> Deserialize for Result<T, E> where T: Deserialize, E: Deserialize {
|
|||
}
|
||||
}
|
||||
|
||||
fn visit_bytes<E>(self, value: &[u8]) -> Result<Field, E> where E: Error {
|
||||
fn visit_bytes<E>(self, value: &[u8]) -> Result<Field, E>
|
||||
where E: Error
|
||||
{
|
||||
match value {
|
||||
b"Ok" => Ok(Field::Ok),
|
||||
b"Err" => Ok(Field::Err),
|
||||
_ => {
|
||||
match str::from_utf8(value) {
|
||||
Ok(value) => Err(Error::unknown_variant(value, VARIANTS)),
|
||||
Err(_) => Err(Error::invalid_value(Unexpected::Bytes(value), &self)),
|
||||
Err(_) => {
|
||||
Err(Error::invalid_value(Unexpected::Bytes(value), &self))
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -1208,7 +1207,7 @@ pub struct IgnoredAny;
|
|||
impl Deserialize for IgnoredAny {
|
||||
#[inline]
|
||||
fn deserialize<D>(deserializer: D) -> Result<IgnoredAny, D::Error>
|
||||
where D: Deserializer,
|
||||
where D: Deserializer
|
||||
{
|
||||
struct IgnoredAnyVisitor;
|
||||
|
||||
|
@ -1241,7 +1240,7 @@ impl Deserialize for IgnoredAny {
|
|||
|
||||
#[inline]
|
||||
fn visit_str<E>(self, _: &str) -> Result<IgnoredAny, E>
|
||||
where E: Error,
|
||||
where E: Error
|
||||
{
|
||||
Ok(IgnoredAny)
|
||||
}
|
||||
|
@ -1253,14 +1252,14 @@ impl Deserialize for IgnoredAny {
|
|||
|
||||
#[inline]
|
||||
fn visit_some<D>(self, _: D) -> Result<IgnoredAny, D::Error>
|
||||
where D: Deserializer,
|
||||
where D: Deserializer
|
||||
{
|
||||
Ok(IgnoredAny)
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn visit_newtype_struct<D>(self, _: D) -> Result<IgnoredAny, D::Error>
|
||||
where D: Deserializer,
|
||||
where D: Deserializer
|
||||
{
|
||||
Ok(IgnoredAny)
|
||||
}
|
||||
|
@ -1272,7 +1271,7 @@ impl Deserialize for IgnoredAny {
|
|||
|
||||
#[inline]
|
||||
fn visit_seq<V>(self, mut visitor: V) -> Result<IgnoredAny, V::Error>
|
||||
where V: SeqVisitor,
|
||||
where V: SeqVisitor
|
||||
{
|
||||
while let Some(_) = try!(visitor.visit::<IgnoredAny>()) {
|
||||
// Gobble
|
||||
|
@ -1282,7 +1281,7 @@ impl Deserialize for IgnoredAny {
|
|||
|
||||
#[inline]
|
||||
fn visit_map<V>(self, mut visitor: V) -> Result<IgnoredAny, V::Error>
|
||||
where V: MapVisitor,
|
||||
where V: MapVisitor
|
||||
{
|
||||
while let Some((_, _)) = try!(visitor.visit::<IgnoredAny, IgnoredAny>()) {
|
||||
// Gobble
|
||||
|
@ -1292,7 +1291,7 @@ impl Deserialize for IgnoredAny {
|
|||
|
||||
#[inline]
|
||||
fn visit_bytes<E>(self, _: &[u8]) -> Result<IgnoredAny, E>
|
||||
where E: Error,
|
||||
where E: Error
|
||||
{
|
||||
Ok(IgnoredAny)
|
||||
}
|
||||
|
|
|
@ -181,7 +181,10 @@ pub trait Error: Sized + error::Error {
|
|||
write!(formatter, "invalid type: {}, expected {}", self.unexp, self.exp)
|
||||
}
|
||||
}
|
||||
Error::custom(InvalidType { unexp: unexp, exp: exp })
|
||||
Error::custom(InvalidType {
|
||||
unexp: unexp,
|
||||
exp: exp,
|
||||
})
|
||||
}
|
||||
|
||||
/// Raised when a `Deserialize` receives a value of the right type but that
|
||||
|
@ -207,7 +210,10 @@ pub trait Error: Sized + error::Error {
|
|||
write!(formatter, "invalid value: {}, expected {}", self.unexp, self.exp)
|
||||
}
|
||||
}
|
||||
Error::custom(InvalidValue { unexp: unexp, exp: exp })
|
||||
Error::custom(InvalidValue {
|
||||
unexp: unexp,
|
||||
exp: exp,
|
||||
})
|
||||
}
|
||||
|
||||
/// Raised when deserializing a sequence or map and the input data contains
|
||||
|
@ -229,7 +235,10 @@ pub trait Error: Sized + error::Error {
|
|||
write!(formatter, "invalid length {}, expected {}", self.len, self.exp)
|
||||
}
|
||||
}
|
||||
Error::custom(InvalidLength { len: len, exp: exp })
|
||||
Error::custom(InvalidLength {
|
||||
len: len,
|
||||
exp: exp,
|
||||
})
|
||||
}
|
||||
|
||||
/// Raised when a `Deserialize` enum type received a variant with an
|
||||
|
@ -253,7 +262,10 @@ pub trait Error: Sized + error::Error {
|
|||
}
|
||||
}
|
||||
}
|
||||
Error::custom(UnknownVariant { variant: variant, expected: expected })
|
||||
Error::custom(UnknownVariant {
|
||||
variant: variant,
|
||||
expected: expected,
|
||||
})
|
||||
}
|
||||
|
||||
/// Raised when a `Deserialize` struct type received a field with an
|
||||
|
@ -277,7 +289,10 @@ pub trait Error: Sized + error::Error {
|
|||
}
|
||||
}
|
||||
}
|
||||
Error::custom(UnknownField { field: field, expected: expected })
|
||||
Error::custom(UnknownField {
|
||||
field: field,
|
||||
expected: expected,
|
||||
})
|
||||
}
|
||||
|
||||
/// Raised when a `Deserialize` struct type expected to receive a required
|
||||
|
@ -470,7 +485,9 @@ pub trait Expected {
|
|||
fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result;
|
||||
}
|
||||
|
||||
impl<T> Expected for T where T: Visitor {
|
||||
impl<T> Expected for T
|
||||
where T: Visitor
|
||||
{
|
||||
fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
|
||||
self.expecting(formatter)
|
||||
}
|
||||
|
@ -521,8 +538,7 @@ pub trait Deserialize: Sized {
|
|||
/// manual for more information about how to implement this method.
|
||||
///
|
||||
/// [impl-deserialize]: https://serde.rs/impl-deserialize.html
|
||||
fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
|
||||
where D: Deserializer;
|
||||
fn deserialize<D>(deserializer: D) -> Result<Self, D::Error> where D: Deserializer;
|
||||
}
|
||||
|
||||
/// `DeserializeSeed` is the stateful form of the `Deserialize` trait. If you
|
||||
|
@ -670,8 +686,7 @@ pub trait DeserializeSeed: Sized {
|
|||
|
||||
/// Equivalent to the more common `Deserialize::deserialize` method, except
|
||||
/// with some initial piece of data (the seed) passed in.
|
||||
fn deserialize<D>(self, deserializer: D) -> Result<Self::Value, D::Error>
|
||||
where D: Deserializer;
|
||||
fn deserialize<D>(self, deserializer: D) -> Result<Self::Value, D::Error> where D: Deserializer;
|
||||
}
|
||||
|
||||
impl<T> DeserializeSeed for PhantomData<T>
|
||||
|
@ -784,56 +799,43 @@ pub trait Deserializer: Sized {
|
|||
/// `Deserializer::deserialize` means your data type will be able to
|
||||
/// deserialize from self-describing formats only, ruling out Bincode and
|
||||
/// many others.
|
||||
fn deserialize<V>(self, visitor: V) -> Result<V::Value, Self::Error>
|
||||
where V: Visitor;
|
||||
fn deserialize<V>(self, visitor: V) -> Result<V::Value, Self::Error> where V: Visitor;
|
||||
|
||||
/// Hint that the `Deserialize` type is expecting a `bool` value.
|
||||
fn deserialize_bool<V>(self, visitor: V) -> Result<V::Value, Self::Error>
|
||||
where V: Visitor;
|
||||
fn deserialize_bool<V>(self, visitor: V) -> Result<V::Value, Self::Error> where V: Visitor;
|
||||
|
||||
/// Hint that the `Deserialize` type is expecting a `u8` value.
|
||||
fn deserialize_u8<V>(self, visitor: V) -> Result<V::Value, Self::Error>
|
||||
where V: Visitor;
|
||||
fn deserialize_u8<V>(self, visitor: V) -> Result<V::Value, Self::Error> where V: Visitor;
|
||||
|
||||
/// Hint that the `Deserialize` type is expecting a `u16` value.
|
||||
fn deserialize_u16<V>(self, visitor: V) -> Result<V::Value, Self::Error>
|
||||
where V: Visitor;
|
||||
fn deserialize_u16<V>(self, visitor: V) -> Result<V::Value, Self::Error> where V: Visitor;
|
||||
|
||||
/// Hint that the `Deserialize` type is expecting a `u32` value.
|
||||
fn deserialize_u32<V>(self, visitor: V) -> Result<V::Value, Self::Error>
|
||||
where V: Visitor;
|
||||
fn deserialize_u32<V>(self, visitor: V) -> Result<V::Value, Self::Error> where V: Visitor;
|
||||
|
||||
/// Hint that the `Deserialize` type is expecting a `u64` value.
|
||||
fn deserialize_u64<V>(self, visitor: V) -> Result<V::Value, Self::Error>
|
||||
where V: Visitor;
|
||||
fn deserialize_u64<V>(self, visitor: V) -> Result<V::Value, Self::Error> where V: Visitor;
|
||||
|
||||
/// Hint that the `Deserialize` type is expecting an `i8` value.
|
||||
fn deserialize_i8<V>(self, visitor: V) -> Result<V::Value, Self::Error>
|
||||
where V: Visitor;
|
||||
fn deserialize_i8<V>(self, visitor: V) -> Result<V::Value, Self::Error> where V: Visitor;
|
||||
|
||||
/// Hint that the `Deserialize` type is expecting an `i16` value.
|
||||
fn deserialize_i16<V>(self, visitor: V) -> Result<V::Value, Self::Error>
|
||||
where V: Visitor;
|
||||
fn deserialize_i16<V>(self, visitor: V) -> Result<V::Value, Self::Error> where V: Visitor;
|
||||
|
||||
/// Hint that the `Deserialize` type is expecting an `i32` value.
|
||||
fn deserialize_i32<V>(self, visitor: V) -> Result<V::Value, Self::Error>
|
||||
where V: Visitor;
|
||||
fn deserialize_i32<V>(self, visitor: V) -> Result<V::Value, Self::Error> where V: Visitor;
|
||||
|
||||
/// Hint that the `Deserialize` type is expecting an `i64` value.
|
||||
fn deserialize_i64<V>(self, visitor: V) -> Result<V::Value, Self::Error>
|
||||
where V: Visitor;
|
||||
fn deserialize_i64<V>(self, visitor: V) -> Result<V::Value, Self::Error> where V: Visitor;
|
||||
|
||||
/// Hint that the `Deserialize` type is expecting a `f32` value.
|
||||
fn deserialize_f32<V>(self, visitor: V) -> Result<V::Value, Self::Error>
|
||||
where V: Visitor;
|
||||
fn deserialize_f32<V>(self, visitor: V) -> Result<V::Value, Self::Error> where V: Visitor;
|
||||
|
||||
/// Hint that the `Deserialize` type is expecting a `f64` value.
|
||||
fn deserialize_f64<V>(self, visitor: V) -> Result<V::Value, Self::Error>
|
||||
where V: Visitor;
|
||||
fn deserialize_f64<V>(self, visitor: V) -> Result<V::Value, Self::Error> where V: Visitor;
|
||||
|
||||
/// Hint that the `Deserialize` type is expecting a `char` value.
|
||||
fn deserialize_char<V>(self, visitor: V) -> Result<V::Value, Self::Error>
|
||||
where V: Visitor;
|
||||
fn deserialize_char<V>(self, visitor: V) -> Result<V::Value, Self::Error> where V: Visitor;
|
||||
|
||||
/// Hint that the `Deserialize` type is expecting a string value and does
|
||||
/// not benefit from taking ownership of buffered data owned by the
|
||||
|
@ -842,8 +844,7 @@ pub trait Deserializer: Sized {
|
|||
/// If the `Visitor` would benefit from taking ownership of `String` data,
|
||||
/// indiciate this to the `Deserializer` by using `deserialize_string`
|
||||
/// instead.
|
||||
fn deserialize_str<V>(self, visitor: V) -> Result<V::Value, Self::Error>
|
||||
where V: Visitor;
|
||||
fn deserialize_str<V>(self, visitor: V) -> Result<V::Value, Self::Error> where V: Visitor;
|
||||
|
||||
/// Hint that the `Deserialize` type is expecting a string value and would
|
||||
/// benefit from taking ownership of buffered data owned by the
|
||||
|
@ -852,8 +853,7 @@ pub trait Deserializer: Sized {
|
|||
/// If the `Visitor` would not benefit from taking ownership of `String`
|
||||
/// data, indicate that to the `Deserializer` by using `deserialize_str`
|
||||
/// instead.
|
||||
fn deserialize_string<V>(self, visitor: V) -> Result<V::Value, Self::Error>
|
||||
where V: Visitor;
|
||||
fn deserialize_string<V>(self, visitor: V) -> Result<V::Value, Self::Error> where V: Visitor;
|
||||
|
||||
/// Hint that the `Deserialize` type is expecting a byte array and does not
|
||||
/// benefit from taking ownership of buffered data owned by the
|
||||
|
@ -862,8 +862,7 @@ pub trait Deserializer: Sized {
|
|||
/// If the `Visitor` would benefit from taking ownership of `Vec<u8>` data,
|
||||
/// indicate this to the `Deserializer` by using `deserialize_byte_buf`
|
||||
/// instead.
|
||||
fn deserialize_bytes<V>(self, visitor: V) -> Result<V::Value, Self::Error>
|
||||
where V: Visitor;
|
||||
fn deserialize_bytes<V>(self, visitor: V) -> Result<V::Value, Self::Error> where V: Visitor;
|
||||
|
||||
/// Hint that the `Deserialize` type is expecting a byte array and would
|
||||
/// benefit from taking ownership of buffered data owned by the
|
||||
|
@ -872,44 +871,43 @@ pub trait Deserializer: Sized {
|
|||
/// If the `Visitor` would not benefit from taking ownership of `Vec<u8>`
|
||||
/// data, indicate that to the `Deserializer` by using `deserialize_bytes`
|
||||
/// instead.
|
||||
fn deserialize_byte_buf<V>(self, visitor: V) -> Result<V::Value, Self::Error>
|
||||
where V: Visitor;
|
||||
fn deserialize_byte_buf<V>(self, visitor: V) -> Result<V::Value, Self::Error> where V: Visitor;
|
||||
|
||||
/// Hint that the `Deserialize` type is expecting an optional value.
|
||||
///
|
||||
/// This allows deserializers that encode an optional value as a nullable
|
||||
/// value to convert the null value into `None` and a regular value into
|
||||
/// `Some(value)`.
|
||||
fn deserialize_option<V>(self, visitor: V) -> Result<V::Value, Self::Error>
|
||||
where V: Visitor;
|
||||
fn deserialize_option<V>(self, visitor: V) -> Result<V::Value, Self::Error> where V: Visitor;
|
||||
|
||||
/// Hint that the `Deserialize` type is expecting a unit value.
|
||||
fn deserialize_unit<V>(self, visitor: V) -> Result<V::Value, Self::Error>
|
||||
where V: Visitor;
|
||||
fn deserialize_unit<V>(self, visitor: V) -> Result<V::Value, Self::Error> where V: Visitor;
|
||||
|
||||
/// Hint that the `Deserialize` type is expecting a unit struct with a
|
||||
/// particular name.
|
||||
fn deserialize_unit_struct<V>(self,
|
||||
name: &'static str,
|
||||
visitor: V) -> Result<V::Value, Self::Error>
|
||||
visitor: V)
|
||||
-> Result<V::Value, Self::Error>
|
||||
where V: Visitor;
|
||||
|
||||
/// Hint that the `Deserialize` type is expecting a newtype struct with a
|
||||
/// particular name.
|
||||
fn deserialize_newtype_struct<V>(self,
|
||||
name: &'static str,
|
||||
visitor: V) -> Result<V::Value, Self::Error>
|
||||
visitor: V)
|
||||
-> Result<V::Value, Self::Error>
|
||||
where V: Visitor;
|
||||
|
||||
/// Hint that the `Deserialize` type is expecting a sequence of values.
|
||||
fn deserialize_seq<V>(self, visitor: V) -> Result<V::Value, Self::Error>
|
||||
where V: Visitor;
|
||||
fn deserialize_seq<V>(self, visitor: V) -> Result<V::Value, Self::Error> where V: Visitor;
|
||||
|
||||
/// Hint that the `Deserialize` type is expecting a sequence of values and
|
||||
/// knows how many values there are without looking at the serialized data.
|
||||
fn deserialize_seq_fixed_size<V>(self,
|
||||
len: usize,
|
||||
visitor: V) -> Result<V::Value, Self::Error>
|
||||
visitor: V)
|
||||
-> Result<V::Value, Self::Error>
|
||||
where V: Visitor;
|
||||
|
||||
/// Hint that the `Deserialize` type is expecting a tuple value with a
|
||||
|
@ -922,19 +920,20 @@ pub trait Deserializer: Sized {
|
|||
fn deserialize_tuple_struct<V>(self,
|
||||
name: &'static str,
|
||||
len: usize,
|
||||
visitor: V) -> Result<V::Value, Self::Error>
|
||||
visitor: V)
|
||||
-> Result<V::Value, Self::Error>
|
||||
where V: Visitor;
|
||||
|
||||
/// Hint that the `Deserialize` type is expecting a map of key-value pairs.
|
||||
fn deserialize_map<V>(self, visitor: V) -> Result<V::Value, Self::Error>
|
||||
where V: Visitor;
|
||||
fn deserialize_map<V>(self, visitor: V) -> Result<V::Value, Self::Error> where V: Visitor;
|
||||
|
||||
/// Hint that the `Deserialize` type is expecting a struct with a particular
|
||||
/// name and fields.
|
||||
fn deserialize_struct<V>(self,
|
||||
name: &'static str,
|
||||
fields: &'static [&'static str],
|
||||
visitor: V) -> Result<V::Value, Self::Error>
|
||||
visitor: V)
|
||||
-> Result<V::Value, Self::Error>
|
||||
where V: Visitor;
|
||||
|
||||
/// Hint that the `Deserialize` type is expecting the name of a struct
|
||||
|
@ -947,7 +946,8 @@ pub trait Deserializer: Sized {
|
|||
fn deserialize_enum<V>(self,
|
||||
name: &'static str,
|
||||
variants: &'static [&'static str],
|
||||
visitor: V) -> Result<V::Value, Self::Error>
|
||||
visitor: V)
|
||||
-> Result<V::Value, Self::Error>
|
||||
where V: Visitor;
|
||||
|
||||
/// Hint that the `Deserialize` type needs to deserialize a value whose type
|
||||
|
@ -1016,77 +1016,77 @@ pub trait Visitor: Sized {
|
|||
|
||||
/// Deserialize a `bool` into a `Value`.
|
||||
fn visit_bool<E>(self, v: bool) -> Result<Self::Value, E>
|
||||
where E: Error,
|
||||
where E: Error
|
||||
{
|
||||
Err(Error::invalid_type(Unexpected::Bool(v), &self))
|
||||
}
|
||||
|
||||
/// Deserialize an `i8` into a `Value`.
|
||||
fn visit_i8<E>(self, v: i8) -> Result<Self::Value, E>
|
||||
where E: Error,
|
||||
where E: Error
|
||||
{
|
||||
self.visit_i64(v as i64)
|
||||
}
|
||||
|
||||
/// Deserialize an `i16` into a `Value`.
|
||||
fn visit_i16<E>(self, v: i16) -> Result<Self::Value, E>
|
||||
where E: Error,
|
||||
where E: Error
|
||||
{
|
||||
self.visit_i64(v as i64)
|
||||
}
|
||||
|
||||
/// Deserialize an `i32` into a `Value`.
|
||||
fn visit_i32<E>(self, v: i32) -> Result<Self::Value, E>
|
||||
where E: Error,
|
||||
where E: Error
|
||||
{
|
||||
self.visit_i64(v as i64)
|
||||
}
|
||||
|
||||
/// Deserialize an `i64` into a `Value`.
|
||||
fn visit_i64<E>(self, v: i64) -> Result<Self::Value, E>
|
||||
where E: Error,
|
||||
where E: Error
|
||||
{
|
||||
Err(Error::invalid_type(Unexpected::Signed(v), &self))
|
||||
}
|
||||
|
||||
/// Deserialize a `u8` into a `Value`.
|
||||
fn visit_u8<E>(self, v: u8) -> Result<Self::Value, E>
|
||||
where E: Error,
|
||||
where E: Error
|
||||
{
|
||||
self.visit_u64(v as u64)
|
||||
}
|
||||
|
||||
/// Deserialize a `u16` into a `Value`.
|
||||
fn visit_u16<E>(self, v: u16) -> Result<Self::Value, E>
|
||||
where E: Error,
|
||||
where E: Error
|
||||
{
|
||||
self.visit_u64(v as u64)
|
||||
}
|
||||
|
||||
/// Deserialize a `u32` into a `Value`.
|
||||
fn visit_u32<E>(self, v: u32) -> Result<Self::Value, E>
|
||||
where E: Error,
|
||||
where E: Error
|
||||
{
|
||||
self.visit_u64(v as u64)
|
||||
}
|
||||
|
||||
/// Deserialize a `u64` into a `Value`.
|
||||
fn visit_u64<E>(self, v: u64) -> Result<Self::Value, E>
|
||||
where E: Error,
|
||||
where E: Error
|
||||
{
|
||||
Err(Error::invalid_type(Unexpected::Unsigned(v), &self))
|
||||
}
|
||||
|
||||
/// Deserialize a `f32` into a `Value`.
|
||||
fn visit_f32<E>(self, v: f32) -> Result<Self::Value, E>
|
||||
where E: Error,
|
||||
where E: Error
|
||||
{
|
||||
self.visit_f64(v as f64)
|
||||
}
|
||||
|
||||
/// Deserialize a `f64` into a `Value`.
|
||||
fn visit_f64<E>(self, v: f64) -> Result<Self::Value, E>
|
||||
where E: Error,
|
||||
where E: Error
|
||||
{
|
||||
Err(Error::invalid_type(Unexpected::Float(v), &self))
|
||||
}
|
||||
|
@ -1094,7 +1094,7 @@ pub trait Visitor: Sized {
|
|||
/// Deserialize a `char` into a `Value`.
|
||||
#[inline]
|
||||
fn visit_char<E>(self, v: char) -> Result<Self::Value, E>
|
||||
where E: Error,
|
||||
where E: Error
|
||||
{
|
||||
self.visit_str(::utils::encode_utf8(v).as_str())
|
||||
}
|
||||
|
@ -1110,7 +1110,7 @@ pub trait Visitor: Sized {
|
|||
/// It is never correct to implement `visit_string` without implementing
|
||||
/// `visit_str`. Implement neither, both, or just `visit_str`.
|
||||
fn visit_str<E>(self, v: &str) -> Result<Self::Value, E>
|
||||
where E: Error,
|
||||
where E: Error
|
||||
{
|
||||
Err(Error::invalid_type(Unexpected::Str(v), &self))
|
||||
}
|
||||
|
@ -1132,28 +1132,28 @@ pub trait Visitor: Sized {
|
|||
#[inline]
|
||||
#[cfg(any(feature = "std", feature = "collections"))]
|
||||
fn visit_string<E>(self, v: String) -> Result<Self::Value, E>
|
||||
where E: Error,
|
||||
where E: Error
|
||||
{
|
||||
self.visit_str(&v)
|
||||
}
|
||||
|
||||
/// Deserialize a `()` into a `Value`.
|
||||
fn visit_unit<E>(self) -> Result<Self::Value, E>
|
||||
where E: Error,
|
||||
where E: Error
|
||||
{
|
||||
Err(Error::invalid_type(Unexpected::Unit, &self))
|
||||
}
|
||||
|
||||
/// Deserialize an absent optional `Value`.
|
||||
fn visit_none<E>(self) -> Result<Self::Value, E>
|
||||
where E: Error,
|
||||
where E: Error
|
||||
{
|
||||
Err(Error::invalid_type(Unexpected::Option, &self))
|
||||
}
|
||||
|
||||
/// Deserialize a present optional `Value`.
|
||||
fn visit_some<D>(self, deserializer: D) -> Result<Self::Value, D::Error>
|
||||
where D: Deserializer,
|
||||
where D: Deserializer
|
||||
{
|
||||
let _ = deserializer;
|
||||
Err(Error::invalid_type(Unexpected::Option, &self))
|
||||
|
@ -1161,7 +1161,7 @@ pub trait Visitor: Sized {
|
|||
|
||||
/// Deserialize `Value` as a newtype struct.
|
||||
fn visit_newtype_struct<D>(self, deserializer: D) -> Result<Self::Value, D::Error>
|
||||
where D: Deserializer,
|
||||
where D: Deserializer
|
||||
{
|
||||
let _ = deserializer;
|
||||
Err(Error::invalid_type(Unexpected::NewtypeStruct, &self))
|
||||
|
@ -1169,7 +1169,7 @@ pub trait Visitor: Sized {
|
|||
|
||||
/// Deserialize `Value` as a sequence of elements.
|
||||
fn visit_seq<V>(self, visitor: V) -> Result<Self::Value, V::Error>
|
||||
where V: SeqVisitor,
|
||||
where V: SeqVisitor
|
||||
{
|
||||
let _ = visitor;
|
||||
Err(Error::invalid_type(Unexpected::Seq, &self))
|
||||
|
@ -1177,7 +1177,7 @@ pub trait Visitor: Sized {
|
|||
|
||||
/// Deserialize `Value` as a key-value map.
|
||||
fn visit_map<V>(self, visitor: V) -> Result<Self::Value, V::Error>
|
||||
where V: MapVisitor,
|
||||
where V: MapVisitor
|
||||
{
|
||||
let _ = visitor;
|
||||
Err(Error::invalid_type(Unexpected::Map, &self))
|
||||
|
@ -1185,7 +1185,7 @@ pub trait Visitor: Sized {
|
|||
|
||||
/// Deserialize `Value` as an enum.
|
||||
fn visit_enum<V>(self, visitor: V) -> Result<Self::Value, V::Error>
|
||||
where V: EnumVisitor,
|
||||
where V: EnumVisitor
|
||||
{
|
||||
let _ = visitor;
|
||||
Err(Error::invalid_type(Unexpected::Enum, &self))
|
||||
|
@ -1202,7 +1202,7 @@ pub trait Visitor: Sized {
|
|||
/// It is never correct to implement `visit_byte_buf` without implementing
|
||||
/// `visit_bytes`. Implement neither, both, or just `visit_bytes`.
|
||||
fn visit_bytes<E>(self, v: &[u8]) -> Result<Self::Value, E>
|
||||
where E: Error,
|
||||
where E: Error
|
||||
{
|
||||
let _ = v;
|
||||
Err(Error::invalid_type(Unexpected::Bytes(v), &self))
|
||||
|
@ -1225,7 +1225,7 @@ pub trait Visitor: Sized {
|
|||
/// `Vec<u8>`.
|
||||
#[cfg(any(feature = "std", feature = "collections"))]
|
||||
fn visit_byte_buf<E>(self, v: Vec<u8>) -> Result<Self::Value, E>
|
||||
where E: Error,
|
||||
where E: Error
|
||||
{
|
||||
self.visit_bytes(&v)
|
||||
}
|
||||
|
@ -1269,7 +1269,9 @@ pub trait SeqVisitor {
|
|||
}
|
||||
}
|
||||
|
||||
impl<'a, V> SeqVisitor for &'a mut V where V: SeqVisitor {
|
||||
impl<'a, V> SeqVisitor for &'a mut V
|
||||
where V: SeqVisitor
|
||||
{
|
||||
type Error = V::Error;
|
||||
|
||||
#[inline]
|
||||
|
@ -1326,7 +1328,10 @@ pub trait MapVisitor {
|
|||
/// `Deserialize` implementations should typically use `MapVisitor::visit`
|
||||
/// instead.
|
||||
#[inline]
|
||||
fn visit_seed<K, V>(&mut self, kseed: K, vseed: V) -> Result<Option<(K::Value, V::Value)>, Self::Error>
|
||||
fn visit_seed<K, V>(&mut self,
|
||||
kseed: K,
|
||||
vseed: V)
|
||||
-> Result<Option<(K::Value, V::Value)>, Self::Error>
|
||||
where K: DeserializeSeed,
|
||||
V: DeserializeSeed
|
||||
{
|
||||
|
@ -1335,7 +1340,7 @@ pub trait MapVisitor {
|
|||
let value = try!(self.visit_value_seed(vseed));
|
||||
Ok(Some((key, value)))
|
||||
}
|
||||
None => Ok(None)
|
||||
None => Ok(None),
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1370,7 +1375,7 @@ pub trait MapVisitor {
|
|||
#[inline]
|
||||
fn visit<K, V>(&mut self) -> Result<Option<(K, V)>, Self::Error>
|
||||
where K: Deserialize,
|
||||
V: Deserialize,
|
||||
V: Deserialize
|
||||
{
|
||||
self.visit_seed(PhantomData, PhantomData)
|
||||
}
|
||||
|
@ -1382,7 +1387,9 @@ pub trait MapVisitor {
|
|||
}
|
||||
}
|
||||
|
||||
impl<'a, V_> MapVisitor for &'a mut V_ where V_: MapVisitor {
|
||||
impl<'a, V_> MapVisitor for &'a mut V_
|
||||
where V_: MapVisitor
|
||||
{
|
||||
type Error = V_::Error;
|
||||
|
||||
#[inline]
|
||||
|
@ -1400,7 +1407,10 @@ impl<'a, V_> MapVisitor for &'a mut V_ where V_: MapVisitor {
|
|||
}
|
||||
|
||||
#[inline]
|
||||
fn visit_seed<K, V>(&mut self, kseed: K, vseed: V) -> Result<Option<(K::Value, V::Value)>, Self::Error>
|
||||
fn visit_seed<K, V>(&mut self,
|
||||
kseed: K,
|
||||
vseed: V)
|
||||
-> Result<Option<(K::Value, V::Value)>, Self::Error>
|
||||
where K: DeserializeSeed,
|
||||
V: DeserializeSeed
|
||||
{
|
||||
|
@ -1410,7 +1420,7 @@ impl<'a, V_> MapVisitor for &'a mut V_ where V_: MapVisitor {
|
|||
#[inline]
|
||||
fn visit<K, V>(&mut self) -> Result<Option<(K, V)>, V_::Error>
|
||||
where K: Deserialize,
|
||||
V: Deserialize,
|
||||
V: Deserialize
|
||||
{
|
||||
(**self).visit()
|
||||
}
|
||||
|
@ -1446,7 +1456,7 @@ pub trait EnumVisitor: Sized {
|
|||
type Error: Error;
|
||||
/// The `Visitor` that will be used to deserialize the content of the enum
|
||||
/// variant.
|
||||
type Variant: VariantVisitor<Error=Self::Error>;
|
||||
type Variant: VariantVisitor<Error = Self::Error>;
|
||||
|
||||
/// `visit_variant` is called to identify which variant to deserialize.
|
||||
///
|
||||
|
@ -1539,9 +1549,7 @@ pub trait VariantVisitor: Sized {
|
|||
/// Err(Error::invalid_type(unexp, &"tuple variant"))
|
||||
/// }
|
||||
/// ```
|
||||
fn visit_tuple<V>(self,
|
||||
len: usize,
|
||||
visitor: V) -> Result<V::Value, Self::Error>
|
||||
fn visit_tuple<V>(self, len: usize, visitor: V) -> Result<V::Value, Self::Error>
|
||||
where V: Visitor;
|
||||
|
||||
/// Called when deserializing a struct-like variant.
|
||||
|
@ -1564,7 +1572,8 @@ pub trait VariantVisitor: Sized {
|
|||
/// ```
|
||||
fn visit_struct<V>(self,
|
||||
fields: &'static [&'static str],
|
||||
visitor: V) -> Result<V::Value, Self::Error>
|
||||
visitor: V)
|
||||
-> Result<V::Value, Self::Error>
|
||||
where V: Visitor;
|
||||
}
|
||||
|
||||
|
|
|
@ -3,14 +3,9 @@ use core::marker::PhantomData;
|
|||
use de::{Deserialize, Deserializer, Error, Visitor};
|
||||
|
||||
#[cfg(any(feature = "std", feature = "collections"))]
|
||||
pub use de::content::{
|
||||
Content,
|
||||
ContentRefDeserializer,
|
||||
ContentDeserializer,
|
||||
TaggedContentVisitor,
|
||||
InternallyTaggedUnitVisitor,
|
||||
UntaggedUnitVisitor,
|
||||
};
|
||||
pub use de::content::{Content, ContentRefDeserializer, ContentDeserializer, TaggedContentVisitor,
|
||||
TagOrContentField, TagOrContentFieldVisitor, InternallyTaggedUnitVisitor,
|
||||
UntaggedUnitVisitor};
|
||||
|
||||
/// If the missing field is of type `Option<T>` then treat is as `None`,
|
||||
/// otherwise it is an error.
|
||||
|
|
|
@ -1,31 +1,15 @@
|
|||
//! This module supports deserializing from primitives with the `ValueDeserializer` trait.
|
||||
|
||||
#[cfg(feature = "std")]
|
||||
use std::collections::{
|
||||
BTreeMap,
|
||||
BTreeSet,
|
||||
HashMap,
|
||||
HashSet,
|
||||
btree_map,
|
||||
btree_set,
|
||||
hash_map,
|
||||
hash_set,
|
||||
};
|
||||
use std::collections::{BTreeMap, BTreeSet, HashMap, HashSet, btree_map, btree_set, hash_map,
|
||||
hash_set};
|
||||
#[cfg(feature = "std")]
|
||||
use std::borrow::Cow;
|
||||
#[cfg(feature = "std")]
|
||||
use std::vec;
|
||||
|
||||
#[cfg(all(feature = "collections", not(feature = "std")))]
|
||||
use collections::{
|
||||
BTreeMap,
|
||||
BTreeSet,
|
||||
Vec,
|
||||
String,
|
||||
btree_map,
|
||||
btree_set,
|
||||
vec,
|
||||
};
|
||||
use collections::{BTreeMap, BTreeSet, Vec, String, btree_map, btree_set, vec};
|
||||
#[cfg(all(feature = "collections", not(feature = "std")))]
|
||||
use collections::borrow::Cow;
|
||||
#[cfg(all(feature = "collections", not(feature = "std")))]
|
||||
|
@ -41,7 +25,7 @@ use std::error;
|
|||
use error;
|
||||
|
||||
use core::fmt::{self, Display};
|
||||
use core::iter::{self, Iterator};
|
||||
use core::iter::{self, Iterator};
|
||||
use core::marker::PhantomData;
|
||||
|
||||
use de::{self, Expected, SeqVisitor};
|
||||
|
@ -63,16 +47,12 @@ type ErrorImpl = ();
|
|||
impl de::Error for Error {
|
||||
#[cfg(any(feature = "std", feature = "collections"))]
|
||||
fn custom<T: Display>(msg: T) -> Self {
|
||||
Error {
|
||||
err: msg.to_string().into_boxed_str(),
|
||||
}
|
||||
Error { err: msg.to_string().into_boxed_str() }
|
||||
}
|
||||
|
||||
#[cfg(not(any(feature = "std", feature = "collections")))]
|
||||
fn custom<T: Display>(_msg: T) -> Self {
|
||||
Error {
|
||||
err: (),
|
||||
}
|
||||
Error { err: () }
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -105,7 +85,7 @@ impl error::Error for Error {
|
|||
/// This trait converts primitive types into a deserializer.
|
||||
pub trait ValueDeserializer<E: de::Error = Error> {
|
||||
/// The actual deserializer type.
|
||||
type Deserializer: de::Deserializer<Error=E>;
|
||||
type Deserializer: de::Deserializer<Error = E>;
|
||||
|
||||
/// Convert this value into a deserializer.
|
||||
fn into_deserializer(self) -> Self::Deserializer;
|
||||
|
@ -114,14 +94,12 @@ pub trait ValueDeserializer<E: de::Error = Error> {
|
|||
///////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
impl<E> ValueDeserializer<E> for ()
|
||||
where E: de::Error,
|
||||
where E: de::Error
|
||||
{
|
||||
type Deserializer = UnitDeserializer<E>;
|
||||
|
||||
fn into_deserializer(self) -> UnitDeserializer<E> {
|
||||
UnitDeserializer {
|
||||
marker: PhantomData,
|
||||
}
|
||||
UnitDeserializer { marker: PhantomData }
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -142,13 +120,13 @@ impl<E> de::Deserializer for UnitDeserializer<E>
|
|||
}
|
||||
|
||||
fn deserialize<V>(self, visitor: V) -> Result<V::Value, Self::Error>
|
||||
where V: de::Visitor,
|
||||
where V: de::Visitor
|
||||
{
|
||||
visitor.visit_unit()
|
||||
}
|
||||
|
||||
fn deserialize_option<V>(self, visitor: V) -> Result<V::Value, Self::Error>
|
||||
where V: de::Visitor,
|
||||
where V: de::Visitor
|
||||
{
|
||||
visitor.visit_none()
|
||||
}
|
||||
|
@ -221,7 +199,7 @@ pub struct StrDeserializer<'a, E> {
|
|||
}
|
||||
|
||||
impl<'a, E> ValueDeserializer<E> for &'a str
|
||||
where E: de::Error,
|
||||
where E: de::Error
|
||||
{
|
||||
type Deserializer = StrDeserializer<'a, E>;
|
||||
|
||||
|
@ -234,21 +212,22 @@ impl<'a, E> ValueDeserializer<E> for &'a str
|
|||
}
|
||||
|
||||
impl<'a, E> de::Deserializer for StrDeserializer<'a, E>
|
||||
where E: de::Error,
|
||||
where E: de::Error
|
||||
{
|
||||
type Error = E;
|
||||
|
||||
fn deserialize<V>(self, visitor: V) -> Result<V::Value, Self::Error>
|
||||
where V: de::Visitor,
|
||||
where V: de::Visitor
|
||||
{
|
||||
visitor.visit_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,
|
||||
_name: &str,
|
||||
_variants: &'static [&'static str],
|
||||
visitor: V)
|
||||
-> Result<V::Value, Self::Error>
|
||||
where V: de::Visitor
|
||||
{
|
||||
visitor.visit_enum(self)
|
||||
}
|
||||
|
@ -261,13 +240,13 @@ impl<'a, E> de::Deserializer for StrDeserializer<'a, E>
|
|||
}
|
||||
|
||||
impl<'a, E> de::EnumVisitor for StrDeserializer<'a, E>
|
||||
where E: de::Error,
|
||||
where E: de::Error
|
||||
{
|
||||
type Error = E;
|
||||
type Variant = private::UnitOnly<E>;
|
||||
|
||||
fn visit_variant_seed<T>(self, seed: T) -> Result<(T::Value, Self::Variant), Self::Error>
|
||||
where T: de::DeserializeSeed,
|
||||
where T: de::DeserializeSeed
|
||||
{
|
||||
seed.deserialize(self).map(private::unit_only)
|
||||
}
|
||||
|
@ -284,7 +263,7 @@ pub struct StringDeserializer<E> {
|
|||
|
||||
#[cfg(any(feature = "std", feature = "collections"))]
|
||||
impl<E> ValueDeserializer<E> for String
|
||||
where E: de::Error,
|
||||
where E: de::Error
|
||||
{
|
||||
type Deserializer = StringDeserializer<E>;
|
||||
|
||||
|
@ -298,21 +277,22 @@ impl<E> ValueDeserializer<E> for String
|
|||
|
||||
#[cfg(any(feature = "std", feature = "collections"))]
|
||||
impl<E> de::Deserializer for StringDeserializer<E>
|
||||
where E: de::Error,
|
||||
where E: de::Error
|
||||
{
|
||||
type Error = E;
|
||||
|
||||
fn deserialize<V>(self, visitor: V) -> Result<V::Value, Self::Error>
|
||||
where V: de::Visitor,
|
||||
where V: de::Visitor
|
||||
{
|
||||
visitor.visit_string(self.value)
|
||||
}
|
||||
|
||||
fn deserialize_enum<V>(self,
|
||||
_name: &str,
|
||||
_variants: &'static [&'static str],
|
||||
visitor: V) -> Result<V::Value, Self::Error>
|
||||
where V: de::Visitor,
|
||||
_name: &str,
|
||||
_variants: &'static [&'static str],
|
||||
visitor: V)
|
||||
-> Result<V::Value, Self::Error>
|
||||
where V: de::Visitor
|
||||
{
|
||||
visitor.visit_enum(self)
|
||||
}
|
||||
|
@ -326,13 +306,13 @@ impl<E> de::Deserializer for StringDeserializer<E>
|
|||
|
||||
#[cfg(any(feature = "std", feature = "collections"))]
|
||||
impl<'a, E> de::EnumVisitor for StringDeserializer<E>
|
||||
where E: de::Error,
|
||||
where E: de::Error
|
||||
{
|
||||
type Error = E;
|
||||
type Variant = private::UnitOnly<E>;
|
||||
|
||||
fn visit_variant_seed<T>(self, seed: T) -> Result<(T::Value, Self::Variant), Self::Error>
|
||||
where T: de::DeserializeSeed,
|
||||
where T: de::DeserializeSeed
|
||||
{
|
||||
seed.deserialize(self).map(private::unit_only)
|
||||
}
|
||||
|
@ -349,7 +329,7 @@ pub struct CowStrDeserializer<'a, E> {
|
|||
|
||||
#[cfg(any(feature = "std", feature = "collections"))]
|
||||
impl<'a, E> ValueDeserializer<E> for Cow<'a, str>
|
||||
where E: de::Error,
|
||||
where E: de::Error
|
||||
{
|
||||
type Deserializer = CowStrDeserializer<'a, E>;
|
||||
|
||||
|
@ -363,12 +343,12 @@ impl<'a, E> ValueDeserializer<E> for Cow<'a, str>
|
|||
|
||||
#[cfg(any(feature = "std", feature = "collections"))]
|
||||
impl<'a, E> de::Deserializer for CowStrDeserializer<'a, E>
|
||||
where E: de::Error,
|
||||
where E: de::Error
|
||||
{
|
||||
type Error = E;
|
||||
|
||||
fn deserialize<V>(self, visitor: V) -> Result<V::Value, Self::Error>
|
||||
where V: de::Visitor,
|
||||
where V: de::Visitor
|
||||
{
|
||||
match self.value {
|
||||
Cow::Borrowed(string) => visitor.visit_str(string),
|
||||
|
@ -377,10 +357,11 @@ impl<'a, E> de::Deserializer for CowStrDeserializer<'a, E>
|
|||
}
|
||||
|
||||
fn deserialize_enum<V>(self,
|
||||
_name: &str,
|
||||
_variants: &'static [&'static str],
|
||||
visitor: V) -> Result<V::Value, Self::Error>
|
||||
where V: de::Visitor,
|
||||
_name: &str,
|
||||
_variants: &'static [&'static str],
|
||||
visitor: V)
|
||||
-> Result<V::Value, Self::Error>
|
||||
where V: de::Visitor
|
||||
{
|
||||
visitor.visit_enum(self)
|
||||
}
|
||||
|
@ -394,13 +375,13 @@ impl<'a, E> de::Deserializer for CowStrDeserializer<'a, E>
|
|||
|
||||
#[cfg(any(feature = "std", feature = "collections"))]
|
||||
impl<'a, E> de::EnumVisitor for CowStrDeserializer<'a, E>
|
||||
where E: de::Error,
|
||||
where E: de::Error
|
||||
{
|
||||
type Error = E;
|
||||
type Variant = private::UnitOnly<E>;
|
||||
|
||||
fn visit_variant_seed<T>(self, seed: T) -> Result<(T::Value, Self::Variant), Self::Error>
|
||||
where T: de::DeserializeSeed,
|
||||
where T: de::DeserializeSeed
|
||||
{
|
||||
seed.deserialize(self).map(private::unit_only)
|
||||
}
|
||||
|
@ -417,7 +398,7 @@ pub struct SeqDeserializer<I, E> {
|
|||
|
||||
impl<I, E> SeqDeserializer<I, E>
|
||||
where I: Iterator,
|
||||
E: de::Error,
|
||||
E: de::Error
|
||||
{
|
||||
/// Construct a new `SeqDeserializer<I>`.
|
||||
pub fn new(iter: I) -> Self {
|
||||
|
@ -446,14 +427,14 @@ impl<I, E> SeqDeserializer<I, E>
|
|||
}
|
||||
|
||||
impl<I, T, E> de::Deserializer for SeqDeserializer<I, E>
|
||||
where I: Iterator<Item=T>,
|
||||
where I: Iterator<Item = T>,
|
||||
T: ValueDeserializer<E>,
|
||||
E: de::Error,
|
||||
E: de::Error
|
||||
{
|
||||
type Error = E;
|
||||
|
||||
fn deserialize<V>(mut self, visitor: V) -> Result<V::Value, Self::Error>
|
||||
where V: de::Visitor,
|
||||
where V: de::Visitor
|
||||
{
|
||||
let v = try!(visitor.visit_seq(&mut self));
|
||||
try!(self.end());
|
||||
|
@ -468,9 +449,9 @@ impl<I, T, E> de::Deserializer for SeqDeserializer<I, E>
|
|||
}
|
||||
|
||||
impl<I, T, E> de::SeqVisitor for SeqDeserializer<I, E>
|
||||
where I: Iterator<Item=T>,
|
||||
where I: Iterator<Item = T>,
|
||||
T: ValueDeserializer<E>,
|
||||
E: de::Error,
|
||||
E: de::Error
|
||||
{
|
||||
type Error = E;
|
||||
|
||||
|
@ -508,7 +489,7 @@ impl Expected for ExpectedInSeq {
|
|||
#[cfg(any(feature = "std", feature = "collections"))]
|
||||
impl<T, E> ValueDeserializer<E> for Vec<T>
|
||||
where T: ValueDeserializer<E>,
|
||||
E: de::Error,
|
||||
E: de::Error
|
||||
{
|
||||
type Deserializer = SeqDeserializer<vec::IntoIter<T>, E>;
|
||||
|
||||
|
@ -520,7 +501,7 @@ impl<T, E> ValueDeserializer<E> for Vec<T>
|
|||
#[cfg(any(feature = "std", feature = "collections"))]
|
||||
impl<T, E> ValueDeserializer<E> for BTreeSet<T>
|
||||
where T: ValueDeserializer<E> + Eq + Ord,
|
||||
E: de::Error,
|
||||
E: de::Error
|
||||
{
|
||||
type Deserializer = SeqDeserializer<btree_set::IntoIter<T>, E>;
|
||||
|
||||
|
@ -532,7 +513,7 @@ impl<T, E> ValueDeserializer<E> for BTreeSet<T>
|
|||
#[cfg(feature = "std")]
|
||||
impl<T, E> ValueDeserializer<E> for HashSet<T>
|
||||
where T: ValueDeserializer<E> + Eq + Hash,
|
||||
E: de::Error,
|
||||
E: de::Error
|
||||
{
|
||||
type Deserializer = SeqDeserializer<hash_set::IntoIter<T>, E>;
|
||||
|
||||
|
@ -551,20 +532,20 @@ pub struct SeqVisitorDeserializer<V_, E> {
|
|||
|
||||
impl<V_, E> SeqVisitorDeserializer<V_, E>
|
||||
where V_: de::SeqVisitor<Error = E>,
|
||||
E: de::Error,
|
||||
E: de::Error
|
||||
{
|
||||
/// Construct a new `SeqVisitorDeserializer<V_, E>`.
|
||||
pub fn new(visitor: V_) -> Self {
|
||||
SeqVisitorDeserializer{
|
||||
SeqVisitorDeserializer {
|
||||
visitor: visitor,
|
||||
marker: PhantomData
|
||||
marker: PhantomData,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl<V_, E> de::Deserializer for SeqVisitorDeserializer<V_, E>
|
||||
where V_: de::SeqVisitor<Error = E>,
|
||||
E: de::Error,
|
||||
E: de::Error
|
||||
{
|
||||
type Error = E;
|
||||
|
||||
|
@ -587,7 +568,7 @@ pub struct MapDeserializer<I, E>
|
|||
I::Item: private::Pair,
|
||||
<I::Item as private::Pair>::First: ValueDeserializer<E>,
|
||||
<I::Item as private::Pair>::Second: ValueDeserializer<E>,
|
||||
E: de::Error,
|
||||
E: de::Error
|
||||
{
|
||||
iter: iter::Fuse<I>,
|
||||
value: Option<<I::Item as private::Pair>::Second>,
|
||||
|
@ -600,7 +581,7 @@ impl<I, E> MapDeserializer<I, E>
|
|||
I::Item: private::Pair,
|
||||
<I::Item as private::Pair>::First: ValueDeserializer<E>,
|
||||
<I::Item as private::Pair>::Second: ValueDeserializer<E>,
|
||||
E: de::Error,
|
||||
E: de::Error
|
||||
{
|
||||
/// Construct a new `MapDeserializer<I, K, V, E>`.
|
||||
pub fn new(iter: I) -> Self {
|
||||
|
@ -628,7 +609,9 @@ impl<I, E> MapDeserializer<I, E>
|
|||
}
|
||||
}
|
||||
|
||||
fn next_pair(&mut self) -> Option<(<I::Item as private::Pair>::First, <I::Item as private::Pair>::Second)> {
|
||||
fn next_pair
|
||||
(&mut self)
|
||||
-> Option<(<I::Item as private::Pair>::First, <I::Item as private::Pair>::Second)> {
|
||||
match self.iter.next() {
|
||||
Some(kv) => {
|
||||
self.count += 1;
|
||||
|
@ -644,12 +627,12 @@ impl<I, E> de::Deserializer for MapDeserializer<I, E>
|
|||
I::Item: private::Pair,
|
||||
<I::Item as private::Pair>::First: ValueDeserializer<E>,
|
||||
<I::Item as private::Pair>::Second: ValueDeserializer<E>,
|
||||
E: de::Error,
|
||||
E: de::Error
|
||||
{
|
||||
type Error = E;
|
||||
|
||||
fn deserialize<V_>(mut self, visitor: V_) -> Result<V_::Value, Self::Error>
|
||||
where V_: de::Visitor,
|
||||
where V_: de::Visitor
|
||||
{
|
||||
let value = try!(visitor.visit_map(&mut self));
|
||||
try!(self.end());
|
||||
|
@ -657,15 +640,18 @@ impl<I, E> de::Deserializer for MapDeserializer<I, E>
|
|||
}
|
||||
|
||||
fn deserialize_seq<V_>(mut self, visitor: V_) -> Result<V_::Value, Self::Error>
|
||||
where V_: de::Visitor,
|
||||
where V_: de::Visitor
|
||||
{
|
||||
let value = try!(visitor.visit_seq(&mut self));
|
||||
try!(self.end());
|
||||
Ok(value)
|
||||
}
|
||||
|
||||
fn deserialize_seq_fixed_size<V_>(self, _len: usize, visitor: V_) -> Result<V_::Value, Self::Error>
|
||||
where V_: de::Visitor,
|
||||
fn deserialize_seq_fixed_size<V_>(self,
|
||||
_len: usize,
|
||||
visitor: V_)
|
||||
-> Result<V_::Value, Self::Error>
|
||||
where V_: de::Visitor
|
||||
{
|
||||
self.deserialize_seq(visitor)
|
||||
}
|
||||
|
@ -682,12 +668,12 @@ impl<I, E> de::MapVisitor for MapDeserializer<I, E>
|
|||
I::Item: private::Pair,
|
||||
<I::Item as private::Pair>::First: ValueDeserializer<E>,
|
||||
<I::Item as private::Pair>::Second: ValueDeserializer<E>,
|
||||
E: de::Error,
|
||||
E: de::Error
|
||||
{
|
||||
type Error = E;
|
||||
|
||||
fn visit_key_seed<T>(&mut self, seed: T) -> Result<Option<T::Value>, Self::Error>
|
||||
where T: de::DeserializeSeed,
|
||||
where T: de::DeserializeSeed
|
||||
{
|
||||
match self.next_pair() {
|
||||
Some((key, value)) => {
|
||||
|
@ -699,7 +685,7 @@ impl<I, E> de::MapVisitor for MapDeserializer<I, E>
|
|||
}
|
||||
|
||||
fn visit_value_seed<T>(&mut self, seed: T) -> Result<T::Value, Self::Error>
|
||||
where T: de::DeserializeSeed,
|
||||
where T: de::DeserializeSeed
|
||||
{
|
||||
let value = self.value.take();
|
||||
// Panic because this indicates a bug in the program rather than an
|
||||
|
@ -708,7 +694,10 @@ impl<I, E> de::MapVisitor for MapDeserializer<I, E>
|
|||
seed.deserialize(value.into_deserializer())
|
||||
}
|
||||
|
||||
fn visit_seed<TK, TV>(&mut self, kseed: TK, vseed: TV) -> Result<Option<(TK::Value, TV::Value)>, Self::Error>
|
||||
fn visit_seed<TK, TV>(&mut self,
|
||||
kseed: TK,
|
||||
vseed: TV)
|
||||
-> Result<Option<(TK::Value, TV::Value)>, Self::Error>
|
||||
where TK: de::DeserializeSeed,
|
||||
TV: de::DeserializeSeed
|
||||
{
|
||||
|
@ -718,7 +707,7 @@ impl<I, E> de::MapVisitor for MapDeserializer<I, E>
|
|||
let value = try!(vseed.deserialize(value.into_deserializer()));
|
||||
Ok(Some((key, value)))
|
||||
}
|
||||
None => Ok(None)
|
||||
None => Ok(None),
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -732,12 +721,12 @@ impl<I, E> de::SeqVisitor for MapDeserializer<I, E>
|
|||
I::Item: private::Pair,
|
||||
<I::Item as private::Pair>::First: ValueDeserializer<E>,
|
||||
<I::Item as private::Pair>::Second: ValueDeserializer<E>,
|
||||
E: de::Error,
|
||||
E: de::Error
|
||||
{
|
||||
type Error = E;
|
||||
|
||||
fn visit_seed<T>(&mut self, seed: T) -> Result<Option<T::Value>, Self::Error>
|
||||
where T: de::DeserializeSeed,
|
||||
where T: de::DeserializeSeed
|
||||
{
|
||||
match self.next_pair() {
|
||||
Some((k, v)) => {
|
||||
|
@ -771,13 +760,13 @@ impl<A, B, E> de::Deserializer for PairDeserializer<A, B, E>
|
|||
}
|
||||
|
||||
fn deserialize<V>(self, visitor: V) -> Result<V::Value, Self::Error>
|
||||
where V: de::Visitor,
|
||||
where V: de::Visitor
|
||||
{
|
||||
self.deserialize_seq(visitor)
|
||||
}
|
||||
|
||||
fn deserialize_seq<V>(self, visitor: V) -> Result<V::Value, Self::Error>
|
||||
where V: de::Visitor,
|
||||
where V: de::Visitor
|
||||
{
|
||||
let mut pair_visitor = PairVisitor(Some(self.0), Some(self.1), PhantomData);
|
||||
let pair = try!(visitor.visit_seq(&mut pair_visitor));
|
||||
|
@ -792,7 +781,7 @@ impl<A, B, E> de::Deserializer for PairDeserializer<A, B, E>
|
|||
}
|
||||
|
||||
fn deserialize_seq_fixed_size<V>(self, len: usize, visitor: V) -> Result<V::Value, Self::Error>
|
||||
where V: de::Visitor,
|
||||
where V: de::Visitor
|
||||
{
|
||||
if len == 2 {
|
||||
self.deserialize_seq(visitor)
|
||||
|
@ -809,12 +798,12 @@ struct PairVisitor<A, B, E>(Option<A>, Option<B>, PhantomData<E>);
|
|||
impl<A, B, E> de::SeqVisitor for PairVisitor<A, B, E>
|
||||
where A: ValueDeserializer<E>,
|
||||
B: ValueDeserializer<E>,
|
||||
E: de::Error,
|
||||
E: de::Error
|
||||
{
|
||||
type Error = E;
|
||||
|
||||
fn visit_seed<T>(&mut self, seed: T) -> Result<Option<T::Value>, Self::Error>
|
||||
where T: de::DeserializeSeed,
|
||||
where T: de::DeserializeSeed
|
||||
{
|
||||
if let Some(k) = self.0.take() {
|
||||
seed.deserialize(k.into_deserializer()).map(Some)
|
||||
|
@ -855,7 +844,7 @@ impl Expected for ExpectedInMap {
|
|||
impl<K, V, E> ValueDeserializer<E> for BTreeMap<K, V>
|
||||
where K: ValueDeserializer<E> + Eq + Ord,
|
||||
V: ValueDeserializer<E>,
|
||||
E: de::Error,
|
||||
E: de::Error
|
||||
{
|
||||
type Deserializer = MapDeserializer<btree_map::IntoIter<K, V>, E>;
|
||||
|
||||
|
@ -868,7 +857,7 @@ impl<K, V, E> ValueDeserializer<E> for BTreeMap<K, V>
|
|||
impl<K, V, E> ValueDeserializer<E> for HashMap<K, V>
|
||||
where K: ValueDeserializer<E> + Eq + Hash,
|
||||
V: ValueDeserializer<E>,
|
||||
E: de::Error,
|
||||
E: de::Error
|
||||
{
|
||||
type Deserializer = MapDeserializer<hash_map::IntoIter<K, V>, E>;
|
||||
|
||||
|
@ -887,20 +876,20 @@ pub struct MapVisitorDeserializer<V_, E> {
|
|||
|
||||
impl<V_, E> MapVisitorDeserializer<V_, E>
|
||||
where V_: de::MapVisitor<Error = E>,
|
||||
E: de::Error,
|
||||
E: de::Error
|
||||
{
|
||||
/// Construct a new `MapVisitorDeserializer<V_, E>`.
|
||||
pub fn new(visitor: V_) -> Self {
|
||||
MapVisitorDeserializer{
|
||||
MapVisitorDeserializer {
|
||||
visitor: visitor,
|
||||
marker: PhantomData
|
||||
marker: PhantomData,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl<V_, E> de::Deserializer for MapVisitorDeserializer<V_, E>
|
||||
where V_: de::MapVisitor<Error = E>,
|
||||
E: de::Error,
|
||||
E: de::Error
|
||||
{
|
||||
type Error = E;
|
||||
|
||||
|
@ -918,7 +907,7 @@ impl<V_, E> de::Deserializer for MapVisitorDeserializer<V_, E>
|
|||
///////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
impl<'a, E> ValueDeserializer<E> for bytes::Bytes<'a>
|
||||
where E: de::Error,
|
||||
where E: de::Error
|
||||
{
|
||||
type Deserializer = BytesDeserializer<'a, E>;
|
||||
|
||||
|
@ -942,7 +931,7 @@ impl<'a, E> de::Deserializer for BytesDeserializer<'a, E>
|
|||
type Error = E;
|
||||
|
||||
fn deserialize<V>(self, visitor: V) -> Result<V::Value, Self::Error>
|
||||
where V: de::Visitor,
|
||||
where V: de::Visitor
|
||||
{
|
||||
visitor.visit_bytes(self.value)
|
||||
}
|
||||
|
@ -958,7 +947,7 @@ impl<'a, E> de::Deserializer for BytesDeserializer<'a, E>
|
|||
|
||||
#[cfg(any(feature = "std", feature = "collections"))]
|
||||
impl<E> ValueDeserializer<E> for bytes::ByteBuf
|
||||
where E: de::Error,
|
||||
where E: de::Error
|
||||
{
|
||||
type Deserializer = ByteBufDeserializer<E>;
|
||||
|
||||
|
@ -979,12 +968,12 @@ pub struct ByteBufDeserializer<E> {
|
|||
|
||||
#[cfg(any(feature = "std", feature = "collections"))]
|
||||
impl<E> de::Deserializer for ByteBufDeserializer<E>
|
||||
where E: de::Error,
|
||||
where E: de::Error
|
||||
{
|
||||
type Error = E;
|
||||
|
||||
fn deserialize<V>(self, visitor: V) -> Result<V::Value, Self::Error>
|
||||
where V: de::Visitor,
|
||||
where V: de::Visitor
|
||||
{
|
||||
visitor.visit_byte_buf(self.value)
|
||||
}
|
||||
|
@ -1020,14 +1009,12 @@ mod private {
|
|||
}
|
||||
|
||||
fn visit_newtype_seed<T>(self, _seed: T) -> Result<T::Value, Self::Error>
|
||||
where T: de::DeserializeSeed,
|
||||
where T: de::DeserializeSeed
|
||||
{
|
||||
Err(de::Error::invalid_type(Unexpected::UnitVariant, &"newtype variant"))
|
||||
}
|
||||
|
||||
fn visit_tuple<V>(self,
|
||||
_len: usize,
|
||||
_visitor: V) -> Result<V::Value, Self::Error>
|
||||
fn visit_tuple<V>(self, _len: usize, _visitor: V) -> Result<V::Value, Self::Error>
|
||||
where V: de::Visitor
|
||||
{
|
||||
Err(de::Error::invalid_type(Unexpected::UnitVariant, &"tuple variant"))
|
||||
|
@ -1035,7 +1022,8 @@ mod private {
|
|||
|
||||
fn visit_struct<V>(self,
|
||||
_fields: &'static [&'static str],
|
||||
_visitor: V) -> Result<V::Value, Self::Error>
|
||||
_visitor: V)
|
||||
-> Result<V::Value, Self::Error>
|
||||
where V: de::Visitor
|
||||
{
|
||||
Err(de::Error::invalid_type(Unexpected::UnitVariant, &"struct variant"))
|
||||
|
@ -1053,6 +1041,8 @@ mod private {
|
|||
impl<A, B> Pair for (A, B) {
|
||||
type First = A;
|
||||
type Second = B;
|
||||
fn split(self) -> (A, B) { self }
|
||||
fn split(self) -> (A, B) {
|
||||
self
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -11,5 +11,7 @@ pub trait Error: Debug + Display {
|
|||
fn description(&self) -> &str;
|
||||
|
||||
/// The lower-level cause of this error, if any.
|
||||
fn cause(&self) -> Option<&Error> { None }
|
||||
fn cause(&self) -> Option<&Error> {
|
||||
None
|
||||
}
|
||||
}
|
||||
|
|
|
@ -4,13 +4,13 @@ use std::io;
|
|||
use std::iter::Peekable;
|
||||
|
||||
/// Iterator over a byte stream that tracks the current position's line and column.
|
||||
pub struct LineColIterator<Iter: Iterator<Item=io::Result<u8>>> {
|
||||
pub struct LineColIterator<Iter: Iterator<Item = io::Result<u8>>> {
|
||||
iter: Iter,
|
||||
line: usize,
|
||||
col: usize,
|
||||
}
|
||||
|
||||
impl<Iter: Iterator<Item=io::Result<u8>>> LineColIterator<Iter> {
|
||||
impl<Iter: Iterator<Item = io::Result<u8>>> LineColIterator<Iter> {
|
||||
/// Construct a new `LineColIterator<Iter>`.
|
||||
pub fn new(iter: Iter) -> LineColIterator<Iter> {
|
||||
LineColIterator {
|
||||
|
@ -21,27 +21,39 @@ impl<Iter: Iterator<Item=io::Result<u8>>> LineColIterator<Iter> {
|
|||
}
|
||||
|
||||
/// Report the current line inside the iterator.
|
||||
pub fn line(&self) -> usize { self.line }
|
||||
pub fn line(&self) -> usize {
|
||||
self.line
|
||||
}
|
||||
|
||||
/// Report the current column inside the iterator.
|
||||
pub fn col(&self) -> usize { self.col }
|
||||
pub fn col(&self) -> usize {
|
||||
self.col
|
||||
}
|
||||
|
||||
/// Gets a reference to the underlying iterator.
|
||||
pub fn get_ref(&self) -> &Iter { &self.iter }
|
||||
pub fn get_ref(&self) -> &Iter {
|
||||
&self.iter
|
||||
}
|
||||
|
||||
/// Gets a mutable reference to the underlying iterator.
|
||||
pub fn get_mut(&mut self) -> &mut Iter { &mut self.iter }
|
||||
pub fn get_mut(&mut self) -> &mut Iter {
|
||||
&mut self.iter
|
||||
}
|
||||
|
||||
/// Unwraps this `LineColIterator`, returning the underlying iterator.
|
||||
pub fn into_inner(self) -> Iter { self.iter }
|
||||
pub fn into_inner(self) -> Iter {
|
||||
self.iter
|
||||
}
|
||||
}
|
||||
|
||||
impl<Iter: Iterator<Item=io::Result<u8>>> LineColIterator<Peekable<Iter>> {
|
||||
impl<Iter: Iterator<Item = io::Result<u8>>> LineColIterator<Peekable<Iter>> {
|
||||
/// peeks at the next value
|
||||
pub fn peek(&mut self) -> Option<&io::Result<u8>> { self.iter.peek() }
|
||||
pub fn peek(&mut self) -> Option<&io::Result<u8>> {
|
||||
self.iter.peek()
|
||||
}
|
||||
}
|
||||
|
||||
impl<Iter: Iterator<Item=io::Result<u8>>> Iterator for LineColIterator<Iter> {
|
||||
impl<Iter: Iterator<Item = io::Result<u8>>> Iterator for LineColIterator<Iter> {
|
||||
type Item = io::Result<u8>;
|
||||
fn next(&mut self) -> Option<io::Result<u8>> {
|
||||
match self.iter.next() {
|
||||
|
@ -50,11 +62,11 @@ impl<Iter: Iterator<Item=io::Result<u8>>> Iterator for LineColIterator<Iter> {
|
|||
self.line += 1;
|
||||
self.col = 0;
|
||||
Some(Ok(b'\n'))
|
||||
},
|
||||
}
|
||||
Some(Ok(c)) => {
|
||||
self.col += 1;
|
||||
Some(Ok(c))
|
||||
},
|
||||
}
|
||||
Some(Err(e)) => Some(Err(e)),
|
||||
}
|
||||
}
|
||||
|
|
|
@ -79,7 +79,7 @@ extern crate core as actual_core;
|
|||
#[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, num, slice, iter, cell, default, result, option};
|
||||
usize, f32, f64, char, str, num, slice, iter, cell, default, result, option};
|
||||
#[cfg(feature = "unstable")]
|
||||
pub use actual_core::nonzero;
|
||||
}
|
||||
|
|
|
@ -188,3 +188,35 @@ macro_rules! forward_to_deserialize {
|
|||
$(forward_to_deserialize_helper!{$func})*
|
||||
};
|
||||
}
|
||||
|
||||
/// Seralize the `$value` that implements Display as a string,
|
||||
/// when that string is statically known to never have more than
|
||||
/// a constant `$MAX_LEN` bytes.
|
||||
///
|
||||
/// Panics if the Display impl tries to write more than `$MAX_LEN` bytes.
|
||||
#[cfg(feature = "std")]
|
||||
// Not exported
|
||||
macro_rules! serialize_display_bounded_length {
|
||||
($value: expr, $MAX_LEN: expr, $serializer: expr) => {
|
||||
{
|
||||
use std::io::Write;
|
||||
let mut buffer: [u8; $MAX_LEN] = unsafe { ::std::mem::uninitialized() };
|
||||
let remaining_len;
|
||||
{
|
||||
let mut remaining = &mut buffer[..];
|
||||
write!(remaining, "{}", $value).unwrap();
|
||||
remaining_len = remaining.len()
|
||||
}
|
||||
let written_len = buffer.len() - remaining_len;
|
||||
let written = &buffer[..written_len];
|
||||
|
||||
// write! only provides std::fmt::Formatter to Display implementations,
|
||||
// which has methods write_str and write_char but no method to write arbitrary bytes.
|
||||
// Therefore, `written` is well-formed in UTF-8.
|
||||
let written_str = unsafe {
|
||||
::std::str::from_utf8_unchecked(written)
|
||||
};
|
||||
$serializer.serialize_str(written_str)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -0,0 +1,635 @@
|
|||
use core::marker::PhantomData;
|
||||
|
||||
#[cfg(all(not(feature = "std"), feature = "collections"))]
|
||||
use collections::{String, Vec};
|
||||
|
||||
#[cfg(all(feature = "alloc", not(feature = "std")))]
|
||||
use alloc::boxed::Box;
|
||||
|
||||
#[cfg(feature = "collections")]
|
||||
use collections::borrow::ToOwned;
|
||||
|
||||
use ser::{self, Serialize, Serializer};
|
||||
|
||||
pub struct SerializeTupleVariantAsMapValue<M> {
|
||||
map: M,
|
||||
name: &'static str,
|
||||
fields: Vec<Content>,
|
||||
}
|
||||
|
||||
impl<M> SerializeTupleVariantAsMapValue<M> {
|
||||
pub fn new(map: M, name: &'static str, len: usize) -> Self {
|
||||
SerializeTupleVariantAsMapValue {
|
||||
map: map,
|
||||
name: name,
|
||||
fields: Vec::with_capacity(len),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl<M> ser::SerializeTupleVariant for SerializeTupleVariantAsMapValue<M>
|
||||
where M: ser::SerializeMap
|
||||
{
|
||||
type Ok = M::Ok;
|
||||
type Error = M::Error;
|
||||
|
||||
fn serialize_field<T: ?Sized + Serialize>(&mut self,
|
||||
value: &T)
|
||||
-> Result<(), M::Error>
|
||||
{
|
||||
let value = try!(value.serialize(ContentSerializer::<M::Error>::new()));
|
||||
self.fields.push(value);
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn end(mut self) -> Result<M::Ok, M::Error> {
|
||||
try!(self.map.serialize_value(&Content::TupleStruct(self.name, self.fields)));
|
||||
self.map.end()
|
||||
}
|
||||
}
|
||||
|
||||
pub struct SerializeStructVariantAsMapValue<M> {
|
||||
map: M,
|
||||
name: &'static str,
|
||||
fields: Vec<(&'static str, Content)>,
|
||||
}
|
||||
|
||||
impl<M> SerializeStructVariantAsMapValue<M> {
|
||||
pub fn new(map: M, name: &'static str, len: usize) -> Self {
|
||||
SerializeStructVariantAsMapValue {
|
||||
map: map,
|
||||
name: name,
|
||||
fields: Vec::with_capacity(len),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl<M> ser::SerializeStructVariant for SerializeStructVariantAsMapValue<M>
|
||||
where M: ser::SerializeMap
|
||||
{
|
||||
type Ok = M::Ok;
|
||||
type Error = M::Error;
|
||||
|
||||
fn serialize_field<T: ?Sized + Serialize>(&mut self,
|
||||
key: &'static str,
|
||||
value: &T)
|
||||
-> Result<(), M::Error>
|
||||
{
|
||||
let value = try!(value.serialize(ContentSerializer::<M::Error>::new()));
|
||||
self.fields.push((key, value));
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn end(mut self) -> Result<M::Ok, M::Error> {
|
||||
try!(self.map.serialize_value(&Content::Struct(self.name, self.fields)));
|
||||
self.map.end()
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Debug)]
|
||||
enum Content {
|
||||
Bool(bool),
|
||||
|
||||
U8(u8),
|
||||
U16(u16),
|
||||
U32(u32),
|
||||
U64(u64),
|
||||
|
||||
I8(i8),
|
||||
I16(i16),
|
||||
I32(i32),
|
||||
I64(i64),
|
||||
|
||||
F32(f32),
|
||||
F64(f64),
|
||||
|
||||
Char(char),
|
||||
String(String),
|
||||
Bytes(Vec<u8>),
|
||||
|
||||
None,
|
||||
Some(Box<Content>),
|
||||
|
||||
Unit,
|
||||
UnitStruct(&'static str),
|
||||
UnitVariant(&'static str, usize, &'static str),
|
||||
NewtypeStruct(&'static str, Box<Content>),
|
||||
NewtypeVariant(&'static str, usize, &'static str, Box<Content>),
|
||||
|
||||
Seq(Vec<Content>),
|
||||
SeqFixedSize(Vec<Content>),
|
||||
Tuple(Vec<Content>),
|
||||
TupleStruct(&'static str, Vec<Content>),
|
||||
TupleVariant(&'static str, usize, &'static str, Vec<Content>),
|
||||
Map(Vec<(Content, Content)>),
|
||||
Struct(&'static str, Vec<(&'static str, Content)>),
|
||||
StructVariant(&'static str, usize, &'static str, Vec<(&'static str, Content)>),
|
||||
}
|
||||
|
||||
impl Serialize for Content {
|
||||
fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
|
||||
where S: Serializer
|
||||
{
|
||||
match *self {
|
||||
Content::Bool(b) => serializer.serialize_bool(b),
|
||||
Content::U8(u) => serializer.serialize_u8(u),
|
||||
Content::U16(u) => serializer.serialize_u16(u),
|
||||
Content::U32(u) => serializer.serialize_u32(u),
|
||||
Content::U64(u) => serializer.serialize_u64(u),
|
||||
Content::I8(i) => serializer.serialize_i8(i),
|
||||
Content::I16(i) => serializer.serialize_i16(i),
|
||||
Content::I32(i) => serializer.serialize_i32(i),
|
||||
Content::I64(i) => serializer.serialize_i64(i),
|
||||
Content::F32(f) => serializer.serialize_f32(f),
|
||||
Content::F64(f) => serializer.serialize_f64(f),
|
||||
Content::Char(c) => serializer.serialize_char(c),
|
||||
Content::String(ref s) => serializer.serialize_str(s),
|
||||
Content::Bytes(ref b) => serializer.serialize_bytes(b),
|
||||
Content::None => serializer.serialize_none(),
|
||||
Content::Some(ref c) => serializer.serialize_some(&**c),
|
||||
Content::Unit => serializer.serialize_unit(),
|
||||
Content::UnitStruct(n) => serializer.serialize_unit_struct(n),
|
||||
Content::UnitVariant(n, i, v) => serializer.serialize_unit_variant(n, i, v),
|
||||
Content::NewtypeStruct(n, ref c) => serializer.serialize_newtype_struct(n, &**c),
|
||||
Content::NewtypeVariant(n, i, v, ref c) => serializer.serialize_newtype_variant(n, i, v, &**c),
|
||||
Content::Seq(ref elements) => elements.serialize(serializer),
|
||||
Content::SeqFixedSize(ref elements) => {
|
||||
use ser::SerializeSeq;
|
||||
let mut seq = try!(serializer.serialize_seq_fixed_size(elements.len()));
|
||||
for e in elements {
|
||||
try!(seq.serialize_element(e));
|
||||
}
|
||||
seq.end()
|
||||
}
|
||||
Content::Tuple(ref elements) => {
|
||||
use ser::SerializeTuple;
|
||||
let mut tuple = try!(serializer.serialize_tuple(elements.len()));
|
||||
for e in elements {
|
||||
try!(tuple.serialize_element(e));
|
||||
}
|
||||
tuple.end()
|
||||
}
|
||||
Content::TupleStruct(n, ref fields) => {
|
||||
use ser::SerializeTupleStruct;
|
||||
let mut ts = try!(serializer.serialize_tuple_struct(n, fields.len()));
|
||||
for f in fields {
|
||||
try!(ts.serialize_field(f));
|
||||
}
|
||||
ts.end()
|
||||
}
|
||||
Content::TupleVariant(n, i, v, ref fields) => {
|
||||
use ser::SerializeTupleVariant;
|
||||
let mut tv = try!(serializer.serialize_tuple_variant(n, i, v, fields.len()));
|
||||
for f in fields {
|
||||
try!(tv.serialize_field(f));
|
||||
}
|
||||
tv.end()
|
||||
}
|
||||
Content::Map(ref entries) => {
|
||||
use ser::SerializeMap;
|
||||
let mut map = try!(serializer.serialize_map(Some(entries.len())));
|
||||
for &(ref k, ref v) in entries {
|
||||
try!(map.serialize_entry(k, v));
|
||||
}
|
||||
map.end()
|
||||
}
|
||||
Content::Struct(n, ref fields) => {
|
||||
use ser::SerializeStruct;
|
||||
let mut s = try!(serializer.serialize_struct(n, fields.len()));
|
||||
for &(k, ref v) in fields {
|
||||
try!(s.serialize_field(k, v));
|
||||
}
|
||||
s.end()
|
||||
}
|
||||
Content::StructVariant(n, i, v, ref fields) => {
|
||||
use ser::SerializeStructVariant;
|
||||
let mut sv = try!(serializer.serialize_struct_variant(n, i, v, fields.len()));
|
||||
for &(k, ref v) in fields {
|
||||
try!(sv.serialize_field(k, v));
|
||||
}
|
||||
sv.end()
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
struct ContentSerializer<E> {
|
||||
error: PhantomData<E>,
|
||||
}
|
||||
|
||||
impl<E> ContentSerializer<E> {
|
||||
fn new() -> Self {
|
||||
ContentSerializer {
|
||||
error: PhantomData,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl<E> Serializer for ContentSerializer<E>
|
||||
where E: ser::Error
|
||||
{
|
||||
type Ok = Content;
|
||||
type Error = E;
|
||||
|
||||
type SerializeSeq = SerializeSeq<E>;
|
||||
type SerializeTuple = SerializeTuple<E>;
|
||||
type SerializeTupleStruct = SerializeTupleStruct<E>;
|
||||
type SerializeTupleVariant = SerializeTupleVariant<E>;
|
||||
type SerializeMap = SerializeMap<E>;
|
||||
type SerializeStruct = SerializeStruct<E>;
|
||||
type SerializeStructVariant = SerializeStructVariant<E>;
|
||||
|
||||
fn serialize_bool(self, v: bool) -> Result<Content, E> {
|
||||
Ok(Content::Bool(v))
|
||||
}
|
||||
|
||||
fn serialize_i8(self, v: i8) -> Result<Content, E> {
|
||||
Ok(Content::I8(v))
|
||||
}
|
||||
|
||||
fn serialize_i16(self, v: i16) -> Result<Content, E> {
|
||||
Ok(Content::I16(v))
|
||||
}
|
||||
|
||||
fn serialize_i32(self, v: i32) -> Result<Content, E> {
|
||||
Ok(Content::I32(v))
|
||||
}
|
||||
|
||||
fn serialize_i64(self, v: i64) -> Result<Content, E> {
|
||||
Ok(Content::I64(v))
|
||||
}
|
||||
|
||||
fn serialize_u8(self, v: u8) -> Result<Content, E> {
|
||||
Ok(Content::U8(v))
|
||||
}
|
||||
|
||||
fn serialize_u16(self, v: u16) -> Result<Content, E> {
|
||||
Ok(Content::U16(v))
|
||||
}
|
||||
|
||||
fn serialize_u32(self, v: u32) -> Result<Content, E> {
|
||||
Ok(Content::U32(v))
|
||||
}
|
||||
|
||||
fn serialize_u64(self, v: u64) -> Result<Content, E> {
|
||||
Ok(Content::U64(v))
|
||||
}
|
||||
|
||||
fn serialize_f32(self, v: f32) -> Result<Content, E> {
|
||||
Ok(Content::F32(v))
|
||||
}
|
||||
|
||||
fn serialize_f64(self, v: f64) -> Result<Content, E> {
|
||||
Ok(Content::F64(v))
|
||||
}
|
||||
|
||||
fn serialize_char(self, v: char) -> Result<Content, E> {
|
||||
Ok(Content::Char(v))
|
||||
}
|
||||
|
||||
fn serialize_str(self, value: &str) -> Result<Content, E> {
|
||||
Ok(Content::String(value.to_owned()))
|
||||
}
|
||||
|
||||
fn serialize_bytes(self, value: &[u8]) -> Result<Content, E> {
|
||||
Ok(Content::Bytes(value.to_owned()))
|
||||
}
|
||||
|
||||
fn serialize_none(self) -> Result<Content, E> {
|
||||
Ok(Content::None)
|
||||
}
|
||||
|
||||
fn serialize_some<T: ?Sized + Serialize>(self,
|
||||
value: &T)
|
||||
-> Result<Content, E> {
|
||||
Ok(Content::Some(Box::new(try!(value.serialize(self)))))
|
||||
}
|
||||
|
||||
fn serialize_unit(self) -> Result<Content, E> {
|
||||
Ok(Content::Unit)
|
||||
}
|
||||
|
||||
fn serialize_unit_struct(self,
|
||||
name: &'static str)
|
||||
-> Result<Content, E> {
|
||||
Ok(Content::UnitStruct(name))
|
||||
}
|
||||
|
||||
fn serialize_unit_variant(self,
|
||||
name: &'static str,
|
||||
variant_index: usize,
|
||||
variant: &'static str)
|
||||
-> Result<Content, E> {
|
||||
Ok(Content::UnitVariant(name, variant_index, variant))
|
||||
}
|
||||
|
||||
fn serialize_newtype_struct<T: ?Sized + Serialize>(self,
|
||||
name: &'static str,
|
||||
value: &T)
|
||||
-> Result<Content, E> {
|
||||
Ok(Content::NewtypeStruct(name, Box::new(try!(value.serialize(self)))))
|
||||
}
|
||||
|
||||
fn serialize_newtype_variant<T: ?Sized + Serialize>(self,
|
||||
name: &'static str,
|
||||
variant_index: usize,
|
||||
variant: &'static str,
|
||||
value: &T)
|
||||
-> Result<Content, E> {
|
||||
Ok(Content::NewtypeVariant(name, variant_index, variant, Box::new(try!(value.serialize(self)))))
|
||||
}
|
||||
|
||||
fn serialize_seq(self,
|
||||
len: Option<usize>)
|
||||
-> Result<Self::SerializeSeq, E> {
|
||||
Ok(SerializeSeq {
|
||||
fixed_size: false,
|
||||
elements: Vec::with_capacity(len.unwrap_or(0)),
|
||||
error: PhantomData,
|
||||
})
|
||||
}
|
||||
|
||||
fn serialize_seq_fixed_size(self,
|
||||
size: usize)
|
||||
-> Result<Self::SerializeSeq, E> {
|
||||
Ok(SerializeSeq {
|
||||
fixed_size: true,
|
||||
elements: Vec::with_capacity(size),
|
||||
error: PhantomData,
|
||||
})
|
||||
}
|
||||
|
||||
fn serialize_tuple(self,
|
||||
len: usize)
|
||||
-> Result<Self::SerializeTuple, E> {
|
||||
Ok(SerializeTuple {
|
||||
elements: Vec::with_capacity(len),
|
||||
error: PhantomData,
|
||||
})
|
||||
}
|
||||
|
||||
fn serialize_tuple_struct(self,
|
||||
name: &'static str,
|
||||
len: usize)
|
||||
-> Result<Self::SerializeTupleStruct, E> {
|
||||
Ok(SerializeTupleStruct {
|
||||
name: name,
|
||||
fields: Vec::with_capacity(len),
|
||||
error: PhantomData,
|
||||
})
|
||||
}
|
||||
|
||||
fn serialize_tuple_variant(self,
|
||||
name: &'static str,
|
||||
variant_index: usize,
|
||||
variant: &'static str,
|
||||
len: usize)
|
||||
-> Result<Self::SerializeTupleVariant, E> {
|
||||
Ok(SerializeTupleVariant {
|
||||
name: name,
|
||||
variant_index: variant_index,
|
||||
variant: variant,
|
||||
fields: Vec::with_capacity(len),
|
||||
error: PhantomData,
|
||||
})
|
||||
}
|
||||
|
||||
fn serialize_map(self,
|
||||
len: Option<usize>)
|
||||
-> Result<Self::SerializeMap, E> {
|
||||
Ok(SerializeMap {
|
||||
entries: Vec::with_capacity(len.unwrap_or(0)),
|
||||
key: None,
|
||||
error: PhantomData,
|
||||
})
|
||||
}
|
||||
|
||||
fn serialize_struct(self,
|
||||
name: &'static str,
|
||||
len: usize)
|
||||
-> Result<Self::SerializeStruct, E> {
|
||||
Ok(SerializeStruct {
|
||||
name: name,
|
||||
fields: Vec::with_capacity(len),
|
||||
error: PhantomData,
|
||||
})
|
||||
}
|
||||
|
||||
fn serialize_struct_variant(self,
|
||||
name: &'static str,
|
||||
variant_index: usize,
|
||||
variant: &'static str,
|
||||
len: usize)
|
||||
-> Result<Self::SerializeStructVariant, E> {
|
||||
Ok(SerializeStructVariant {
|
||||
name: name,
|
||||
variant_index: variant_index,
|
||||
variant: variant,
|
||||
fields: Vec::with_capacity(len),
|
||||
error: PhantomData,
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
struct SerializeSeq<E> {
|
||||
fixed_size: bool,
|
||||
elements: Vec<Content>,
|
||||
error: PhantomData<E>,
|
||||
}
|
||||
|
||||
impl<E> ser::SerializeSeq for SerializeSeq<E>
|
||||
where E: ser::Error
|
||||
{
|
||||
type Ok = Content;
|
||||
type Error = E;
|
||||
|
||||
fn serialize_element<T: ?Sized + Serialize>(&mut self,
|
||||
value: &T)
|
||||
-> Result<(), E> {
|
||||
let value = try!(value.serialize(ContentSerializer::<E>::new()));
|
||||
self.elements.push(value);
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn end(self) -> Result<Content, E> {
|
||||
Ok(if self.fixed_size {
|
||||
Content::SeqFixedSize(self.elements)
|
||||
} else {
|
||||
Content::Seq(self.elements)
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
struct SerializeTuple<E> {
|
||||
elements: Vec<Content>,
|
||||
error: PhantomData<E>,
|
||||
}
|
||||
|
||||
impl<E> ser::SerializeTuple for SerializeTuple<E>
|
||||
where E: ser::Error
|
||||
{
|
||||
type Ok = Content;
|
||||
type Error = E;
|
||||
|
||||
fn serialize_element<T: ?Sized + Serialize>(&mut self,
|
||||
value: &T)
|
||||
-> Result<(), E> {
|
||||
let value = try!(value.serialize(ContentSerializer::<E>::new()));
|
||||
self.elements.push(value);
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn end(self) -> Result<Content, E> {
|
||||
Ok(Content::Tuple(self.elements))
|
||||
}
|
||||
}
|
||||
|
||||
struct SerializeTupleStruct<E> {
|
||||
name: &'static str,
|
||||
fields: Vec<Content>,
|
||||
error: PhantomData<E>,
|
||||
}
|
||||
|
||||
impl<E> ser::SerializeTupleStruct for SerializeTupleStruct<E>
|
||||
where E: ser::Error
|
||||
{
|
||||
type Ok = Content;
|
||||
type Error = E;
|
||||
|
||||
fn serialize_field<T: ?Sized + Serialize>(&mut self,
|
||||
value: &T)
|
||||
-> Result<(), E> {
|
||||
let value = try!(value.serialize(ContentSerializer::<E>::new()));
|
||||
self.fields.push(value);
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn end(self) -> Result<Content, E> {
|
||||
Ok(Content::TupleStruct(self.name, self.fields))
|
||||
}
|
||||
}
|
||||
|
||||
struct SerializeTupleVariant<E> {
|
||||
name: &'static str,
|
||||
variant_index: usize,
|
||||
variant: &'static str,
|
||||
fields: Vec<Content>,
|
||||
error: PhantomData<E>,
|
||||
}
|
||||
|
||||
impl<E> ser::SerializeTupleVariant for SerializeTupleVariant<E>
|
||||
where E: ser::Error
|
||||
{
|
||||
type Ok = Content;
|
||||
type Error = E;
|
||||
|
||||
fn serialize_field<T: ?Sized + Serialize>(&mut self,
|
||||
value: &T)
|
||||
-> Result<(), E> {
|
||||
let value = try!(value.serialize(ContentSerializer::<E>::new()));
|
||||
self.fields.push(value);
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn end(self) -> Result<Content, E> {
|
||||
Ok(Content::TupleVariant(self.name, self.variant_index, self.variant, self.fields))
|
||||
}
|
||||
}
|
||||
|
||||
struct SerializeMap<E> {
|
||||
entries: Vec<(Content, Content)>,
|
||||
key: Option<Content>,
|
||||
error: PhantomData<E>,
|
||||
}
|
||||
|
||||
impl<E> ser::SerializeMap for SerializeMap<E>
|
||||
where E: ser::Error
|
||||
{
|
||||
type Ok = Content;
|
||||
type Error = E;
|
||||
|
||||
fn serialize_key<T: ?Sized + Serialize>(&mut self,
|
||||
key: &T)
|
||||
-> Result<(), E> {
|
||||
let key = try!(key.serialize(ContentSerializer::<E>::new()));
|
||||
self.key = Some(key);
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn serialize_value<T: ?Sized + Serialize>(&mut self,
|
||||
value: &T)
|
||||
-> Result<(), E> {
|
||||
let key = self.key.take().expect("serialize_value called before serialize_key");
|
||||
let value = try!(value.serialize(ContentSerializer::<E>::new()));
|
||||
self.entries.push((key, value));
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn end(self) -> Result<Content, E> {
|
||||
Ok(Content::Map(self.entries))
|
||||
}
|
||||
|
||||
fn serialize_entry<K: ?Sized + Serialize, V: ?Sized + Serialize>(&mut self,
|
||||
key: &K,
|
||||
value: &V)
|
||||
-> Result<(), E> {
|
||||
let key = try!(key.serialize(ContentSerializer::<E>::new()));
|
||||
let value = try!(value.serialize(ContentSerializer::<E>::new()));
|
||||
self.entries.push((key, value));
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
|
||||
struct SerializeStruct<E> {
|
||||
name: &'static str,
|
||||
fields: Vec<(&'static str, Content)>,
|
||||
error: PhantomData<E>,
|
||||
}
|
||||
|
||||
impl<E> ser::SerializeStruct for SerializeStruct<E>
|
||||
where E: ser::Error
|
||||
{
|
||||
type Ok = Content;
|
||||
type Error = E;
|
||||
|
||||
fn serialize_field<T: ?Sized + Serialize>(&mut self,
|
||||
key: &'static str,
|
||||
value: &T)
|
||||
-> Result<(), E> {
|
||||
let value = try!(value.serialize(ContentSerializer::<E>::new()));
|
||||
self.fields.push((key, value));
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn end(self) -> Result<Content, E> {
|
||||
Ok(Content::Struct(self.name, self.fields))
|
||||
}
|
||||
}
|
||||
|
||||
struct SerializeStructVariant<E> {
|
||||
name: &'static str,
|
||||
variant_index: usize,
|
||||
variant: &'static str,
|
||||
fields: Vec<(&'static str, Content)>,
|
||||
error: PhantomData<E>,
|
||||
}
|
||||
|
||||
impl<E> ser::SerializeStructVariant for SerializeStructVariant<E>
|
||||
where E: ser::Error
|
||||
{
|
||||
type Ok = Content;
|
||||
type Error = E;
|
||||
|
||||
fn serialize_field<T: ?Sized + Serialize>(&mut self,
|
||||
key: &'static str,
|
||||
value: &T)
|
||||
-> Result<(), E> {
|
||||
let value = try!(value.serialize(ContentSerializer::<E>::new()));
|
||||
self.fields.push((key, value));
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn end(self) -> Result<Content, E> {
|
||||
Ok(Content::StructVariant(self.name, self.variant_index, self.variant, self.fields))
|
||||
}
|
||||
}
|
|
@ -4,25 +4,9 @@ use std::borrow::Cow;
|
|||
use collections::borrow::Cow;
|
||||
|
||||
#[cfg(feature = "std")]
|
||||
use std::collections::{
|
||||
BinaryHeap,
|
||||
BTreeMap,
|
||||
BTreeSet,
|
||||
LinkedList,
|
||||
HashMap,
|
||||
HashSet,
|
||||
VecDeque,
|
||||
};
|
||||
use std::collections::{BinaryHeap, BTreeMap, BTreeSet, LinkedList, HashMap, HashSet, VecDeque};
|
||||
#[cfg(all(feature = "collections", not(feature = "std")))]
|
||||
use collections::{
|
||||
BinaryHeap,
|
||||
BTreeMap,
|
||||
BTreeSet,
|
||||
LinkedList,
|
||||
VecDeque,
|
||||
String,
|
||||
Vec,
|
||||
};
|
||||
use collections::{BinaryHeap, BTreeMap, BTreeSet, LinkedList, VecDeque, String, Vec};
|
||||
|
||||
#[cfg(feature = "collections")]
|
||||
use collections::borrow::ToOwned;
|
||||
|
@ -57,12 +41,7 @@ use core::marker::PhantomData;
|
|||
#[cfg(feature = "unstable")]
|
||||
use core::nonzero::{NonZero, Zeroable};
|
||||
|
||||
use super::{
|
||||
Serialize,
|
||||
SerializeSeq,
|
||||
SerializeTuple,
|
||||
Serializer,
|
||||
};
|
||||
use super::{Serialize, SerializeSeq, SerializeTuple, Serializer};
|
||||
#[cfg(feature = "std")]
|
||||
use super::Error;
|
||||
|
||||
|
@ -101,7 +80,7 @@ impl_visit!(char, serialize_char);
|
|||
impl Serialize for str {
|
||||
#[inline]
|
||||
fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
|
||||
where S: Serializer,
|
||||
where S: Serializer
|
||||
{
|
||||
serializer.serialize_str(self)
|
||||
}
|
||||
|
@ -111,7 +90,7 @@ impl Serialize for str {
|
|||
impl Serialize for String {
|
||||
#[inline]
|
||||
fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
|
||||
where S: Serializer,
|
||||
where S: Serializer
|
||||
{
|
||||
(&self[..]).serialize(serializer)
|
||||
}
|
||||
|
@ -124,7 +103,7 @@ impl<T> Serialize for Option<T>
|
|||
{
|
||||
#[inline]
|
||||
fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
|
||||
where S: Serializer,
|
||||
where S: Serializer
|
||||
{
|
||||
match *self {
|
||||
Some(ref value) => serializer.serialize_some(value),
|
||||
|
@ -138,7 +117,7 @@ impl<T> Serialize for Option<T>
|
|||
impl<T> Serialize for PhantomData<T> {
|
||||
#[inline]
|
||||
fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
|
||||
where S: Serializer,
|
||||
where S: Serializer
|
||||
{
|
||||
serializer.serialize_unit_struct("PhantomData")
|
||||
}
|
||||
|
@ -211,7 +190,7 @@ macro_rules! serialize_seq {
|
|||
}
|
||||
|
||||
impl<T> Serialize for [T]
|
||||
where T: Serialize,
|
||||
where T: Serialize
|
||||
{
|
||||
serialize_seq!();
|
||||
}
|
||||
|
@ -225,7 +204,7 @@ impl<T> Serialize for BinaryHeap<T>
|
|||
|
||||
#[cfg(any(feature = "std", feature = "collections"))]
|
||||
impl<T> Serialize for BTreeSet<T>
|
||||
where T: Serialize + Ord,
|
||||
where T: Serialize + Ord
|
||||
{
|
||||
serialize_seq!();
|
||||
}
|
||||
|
@ -233,14 +212,14 @@ impl<T> Serialize for BTreeSet<T>
|
|||
#[cfg(feature = "std")]
|
||||
impl<T, H> Serialize for HashSet<T, H>
|
||||
where T: Serialize + Eq + Hash,
|
||||
H: BuildHasher,
|
||||
H: BuildHasher
|
||||
{
|
||||
serialize_seq!();
|
||||
}
|
||||
|
||||
#[cfg(any(feature = "std", feature = "collections"))]
|
||||
impl<T> Serialize for LinkedList<T>
|
||||
where T: Serialize,
|
||||
where T: Serialize
|
||||
{
|
||||
serialize_seq!();
|
||||
}
|
||||
|
@ -262,11 +241,11 @@ impl<T> Serialize for VecDeque<T>
|
|||
#[cfg(feature = "unstable")]
|
||||
impl<A> Serialize for ops::Range<A>
|
||||
where ops::Range<A>: ExactSizeIterator + iter::Iterator<Item = A> + Clone,
|
||||
A: Serialize,
|
||||
A: Serialize
|
||||
{
|
||||
#[inline]
|
||||
fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
|
||||
where S: Serializer,
|
||||
where S: Serializer
|
||||
{
|
||||
let mut seq = try!(serializer.serialize_seq(Some(self.len())));
|
||||
for e in self.clone() {
|
||||
|
@ -279,11 +258,11 @@ impl<A> Serialize for ops::Range<A>
|
|||
#[cfg(feature = "unstable")]
|
||||
impl<A> Serialize for ops::RangeInclusive<A>
|
||||
where ops::RangeInclusive<A>: ExactSizeIterator + iter::Iterator<Item = A> + Clone,
|
||||
A: Serialize,
|
||||
A: Serialize
|
||||
{
|
||||
#[inline]
|
||||
fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
|
||||
where S: Serializer,
|
||||
where S: Serializer
|
||||
{
|
||||
let mut seq = try!(serializer.serialize_seq(Some(self.len())));
|
||||
for e in self.clone() {
|
||||
|
@ -298,7 +277,7 @@ impl<A> Serialize for ops::RangeInclusive<A>
|
|||
impl Serialize for () {
|
||||
#[inline]
|
||||
fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
|
||||
where S: Serializer,
|
||||
where S: Serializer
|
||||
{
|
||||
serializer.serialize_unit()
|
||||
}
|
||||
|
@ -518,7 +497,7 @@ macro_rules! serialize_map {
|
|||
#[cfg(any(feature = "std", feature = "collections"))]
|
||||
impl<K, V> Serialize for BTreeMap<K, V>
|
||||
where K: Serialize + Ord,
|
||||
V: Serialize,
|
||||
V: Serialize
|
||||
{
|
||||
serialize_map!();
|
||||
}
|
||||
|
@ -527,26 +506,30 @@ impl<K, V> Serialize for BTreeMap<K, V>
|
|||
impl<K, V, H> Serialize for HashMap<K, V, H>
|
||||
where K: Serialize + Eq + Hash,
|
||||
V: Serialize,
|
||||
H: BuildHasher,
|
||||
H: BuildHasher
|
||||
{
|
||||
serialize_map!();
|
||||
}
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
impl<'a, T: ?Sized> Serialize for &'a T where T: Serialize {
|
||||
impl<'a, T: ?Sized> Serialize for &'a T
|
||||
where T: Serialize
|
||||
{
|
||||
#[inline]
|
||||
fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
|
||||
where S: Serializer,
|
||||
where S: Serializer
|
||||
{
|
||||
(**self).serialize(serializer)
|
||||
}
|
||||
}
|
||||
|
||||
impl<'a, T: ?Sized> Serialize for &'a mut T where T: Serialize {
|
||||
impl<'a, T: ?Sized> Serialize for &'a mut T
|
||||
where T: Serialize
|
||||
{
|
||||
#[inline]
|
||||
fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
|
||||
where S: Serializer,
|
||||
where S: Serializer
|
||||
{
|
||||
(**self).serialize(serializer)
|
||||
}
|
||||
|
@ -558,7 +541,7 @@ impl<T: ?Sized> Serialize for Box<T>
|
|||
{
|
||||
#[inline]
|
||||
fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
|
||||
where S: Serializer,
|
||||
where S: Serializer
|
||||
{
|
||||
(**self).serialize(serializer)
|
||||
}
|
||||
|
@ -570,7 +553,7 @@ impl<T> Serialize for Rc<T>
|
|||
{
|
||||
#[inline]
|
||||
fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
|
||||
where S: Serializer,
|
||||
where S: Serializer
|
||||
{
|
||||
(**self).serialize(serializer)
|
||||
}
|
||||
|
@ -582,7 +565,7 @@ impl<T> Serialize for Arc<T>
|
|||
{
|
||||
#[inline]
|
||||
fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
|
||||
where S: Serializer,
|
||||
where S: Serializer
|
||||
{
|
||||
(**self).serialize(serializer)
|
||||
}
|
||||
|
@ -594,7 +577,7 @@ impl<'a, T: ?Sized> Serialize for Cow<'a, T>
|
|||
{
|
||||
#[inline]
|
||||
fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
|
||||
where S: Serializer,
|
||||
where S: Serializer
|
||||
{
|
||||
(**self).serialize(serializer)
|
||||
}
|
||||
|
@ -610,9 +593,7 @@ impl<T, E> Serialize for Result<T, E>
|
|||
where S: Serializer
|
||||
{
|
||||
match *self {
|
||||
Result::Ok(ref value) => {
|
||||
serializer.serialize_newtype_variant("Result", 0, "Ok", value)
|
||||
}
|
||||
Result::Ok(ref value) => serializer.serialize_newtype_variant("Result", 0, "Ok", value),
|
||||
Result::Err(ref value) => {
|
||||
serializer.serialize_newtype_variant("Result", 1, "Err", value)
|
||||
}
|
||||
|
@ -625,7 +606,7 @@ impl<T, E> Serialize for Result<T, E>
|
|||
#[cfg(feature = "std")]
|
||||
impl Serialize for Duration {
|
||||
fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
|
||||
where S: Serializer,
|
||||
where S: Serializer
|
||||
{
|
||||
use super::SerializeStruct;
|
||||
let mut state = try!(serializer.serialize_struct("Duration", 2));
|
||||
|
@ -640,27 +621,34 @@ impl Serialize for Duration {
|
|||
#[cfg(feature = "std")]
|
||||
impl Serialize for net::IpAddr {
|
||||
fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
|
||||
where S: Serializer,
|
||||
where S: Serializer
|
||||
{
|
||||
self.to_string().serialize(serializer)
|
||||
match *self {
|
||||
net::IpAddr::V4(ref a) => a.serialize(serializer),
|
||||
net::IpAddr::V6(ref a) => a.serialize(serializer),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(feature = "std")]
|
||||
impl Serialize for net::Ipv4Addr {
|
||||
fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
|
||||
where S: Serializer,
|
||||
where S: Serializer
|
||||
{
|
||||
self.to_string().serialize(serializer)
|
||||
/// "101.102.103.104".len()
|
||||
const MAX_LEN: usize = 15;
|
||||
serialize_display_bounded_length!(self, MAX_LEN, serializer)
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(feature = "std")]
|
||||
impl Serialize for net::Ipv6Addr {
|
||||
fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
|
||||
where S: Serializer,
|
||||
where S: Serializer
|
||||
{
|
||||
self.to_string().serialize(serializer)
|
||||
/// "1000:1002:1003:1004:1005:1006:1007:1008".len()
|
||||
const MAX_LEN: usize = 39;
|
||||
serialize_display_bounded_length!(self, MAX_LEN, serializer)
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -669,7 +657,7 @@ impl Serialize for net::Ipv6Addr {
|
|||
#[cfg(feature = "std")]
|
||||
impl Serialize for net::SocketAddr {
|
||||
fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
|
||||
where S: Serializer,
|
||||
where S: Serializer
|
||||
{
|
||||
match *self {
|
||||
net::SocketAddr::V4(ref addr) => addr.serialize(serializer),
|
||||
|
@ -681,18 +669,22 @@ impl Serialize for net::SocketAddr {
|
|||
#[cfg(feature = "std")]
|
||||
impl Serialize for net::SocketAddrV4 {
|
||||
fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
|
||||
where S: Serializer,
|
||||
where S: Serializer
|
||||
{
|
||||
self.to_string().serialize(serializer)
|
||||
/// "101.102.103.104:65000".len()
|
||||
const MAX_LEN: usize = 21;
|
||||
serialize_display_bounded_length!(self, MAX_LEN, serializer)
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(feature = "std")]
|
||||
impl Serialize for net::SocketAddrV6 {
|
||||
fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
|
||||
where S: Serializer,
|
||||
where S: Serializer
|
||||
{
|
||||
self.to_string().serialize(serializer)
|
||||
/// "[1000:1002:1003:1004:1005:1006:1007:1008]:65000".len()
|
||||
const MAX_LEN: usize = 47;
|
||||
serialize_display_bounded_length!(self, MAX_LEN, serializer)
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -701,7 +693,7 @@ impl Serialize for net::SocketAddrV6 {
|
|||
#[cfg(feature = "std")]
|
||||
impl Serialize for path::Path {
|
||||
fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
|
||||
where S: Serializer,
|
||||
where S: Serializer
|
||||
{
|
||||
match self.to_str() {
|
||||
Some(s) => s.serialize(serializer),
|
||||
|
@ -713,7 +705,7 @@ impl Serialize for path::Path {
|
|||
#[cfg(feature = "std")]
|
||||
impl Serialize for path::PathBuf {
|
||||
fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
|
||||
where S: Serializer,
|
||||
where S: Serializer
|
||||
{
|
||||
self.as_path().serialize(serializer)
|
||||
}
|
||||
|
|
|
@ -2,17 +2,8 @@
|
|||
|
||||
use core::marker::PhantomData;
|
||||
|
||||
use ser::{
|
||||
self,
|
||||
Serialize,
|
||||
SerializeSeq,
|
||||
SerializeTuple,
|
||||
SerializeTupleStruct,
|
||||
SerializeTupleVariant,
|
||||
SerializeMap,
|
||||
SerializeStruct,
|
||||
SerializeStructVariant,
|
||||
};
|
||||
use ser::{self, Serialize, SerializeSeq, SerializeTuple, SerializeTupleStruct,
|
||||
SerializeTupleVariant, SerializeMap, SerializeStruct, SerializeStructVariant};
|
||||
|
||||
/// Helper type for implementing a `Serializer` that does not support
|
||||
/// serializing one of the compound types.
|
||||
|
@ -50,14 +41,12 @@ pub struct Impossible<Ok, E> {
|
|||
enum Void {}
|
||||
|
||||
impl<Ok, E> SerializeSeq for Impossible<Ok, E>
|
||||
where E: ser::Error,
|
||||
where E: ser::Error
|
||||
{
|
||||
type Ok = Ok;
|
||||
type Error = E;
|
||||
|
||||
fn serialize_element<T: ?Sized + Serialize>(&mut self,
|
||||
_value: &T)
|
||||
-> Result<(), E> {
|
||||
fn serialize_element<T: ?Sized + Serialize>(&mut self, _value: &T) -> Result<(), E> {
|
||||
match self.void {}
|
||||
}
|
||||
|
||||
|
@ -67,14 +56,12 @@ impl<Ok, E> SerializeSeq for Impossible<Ok, E>
|
|||
}
|
||||
|
||||
impl<Ok, E> SerializeTuple for Impossible<Ok, E>
|
||||
where E: ser::Error,
|
||||
where E: ser::Error
|
||||
{
|
||||
type Ok = Ok;
|
||||
type Error = E;
|
||||
|
||||
fn serialize_element<T: ?Sized + Serialize>(&mut self,
|
||||
_value: &T)
|
||||
-> Result<(), E> {
|
||||
fn serialize_element<T: ?Sized + Serialize>(&mut self, _value: &T) -> Result<(), E> {
|
||||
match self.void {}
|
||||
}
|
||||
|
||||
|
@ -84,14 +71,12 @@ impl<Ok, E> SerializeTuple for Impossible<Ok, E>
|
|||
}
|
||||
|
||||
impl<Ok, E> SerializeTupleStruct for Impossible<Ok, E>
|
||||
where E: ser::Error,
|
||||
where E: ser::Error
|
||||
{
|
||||
type Ok = Ok;
|
||||
type Error = E;
|
||||
|
||||
fn serialize_field<T: ?Sized + Serialize>(&mut self,
|
||||
_value: &T)
|
||||
-> Result<(), E> {
|
||||
fn serialize_field<T: ?Sized + Serialize>(&mut self, _value: &T) -> Result<(), E> {
|
||||
match self.void {}
|
||||
}
|
||||
|
||||
|
@ -101,14 +86,12 @@ impl<Ok, E> SerializeTupleStruct for Impossible<Ok, E>
|
|||
}
|
||||
|
||||
impl<Ok, E> SerializeTupleVariant for Impossible<Ok, E>
|
||||
where E: ser::Error,
|
||||
where E: ser::Error
|
||||
{
|
||||
type Ok = Ok;
|
||||
type Error = E;
|
||||
|
||||
fn serialize_field<T: ?Sized + Serialize>(&mut self,
|
||||
_value: &T)
|
||||
-> Result<(), E> {
|
||||
fn serialize_field<T: ?Sized + Serialize>(&mut self, _value: &T) -> Result<(), E> {
|
||||
match self.void {}
|
||||
}
|
||||
|
||||
|
@ -118,20 +101,16 @@ impl<Ok, E> SerializeTupleVariant for Impossible<Ok, E>
|
|||
}
|
||||
|
||||
impl<Ok, E> SerializeMap for Impossible<Ok, E>
|
||||
where E: ser::Error,
|
||||
where E: ser::Error
|
||||
{
|
||||
type Ok = Ok;
|
||||
type Error = E;
|
||||
|
||||
fn serialize_key<T: ?Sized + Serialize>(&mut self,
|
||||
_key: &T)
|
||||
-> Result<(), E> {
|
||||
fn serialize_key<T: ?Sized + Serialize>(&mut self, _key: &T) -> Result<(), E> {
|
||||
match self.void {}
|
||||
}
|
||||
|
||||
fn serialize_value<T: ?Sized + Serialize>(&mut self,
|
||||
_value: &T)
|
||||
-> Result<(), E> {
|
||||
fn serialize_value<T: ?Sized + Serialize>(&mut self, _value: &T) -> Result<(), E> {
|
||||
match self.void {}
|
||||
}
|
||||
|
||||
|
@ -141,13 +120,13 @@ impl<Ok, E> SerializeMap for Impossible<Ok, E>
|
|||
}
|
||||
|
||||
impl<Ok, E> SerializeStruct for Impossible<Ok, E>
|
||||
where E: ser::Error,
|
||||
where E: ser::Error
|
||||
{
|
||||
type Ok = Ok;
|
||||
type Error = E;
|
||||
|
||||
fn serialize_field<T: ?Sized + Serialize>(&mut self,
|
||||
_key: &'static str,
|
||||
_key: &'static str,
|
||||
_value: &T)
|
||||
-> Result<(), E> {
|
||||
match self.void {}
|
||||
|
@ -159,13 +138,13 @@ impl<Ok, E> SerializeStruct for Impossible<Ok, E>
|
|||
}
|
||||
|
||||
impl<Ok, E> SerializeStructVariant for Impossible<Ok, E>
|
||||
where E: ser::Error,
|
||||
where E: ser::Error
|
||||
{
|
||||
type Ok = Ok;
|
||||
type Error = E;
|
||||
|
||||
fn serialize_field<T: ?Sized + Serialize>(&mut self,
|
||||
_key: &'static str,
|
||||
_key: &'static str,
|
||||
_value: &T)
|
||||
-> Result<(), E> {
|
||||
match self.void {}
|
||||
|
|
|
@ -107,6 +107,8 @@ mod impossible;
|
|||
// Helpers used by generated code. Not public API.
|
||||
#[doc(hidden)]
|
||||
pub mod private;
|
||||
#[cfg(any(feature = "std", feature = "collections"))]
|
||||
mod content;
|
||||
|
||||
pub use self::impossible::Impossible;
|
||||
|
||||
|
@ -174,8 +176,7 @@ pub trait Serialize {
|
|||
/// for more information about how to implement this method.
|
||||
///
|
||||
/// [impl-serialize]: https://serde.rs/impl-serialize.html
|
||||
fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
|
||||
where S: Serializer;
|
||||
fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error> where S: Serializer;
|
||||
}
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
|
@ -254,31 +255,31 @@ pub trait Serializer: Sized {
|
|||
|
||||
/// Type returned from `serialize_seq` and `serialize_seq_fixed_size` for
|
||||
/// serializing the content of the sequence.
|
||||
type SerializeSeq: SerializeSeq<Ok=Self::Ok, Error=Self::Error>;
|
||||
type SerializeSeq: SerializeSeq<Ok = Self::Ok, Error = Self::Error>;
|
||||
|
||||
/// Type returned from `serialize_tuple` for serializing the content of the
|
||||
/// tuple.
|
||||
type SerializeTuple: SerializeTuple<Ok=Self::Ok, Error=Self::Error>;
|
||||
type SerializeTuple: SerializeTuple<Ok = Self::Ok, Error = Self::Error>;
|
||||
|
||||
/// Type returned from `serialize_tuple_struct` for serializing the content
|
||||
/// of the tuple struct.
|
||||
type SerializeTupleStruct: SerializeTupleStruct<Ok=Self::Ok, Error=Self::Error>;
|
||||
type SerializeTupleStruct: SerializeTupleStruct<Ok = Self::Ok, Error = Self::Error>;
|
||||
|
||||
/// Type returned from `serialize_tuple_variant` for serializing the content
|
||||
/// of the tuple variant.
|
||||
type SerializeTupleVariant: SerializeTupleVariant<Ok=Self::Ok, Error=Self::Error>;
|
||||
type SerializeTupleVariant: SerializeTupleVariant<Ok = Self::Ok, Error = Self::Error>;
|
||||
|
||||
/// Type returned from `serialize_map` for serializing the content of the
|
||||
/// map.
|
||||
type SerializeMap: SerializeMap<Ok=Self::Ok, Error=Self::Error>;
|
||||
type SerializeMap: SerializeMap<Ok = Self::Ok, Error = Self::Error>;
|
||||
|
||||
/// Type returned from `serialize_struct` for serializing the content of the
|
||||
/// struct.
|
||||
type SerializeStruct: SerializeStruct<Ok=Self::Ok, Error=Self::Error>;
|
||||
type SerializeStruct: SerializeStruct<Ok = Self::Ok, Error = Self::Error>;
|
||||
|
||||
/// Type returned from `serialize_struct_variant` for serializing the
|
||||
/// content of the struct variant.
|
||||
type SerializeStructVariant: SerializeStructVariant<Ok=Self::Ok, Error=Self::Error>;
|
||||
type SerializeStructVariant: SerializeStructVariant<Ok = Self::Ok, Error = Self::Error>;
|
||||
|
||||
/// Serialize a `bool` value.
|
||||
fn serialize_bool(self, v: bool) -> Result<Self::Ok, Self::Error>;
|
||||
|
@ -371,10 +372,7 @@ pub trait Serializer: Sized {
|
|||
fn serialize_none(self) -> Result<Self::Ok, Self::Error>;
|
||||
|
||||
/// Serialize a `Some(T)` value.
|
||||
fn serialize_some<T: ?Sized + Serialize>(
|
||||
self,
|
||||
value: &T,
|
||||
) -> Result<Self::Ok, Self::Error>;
|
||||
fn serialize_some<T: ?Sized + Serialize>(self, value: &T) -> Result<Self::Ok, Self::Error>;
|
||||
|
||||
/// Serialize a `()` value.
|
||||
fn serialize_unit(self) -> Result<Self::Ok, Self::Error>;
|
||||
|
@ -382,10 +380,7 @@ pub trait Serializer: Sized {
|
|||
/// Serialize a unit struct like `struct Unit` or `PhantomData<T>`.
|
||||
///
|
||||
/// A reasonable implementation would be to forward to `serialize_unit`.
|
||||
fn serialize_unit_struct(
|
||||
self,
|
||||
name: &'static str,
|
||||
) -> Result<Self::Ok, Self::Error>;
|
||||
fn serialize_unit_struct(self, name: &'static str) -> Result<Self::Ok, Self::Error>;
|
||||
|
||||
/// Serialize a unit variant like `E::A` in `enum E { A, B }`.
|
||||
///
|
||||
|
@ -401,12 +396,11 @@ pub trait Serializer: Sized {
|
|||
/// E::B => serializer.serialize_unit_variant("E", 1, "B"),
|
||||
/// }
|
||||
/// ```
|
||||
fn serialize_unit_variant(
|
||||
self,
|
||||
name: &'static str,
|
||||
variant_index: usize,
|
||||
variant: &'static str,
|
||||
) -> Result<Self::Ok, Self::Error>;
|
||||
fn serialize_unit_variant(self,
|
||||
name: &'static str,
|
||||
variant_index: usize,
|
||||
variant: &'static str)
|
||||
-> Result<Self::Ok, Self::Error>;
|
||||
|
||||
/// Serialize a newtype struct like `struct Millimeters(u8)`.
|
||||
///
|
||||
|
@ -417,11 +411,10 @@ pub trait Serializer: Sized {
|
|||
/// ```rust,ignore
|
||||
/// serializer.serialize_newtype_struct("Millimeters", &self.0)
|
||||
/// ```
|
||||
fn serialize_newtype_struct<T: ?Sized + Serialize>(
|
||||
self,
|
||||
name: &'static str,
|
||||
value: &T,
|
||||
) -> Result<Self::Ok, Self::Error>;
|
||||
fn serialize_newtype_struct<T: ?Sized + Serialize>(self,
|
||||
name: &'static str,
|
||||
value: &T)
|
||||
-> Result<Self::Ok, Self::Error>;
|
||||
|
||||
/// Serialize a newtype variant like `E::N` in `enum E { N(u8) }`.
|
||||
///
|
||||
|
@ -434,13 +427,12 @@ pub trait Serializer: Sized {
|
|||
/// E::N(ref n) => serializer.serialize_newtype_variant("E", 0, "N", n),
|
||||
/// }
|
||||
/// ```
|
||||
fn serialize_newtype_variant<T: ?Sized + Serialize>(
|
||||
self,
|
||||
name: &'static str,
|
||||
variant_index: usize,
|
||||
variant: &'static str,
|
||||
value: &T,
|
||||
) -> Result<Self::Ok, Self::Error>;
|
||||
fn serialize_newtype_variant<T: ?Sized + Serialize>(self,
|
||||
name: &'static str,
|
||||
variant_index: usize,
|
||||
variant: &'static str,
|
||||
value: &T)
|
||||
-> Result<Self::Ok, Self::Error>;
|
||||
|
||||
/// Begin to serialize a dynamically sized sequence. This call must be
|
||||
/// followed by zero or more calls to `serialize_element`, then a call to
|
||||
|
@ -457,10 +449,7 @@ pub trait Serializer: Sized {
|
|||
/// }
|
||||
/// seq.end()
|
||||
/// ```
|
||||
fn serialize_seq(
|
||||
self,
|
||||
len: Option<usize>,
|
||||
) -> Result<Self::SerializeSeq, Self::Error>;
|
||||
fn serialize_seq(self, len: Option<usize>) -> Result<Self::SerializeSeq, Self::Error>;
|
||||
|
||||
/// Begin to serialize a statically sized sequence whose length will be
|
||||
/// known at deserialization time without looking at the serialized data.
|
||||
|
@ -474,10 +463,7 @@ pub trait Serializer: Sized {
|
|||
/// }
|
||||
/// seq.end()
|
||||
/// ```
|
||||
fn serialize_seq_fixed_size(
|
||||
self,
|
||||
size: usize,
|
||||
) -> Result<Self::SerializeSeq, Self::Error>;
|
||||
fn serialize_seq_fixed_size(self, size: usize) -> Result<Self::SerializeSeq, Self::Error>;
|
||||
|
||||
/// Begin to serialize a tuple. This call must be followed by zero or more
|
||||
/// calls to `serialize_field`, then a call to `end`.
|
||||
|
@ -489,10 +475,7 @@ pub trait Serializer: Sized {
|
|||
/// tup.serialize_field(&self.2)?;
|
||||
/// tup.end()
|
||||
/// ```
|
||||
fn serialize_tuple(
|
||||
self,
|
||||
len: usize,
|
||||
) -> Result<Self::SerializeTuple, Self::Error>;
|
||||
fn serialize_tuple(self, len: usize) -> Result<Self::SerializeTuple, Self::Error>;
|
||||
|
||||
/// Begin to serialize a tuple struct like `struct Rgb(u8, u8, u8)`. This
|
||||
/// call must be followed by zero or more calls to `serialize_field`, then a
|
||||
|
@ -508,11 +491,10 @@ pub trait Serializer: Sized {
|
|||
/// ts.serialize_field(&self.2)?;
|
||||
/// ts.end()
|
||||
/// ```
|
||||
fn serialize_tuple_struct(
|
||||
self,
|
||||
name: &'static str,
|
||||
len: usize,
|
||||
) -> Result<Self::SerializeTupleStruct, Self::Error>;
|
||||
fn serialize_tuple_struct(self,
|
||||
name: &'static str,
|
||||
len: usize)
|
||||
-> Result<Self::SerializeTupleStruct, Self::Error>;
|
||||
|
||||
/// Begin to serialize a tuple variant like `E::T` in `enum E { T(u8, u8)
|
||||
/// }`. This call must be followed by zero or more calls to
|
||||
|
@ -532,13 +514,12 @@ pub trait Serializer: Sized {
|
|||
/// }
|
||||
/// }
|
||||
/// ```
|
||||
fn serialize_tuple_variant(
|
||||
self,
|
||||
name: &'static str,
|
||||
variant_index: usize,
|
||||
variant: &'static str,
|
||||
len: usize,
|
||||
) -> Result<Self::SerializeTupleVariant, Self::Error>;
|
||||
fn serialize_tuple_variant(self,
|
||||
name: &'static str,
|
||||
variant_index: usize,
|
||||
variant: &'static str,
|
||||
len: usize)
|
||||
-> Result<Self::SerializeTupleVariant, Self::Error>;
|
||||
|
||||
/// Begin to serialize a map. This call must be followed by zero or more
|
||||
/// calls to `serialize_key` and `serialize_value`, then a call to `end`.
|
||||
|
@ -554,10 +535,7 @@ pub trait Serializer: Sized {
|
|||
/// }
|
||||
/// map.end()
|
||||
/// ```
|
||||
fn serialize_map(
|
||||
self,
|
||||
len: Option<usize>,
|
||||
) -> Result<Self::SerializeMap, Self::Error>;
|
||||
fn serialize_map(self, len: Option<usize>) -> Result<Self::SerializeMap, Self::Error>;
|
||||
|
||||
/// Begin to serialize a struct like `struct Rgb { r: u8, g: u8, b: u8 }`.
|
||||
/// This call must be followed by zero or more calls to `serialize_field`,
|
||||
|
@ -573,11 +551,10 @@ pub trait Serializer: Sized {
|
|||
/// struc.serialize_field("b", &self.b)?;
|
||||
/// struc.end()
|
||||
/// ```
|
||||
fn serialize_struct(
|
||||
self,
|
||||
name: &'static str,
|
||||
len: usize,
|
||||
) -> Result<Self::SerializeStruct, Self::Error>;
|
||||
fn serialize_struct(self,
|
||||
name: &'static str,
|
||||
len: usize)
|
||||
-> Result<Self::SerializeStruct, Self::Error>;
|
||||
|
||||
/// Begin to serialize a struct variant like `E::S` in `enum E { S { r: u8,
|
||||
/// g: u8, b: u8 } }`. This call must be followed by zero or more calls to
|
||||
|
@ -598,13 +575,12 @@ pub trait Serializer: Sized {
|
|||
/// }
|
||||
/// }
|
||||
/// ```
|
||||
fn serialize_struct_variant(
|
||||
self,
|
||||
name: &'static str,
|
||||
variant_index: usize,
|
||||
variant: &'static str,
|
||||
len: usize,
|
||||
) -> Result<Self::SerializeStructVariant, Self::Error>;
|
||||
fn serialize_struct_variant(self,
|
||||
name: &'static str,
|
||||
variant_index: usize,
|
||||
variant: &'static str,
|
||||
len: usize)
|
||||
-> Result<Self::SerializeStructVariant, Self::Error>;
|
||||
|
||||
/// Collect an iterator as a sequence.
|
||||
///
|
||||
|
@ -613,7 +589,7 @@ pub trait Serializer: Sized {
|
|||
/// this method.
|
||||
fn collect_seq<I>(self, iter: I) -> Result<Self::Ok, Self::Error>
|
||||
where I: IntoIterator,
|
||||
<I as IntoIterator>::Item: Serialize,
|
||||
<I as IntoIterator>::Item: Serialize
|
||||
{
|
||||
let iter = iter.into_iter();
|
||||
let mut serializer = try!(self.serialize_seq(iter.len_hint()));
|
||||
|
@ -631,7 +607,7 @@ pub trait Serializer: Sized {
|
|||
fn collect_map<K, V, I>(self, iter: I) -> Result<Self::Ok, Self::Error>
|
||||
where K: Serialize,
|
||||
V: Serialize,
|
||||
I: IntoIterator<Item = (K, V)>,
|
||||
I: IntoIterator<Item = (K, V)>
|
||||
{
|
||||
let iter = iter.into_iter();
|
||||
let mut serializer = try!(self.serialize_map(iter.len_hint()));
|
||||
|
@ -773,11 +749,10 @@ pub trait SerializeMap {
|
|||
/// `serialize_value`. This is appropriate for serializers that do not care
|
||||
/// about performance or are not able to optimize `serialize_entry` any
|
||||
/// better than this.
|
||||
fn serialize_entry<K: ?Sized + Serialize, V: ?Sized + Serialize>(
|
||||
&mut self,
|
||||
key: &K,
|
||||
value: &V,
|
||||
) -> Result<(), Self::Error> {
|
||||
fn serialize_entry<K: ?Sized + Serialize, V: ?Sized + Serialize>(&mut self,
|
||||
key: &K,
|
||||
value: &V)
|
||||
-> Result<(), Self::Error> {
|
||||
try!(self.serialize_key(key));
|
||||
self.serialize_value(value)
|
||||
}
|
||||
|
@ -803,7 +778,10 @@ pub trait SerializeStruct {
|
|||
type Error: Error;
|
||||
|
||||
/// Serialize a struct field.
|
||||
fn serialize_field<T: ?Sized + Serialize>(&mut self, key: &'static str, value: &T) -> Result<(), Self::Error>;
|
||||
fn serialize_field<T: ?Sized + Serialize>(&mut self,
|
||||
key: &'static str,
|
||||
value: &T)
|
||||
-> Result<(), Self::Error>;
|
||||
|
||||
/// Finish serializing a struct.
|
||||
fn end(self) -> Result<Self::Ok, Self::Error>;
|
||||
|
@ -830,7 +808,10 @@ pub trait SerializeStructVariant {
|
|||
type Error: Error;
|
||||
|
||||
/// Serialize a struct variant field.
|
||||
fn serialize_field<T: ?Sized + Serialize>(&mut self, key: &'static str, value: &T) -> Result<(), Self::Error>;
|
||||
fn serialize_field<T: ?Sized + Serialize>(&mut self,
|
||||
key: &'static str,
|
||||
value: &T)
|
||||
-> Result<(), Self::Error>;
|
||||
|
||||
/// Finish serializing a struct variant.
|
||||
fn end(self) -> Result<Self::Ok, Self::Error>;
|
||||
|
|
|
@ -1,16 +1,18 @@
|
|||
use core::fmt::{self, Display};
|
||||
|
||||
use ser::{self, Serialize, Serializer, SerializeMap, SerializeStruct};
|
||||
use ser::{self, Serialize, Serializer, SerializeMap, SerializeStruct, Impossible};
|
||||
|
||||
#[cfg(any(feature = "std", feature = "collections"))]
|
||||
use ser::content::{SerializeTupleVariantAsMapValue, SerializeStructVariantAsMapValue};
|
||||
|
||||
/// Not public API.
|
||||
pub fn serialize_tagged_newtype<S, T>(
|
||||
serializer: S,
|
||||
type_ident: &'static str,
|
||||
variant_ident: &'static str,
|
||||
tag: &'static str,
|
||||
variant_name: &'static str,
|
||||
value: T,
|
||||
) -> Result<S::Ok, S::Error>
|
||||
pub fn serialize_tagged_newtype<S, T>(serializer: S,
|
||||
type_ident: &'static str,
|
||||
variant_ident: &'static str,
|
||||
tag: &'static str,
|
||||
variant_name: &'static str,
|
||||
value: T)
|
||||
-> Result<S::Ok, S::Error>
|
||||
where S: Serializer,
|
||||
T: Serialize
|
||||
{
|
||||
|
@ -44,6 +46,7 @@ enum Unsupported {
|
|||
Sequence,
|
||||
Tuple,
|
||||
TupleStruct,
|
||||
#[cfg(not(any(feature = "std", feature = "collections")))]
|
||||
Enum,
|
||||
}
|
||||
|
||||
|
@ -62,6 +65,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")))]
|
||||
Unsupported::Enum => formatter.write_str("an enum"),
|
||||
}
|
||||
}
|
||||
|
@ -99,13 +103,21 @@ impl<S> Serializer for TaggedSerializer<S>
|
|||
type Ok = S::Ok;
|
||||
type Error = S::Error;
|
||||
|
||||
type SerializeSeq = S::SerializeSeq;
|
||||
type SerializeTuple = S::SerializeTuple;
|
||||
type SerializeTupleStruct = S::SerializeTupleStruct;
|
||||
type SerializeTupleVariant = S::SerializeTupleVariant;
|
||||
type SerializeSeq = Impossible<S::Ok, S::Error>;
|
||||
type SerializeTuple = Impossible<S::Ok, S::Error>;
|
||||
type SerializeTupleStruct = Impossible<S::Ok, S::Error>;
|
||||
type SerializeMap = S::SerializeMap;
|
||||
type SerializeStruct = S::SerializeStruct;
|
||||
type SerializeStructVariant = S::SerializeStructVariant;
|
||||
|
||||
#[cfg(not(any(feature = "std", feature = "collections")))]
|
||||
type SerializeTupleVariant = Impossible<S::Ok, S::Error>;
|
||||
#[cfg(any(feature = "std", feature = "collections"))]
|
||||
type SerializeTupleVariant = SerializeTupleVariantAsMapValue<S::SerializeMap>;
|
||||
|
||||
#[cfg(not(any(feature = "std", feature = "collections")))]
|
||||
type SerializeStructVariant = Impossible<S::Ok, S::Error>;
|
||||
#[cfg(any(feature = "std", feature = "collections"))]
|
||||
type SerializeStructVariant = SerializeStructVariantAsMapValue<S::SerializeMap>;
|
||||
|
||||
fn serialize_bool(self, _: bool) -> Result<Self::Ok, Self::Error> {
|
||||
Err(self.bad_type(Unsupported::Boolean))
|
||||
|
@ -181,20 +193,38 @@ impl<S> Serializer for TaggedSerializer<S>
|
|||
Err(self.bad_type(Unsupported::UnitStruct))
|
||||
}
|
||||
|
||||
fn serialize_unit_variant(self, _: &'static str, _: usize, _: &'static str) -> Result<Self::Ok, Self::Error> {
|
||||
Err(self.bad_type(Unsupported::Enum))
|
||||
fn serialize_unit_variant(self,
|
||||
_: &'static str,
|
||||
_: usize,
|
||||
inner_variant: &'static str)
|
||||
-> Result<Self::Ok, Self::Error> {
|
||||
let mut map = try!(self.delegate.serialize_map(Some(2)));
|
||||
try!(map.serialize_entry(self.tag, self.variant_name));
|
||||
try!(map.serialize_entry(inner_variant, &()));
|
||||
map.end()
|
||||
}
|
||||
|
||||
fn serialize_newtype_struct<T: ?Sized>(self, _: &'static str, value: &T) -> Result<Self::Ok, Self::Error>
|
||||
fn serialize_newtype_struct<T: ?Sized>(self,
|
||||
_: &'static str,
|
||||
value: &T)
|
||||
-> Result<Self::Ok, Self::Error>
|
||||
where T: Serialize
|
||||
{
|
||||
value.serialize(self)
|
||||
}
|
||||
|
||||
fn serialize_newtype_variant<T: ?Sized>(self, _: &'static str, _: usize, _: &'static str, _: &T) -> Result<Self::Ok, Self::Error>
|
||||
fn serialize_newtype_variant<T: ?Sized>(self,
|
||||
_: &'static str,
|
||||
_: usize,
|
||||
inner_variant: &'static str,
|
||||
inner_value: &T)
|
||||
-> Result<Self::Ok, Self::Error>
|
||||
where T: Serialize
|
||||
{
|
||||
Err(self.bad_type(Unsupported::Enum))
|
||||
let mut map = try!(self.delegate.serialize_map(Some(2)));
|
||||
try!(map.serialize_entry(self.tag, self.variant_name));
|
||||
try!(map.serialize_entry(inner_variant, inner_value));
|
||||
map.end()
|
||||
}
|
||||
|
||||
fn serialize_seq(self, _: Option<usize>) -> Result<Self::SerializeSeq, Self::Error> {
|
||||
|
@ -209,27 +239,75 @@ impl<S> Serializer for TaggedSerializer<S>
|
|||
Err(self.bad_type(Unsupported::Tuple))
|
||||
}
|
||||
|
||||
fn serialize_tuple_struct(self, _: &'static str, _: usize) -> Result<Self::SerializeTupleStruct, Self::Error> {
|
||||
fn serialize_tuple_struct(self,
|
||||
_: &'static str,
|
||||
_: usize)
|
||||
-> Result<Self::SerializeTupleStruct, Self::Error> {
|
||||
Err(self.bad_type(Unsupported::TupleStruct))
|
||||
}
|
||||
|
||||
fn serialize_tuple_variant(self, _: &'static str, _: usize, _: &'static str, _: usize) -> Result<Self::SerializeTupleVariant, Self::Error> {
|
||||
#[cfg(not(any(feature = "std", feature = "collections")))]
|
||||
fn serialize_tuple_variant(self,
|
||||
_: &'static str,
|
||||
_: usize,
|
||||
_: &'static str,
|
||||
_: usize)
|
||||
-> Result<Self::SerializeTupleVariant, Self::Error> {
|
||||
// Lack of push-based serialization means we need to buffer the content
|
||||
// of the tuple variant, so it requires std.
|
||||
Err(self.bad_type(Unsupported::Enum))
|
||||
}
|
||||
|
||||
#[cfg(any(feature = "std", feature = "collections"))]
|
||||
fn serialize_tuple_variant(self,
|
||||
_: &'static str,
|
||||
_: usize,
|
||||
inner_variant: &'static str,
|
||||
len: usize)
|
||||
-> Result<Self::SerializeTupleVariant, Self::Error> {
|
||||
let mut map = try!(self.delegate.serialize_map(Some(2)));
|
||||
try!(map.serialize_entry(self.tag, self.variant_name));
|
||||
try!(map.serialize_key(inner_variant));
|
||||
Ok(SerializeTupleVariantAsMapValue::new(map, inner_variant, len))
|
||||
}
|
||||
|
||||
fn serialize_map(self, len: Option<usize>) -> Result<Self::SerializeMap, Self::Error> {
|
||||
let mut map = try!(self.delegate.serialize_map(len.map(|len| len + 1)));
|
||||
try!(map.serialize_entry(self.tag, self.variant_name));
|
||||
Ok(map)
|
||||
}
|
||||
|
||||
fn serialize_struct(self, name: &'static str, len: usize) -> Result<Self::SerializeStruct, Self::Error> {
|
||||
fn serialize_struct(self,
|
||||
name: &'static str,
|
||||
len: usize)
|
||||
-> Result<Self::SerializeStruct, Self::Error> {
|
||||
let mut state = try!(self.delegate.serialize_struct(name, len + 1));
|
||||
try!(state.serialize_field(self.tag, self.variant_name));
|
||||
Ok(state)
|
||||
}
|
||||
|
||||
fn serialize_struct_variant(self, _: &'static str, _: usize, _: &'static str, _: usize) -> Result<Self::SerializeStructVariant, Self::Error> {
|
||||
#[cfg(not(any(feature = "std", feature = "collections")))]
|
||||
fn serialize_struct_variant(self,
|
||||
_: &'static str,
|
||||
_: usize,
|
||||
_: &'static str,
|
||||
_: usize)
|
||||
-> Result<Self::SerializeStructVariant, Self::Error> {
|
||||
// Lack of push-based serialization means we need to buffer the content
|
||||
// of the struct variant, so it requires std.
|
||||
Err(self.bad_type(Unsupported::Enum))
|
||||
}
|
||||
|
||||
#[cfg(any(feature = "std", feature = "collections"))]
|
||||
fn serialize_struct_variant(self,
|
||||
_: &'static str,
|
||||
_: usize,
|
||||
inner_variant: &'static str,
|
||||
len: usize)
|
||||
-> Result<Self::SerializeStructVariant, Self::Error> {
|
||||
let mut map = try!(self.delegate.serialize_map(Some(2)));
|
||||
try!(map.serialize_entry(self.tag, self.variant_name));
|
||||
try!(map.serialize_key(inner_variant));
|
||||
Ok(SerializeStructVariantAsMapValue::new(map, inner_variant, len))
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,12 +1,12 @@
|
|||
//! Private utility functions
|
||||
|
||||
const TAG_CONT: u8 = 0b1000_0000;
|
||||
const TAG_TWO_B: u8 = 0b1100_0000;
|
||||
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;
|
||||
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 {
|
||||
|
@ -21,17 +21,20 @@ pub fn encode_utf8(c: char) -> EncodeUtf8 {
|
|||
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[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[2] = (code >> 6 & 0x3F) as u8 | TAG_CONT;
|
||||
buf[3] = (code & 0x3F) as u8 | TAG_CONT;
|
||||
0
|
||||
};
|
||||
EncodeUtf8 { buf: buf, pos: pos }
|
||||
EncodeUtf8 {
|
||||
buf: buf,
|
||||
pos: pos,
|
||||
}
|
||||
}
|
||||
|
||||
pub struct EncodeUtf8 {
|
||||
|
@ -47,23 +50,22 @@ impl EncodeUtf8 {
|
|||
}
|
||||
|
||||
#[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}')
|
||||
];
|
||||
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 {
|
||||
r.binary_search_by(|&(lo, hi)| if c < lo {
|
||||
Greater
|
||||
} else if hi < c {
|
||||
Less
|
||||
} else {
|
||||
Equal
|
||||
}
|
||||
})
|
||||
.is_ok()
|
||||
})
|
||||
.is_ok()
|
||||
}
|
||||
|
||||
#[allow(non_snake_case)]
|
||||
|
|
|
@ -1 +1 @@
|
|||
{"files":{".cargo-ok":"e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855","Cargo.toml":"c819ec91ff1c48b816f817bd2c7b30a8bd29515f970ed0215cf92114927d56c5","src/de.rs":"513e24c9b8da5472bb1039c26da498994c14ede3fcf56fad634db0aea04d5bfe","src/error.rs":"af2aaa123153b774cfc22a20dd540ff7e92cdb8d97335f19e5991a1bc79f8e8e","src/lib.rs":"340a83d8a158fd77fe71ce2fec5222e25ef692d6e95dae95a4a18a1749b6a95c","src/macros.rs":"a5b8d09dc71adc88180fe5b43de2438afe53ce3cad1023f813ad5da7b0677444","src/map.rs":"d317b80ccb30c6f4efd35d585ff5f83d5939ce70a255663b6a60a1314659a012","src/number.rs":"6dd7f28a89ff30a043edc56dd416f7420d9541d66c1448963c1686cb6d890c61","src/read.rs":"ee527e1d8462f20a986d2b37c502e7cd27fe46151fd241b751e6af3a6b20070f","src/ser.rs":"9ca1cdeda317630c240fbf8671cab5c14046fd65a987007c21d8d7e066e12382","src/value.rs":"67bd1088763f2f4760e6efc19be5d020737b8c59b19901616dad2007e141d54a"},"package":"cf37ce931677e98b4fa5e6469aaa3ab4b6228309ea33b1b22d3ec055adfc4515"}
|
||||
{"files":{".cargo-ok":"e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855","Cargo.toml":"9cec5418a9057b56d49b8f2e3b43f869e8f9d2f706caa5a16363e0663c9a166b","LICENSE-APACHE":"a60eea817514531668d7e00765731449fe14d059d3249e0bc93b36de45f759f2","LICENSE-MIT":"6485b8ed310d3f0340bf1ad1f47645069ce4069dcc6bb46c7d5c6faf41de1fdb","README.md":"ea5aacdf7067bf6e0e68ccf1b4a4a30b15af45fcfa628425b0cceee2cd632574","src/de.rs":"5663e0ff0d587a16ab0aad40c991f3283945ac66f551457006bcb384793dd4a6","src/error.rs":"2e2a388fd5dfc9445ba133268daddaa362e333883b8caadcf5bb7c1f5c4fecd5","src/lib.rs":"ec6758d1f31d9a2e9a1c2f103aa3f5536486b6a8d0357dd5137637f31d4ede61","src/macros.rs":"7476997fa78a020d5e9f95160b101d6367db1ecd39cb2faae61fa170ab219094","src/map.rs":"a6bccaeeba053c3ef7f06cb91e2668d995629b1a6d88c6cc823ebd41d6654536","src/number.rs":"7b684584a57aaf609462a709dafa646b1efdad75c7373f8cfec8c2d2c4271e26","src/read.rs":"8ca8c8a3d1155e15be1a0eafea0876895af72fad3fd7f87f2d590c1663750267","src/ser.rs":"9ca1cdeda317630c240fbf8671cab5c14046fd65a987007c21d8d7e066e12382","src/value.rs":"4f1a70e0f9a6a3bd96a72a00980c45df5582c24b88388c0b32c8cb5c239eed1b"},"package":"6501ac6f8b74f9b1033f7ddf79a08edfa0f58d6f8e3190cb8dc97736afa257a8"}
|
|
@ -1,14 +1,15 @@
|
|||
[package]
|
||||
name = "serde_json"
|
||||
version = "0.9.5"
|
||||
version = "0.9.8"
|
||||
authors = ["Erick Tryzelaar <erick.tryzelaar@gmail.com>"]
|
||||
license = "MIT/Apache-2.0"
|
||||
description = "A JSON serialization file format"
|
||||
repository = "https://github.com/serde-rs/json"
|
||||
documentation = "http://docs.serde.rs/serde_json/"
|
||||
readme = "../README.md"
|
||||
keywords = ["json", "serde", "serialization"]
|
||||
categories = ["encoding"]
|
||||
readme = "../README.md"
|
||||
include = ["Cargo.toml", "src/**/*.rs", "README.md", "LICENSE-APACHE", "LICENSE-MIT"]
|
||||
|
||||
[badges]
|
||||
travis-ci = { repository = "serde-rs/json" }
|
||||
|
@ -19,7 +20,7 @@ preserve_order = ["linked-hash-map"]
|
|||
[dependencies]
|
||||
serde = "0.9.4"
|
||||
num-traits = "0.1.32"
|
||||
linked-hash-map = { version = "0.3", optional = true }
|
||||
linked-hash-map = { version = "0.4.1", optional = true }
|
||||
itoa = "0.3"
|
||||
dtoa = "0.4"
|
||||
|
||||
|
|
|
@ -0,0 +1,201 @@
|
|||
Apache License
|
||||
Version 2.0, January 2004
|
||||
http://www.apache.org/licenses/
|
||||
|
||||
TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
|
||||
|
||||
1. Definitions.
|
||||
|
||||
"License" shall mean the terms and conditions for use, reproduction,
|
||||
and distribution as defined by Sections 1 through 9 of this document.
|
||||
|
||||
"Licensor" shall mean the copyright owner or entity authorized by
|
||||
the copyright owner that is granting the License.
|
||||
|
||||
"Legal Entity" shall mean the union of the acting entity and all
|
||||
other entities that control, are controlled by, or are under common
|
||||
control with that entity. For the purposes of this definition,
|
||||
"control" means (i) the power, direct or indirect, to cause the
|
||||
direction or management of such entity, whether by contract or
|
||||
otherwise, or (ii) ownership of fifty percent (50%) or more of the
|
||||
outstanding shares, or (iii) beneficial ownership of such entity.
|
||||
|
||||
"You" (or "Your") shall mean an individual or Legal Entity
|
||||
exercising permissions granted by this License.
|
||||
|
||||
"Source" form shall mean the preferred form for making modifications,
|
||||
including but not limited to software source code, documentation
|
||||
source, and configuration files.
|
||||
|
||||
"Object" form shall mean any form resulting from mechanical
|
||||
transformation or translation of a Source form, including but
|
||||
not limited to compiled object code, generated documentation,
|
||||
and conversions to other media types.
|
||||
|
||||
"Work" shall mean the work of authorship, whether in Source or
|
||||
Object form, made available under the License, as indicated by a
|
||||
copyright notice that is included in or attached to the work
|
||||
(an example is provided in the Appendix below).
|
||||
|
||||
"Derivative Works" shall mean any work, whether in Source or Object
|
||||
form, that is based on (or derived from) the Work and for which the
|
||||
editorial revisions, annotations, elaborations, or other modifications
|
||||
represent, as a whole, an original work of authorship. For the purposes
|
||||
of this License, Derivative Works shall not include works that remain
|
||||
separable from, or merely link (or bind by name) to the interfaces of,
|
||||
the Work and Derivative Works thereof.
|
||||
|
||||
"Contribution" shall mean any work of authorship, including
|
||||
the original version of the Work and any modifications or additions
|
||||
to that Work or Derivative Works thereof, that is intentionally
|
||||
submitted to Licensor for inclusion in the Work by the copyright owner
|
||||
or by an individual or Legal Entity authorized to submit on behalf of
|
||||
the copyright owner. For the purposes of this definition, "submitted"
|
||||
means any form of electronic, verbal, or written communication sent
|
||||
to the Licensor or its representatives, including but not limited to
|
||||
communication on electronic mailing lists, source code control systems,
|
||||
and issue tracking systems that are managed by, or on behalf of, the
|
||||
Licensor for the purpose of discussing and improving the Work, but
|
||||
excluding communication that is conspicuously marked or otherwise
|
||||
designated in writing by the copyright owner as "Not a Contribution."
|
||||
|
||||
"Contributor" shall mean Licensor and any individual or Legal Entity
|
||||
on behalf of whom a Contribution has been received by Licensor and
|
||||
subsequently incorporated within the Work.
|
||||
|
||||
2. Grant of Copyright License. Subject to the terms and conditions of
|
||||
this License, each Contributor hereby grants to You a perpetual,
|
||||
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
|
||||
copyright license to reproduce, prepare Derivative Works of,
|
||||
publicly display, publicly perform, sublicense, and distribute the
|
||||
Work and such Derivative Works in Source or Object form.
|
||||
|
||||
3. Grant of Patent License. Subject to the terms and conditions of
|
||||
this License, each Contributor hereby grants to You a perpetual,
|
||||
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
|
||||
(except as stated in this section) patent license to make, have made,
|
||||
use, offer to sell, sell, import, and otherwise transfer the Work,
|
||||
where such license applies only to those patent claims licensable
|
||||
by such Contributor that are necessarily infringed by their
|
||||
Contribution(s) alone or by combination of their Contribution(s)
|
||||
with the Work to which such Contribution(s) was submitted. If You
|
||||
institute patent litigation against any entity (including a
|
||||
cross-claim or counterclaim in a lawsuit) alleging that the Work
|
||||
or a Contribution incorporated within the Work constitutes direct
|
||||
or contributory patent infringement, then any patent licenses
|
||||
granted to You under this License for that Work shall terminate
|
||||
as of the date such litigation is filed.
|
||||
|
||||
4. Redistribution. You may reproduce and distribute copies of the
|
||||
Work or Derivative Works thereof in any medium, with or without
|
||||
modifications, and in Source or Object form, provided that You
|
||||
meet the following conditions:
|
||||
|
||||
(a) You must give any other recipients of the Work or
|
||||
Derivative Works a copy of this License; and
|
||||
|
||||
(b) You must cause any modified files to carry prominent notices
|
||||
stating that You changed the files; and
|
||||
|
||||
(c) You must retain, in the Source form of any Derivative Works
|
||||
that You distribute, all copyright, patent, trademark, and
|
||||
attribution notices from the Source form of the Work,
|
||||
excluding those notices that do not pertain to any part of
|
||||
the Derivative Works; and
|
||||
|
||||
(d) If the Work includes a "NOTICE" text file as part of its
|
||||
distribution, then any Derivative Works that You distribute must
|
||||
include a readable copy of the attribution notices contained
|
||||
within such NOTICE file, excluding those notices that do not
|
||||
pertain to any part of the Derivative Works, in at least one
|
||||
of the following places: within a NOTICE text file distributed
|
||||
as part of the Derivative Works; within the Source form or
|
||||
documentation, if provided along with the Derivative Works; or,
|
||||
within a display generated by the Derivative Works, if and
|
||||
wherever such third-party notices normally appear. The contents
|
||||
of the NOTICE file are for informational purposes only and
|
||||
do not modify the License. You may add Your own attribution
|
||||
notices within Derivative Works that You distribute, alongside
|
||||
or as an addendum to the NOTICE text from the Work, provided
|
||||
that such additional attribution notices cannot be construed
|
||||
as modifying the License.
|
||||
|
||||
You may add Your own copyright statement to Your modifications and
|
||||
may provide additional or different license terms and conditions
|
||||
for use, reproduction, or distribution of Your modifications, or
|
||||
for any such Derivative Works as a whole, provided Your use,
|
||||
reproduction, and distribution of the Work otherwise complies with
|
||||
the conditions stated in this License.
|
||||
|
||||
5. Submission of Contributions. Unless You explicitly state otherwise,
|
||||
any Contribution intentionally submitted for inclusion in the Work
|
||||
by You to the Licensor shall be under the terms and conditions of
|
||||
this License, without any additional terms or conditions.
|
||||
Notwithstanding the above, nothing herein shall supersede or modify
|
||||
the terms of any separate license agreement you may have executed
|
||||
with Licensor regarding such Contributions.
|
||||
|
||||
6. Trademarks. This License does not grant permission to use the trade
|
||||
names, trademarks, service marks, or product names of the Licensor,
|
||||
except as required for reasonable and customary use in describing the
|
||||
origin of the Work and reproducing the content of the NOTICE file.
|
||||
|
||||
7. Disclaimer of Warranty. Unless required by applicable law or
|
||||
agreed to in writing, Licensor provides the Work (and each
|
||||
Contributor provides its Contributions) on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
|
||||
implied, including, without limitation, any warranties or conditions
|
||||
of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
|
||||
PARTICULAR PURPOSE. You are solely responsible for determining the
|
||||
appropriateness of using or redistributing the Work and assume any
|
||||
risks associated with Your exercise of permissions under this License.
|
||||
|
||||
8. Limitation of Liability. In no event and under no legal theory,
|
||||
whether in tort (including negligence), contract, or otherwise,
|
||||
unless required by applicable law (such as deliberate and grossly
|
||||
negligent acts) or agreed to in writing, shall any Contributor be
|
||||
liable to You for damages, including any direct, indirect, special,
|
||||
incidental, or consequential damages of any character arising as a
|
||||
result of this License or out of the use or inability to use the
|
||||
Work (including but not limited to damages for loss of goodwill,
|
||||
work stoppage, computer failure or malfunction, or any and all
|
||||
other commercial damages or losses), even if such Contributor
|
||||
has been advised of the possibility of such damages.
|
||||
|
||||
9. Accepting Warranty or Additional Liability. While redistributing
|
||||
the Work or Derivative Works thereof, You may choose to offer,
|
||||
and charge a fee for, acceptance of support, warranty, indemnity,
|
||||
or other liability obligations and/or rights consistent with this
|
||||
License. However, in accepting such obligations, You may act only
|
||||
on Your own behalf and on Your sole responsibility, not on behalf
|
||||
of any other Contributor, and only if You agree to indemnify,
|
||||
defend, and hold each Contributor harmless for any liability
|
||||
incurred by, or claims asserted against, such Contributor by reason
|
||||
of your accepting any such warranty or additional liability.
|
||||
|
||||
END OF TERMS AND CONDITIONS
|
||||
|
||||
APPENDIX: How to apply the Apache License to your work.
|
||||
|
||||
To apply the Apache License to your work, attach the following
|
||||
boilerplate notice, with the fields enclosed by brackets "[]"
|
||||
replaced with your own identifying information. (Don't include
|
||||
the brackets!) The text should be enclosed in the appropriate
|
||||
comment syntax for the file format. We also recommend that a
|
||||
file or class name and description of purpose be included on the
|
||||
same "printed page" as the copyright notice for easier
|
||||
identification within third-party archives.
|
||||
|
||||
Copyright [yyyy] [name of copyright owner]
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
|
@ -0,0 +1,25 @@
|
|||
Copyright (c) 2014 The Rust Project Developers
|
||||
|
||||
Permission is hereby granted, free of charge, to any
|
||||
person obtaining a copy of this software and associated
|
||||
documentation files (the "Software"), to deal in the
|
||||
Software without restriction, including without
|
||||
limitation the rights to use, copy, modify, merge,
|
||||
publish, distribute, sublicense, and/or sell copies of
|
||||
the Software, and to permit persons to whom the Software
|
||||
is furnished to do so, subject to the following
|
||||
conditions:
|
||||
|
||||
The above copyright notice and this permission notice
|
||||
shall be included in all copies or substantial portions
|
||||
of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF
|
||||
ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED
|
||||
TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A
|
||||
PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT
|
||||
SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
|
||||
CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
|
||||
OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR
|
||||
IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
|
||||
DEALINGS IN THE SOFTWARE.
|
|
@ -0,0 +1,252 @@
|
|||
# Serde JSON   [![Build Status](https://api.travis-ci.org/serde-rs/json.svg?branch=master)](https://travis-ci.org/serde-rs/json) [![Latest Version](https://img.shields.io/crates/v/serde_json.svg)](https://crates.io/crates/serde\_json)
|
||||
|
||||
**Serde is a framework for *ser*ializing and *de*serializing Rust data structures efficiently and generically.**
|
||||
|
||||
---
|
||||
|
||||
```toml
|
||||
[dependencies]
|
||||
serde_json = "0.9"
|
||||
```
|
||||
|
||||
You may be looking for:
|
||||
|
||||
- [JSON API documentation](https://docs.serde.rs/serde_json/)
|
||||
- [Serde API documentation](https://docs.serde.rs/serde/)
|
||||
- [Detailed documentation about Serde](https://serde.rs/)
|
||||
- [Setting up `#[derive(Serialize, Deserialize)]`](https://serde.rs/codegen.html)
|
||||
- [Release notes](https://github.com/serde-rs/json/releases)
|
||||
|
||||
JSON is a ubiquitous open-standard format that uses human-readable text to
|
||||
transmit data objects consisting of key-value pairs.
|
||||
|
||||
```json,ignore
|
||||
{
|
||||
"name": "John Doe",
|
||||
"age": 43,
|
||||
"address": {
|
||||
"street": "10 Downing Street",
|
||||
"city": "London"
|
||||
},
|
||||
"phones": [
|
||||
"+44 1234567",
|
||||
"+44 2345678"
|
||||
]
|
||||
}
|
||||
```
|
||||
|
||||
There are three common ways that you might find yourself needing to work
|
||||
with JSON data in Rust.
|
||||
|
||||
- **As text data.** An unprocessed string of JSON data that you receive on
|
||||
an HTTP endpoint, read from a file, or prepare to send to a remote
|
||||
server.
|
||||
- **As an untyped or loosely typed representation.** Maybe you want to
|
||||
check that some JSON data is valid before passing it on, but without
|
||||
knowing the structure of what it contains. Or you want to do very basic
|
||||
manipulations like add a level of nesting.
|
||||
- **As a strongly typed Rust data structure.** When you expect all or most
|
||||
of your data to conform to a particular structure and want to get real
|
||||
work done without JSON's loosey-goosey nature tripping you up.
|
||||
|
||||
Serde JSON provides efficient, flexible, safe ways of converting data
|
||||
between each of these representations.
|
||||
|
||||
## JSON to the Value enum
|
||||
|
||||
Any valid JSON data can be manipulated in the following recursive enum
|
||||
representation. This data structure is [`serde_json::Value`][value].
|
||||
|
||||
```rust,ignore
|
||||
enum Value {
|
||||
Null,
|
||||
Bool(bool),
|
||||
Number(Number),
|
||||
String(String),
|
||||
Array(Vec<Value>),
|
||||
Object(Map<String, Value>),
|
||||
}
|
||||
```
|
||||
|
||||
A string of JSON data can be parsed into a `serde_json::Value` by the
|
||||
[`serde_json::from_str`][from_str] function. There is also
|
||||
[`from_slice`][from_slice] for parsing from a byte slice &[u8],
|
||||
[`from_iter`][from_iter] for parsing from an iterator of bytes, and
|
||||
[`from_reader`][from_reader] for parsing from any `io::Read` like a File or
|
||||
a TCP stream.
|
||||
|
||||
```rust
|
||||
use serde_json::Value;
|
||||
|
||||
let data = r#" { "name": "John Doe", "age": 43, ... } "#;
|
||||
let v: Value = serde_json::from_str(data)?;
|
||||
println!("Please call {} at the number {}", v["name"], v["phones"][0]);
|
||||
```
|
||||
|
||||
The `Value` representation is sufficient for very basic tasks but is brittle
|
||||
and tedious to work with. Error handling is verbose to implement correctly,
|
||||
for example imagine trying to detect the presence of unrecognized fields in
|
||||
the input data. The compiler is powerless to help you when you make a
|
||||
mistake, for example imagine typoing `v["name"]` as `v["nmae"]` in one of
|
||||
the dozens of places it is used in your code.
|
||||
|
||||
## JSON to strongly typed data structures
|
||||
|
||||
Serde provides a powerful way of mapping JSON data into Rust data structures
|
||||
largely automatically.
|
||||
|
||||
```rust
|
||||
#[derive(Serialize, Deserialize)]
|
||||
struct Person {
|
||||
name: String,
|
||||
age: u8,
|
||||
address: Address,
|
||||
phones: Vec<String>,
|
||||
}
|
||||
|
||||
#[derive(Serialize, Deserialize)]
|
||||
struct Address {
|
||||
street: String,
|
||||
city: String,
|
||||
}
|
||||
|
||||
let data = r#" { "name": "John Doe", "age": 43, ... } "#;
|
||||
let p: Person = serde_json::from_str(data)?;
|
||||
println!("Please call {} at the number {}", p.name, p.phones[0]);
|
||||
```
|
||||
|
||||
This is the same `serde_json::from_str` function as before, but this time we
|
||||
assign the return value to a variable of type `Person` so Serde JSON will
|
||||
automatically interpret the input data as a `Person` and produce informative
|
||||
error messages if the layout does not conform to what a `Person` is expected
|
||||
to look like.
|
||||
|
||||
Any type that implements Serde's `Deserialize` trait can be deserialized
|
||||
this way. This includes built-in Rust standard library types like `Vec<T>`
|
||||
and `HashMap<K, V>`, as well as any structs or enums annotated with
|
||||
`#[derive(Deserialize)]`.
|
||||
|
||||
Once we have `p` of type `Person`, our IDE and the Rust compiler can help us
|
||||
use it correctly like they do for any other Rust code. The IDE can
|
||||
autocomplete field names to prevent typos, which was impossible in the
|
||||
`serde_json::Value` representation. And the Rust compiler can check that
|
||||
when we write `p.phones[0]`, then `p.phones` is guaranteed to be a
|
||||
`Vec<String>` so indexing into it makes sense and produces a `String`.
|
||||
|
||||
## Constructing JSON
|
||||
|
||||
Serde JSON provides a [`json!` macro][macro] to build `serde_json::Value`
|
||||
objects with very natural JSON syntax. In order to use this macro,
|
||||
`serde_json` needs to be imported with the `#[macro_use]` attribute.
|
||||
|
||||
```rust
|
||||
#[macro_use]
|
||||
extern crate serde_json;
|
||||
|
||||
fn main() {
|
||||
// The type of `john` is `serde_json::Value`
|
||||
let john = json!({
|
||||
"name": "John Doe",
|
||||
"age": 43,
|
||||
"phones": [
|
||||
"+44 1234567",
|
||||
"+44 2345678"
|
||||
]
|
||||
});
|
||||
|
||||
println!("first phone number: {}", john["phones"][0]);
|
||||
|
||||
// Convert to a string of JSON and print it out
|
||||
println!("{}", john.to_string());
|
||||
}
|
||||
```
|
||||
|
||||
The `Value::to_string()` function converts a `serde_json::Value` into a
|
||||
`String` of JSON text.
|
||||
|
||||
One neat thing about the `json!` macro is that variables and expressions can
|
||||
be interpolated directly into the JSON value as you are building it. Serde
|
||||
will check at compile time that the value you are interpolating is able to
|
||||
be represented as JSON.
|
||||
|
||||
```rust
|
||||
let full_name = "John Doe";
|
||||
let age_last_year = 42;
|
||||
|
||||
// The type of `john` is `serde_json::Value`
|
||||
let john = json!({
|
||||
"name": full_name,
|
||||
"age": age_last_year + 1,
|
||||
"phones": [
|
||||
format!("+44 {}", random_phone())
|
||||
]
|
||||
});
|
||||
```
|
||||
|
||||
This is amazingly convenient but we have the problem we had before with
|
||||
`Value` which is that the IDE and Rust compiler cannot help us if we get it
|
||||
wrong. Serde JSON provides a better way of serializing strongly-typed data
|
||||
structures into JSON text.
|
||||
|
||||
## Serializing data structures
|
||||
|
||||
A data structure can be converted to a JSON string by
|
||||
[`serde_json::to_string`][to_string]. There is also
|
||||
[`serde_json::to_vec`][to_vec] which serializes to a `Vec<u8>` and
|
||||
[`serde_json::to_writer`][to_writer] which serializes to any `io::Write`
|
||||
such as a File or a TCP stream.
|
||||
|
||||
```rust
|
||||
#[derive(Serialize, Deserialize)]
|
||||
struct Address {
|
||||
street: String,
|
||||
city: String,
|
||||
}
|
||||
|
||||
let address = Address {
|
||||
street: "10 Downing Street".to_owned(),
|
||||
city: "London".to_owned(),
|
||||
};
|
||||
|
||||
let j = serde_json::to_string(&address)?;
|
||||
```
|
||||
|
||||
Any type that implements Serde's `Serialize` trait can be serialized this
|
||||
way. This includes built-in Rust standard library types like `Vec<T>` and
|
||||
`HashMap<K, V>`, as well as any structs or enums annotated with
|
||||
`#[derive(Serialize)]`.
|
||||
|
||||
## Getting help
|
||||
|
||||
Serde developers live in the #serde channel on
|
||||
[`irc.mozilla.org`](https://wiki.mozilla.org/IRC). The #rust channel is also a
|
||||
good resource with generally faster response time but less specific knowledge
|
||||
about Serde. If IRC is not your thing, we are happy to respond to [GitHub
|
||||
issues](https://github.com/serde-rs/json/issues/new) as well.
|
||||
|
||||
## License
|
||||
|
||||
Serde JSON is licensed under either of
|
||||
|
||||
* Apache License, Version 2.0, ([LICENSE-APACHE](LICENSE-APACHE) or
|
||||
http://www.apache.org/licenses/LICENSE-2.0)
|
||||
* MIT license ([LICENSE-MIT](LICENSE-MIT) or
|
||||
http://opensource.org/licenses/MIT)
|
||||
|
||||
at your option.
|
||||
|
||||
### Contribution
|
||||
|
||||
Unless you explicitly state otherwise, any contribution intentionally submitted
|
||||
for inclusion in Serde JSON by you, as defined in the Apache-2.0 license, shall
|
||||
be dual licensed as above, without any additional terms or conditions.
|
||||
|
||||
[value]: https://docs.serde.rs/serde_json/value/enum.Value.html
|
||||
[from_str]: https://docs.serde.rs/serde_json/de/fn.from_str.html
|
||||
[from_slice]: https://docs.serde.rs/serde_json/de/fn.from_slice.html
|
||||
[from_iter]: https://docs.serde.rs/serde_json/de/fn.from_iter.html
|
||||
[from_reader]: https://docs.serde.rs/serde_json/de/fn.from_reader.html
|
||||
[to_string]: https://docs.serde.rs/serde_json/ser/fn.to_string.html
|
||||
[to_vec]: https://docs.serde.rs/serde_json/ser/fn.to_vec.html
|
||||
[to_writer]: https://docs.serde.rs/serde_json/ser/fn.to_writer.html
|
||||
[macro]: https://docs.serde.rs/serde_json/macro.json.html
|
|
@ -8,7 +8,9 @@ use serde::de::{self, Unexpected};
|
|||
|
||||
use super::error::{Error, ErrorCode, Result};
|
||||
|
||||
use read::{self, Read};
|
||||
use read;
|
||||
|
||||
pub use read::{Read, IteratorRead, SliceRead, StrRead};
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
|
@ -19,8 +21,19 @@ pub struct Deserializer<R> {
|
|||
remaining_depth: u8,
|
||||
}
|
||||
|
||||
impl<R> Deserializer<R> {
|
||||
fn new(read: R) -> Self {
|
||||
impl<R> Deserializer<R>
|
||||
where R: read::Read
|
||||
{
|
||||
/// Create a JSON deserializer from one of the possible serde_json input
|
||||
/// sources.
|
||||
///
|
||||
/// Typically it is more convenient to use one of these methods instead:
|
||||
///
|
||||
/// - Deserializer::from_str
|
||||
/// - Deserializer::from_bytes
|
||||
/// - Deserializer::from_iter
|
||||
/// - Deserializer::from_reader
|
||||
pub fn new(read: R) -> Self {
|
||||
Deserializer {
|
||||
read: read,
|
||||
str_buf: Vec::with_capacity(128),
|
||||
|
@ -32,30 +45,30 @@ impl<R> Deserializer<R> {
|
|||
impl<I> Deserializer<read::IteratorRead<I>>
|
||||
where I: Iterator<Item = io::Result<u8>>
|
||||
{
|
||||
/// Creates a JSON parser from a `std::iter::Iterator`.
|
||||
/// Creates a JSON deserializer from a `std::iter::Iterator`.
|
||||
pub fn from_iter(iter: I) -> Self {
|
||||
Deserializer::new(read::IteratorRead::new(iter))
|
||||
}
|
||||
}
|
||||
|
||||
impl<R> Deserializer<read::IteratorRead<io::Bytes<R>>>
|
||||
impl<R> Deserializer<read::IoRead<R>>
|
||||
where R: io::Read
|
||||
{
|
||||
/// Creates a JSON parser from an `io::Read`.
|
||||
/// Creates a JSON deserializer from an `io::Read`.
|
||||
pub fn from_reader(reader: R) -> Self {
|
||||
Deserializer::new(read::IteratorRead::new(reader.bytes()))
|
||||
Deserializer::new(read::IoRead::new(reader))
|
||||
}
|
||||
}
|
||||
|
||||
impl<'a> Deserializer<read::SliceRead<'a>> {
|
||||
/// Creates a JSON parser from a `&[u8]`.
|
||||
/// Creates a JSON deserializer from a `&[u8]`.
|
||||
pub fn from_slice(bytes: &'a [u8]) -> Self {
|
||||
Deserializer::new(read::SliceRead::new(bytes))
|
||||
}
|
||||
}
|
||||
|
||||
impl<'a> Deserializer<read::StrRead<'a>> {
|
||||
/// Creates a JSON parser from a `&str`.
|
||||
/// Creates a JSON deserializer from a `&str`.
|
||||
pub fn from_str(s: &'a str) -> Self {
|
||||
Deserializer::new(read::StrRead::new(s))
|
||||
}
|
||||
|
@ -647,9 +660,69 @@ impl<'a, R: Read> de::Deserializer for &'a mut Deserializer<R> {
|
|||
}
|
||||
}
|
||||
|
||||
/// Parses a JSON string as bytes. Note that this function does not
|
||||
/// check whether the bytes represent valid unicode code points.
|
||||
///
|
||||
/// The JSON specification requires that strings only contain valid
|
||||
/// unicode characters. To deal with non-conforming JSON, you may use
|
||||
/// this function, which attempts to parse a string without checking
|
||||
/// whether the bytes represent valid unicode code points.
|
||||
///
|
||||
/// Escape sequences are processed as usual, and for `\uXXXX` escapes
|
||||
/// it is still checked if the hex number represents a valid unicode
|
||||
/// code point.
|
||||
///
|
||||
/// # Example usage
|
||||
///
|
||||
/// You can use this to parse JSON strings containing non-unicode bytes:
|
||||
///
|
||||
/// ```
|
||||
/// # extern crate serde;
|
||||
/// # extern crate serde_json;
|
||||
/// #
|
||||
/// let bytes = serde::bytes::ByteBuf::from(b"some raw bytes: \xe5\x00\xe5".to_vec());
|
||||
/// let parsed = serde_json::from_slice( b"\"some raw bytes: \xe5\x00\xe5\"").unwrap();
|
||||
///
|
||||
/// assert_eq!(bytes, parsed);
|
||||
/// ```
|
||||
///
|
||||
/// `\u` escape sequences with invalid unicode code points still fail to parse:
|
||||
///
|
||||
/// ```
|
||||
/// # extern crate serde;
|
||||
/// # extern crate serde_json;
|
||||
/// #
|
||||
/// let json = "\"invalid unicode surrogate: \\uD801\"";
|
||||
/// let parsed: Result<serde::bytes::ByteBuf, _> = serde_json::from_str(json);
|
||||
/// assert!(parsed.is_err(), "{} should not parse: {:?}", json, parsed);
|
||||
/// ```
|
||||
fn deserialize_bytes<V>(self, visitor: V) -> Result<V::Value>
|
||||
where V: de::Visitor
|
||||
{
|
||||
try!(self.parse_whitespace());
|
||||
|
||||
match try!(self.peek_or_null()) {
|
||||
b'"' => {
|
||||
self.eat_char();
|
||||
self.str_buf.clear();
|
||||
let slice = try!(self.read.parse_str_raw(&mut self.str_buf));
|
||||
visitor.visit_bytes(slice)
|
||||
}
|
||||
_ => self.deserialize(visitor),
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn deserialize_byte_buf<V>(self, visitor: V) -> Result<V::Value>
|
||||
where V: de::Visitor
|
||||
{
|
||||
self.deserialize_bytes(visitor)
|
||||
}
|
||||
|
||||
forward_to_deserialize! {
|
||||
bool u8 u16 u32 u64 i8 i16 i32 i64 f32 f64 char str string unit seq
|
||||
seq_fixed_size bytes byte_buf map unit_struct tuple_struct struct
|
||||
seq_fixed_size map unit_struct tuple_struct struct
|
||||
struct_field tuple ignored_any
|
||||
}
|
||||
}
|
||||
|
@ -873,14 +946,51 @@ impl<'a, R: Read + 'a> de::VariantVisitor for UnitVariantVisitor<'a, R> {
|
|||
//////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
/// Iterator that deserializes a stream into multiple JSON values.
|
||||
pub struct StreamDeserializer<R, T>
|
||||
where R: Read,
|
||||
T: de::Deserialize,
|
||||
{
|
||||
///
|
||||
/// A stream deserializer can be created from any JSON deserializer using the
|
||||
/// `Deserializer::into_iter` method.
|
||||
///
|
||||
/// ```rust
|
||||
/// extern crate serde_json;
|
||||
///
|
||||
/// use serde_json::{Deserializer, Value};
|
||||
///
|
||||
/// fn main() {
|
||||
/// let data = "1 2 {\"k\": 3}";
|
||||
///
|
||||
/// let stream = Deserializer::from_str(data).into_iter::<Value>();
|
||||
///
|
||||
/// for value in stream {
|
||||
/// println!("{}", value.unwrap());
|
||||
/// }
|
||||
/// }
|
||||
/// ```
|
||||
pub struct StreamDeserializer<R, T> {
|
||||
de: Deserializer<R>,
|
||||
_marker: PhantomData<T>,
|
||||
}
|
||||
|
||||
impl<R, T> StreamDeserializer<R, T>
|
||||
where R: read::Read,
|
||||
T: de::Deserialize
|
||||
{
|
||||
/// Create a JSON stream deserializer from one of the possible serde_json
|
||||
/// input sources.
|
||||
///
|
||||
/// Typically it is more convenient to use one of these methods instead:
|
||||
///
|
||||
/// - Deserializer::from_str(...).into_iter()
|
||||
/// - Deserializer::from_bytes(...).into_iter()
|
||||
/// - Deserializer::from_iter(...).into_iter()
|
||||
/// - Deserializer::from_reader(...).into_iter()
|
||||
pub fn new(read: R) -> Self {
|
||||
StreamDeserializer {
|
||||
de: Deserializer::new(read),
|
||||
_marker: PhantomData,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl<R, T> Iterator for StreamDeserializer<R, T>
|
||||
where R: Read,
|
||||
T: de::Deserialize,
|
||||
|
|
|
@ -59,6 +59,9 @@ pub enum ErrorCode {
|
|||
/// Expected this character to start a JSON value.
|
||||
ExpectedSomeValue,
|
||||
|
||||
/// Expected this character to start a JSON string.
|
||||
ExpectedSomeString,
|
||||
|
||||
/// Invalid hex escape code.
|
||||
InvalidEscape,
|
||||
|
||||
|
@ -140,6 +143,9 @@ impl Display for ErrorCode {
|
|||
ErrorCode::ExpectedSomeValue => {
|
||||
f.write_str("expected value")
|
||||
}
|
||||
ErrorCode::ExpectedSomeString => {
|
||||
f.write_str("expected string")
|
||||
}
|
||||
ErrorCode::InvalidEscape => {
|
||||
f.write_str("invalid escape")
|
||||
}
|
||||
|
@ -174,7 +180,10 @@ impl Display for ErrorCode {
|
|||
impl error::Error for Error {
|
||||
fn description(&self) -> &str {
|
||||
match *self.err {
|
||||
ErrorImpl::Syntax(..) => "syntax error",
|
||||
ErrorImpl::Syntax(..) => {
|
||||
// If you want a better message, use Display::fmt or to_string().
|
||||
"JSON error"
|
||||
}
|
||||
ErrorImpl::Io(ref error) => error::Error::description(error),
|
||||
}
|
||||
}
|
||||
|
|
|
@ -283,9 +283,9 @@ mod macros;
|
|||
|
||||
pub mod de;
|
||||
pub mod error;
|
||||
pub mod map;
|
||||
pub mod ser;
|
||||
pub mod value;
|
||||
|
||||
mod map;
|
||||
mod number;
|
||||
mod read;
|
||||
|
|
|
@ -254,6 +254,6 @@ macro_rules! json_internal {
|
|||
// Any Serialize type: numbers, strings, struct literals, variables etc.
|
||||
// Must be below every other rule.
|
||||
($other:expr) => {
|
||||
$crate::to_value(&$other).unwrap()
|
||||
$crate::value::ToJson::to_json(&$other).unwrap()
|
||||
};
|
||||
}
|
||||
|
|
|
@ -1,3 +1,8 @@
|
|||
//! A map of String to serde_json::Value.
|
||||
//!
|
||||
//! By default the map is backed by a BTreeMap. Enable the `preserve_order`
|
||||
//! feature of serde_json to use LinkedHashMap instead.
|
||||
|
||||
use serde::{ser, de};
|
||||
use std::fmt::{self, Debug};
|
||||
use value::Value;
|
||||
|
@ -12,7 +17,7 @@ use std::collections::{BTreeMap, btree_map};
|
|||
#[cfg(feature = "preserve_order")]
|
||||
use linked_hash_map::{self, LinkedHashMap};
|
||||
|
||||
/// Represents a key/value type.
|
||||
/// Represents a JSON key/value type.
|
||||
pub struct Map<K, V> {
|
||||
map: MapImpl<K, V>,
|
||||
}
|
||||
|
@ -118,6 +123,26 @@ impl Map<String, Value> {
|
|||
self.map.remove(key)
|
||||
}
|
||||
|
||||
/// Gets the given key's corresponding entry in the map for in-place
|
||||
/// manipulation.
|
||||
pub fn entry<S>(&mut self, key: S) -> Entry
|
||||
where S: Into<String>
|
||||
{
|
||||
#[cfg(not(feature = "preserve_order"))]
|
||||
use std::collections::btree_map::Entry as EntryImpl;
|
||||
#[cfg(feature = "preserve_order")]
|
||||
use linked_hash_map::Entry as EntryImpl;
|
||||
|
||||
match self.map.entry(key.into()) {
|
||||
EntryImpl::Vacant(vacant) => {
|
||||
Entry::Vacant(VacantEntry { vacant: vacant })
|
||||
}
|
||||
EntryImpl::Occupied(occupied) => {
|
||||
Entry::Occupied(OccupiedEntry { occupied: occupied })
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// Returns the number of elements in the map.
|
||||
#[inline]
|
||||
pub fn len(&self) -> usize {
|
||||
|
@ -132,32 +157,32 @@ impl Map<String, Value> {
|
|||
|
||||
/// Gets an iterator over the entries of the map.
|
||||
#[inline]
|
||||
pub fn iter(&self) -> MapIter {
|
||||
MapIter {
|
||||
pub fn iter(&self) -> Iter {
|
||||
Iter {
|
||||
iter: self.map.iter(),
|
||||
}
|
||||
}
|
||||
|
||||
/// Gets a mutable iterator over the entries of the map.
|
||||
#[inline]
|
||||
pub fn iter_mut(&mut self) -> MapIterMut {
|
||||
MapIterMut {
|
||||
pub fn iter_mut(&mut self) -> IterMut {
|
||||
IterMut {
|
||||
iter: self.map.iter_mut(),
|
||||
}
|
||||
}
|
||||
|
||||
/// Gets an iterator over the keys of the map.
|
||||
#[inline]
|
||||
pub fn keys(&self) -> MapKeys {
|
||||
MapKeys {
|
||||
pub fn keys(&self) -> Keys {
|
||||
Keys {
|
||||
iter: self.map.keys(),
|
||||
}
|
||||
}
|
||||
|
||||
/// Gets an iterator over the values of the map.
|
||||
#[inline]
|
||||
pub fn values(&self) -> MapValues {
|
||||
MapValues {
|
||||
pub fn values(&self) -> Values {
|
||||
Values {
|
||||
iter: self.map.values(),
|
||||
}
|
||||
}
|
||||
|
@ -214,6 +239,26 @@ impl<'a, Q: ?Sized> ops::Index<&'a Q> for Map<String, Value>
|
|||
}
|
||||
}
|
||||
|
||||
/// Mutably access an element of this map. Panics if the given key is not
|
||||
/// present in the map.
|
||||
///
|
||||
/// ```rust
|
||||
/// # #[macro_use] extern crate serde_json;
|
||||
/// # fn main() {
|
||||
/// # let mut map = serde_json::Map::new();
|
||||
/// # map.insert("key".to_owned(), serde_json::Value::Null);
|
||||
/// map["key"] = json!("value");
|
||||
/// # }
|
||||
/// ```
|
||||
impl<'a, Q: ?Sized> ops::IndexMut<&'a Q> for Map<String, Value>
|
||||
where String: Borrow<Q>,
|
||||
Q: Ord + Eq + Hash
|
||||
{
|
||||
fn index_mut(&mut self, index: &Q) -> &mut Value {
|
||||
self.map.get_mut(index).expect("no entry found for key")
|
||||
}
|
||||
}
|
||||
|
||||
impl Debug for Map<String, Value> {
|
||||
#[inline]
|
||||
fn fmt(&self, formatter: &mut fmt::Formatter) -> Result<(), fmt::Error> {
|
||||
|
@ -321,98 +366,410 @@ macro_rules! delegate_iterator {
|
|||
|
||||
//////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
/// A view into a single entry in a map, which may either be vacant or occupied.
|
||||
/// This enum is constructed from the [`entry`] method on [`Map`].
|
||||
///
|
||||
/// [`entry`]: struct.Map.html#method.entry
|
||||
/// [`BTreeMap`]: struct.Map.html
|
||||
pub enum Entry<'a> {
|
||||
/// A vacant Entry.
|
||||
Vacant(VacantEntry<'a>),
|
||||
/// An occupied Entry.
|
||||
Occupied(OccupiedEntry<'a>),
|
||||
}
|
||||
|
||||
/// A vacant Entry. It is part of the [`Entry`] enum.
|
||||
///
|
||||
/// [`Entry`]: enum.Entry.html
|
||||
pub struct VacantEntry<'a> {
|
||||
vacant: VacantEntryImpl<'a>,
|
||||
}
|
||||
|
||||
/// An occupied Entry. It is part of the [`Entry`] enum.
|
||||
///
|
||||
/// [`Entry`]: enum.Entry.html
|
||||
pub struct OccupiedEntry<'a> {
|
||||
occupied: OccupiedEntryImpl<'a>,
|
||||
}
|
||||
|
||||
#[cfg(not(feature = "preserve_order"))]
|
||||
type VacantEntryImpl<'a> = btree_map::VacantEntry<'a, String, Value>;
|
||||
#[cfg(feature = "preserve_order")]
|
||||
type VacantEntryImpl<'a> = linked_hash_map::VacantEntry<'a, String, Value>;
|
||||
|
||||
#[cfg(not(feature = "preserve_order"))]
|
||||
type OccupiedEntryImpl<'a> = btree_map::OccupiedEntry<'a, String, Value>;
|
||||
#[cfg(feature = "preserve_order")]
|
||||
type OccupiedEntryImpl<'a> = linked_hash_map::OccupiedEntry<'a, String, Value>;
|
||||
|
||||
impl<'a> Entry<'a> {
|
||||
/// Returns a reference to this entry's key.
|
||||
///
|
||||
/// # Examples
|
||||
///
|
||||
/// ```rust
|
||||
/// let mut map = serde_json::Map::new();
|
||||
/// assert_eq!(map.entry("serde").key(), &"serde");
|
||||
/// ```
|
||||
pub fn key(&self) -> &String {
|
||||
match *self {
|
||||
Entry::Vacant(ref e) => e.key(),
|
||||
Entry::Occupied(ref e) => e.key(),
|
||||
}
|
||||
}
|
||||
|
||||
/// Ensures a value is in the entry by inserting the default if empty, and
|
||||
/// returns a mutable reference to the value in the entry.
|
||||
///
|
||||
/// # Examples
|
||||
///
|
||||
/// ```rust
|
||||
/// # #[macro_use] extern crate serde_json;
|
||||
/// # fn main() {
|
||||
/// let mut map = serde_json::Map::new();
|
||||
/// map.entry("serde").or_insert(json!(12));
|
||||
///
|
||||
/// assert_eq!(map["serde"], 12);
|
||||
/// # }
|
||||
/// ```
|
||||
pub fn or_insert(self, default: Value) -> &'a mut Value {
|
||||
match self {
|
||||
Entry::Vacant(entry) => entry.insert(default.into()),
|
||||
Entry::Occupied(entry) => entry.into_mut(),
|
||||
}
|
||||
}
|
||||
|
||||
/// Ensures a value is in the entry by inserting the result of the default
|
||||
/// function if empty, and returns a mutable reference to the value in the
|
||||
/// entry.
|
||||
///
|
||||
/// # Examples
|
||||
///
|
||||
/// ```rust
|
||||
/// # #[macro_use] extern crate serde_json;
|
||||
/// # fn main() {
|
||||
/// let mut map = serde_json::Map::new();
|
||||
/// map.entry("serde").or_insert_with(|| json!("hoho"));
|
||||
///
|
||||
/// assert_eq!(map["serde"], "hoho".to_owned());
|
||||
/// # }
|
||||
/// ```
|
||||
pub fn or_insert_with<F>(self, default: F) -> &'a mut Value
|
||||
where F: FnOnce() -> Value
|
||||
{
|
||||
match self {
|
||||
Entry::Vacant(entry) => entry.insert(default()),
|
||||
Entry::Occupied(entry) => entry.into_mut(),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl<'a> VacantEntry<'a> {
|
||||
/// Gets a reference to the key that would be used when inserting a value
|
||||
/// through the VacantEntry.
|
||||
///
|
||||
/// # Examples
|
||||
///
|
||||
/// ```rust
|
||||
/// use serde_json::map::Entry;
|
||||
///
|
||||
/// let mut map = serde_json::Map::new();
|
||||
///
|
||||
/// match map.entry("serde") {
|
||||
/// Entry::Vacant(vacant) => {
|
||||
/// assert_eq!(vacant.key(), &"serde");
|
||||
/// }
|
||||
/// Entry::Occupied(_) => unimplemented!(),
|
||||
/// }
|
||||
/// ```
|
||||
#[inline]
|
||||
pub fn key(&self) -> &String {
|
||||
self.vacant.key()
|
||||
}
|
||||
|
||||
/// Sets the value of the entry with the VacantEntry's key, and returns a
|
||||
/// mutable reference to it.
|
||||
///
|
||||
/// # Examples
|
||||
///
|
||||
/// ```rust
|
||||
/// # #[macro_use] extern crate serde_json;
|
||||
/// # fn main() {
|
||||
/// use serde_json::map::Entry;
|
||||
///
|
||||
/// let mut map = serde_json::Map::new();
|
||||
///
|
||||
/// match map.entry("serde") {
|
||||
/// Entry::Vacant(vacant) => {
|
||||
/// vacant.insert(json!("hoho"));
|
||||
/// }
|
||||
/// Entry::Occupied(_) => unimplemented!(),
|
||||
/// }
|
||||
/// # }
|
||||
/// ```
|
||||
#[inline]
|
||||
pub fn insert(self, value: Value) -> &'a mut Value {
|
||||
self.vacant.insert(value.into())
|
||||
}
|
||||
}
|
||||
|
||||
impl<'a> OccupiedEntry<'a> {
|
||||
/// Gets a reference to the key in the entry.
|
||||
///
|
||||
/// # Examples
|
||||
///
|
||||
/// ```rust
|
||||
/// # #[macro_use] extern crate serde_json;
|
||||
/// # fn main() {
|
||||
/// use serde_json::map::Entry;
|
||||
///
|
||||
/// let mut map = serde_json::Map::new();
|
||||
/// map.insert("serde".to_owned(), json!(12));
|
||||
///
|
||||
/// match map.entry("serde") {
|
||||
/// Entry::Occupied(occupied) => {
|
||||
/// assert_eq!(occupied.key(), &"serde");
|
||||
/// }
|
||||
/// Entry::Vacant(_) => unimplemented!(),
|
||||
/// }
|
||||
/// # }
|
||||
/// ```
|
||||
#[inline]
|
||||
pub fn key(&self) -> &String {
|
||||
self.occupied.key()
|
||||
}
|
||||
|
||||
/// Gets a reference to the value in the entry.
|
||||
///
|
||||
/// # Examples
|
||||
///
|
||||
/// ```rust
|
||||
/// # #[macro_use] extern crate serde_json;
|
||||
/// # fn main() {
|
||||
/// use serde_json::map::Entry;
|
||||
///
|
||||
/// let mut map = serde_json::Map::new();
|
||||
/// map.insert("serde".to_owned(), json!(12));
|
||||
///
|
||||
/// match map.entry("serde") {
|
||||
/// Entry::Occupied(occupied) => {
|
||||
/// assert_eq!(occupied.get(), 12);
|
||||
/// }
|
||||
/// Entry::Vacant(_) => unimplemented!(),
|
||||
/// }
|
||||
/// # }
|
||||
/// ```
|
||||
#[inline]
|
||||
pub fn get(&self) -> &Value {
|
||||
self.occupied.get()
|
||||
}
|
||||
|
||||
/// Gets a mutable reference to the value in the entry.
|
||||
///
|
||||
/// # Examples
|
||||
///
|
||||
/// ```rust
|
||||
/// # #[macro_use] extern crate serde_json;
|
||||
/// # fn main() {
|
||||
/// use serde_json::map::Entry;
|
||||
///
|
||||
/// let mut map = serde_json::Map::new();
|
||||
/// map.insert("serde".to_owned(), json!([1, 2, 3]));
|
||||
///
|
||||
/// match map.entry("serde") {
|
||||
/// Entry::Occupied(mut occupied) => {
|
||||
/// occupied.get_mut().as_array_mut().unwrap().push(json!(4));
|
||||
/// }
|
||||
/// Entry::Vacant(_) => unimplemented!(),
|
||||
/// }
|
||||
///
|
||||
/// assert_eq!(map["serde"].as_array().unwrap().len(), 4);
|
||||
/// # }
|
||||
/// ```
|
||||
#[inline]
|
||||
pub fn get_mut(&mut self) -> &mut Value {
|
||||
self.occupied.get_mut()
|
||||
}
|
||||
|
||||
/// Converts the entry into a mutable reference to its value.
|
||||
///
|
||||
/// # Examples
|
||||
///
|
||||
/// ```rust
|
||||
/// # #[macro_use] extern crate serde_json;
|
||||
/// # fn main() {
|
||||
/// use serde_json::map::Entry;
|
||||
///
|
||||
/// let mut map = serde_json::Map::new();
|
||||
/// map.insert("serde".to_owned(), json!([1, 2, 3]));
|
||||
///
|
||||
/// match map.entry("serde") {
|
||||
/// Entry::Occupied(mut occupied) => {
|
||||
/// occupied.into_mut().as_array_mut().unwrap().push(json!(4));
|
||||
/// }
|
||||
/// Entry::Vacant(_) => unimplemented!(),
|
||||
/// }
|
||||
///
|
||||
/// assert_eq!(map["serde"].as_array().unwrap().len(), 4);
|
||||
/// # }
|
||||
/// ```
|
||||
#[inline]
|
||||
pub fn into_mut(self) -> &'a mut Value {
|
||||
self.occupied.into_mut()
|
||||
}
|
||||
|
||||
/// Sets the value of the entry with the `OccupiedEntry`'s key, and returns
|
||||
/// the entry's old value.
|
||||
///
|
||||
/// # Examples
|
||||
///
|
||||
/// ```rust
|
||||
/// # #[macro_use] extern crate serde_json;
|
||||
/// # fn main() {
|
||||
/// use serde_json::map::Entry;
|
||||
///
|
||||
/// let mut map = serde_json::Map::new();
|
||||
/// map.insert("serde".to_owned(), json!(12));
|
||||
///
|
||||
/// match map.entry("serde") {
|
||||
/// Entry::Occupied(mut occupied) => {
|
||||
/// assert_eq!(occupied.insert(json!(13)), 12);
|
||||
/// assert_eq!(occupied.get(), 13);
|
||||
/// }
|
||||
/// Entry::Vacant(_) => unimplemented!(),
|
||||
/// }
|
||||
/// # }
|
||||
/// ```
|
||||
#[inline]
|
||||
pub fn insert(&mut self, value: Value) -> Value {
|
||||
self.occupied.insert(value.into())
|
||||
}
|
||||
|
||||
/// Takes the value of the entry out of the map, and returns it.
|
||||
///
|
||||
/// # Examples
|
||||
///
|
||||
/// ```rust
|
||||
/// # #[macro_use] extern crate serde_json;
|
||||
/// # fn main() {
|
||||
/// use serde_json::map::Entry;
|
||||
///
|
||||
/// let mut map = serde_json::Map::new();
|
||||
/// map.insert("serde".to_owned(), json!(12));
|
||||
///
|
||||
/// match map.entry("serde") {
|
||||
/// Entry::Occupied(occupied) => {
|
||||
/// assert_eq!(occupied.remove(), 12);
|
||||
/// }
|
||||
/// Entry::Vacant(_) => unimplemented!(),
|
||||
/// }
|
||||
/// # }
|
||||
/// ```
|
||||
#[inline]
|
||||
pub fn remove(self) -> Value {
|
||||
self.occupied.remove()
|
||||
}
|
||||
}
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
impl<'a> IntoIterator for &'a Map<String, Value> {
|
||||
type Item = (&'a String, &'a Value);
|
||||
type IntoIter = MapIter<'a>;
|
||||
type IntoIter = Iter<'a>;
|
||||
#[inline]
|
||||
fn into_iter(self) -> Self::IntoIter {
|
||||
MapIter {
|
||||
Iter {
|
||||
iter: self.map.iter(),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
pub struct MapIter<'a> {
|
||||
iter: MapIterImpl<'a>,
|
||||
/// An iterator over a serde_json::Map's entries.
|
||||
pub struct Iter<'a> {
|
||||
iter: IterImpl<'a>,
|
||||
}
|
||||
|
||||
#[cfg(not(feature = "preserve_order"))]
|
||||
type MapIterImpl<'a> = btree_map::Iter<'a, String, Value>;
|
||||
type IterImpl<'a> = btree_map::Iter<'a, String, Value>;
|
||||
#[cfg(feature = "preserve_order")]
|
||||
type MapIterImpl<'a> = linked_hash_map::Iter<'a, String, Value>;
|
||||
type IterImpl<'a> = linked_hash_map::Iter<'a, String, Value>;
|
||||
|
||||
delegate_iterator!((MapIter<'a>) => (&'a String, &'a Value));
|
||||
delegate_iterator!((Iter<'a>) => (&'a String, &'a Value));
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
impl<'a> IntoIterator for &'a mut Map<String, Value> {
|
||||
type Item = (&'a String, &'a mut Value);
|
||||
type IntoIter = MapIterMut<'a>;
|
||||
type IntoIter = IterMut<'a>;
|
||||
#[inline]
|
||||
fn into_iter(self) -> Self::IntoIter {
|
||||
MapIterMut {
|
||||
IterMut {
|
||||
iter: self.map.iter_mut(),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
pub struct MapIterMut<'a> {
|
||||
iter: MapIterMutImpl<'a>,
|
||||
/// A mutable iterator over a serde_json::Map's entries.
|
||||
pub struct IterMut<'a> {
|
||||
iter: IterMutImpl<'a>,
|
||||
}
|
||||
|
||||
#[cfg(not(feature = "preserve_order"))]
|
||||
type MapIterMutImpl<'a> = btree_map::IterMut<'a, String, Value>;
|
||||
type IterMutImpl<'a> = btree_map::IterMut<'a, String, Value>;
|
||||
#[cfg(feature = "preserve_order")]
|
||||
type MapIterMutImpl<'a> = linked_hash_map::IterMut<'a, String, Value>;
|
||||
type IterMutImpl<'a> = linked_hash_map::IterMut<'a, String, Value>;
|
||||
|
||||
delegate_iterator!((MapIterMut<'a>) => (&'a String, &'a mut Value));
|
||||
delegate_iterator!((IterMut<'a>) => (&'a String, &'a mut Value));
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
impl IntoIterator for Map<String, Value> {
|
||||
type Item = (String, Value);
|
||||
type IntoIter = MapIntoIter;
|
||||
type IntoIter = IntoIter;
|
||||
#[inline]
|
||||
fn into_iter(self) -> Self::IntoIter {
|
||||
MapIntoIter {
|
||||
IntoIter {
|
||||
iter: self.map.into_iter(),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
pub struct MapIntoIter {
|
||||
iter: MapIntoIterImpl,
|
||||
/// An owning iterator over a serde_json::Map's entries.
|
||||
pub struct IntoIter {
|
||||
iter: IntoIterImpl,
|
||||
}
|
||||
|
||||
#[cfg(not(feature = "preserve_order"))]
|
||||
type MapIntoIterImpl = btree_map::IntoIter<String, Value>;
|
||||
type IntoIterImpl = btree_map::IntoIter<String, Value>;
|
||||
#[cfg(feature = "preserve_order")]
|
||||
type MapIntoIterImpl = linked_hash_map::IntoIter<String, Value>;
|
||||
type IntoIterImpl = linked_hash_map::IntoIter<String, Value>;
|
||||
|
||||
delegate_iterator!((MapIntoIter) => (String, Value));
|
||||
delegate_iterator!((IntoIter) => (String, Value));
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
pub struct MapKeys<'a> {
|
||||
iter: MapKeysImpl<'a>,
|
||||
/// An iterator over a serde_json::Map's keys.
|
||||
pub struct Keys<'a> {
|
||||
iter: KeysImpl<'a>,
|
||||
}
|
||||
|
||||
#[cfg(not(feature = "preserve_order"))]
|
||||
type MapKeysImpl<'a> = btree_map::Keys<'a, String, Value>;
|
||||
type KeysImpl<'a> = btree_map::Keys<'a, String, Value>;
|
||||
#[cfg(feature = "preserve_order")]
|
||||
type MapKeysImpl<'a> = linked_hash_map::Keys<'a, String, Value>;
|
||||
type KeysImpl<'a> = linked_hash_map::Keys<'a, String, Value>;
|
||||
|
||||
delegate_iterator!((MapKeys<'a>) => &'a String);
|
||||
delegate_iterator!((Keys<'a>) => &'a String);
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
pub struct MapValues<'a> {
|
||||
iter: MapValuesImpl<'a>,
|
||||
/// An iterator over a serde_json::Map's values.
|
||||
pub struct Values<'a> {
|
||||
iter: ValuesImpl<'a>,
|
||||
}
|
||||
|
||||
#[cfg(not(feature = "preserve_order"))]
|
||||
type MapValuesImpl<'a> = btree_map::Values<'a, String, Value>;
|
||||
type ValuesImpl<'a> = btree_map::Values<'a, String, Value>;
|
||||
#[cfg(feature = "preserve_order")]
|
||||
type MapValuesImpl<'a> = linked_hash_map::Values<'a, String, Value>;
|
||||
type ValuesImpl<'a> = linked_hash_map::Values<'a, String, Value>;
|
||||
|
||||
delegate_iterator!((MapValues<'a>) => &'a Value);
|
||||
delegate_iterator!((Values<'a>) => &'a Value);
|
||||
|
|
|
@ -24,7 +24,7 @@ enum N {
|
|||
}
|
||||
|
||||
impl Number {
|
||||
/// Returns true if the number can be represented by i64.
|
||||
/// Returns `true` if the number can be represented as `i64`.
|
||||
#[inline]
|
||||
pub fn is_i64(&self) -> bool {
|
||||
match self.n {
|
||||
|
@ -34,7 +34,7 @@ impl Number {
|
|||
}
|
||||
}
|
||||
|
||||
/// Returns true if the number can be represented as u64.
|
||||
/// Returns `true` if the number can be represented as `u64`.
|
||||
#[inline]
|
||||
pub fn is_u64(&self) -> bool {
|
||||
match self.n {
|
||||
|
@ -43,7 +43,7 @@ impl Number {
|
|||
}
|
||||
}
|
||||
|
||||
/// Returns true if the number can be represented as f64.
|
||||
/// Returns `true` if the number can be represented as `f64`.
|
||||
#[inline]
|
||||
pub fn is_f64(&self) -> bool {
|
||||
match self.n {
|
||||
|
@ -52,7 +52,7 @@ impl Number {
|
|||
}
|
||||
}
|
||||
|
||||
/// Returns the number represented as i64 if possible, or else None.
|
||||
/// Returns the number represented as `i64` if possible, or else `None`.
|
||||
#[inline]
|
||||
pub fn as_i64(&self) -> Option<i64> {
|
||||
match self.n {
|
||||
|
@ -62,7 +62,7 @@ impl Number {
|
|||
}
|
||||
}
|
||||
|
||||
/// Returns the number represented as u64 if possible, or else None.
|
||||
/// Returns the number represented as `u64` if possible, or else `None`.
|
||||
#[inline]
|
||||
pub fn as_u64(&self) -> Option<u64> {
|
||||
match self.n {
|
||||
|
@ -72,7 +72,7 @@ impl Number {
|
|||
}
|
||||
}
|
||||
|
||||
/// Returns the number represented as f64 if possible, or else None.
|
||||
/// Returns the number represented as `f64` if possible, or else `None`.
|
||||
#[inline]
|
||||
pub fn as_f64(&self) -> Option<f64> {
|
||||
match self.n {
|
||||
|
@ -82,7 +82,7 @@ impl Number {
|
|||
}
|
||||
}
|
||||
|
||||
/// Converts a finite f64 to a Number. Infinite or NaN values are not JSON
|
||||
/// Converts a finite `f64` to a `Number`. Infinite or NaN values are not JSON
|
||||
/// numbers.
|
||||
#[inline]
|
||||
pub fn from_f64(f: f64) -> Option<Number> {
|
||||
|
@ -180,6 +180,27 @@ impl Deserializer for Number {
|
|||
}
|
||||
}
|
||||
|
||||
impl<'a> Deserializer for &'a Number {
|
||||
type Error = Error;
|
||||
|
||||
#[inline]
|
||||
fn deserialize<V>(self, visitor: V) -> Result<V::Value, Error>
|
||||
where V: Visitor
|
||||
{
|
||||
match self.n {
|
||||
N::PosInt(i) => visitor.visit_u64(i),
|
||||
N::NegInt(i) => visitor.visit_i64(i),
|
||||
N::Float(f) => visitor.visit_f64(f),
|
||||
}
|
||||
}
|
||||
|
||||
forward_to_deserialize! {
|
||||
bool u8 u16 u32 u64 i8 i16 i32 i64 f32 f64 char str string unit option
|
||||
seq seq_fixed_size bytes byte_buf map unit_struct newtype_struct
|
||||
tuple_struct struct struct_field tuple enum ignored_any
|
||||
}
|
||||
}
|
||||
|
||||
macro_rules! from_signed {
|
||||
($($signed_ty:ident)*) => {
|
||||
$(
|
||||
|
|
|
@ -7,11 +7,17 @@ use super::error::{Error, ErrorCode, Result};
|
|||
/// Trait used by the deserializer for iterating over input. This is manually
|
||||
/// "specialized" for iterating over &[u8]. Once feature(specialization) is
|
||||
/// stable we can use actual specialization.
|
||||
pub trait Read {
|
||||
///
|
||||
/// This trait is sealed and cannot be implemented for types outside of
|
||||
/// `serde_json`.
|
||||
pub trait Read: private::Sealed {
|
||||
#[doc(hidden)]
|
||||
fn next(&mut self) -> io::Result<Option<u8>>;
|
||||
#[doc(hidden)]
|
||||
fn peek(&mut self) -> io::Result<Option<u8>>;
|
||||
|
||||
/// Only valid after a call to peek(). Discards the peeked byte.
|
||||
#[doc(hidden)]
|
||||
fn discard(&mut self);
|
||||
|
||||
/// Position of the most recent call to next().
|
||||
|
@ -21,6 +27,7 @@ pub trait Read {
|
|||
/// actually peek() because we don't always know.
|
||||
///
|
||||
/// Only called in case of an error, so performance is not important.
|
||||
#[doc(hidden)]
|
||||
fn position(&self) -> Position;
|
||||
|
||||
/// Position of the most recent call to peek().
|
||||
|
@ -30,15 +37,29 @@ pub trait Read {
|
|||
/// actually next() because we don't always know.
|
||||
///
|
||||
/// Only called in case of an error, so performance is not important.
|
||||
#[doc(hidden)]
|
||||
fn peek_position(&self) -> Position;
|
||||
|
||||
/// Assumes the previous byte was a quotation mark. Parses a JSON-escaped
|
||||
/// string until the next quotation mark using the given scratch space if
|
||||
/// necessary. The scratch space is initially empty.
|
||||
#[doc(hidden)]
|
||||
fn parse_str<'s>(
|
||||
&'s mut self,
|
||||
scratch: &'s mut Vec<u8>
|
||||
scratch: &'s mut Vec<u8>,
|
||||
) -> Result<&'s str>;
|
||||
|
||||
/// Assumes the previous byte was a quotation mark. Parses a JSON-escaped
|
||||
/// string until the next quotation mark using the given scratch space if
|
||||
/// necessary. The scratch space is initially empty.
|
||||
///
|
||||
/// This function returns the raw bytes in the string with escape sequences
|
||||
/// expanded but without performing unicode validation.
|
||||
#[doc(hidden)]
|
||||
fn parse_str_raw<'s>(
|
||||
&'s mut self,
|
||||
scratch: &'s mut Vec<u8>
|
||||
) -> Result<&'s [u8]>;
|
||||
}
|
||||
|
||||
pub struct Position {
|
||||
|
@ -46,6 +67,7 @@ pub struct Position {
|
|||
pub column: usize,
|
||||
}
|
||||
|
||||
/// JSON input source that reads from an iterator of bytes.
|
||||
pub struct IteratorRead<Iter>
|
||||
where Iter: Iterator<Item = io::Result<u8>>,
|
||||
{
|
||||
|
@ -54,25 +76,41 @@ pub struct IteratorRead<Iter>
|
|||
ch: Option<u8>,
|
||||
}
|
||||
|
||||
/// Specialization for Iter=&[u8]. This is more efficient than other iterators
|
||||
/// because peek() can be read-only and we can compute line/col position only if
|
||||
/// an error happens.
|
||||
/// JSON input source that reads from a std::io input stream.
|
||||
pub struct IoRead<R>
|
||||
where R: io::Read
|
||||
{
|
||||
delegate: IteratorRead<io::Bytes<R>>,
|
||||
}
|
||||
|
||||
/// JSON input source that reads from a slice of bytes.
|
||||
//
|
||||
// This is more efficient than other iterators because peek() can be read-only
|
||||
// and we can compute line/col position only if an error happens.
|
||||
pub struct SliceRead<'a> {
|
||||
slice: &'a [u8],
|
||||
/// Index of the *next* byte that will be returned by next() or peek().
|
||||
index: usize,
|
||||
}
|
||||
|
||||
/// Elide UTF-8 checks by assuming that the input is valid UTF-8.
|
||||
/// JSON input source that reads from a UTF-8 string.
|
||||
//
|
||||
// Able to elide UTF-8 checks by assuming that the input is valid UTF-8.
|
||||
pub struct StrRead<'a> {
|
||||
delegate: SliceRead<'a>,
|
||||
}
|
||||
|
||||
// Prevent users from implementing the Read trait.
|
||||
mod private {
|
||||
pub trait Sealed {}
|
||||
}
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
impl<Iter> IteratorRead<Iter>
|
||||
where Iter: Iterator<Item = io::Result<u8>>,
|
||||
{
|
||||
/// Create a JSON input source to read from an iterator of bytes.
|
||||
pub fn new(iter: Iter) -> Self {
|
||||
IteratorRead {
|
||||
iter: LineColIterator::new(iter),
|
||||
|
@ -81,6 +119,50 @@ impl<Iter> IteratorRead<Iter>
|
|||
}
|
||||
}
|
||||
|
||||
impl<Iter> private::Sealed for IteratorRead<Iter>
|
||||
where Iter: Iterator<Item = io::Result<u8>> {}
|
||||
|
||||
impl<Iter> IteratorRead<Iter>
|
||||
where Iter: Iterator<Item = io::Result<u8>>
|
||||
{
|
||||
fn parse_str_bytes<'s, T, F>(
|
||||
&'s mut self,
|
||||
scratch: &'s mut Vec<u8>,
|
||||
validate: bool,
|
||||
result: F
|
||||
) -> Result<T>
|
||||
where T: 's,
|
||||
F: FnOnce(&'s Self, &'s [u8]) -> Result<T>,
|
||||
{
|
||||
loop {
|
||||
let ch = match try!(self.next()) {
|
||||
Some(ch) => ch,
|
||||
None => {
|
||||
return error(self, ErrorCode::EOFWhileParsingString);
|
||||
}
|
||||
};
|
||||
if !ESCAPE[ch as usize] {
|
||||
scratch.push(ch);
|
||||
continue;
|
||||
}
|
||||
match ch {
|
||||
b'"' => {
|
||||
return result(self, scratch);
|
||||
}
|
||||
b'\\' => {
|
||||
try!(parse_escape(self, scratch));
|
||||
}
|
||||
_ => {
|
||||
if validate {
|
||||
return error(self, ErrorCode::InvalidUnicodeCodePoint);
|
||||
}
|
||||
scratch.push(ch);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl<Iter> Read for IteratorRead<Iter>
|
||||
where Iter: Iterator<Item = io::Result<u8>>,
|
||||
{
|
||||
|
@ -137,35 +219,82 @@ impl<Iter> Read for IteratorRead<Iter>
|
|||
&'s mut self,
|
||||
scratch: &'s mut Vec<u8>
|
||||
) -> Result<&'s str> {
|
||||
loop {
|
||||
let ch = match try!(self.next()) {
|
||||
Some(ch) => ch,
|
||||
None => {
|
||||
return error(self, ErrorCode::EOFWhileParsingString);
|
||||
}
|
||||
};
|
||||
if !ESCAPE[ch as usize] {
|
||||
scratch.push(ch);
|
||||
continue;
|
||||
}
|
||||
match ch {
|
||||
b'"' => {
|
||||
return as_str(self, scratch);
|
||||
}
|
||||
b'\\' => {
|
||||
try!(parse_escape(self, scratch));
|
||||
}
|
||||
_ => {
|
||||
return error(self, ErrorCode::InvalidUnicodeCodePoint);
|
||||
}
|
||||
}
|
||||
self.parse_str_bytes(scratch, true, as_str)
|
||||
}
|
||||
|
||||
fn parse_str_raw<'s>(
|
||||
&'s mut self,
|
||||
scratch: &'s mut Vec<u8>
|
||||
) -> Result<&'s [u8]> {
|
||||
self.parse_str_bytes(scratch, false, |_, bytes| Ok(bytes))
|
||||
}
|
||||
}
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
impl<R> IoRead<R>
|
||||
where R: io::Read
|
||||
{
|
||||
/// Create a JSON input source to read from a std::io input stream.
|
||||
pub fn new(reader: R) -> Self {
|
||||
IoRead {
|
||||
delegate: IteratorRead::new(reader.bytes()),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl<R> private::Sealed for IoRead<R>
|
||||
where R: io::Read {}
|
||||
|
||||
impl<R> Read for IoRead<R>
|
||||
where R: io::Read
|
||||
{
|
||||
#[inline]
|
||||
fn next(&mut self) -> io::Result<Option<u8>> {
|
||||
self.delegate.next()
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn peek(&mut self) -> io::Result<Option<u8>> {
|
||||
self.delegate.peek()
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn discard(&mut self) {
|
||||
self.delegate.discard();
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn position(&self) -> Position {
|
||||
self.delegate.position()
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn peek_position(&self) -> Position {
|
||||
self.delegate.peek_position()
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn parse_str<'s>(
|
||||
&'s mut self,
|
||||
scratch: &'s mut Vec<u8>
|
||||
) -> Result<&'s str> {
|
||||
self.delegate.parse_str(scratch)
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn parse_str_raw<'s>(
|
||||
&'s mut self,
|
||||
scratch: &'s mut Vec<u8>
|
||||
) -> Result<&'s [u8]> {
|
||||
self.delegate.parse_str_raw(scratch)
|
||||
}
|
||||
}
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
impl<'a> SliceRead<'a> {
|
||||
/// Create a JSON input source to read from a slice of bytes.
|
||||
pub fn new(slice: &'a [u8]) -> Self {
|
||||
SliceRead {
|
||||
slice: slice,
|
||||
|
@ -198,6 +327,7 @@ impl<'a> SliceRead<'a> {
|
|||
fn parse_str_bytes<'s, T, F>(
|
||||
&'s mut self,
|
||||
scratch: &'s mut Vec<u8>,
|
||||
validate: bool,
|
||||
result: F
|
||||
) -> Result<T>
|
||||
where T: 's,
|
||||
|
@ -235,13 +365,18 @@ impl<'a> SliceRead<'a> {
|
|||
start = self.index;
|
||||
}
|
||||
_ => {
|
||||
return error(self, ErrorCode::InvalidUnicodeCodePoint);
|
||||
if validate {
|
||||
return error(self, ErrorCode::InvalidUnicodeCodePoint);
|
||||
}
|
||||
self.index += 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl<'a> private::Sealed for SliceRead<'a> {}
|
||||
|
||||
impl<'a> Read for SliceRead<'a> {
|
||||
#[inline]
|
||||
fn next(&mut self) -> io::Result<Option<u8>> {
|
||||
|
@ -286,13 +421,22 @@ impl<'a> Read for SliceRead<'a> {
|
|||
&'s mut self,
|
||||
scratch: &'s mut Vec<u8>
|
||||
) -> Result<&'s str> {
|
||||
self.parse_str_bytes(scratch, as_str)
|
||||
self.parse_str_bytes(scratch, true, as_str)
|
||||
}
|
||||
|
||||
fn parse_str_raw<'s>(
|
||||
&'s mut self,
|
||||
scratch: &'s mut Vec<u8>
|
||||
) -> Result<&'s [u8]> {
|
||||
self.parse_str_bytes(scratch, false, |_, bytes| Ok(bytes))
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
impl<'a> StrRead<'a> {
|
||||
/// Create a JSON input source to read from a UTF-8 string.
|
||||
pub fn new(s: &'a str) -> Self {
|
||||
StrRead {
|
||||
delegate: SliceRead::new(s.as_bytes()),
|
||||
|
@ -300,6 +444,8 @@ impl<'a> StrRead<'a> {
|
|||
}
|
||||
}
|
||||
|
||||
impl<'a> private::Sealed for StrRead<'a> {}
|
||||
|
||||
impl<'a> Read for StrRead<'a> {
|
||||
#[inline]
|
||||
fn next(&mut self) -> io::Result<Option<u8>> {
|
||||
|
@ -328,12 +474,19 @@ impl<'a> Read for StrRead<'a> {
|
|||
&'s mut self,
|
||||
scratch: &'s mut Vec<u8>
|
||||
) -> Result<&'s str> {
|
||||
self.delegate.parse_str_bytes(scratch, |_, bytes| {
|
||||
self.delegate.parse_str_bytes(scratch, true, |_, bytes| {
|
||||
// The input is assumed to be valid UTF-8 and the \u-escapes are
|
||||
// checked along the way, so don't need to check here.
|
||||
Ok(unsafe { str::from_utf8_unchecked(bytes) })
|
||||
})
|
||||
}
|
||||
|
||||
fn parse_str_raw<'s>(
|
||||
&'s mut self,
|
||||
scratch: &'s mut Vec<u8>
|
||||
) -> Result<&'s [u8]> {
|
||||
self.delegate.parse_str_raw(scratch)
|
||||
}
|
||||
}
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////////
|
||||
|
|
|
@ -85,8 +85,10 @@ use std::fmt;
|
|||
use std::i64;
|
||||
use std::io;
|
||||
use std::ops;
|
||||
use std::slice;
|
||||
use std::str;
|
||||
use std::vec;
|
||||
use std::borrow::Cow;
|
||||
|
||||
use serde::de::{self, Unexpected};
|
||||
use serde::ser;
|
||||
|
@ -499,10 +501,20 @@ impl Default for Value {
|
|||
/// This trait is sealed and cannot be implemented for types outside of
|
||||
/// `serde_json`.
|
||||
pub trait Index: private::Sealed {
|
||||
/// Return None if the key is not already in the array or object.
|
||||
#[doc(hidden)]
|
||||
fn index_into<'v>(&self, v: &'v Value) -> Option<&'v Value>;
|
||||
|
||||
/// Return None if the key is not already in the array or object.
|
||||
#[doc(hidden)]
|
||||
fn index_into_mut<'v>(&self, v: &'v mut Value) -> Option<&'v mut Value>;
|
||||
|
||||
/// Panic if array index out of bounds. If key is not already in the object,
|
||||
/// insert it with a value of null. Panic if Value is a type that cannot be
|
||||
/// indexed into, except if Value is null then it can be treated as an empty
|
||||
/// object.
|
||||
#[doc(hidden)]
|
||||
fn index_or_insert<'v>(&self, v: &'v mut Value) -> &'v mut Value;
|
||||
}
|
||||
|
||||
impl Index for usize {
|
||||
|
@ -518,6 +530,18 @@ impl Index for usize {
|
|||
_ => None,
|
||||
}
|
||||
}
|
||||
fn index_or_insert<'v>(&self, v: &'v mut Value) -> &'v mut Value {
|
||||
match *v {
|
||||
Value::Array(ref mut vec) => {
|
||||
let len = vec.len();
|
||||
vec.get_mut(*self).unwrap_or_else(|| {
|
||||
panic!("cannot access index {} of JSON array of length {}",
|
||||
self, len)
|
||||
})
|
||||
}
|
||||
_ => panic!("cannot access index {} of JSON {}", self, Type(v)),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl Index for str {
|
||||
|
@ -533,20 +557,35 @@ impl Index for str {
|
|||
_ => None,
|
||||
}
|
||||
}
|
||||
fn index_or_insert<'v>(&self, v: &'v mut Value) -> &'v mut Value {
|
||||
if let Value::Null = *v {
|
||||
let mut map = Map::new();
|
||||
map.insert(self.to_owned(), Value::Null);
|
||||
*v = Value::Object(map);
|
||||
}
|
||||
match *v {
|
||||
Value::Object(ref mut map) => {
|
||||
// TODO: use entry() once LinkedHashMap supports entry()
|
||||
// https://github.com/contain-rs/linked-hash-map/issues/5
|
||||
if !map.contains_key(self) {
|
||||
map.insert(self.to_owned(), Value::Null);
|
||||
}
|
||||
map.get_mut(self).unwrap()
|
||||
}
|
||||
_ => panic!("cannot access key {:?} in JSON {}", self, Type(v)),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl Index for String {
|
||||
fn index_into<'v>(&self, v: &'v Value) -> Option<&'v Value> {
|
||||
match *v {
|
||||
Value::Object(ref map) => map.get(self),
|
||||
_ => None,
|
||||
}
|
||||
self[..].index_into(v)
|
||||
}
|
||||
fn index_into_mut<'v>(&self, v: &'v mut Value) -> Option<&'v mut Value> {
|
||||
match *v {
|
||||
Value::Object(ref mut map) => map.get_mut(self),
|
||||
_ => None,
|
||||
}
|
||||
self[..].index_into_mut(v)
|
||||
}
|
||||
fn index_or_insert<'v>(&self, v: &'v mut Value) -> &'v mut Value {
|
||||
self[..].index_or_insert(v)
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -557,6 +596,9 @@ impl<'a, T: ?Sized> Index for &'a T where T: Index {
|
|||
fn index_into_mut<'v>(&self, v: &'v mut Value) -> Option<&'v mut Value> {
|
||||
(**self).index_into_mut(v)
|
||||
}
|
||||
fn index_or_insert<'v>(&self, v: &'v mut Value) -> &'v mut Value {
|
||||
(**self).index_or_insert(v)
|
||||
}
|
||||
}
|
||||
|
||||
// Prevent users from implementing the Index trait.
|
||||
|
@ -568,6 +610,22 @@ mod private {
|
|||
impl<'a, T: ?Sized> Sealed for &'a T where T: Sealed {}
|
||||
}
|
||||
|
||||
/// Used in panic messages.
|
||||
struct Type<'a>(&'a Value);
|
||||
|
||||
impl<'a> fmt::Display for Type<'a> {
|
||||
fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
|
||||
match *self.0 {
|
||||
Value::Null => formatter.write_str("null"),
|
||||
Value::Bool(_) => formatter.write_str("boolean"),
|
||||
Value::Number(_) => formatter.write_str("number"),
|
||||
Value::String(_) => formatter.write_str("string"),
|
||||
Value::Array(_) => formatter.write_str("array"),
|
||||
Value::Object(_) => formatter.write_str("object"),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// The usual semantics of Index is to panic on invalid indexing.
|
||||
//
|
||||
// That said, the usual semantics are for things like Vec and BTreeMap which
|
||||
|
@ -625,6 +683,46 @@ impl<I> ops::Index<I> for Value where I: Index {
|
|||
}
|
||||
}
|
||||
|
||||
impl<I> ops::IndexMut<I> for Value where I: Index {
|
||||
/// Write into a `serde_json::Value` using the syntax `value[0] = ...` or
|
||||
/// `value["k"] = ...`.
|
||||
///
|
||||
/// If the index is a number, the value must be an array of length bigger
|
||||
/// than the index. Indexing into a value that is not an array or an array
|
||||
/// that is too small will panic.
|
||||
///
|
||||
/// If the index is a string, the value must be an object or null which is
|
||||
/// treated like an empty object. If the key is not already present in the
|
||||
/// object, it will be inserted with a value of null. Indexing into a value
|
||||
/// that is neither an object nor null will panic.
|
||||
///
|
||||
/// # Examples
|
||||
///
|
||||
/// ```rust
|
||||
/// # #[macro_use] extern crate serde_json;
|
||||
/// # fn main() {
|
||||
/// let mut data = json!({ "x": 0 });
|
||||
///
|
||||
/// // replace an existing key
|
||||
/// data["x"] = json!(1);
|
||||
///
|
||||
/// // insert a new key
|
||||
/// data["y"] = json!([false, false, false]);
|
||||
///
|
||||
/// // replace an array value
|
||||
/// data["y"][0] = json!(true);
|
||||
///
|
||||
/// // inserted a deeply nested key
|
||||
/// data["a"]["b"]["c"]["d"] = json!(true);
|
||||
///
|
||||
/// println!("{}", data);
|
||||
/// # }
|
||||
/// ```
|
||||
fn index_mut(&mut self, index: I) -> &mut Value {
|
||||
index.index_or_insert(self)
|
||||
}
|
||||
}
|
||||
|
||||
impl PartialEq<str> for Value {
|
||||
fn eq(&self, other: &str) -> bool {
|
||||
self.as_str().map_or(false, |s| s == other)
|
||||
|
@ -716,17 +814,230 @@ from_integer! {
|
|||
}
|
||||
|
||||
impl From<f32> for Value {
|
||||
/// Convert 32-bit floating point number to `Value`
|
||||
///
|
||||
/// # Examples
|
||||
///
|
||||
/// ```rust
|
||||
/// # extern crate serde_json;
|
||||
/// use serde_json::Value;
|
||||
///
|
||||
/// # fn main() {
|
||||
/// let f: f32 = 13.37;
|
||||
/// let x: Value = f.into();
|
||||
/// # }
|
||||
/// ```
|
||||
fn from(f: f32) -> Self {
|
||||
From::from(f as f64)
|
||||
}
|
||||
}
|
||||
|
||||
impl From<f64> for Value {
|
||||
/// Convert 64-bit floating point number to `Value`
|
||||
///
|
||||
/// # Examples
|
||||
///
|
||||
/// ```rust
|
||||
/// # extern crate serde_json;
|
||||
/// use serde_json::Value;
|
||||
///
|
||||
/// # fn main() {
|
||||
/// let f: f64 = 13.37;
|
||||
/// let x: Value = f.into();
|
||||
/// # }
|
||||
/// ```
|
||||
fn from(f: f64) -> Self {
|
||||
Number::from_f64(f).map_or(Value::Null, Value::Number)
|
||||
}
|
||||
}
|
||||
|
||||
impl From<bool> for Value {
|
||||
/// Convert boolean to `Value`
|
||||
///
|
||||
/// # Examples
|
||||
///
|
||||
/// ```rust
|
||||
/// # extern crate serde_json;
|
||||
/// use serde_json::Value;
|
||||
///
|
||||
/// # fn main() {
|
||||
/// let b = false;
|
||||
/// let x: Value = b.into();
|
||||
/// # }
|
||||
/// ```
|
||||
fn from(f: bool) -> Self {
|
||||
Value::Bool(f)
|
||||
}
|
||||
}
|
||||
|
||||
impl From<String> for Value {
|
||||
/// Convert `String` to `Value`
|
||||
///
|
||||
/// # Examples
|
||||
///
|
||||
/// ```rust
|
||||
/// # extern crate serde_json;
|
||||
/// use serde_json::Value;
|
||||
///
|
||||
/// # fn main() {
|
||||
/// let s: String = "lorem".to_string();
|
||||
/// let x: Value = s.into();
|
||||
/// # }
|
||||
/// ```
|
||||
fn from(f: String) -> Self {
|
||||
Value::String(f)
|
||||
}
|
||||
}
|
||||
|
||||
impl<'a> From<&'a str> for Value {
|
||||
/// Convert string slice to `Value`
|
||||
///
|
||||
/// # Examples
|
||||
///
|
||||
/// ```rust
|
||||
/// # extern crate serde_json;
|
||||
/// use serde_json::Value;
|
||||
///
|
||||
/// # fn main() {
|
||||
/// let s: &str = "lorem";
|
||||
/// let x: Value = s.into();
|
||||
/// # }
|
||||
/// ```
|
||||
fn from(f: &str) -> Self {
|
||||
Value::String(f.to_string())
|
||||
}
|
||||
}
|
||||
|
||||
impl<'a> From<Cow<'a, str>> for Value {
|
||||
/// Convert copy-on-write string to `Value`
|
||||
///
|
||||
/// # Examples
|
||||
///
|
||||
/// ```rust
|
||||
/// # extern crate serde_json;
|
||||
/// use serde_json::Value;
|
||||
/// use std::borrow::Cow;
|
||||
/// # fn main() {
|
||||
///
|
||||
/// let s: Cow<str> = Cow::Borrowed("lorem");
|
||||
/// let x: Value = s.into();
|
||||
/// # }
|
||||
/// ```
|
||||
///
|
||||
/// ```rust
|
||||
/// # extern crate serde_json;
|
||||
/// use serde_json::Value;
|
||||
/// use std::borrow::Cow;
|
||||
///
|
||||
/// # fn main() {
|
||||
/// let s: Cow<str> = Cow::Owned("lorem".to_string());
|
||||
/// let x: Value = s.into();
|
||||
/// # }
|
||||
/// ```
|
||||
fn from(f: Cow<'a, str>) -> Self {
|
||||
Value::String(f.to_string())
|
||||
}
|
||||
}
|
||||
|
||||
impl From<Map<String, Value>> for Value {
|
||||
/// Convert map (with string keys) to `Value`
|
||||
///
|
||||
/// # Examples
|
||||
///
|
||||
/// ```rust
|
||||
/// # extern crate serde_json;
|
||||
/// use serde_json::{Map, Value};
|
||||
/// # fn main() {
|
||||
///
|
||||
/// let mut m = Map::new();
|
||||
/// m.insert("Lorem".to_string(), "ipsum".into());
|
||||
/// let x: Value = m.into();
|
||||
/// # }
|
||||
/// ```
|
||||
fn from(f: Map<String, Value>) -> Self {
|
||||
Value::Object(f)
|
||||
}
|
||||
}
|
||||
|
||||
impl<T: Into<Value>> From<Vec<T>> for Value {
|
||||
/// Convert a `Vec` to `Value`
|
||||
///
|
||||
/// # Examples
|
||||
///
|
||||
/// ```rust
|
||||
/// # extern crate serde_json;
|
||||
/// use serde_json::Value;
|
||||
/// # fn main() {
|
||||
///
|
||||
/// let v = vec!["lorem", "ipsum", "dolor"];
|
||||
/// let x: Value = v.into();
|
||||
/// # }
|
||||
/// ```
|
||||
fn from(f: Vec<T>) -> Self {
|
||||
Value::Array(f.into_iter().map(Into::into).collect())
|
||||
}
|
||||
}
|
||||
|
||||
impl<'a, T: Clone + Into<Value>> From<&'a [T]> for Value {
|
||||
/// Convert a slice to `Value`
|
||||
///
|
||||
/// # Examples
|
||||
///
|
||||
/// ```rust
|
||||
/// # extern crate serde_json;
|
||||
/// use serde_json::Value;
|
||||
/// # fn main() {
|
||||
///
|
||||
/// let v: &[&str] = &["lorem", "ipsum", "dolor"];
|
||||
/// let x: Value = v.into();
|
||||
/// # }
|
||||
/// ```
|
||||
fn from(f: &'a [T]) -> Self {
|
||||
Value::Array(f.into_iter().cloned().map(Into::into).collect())
|
||||
}
|
||||
}
|
||||
|
||||
impl<T: Into<Value>> ::std::iter::FromIterator<T> for Value {
|
||||
/// Convert an iteratable type to a `Value`
|
||||
///
|
||||
/// # Examples
|
||||
///
|
||||
/// ```rust
|
||||
/// # extern crate serde_json;
|
||||
/// use serde_json::Value;
|
||||
/// # fn main() {
|
||||
///
|
||||
/// let v = std::iter::repeat(42).take(5);
|
||||
/// let x: Value = v.collect();
|
||||
/// # }
|
||||
/// ```
|
||||
///
|
||||
/// ```rust
|
||||
/// # extern crate serde_json;
|
||||
/// use serde_json::Value;
|
||||
///
|
||||
/// # fn main() {
|
||||
/// let v: Vec<_> = vec!["lorem", "ipsum", "dolor"];
|
||||
/// let x: Value = v.into_iter().collect();
|
||||
/// # }
|
||||
/// ```
|
||||
///
|
||||
/// ```rust
|
||||
/// # extern crate serde_json;
|
||||
/// use std::iter::FromIterator;
|
||||
/// use serde_json::Value;
|
||||
///
|
||||
/// # fn main() {
|
||||
/// let x: Value = Value::from_iter(vec!["lorem", "ipsum", "dolor"]);
|
||||
/// # }
|
||||
/// ```
|
||||
fn from_iter<I: IntoIterator<Item=T>>(iter: I) -> Self {
|
||||
let vec: Vec<Value> = iter.into_iter().map(|x| x.into()).collect();
|
||||
|
||||
Value::Array(vec)
|
||||
}
|
||||
}
|
||||
|
||||
impl ser::Serialize for Value {
|
||||
#[inline]
|
||||
fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
|
||||
|
@ -1519,7 +1830,7 @@ impl de::MapVisitor for MapDeserializer {
|
|||
match self.iter.next() {
|
||||
Some((key, value)) => {
|
||||
self.value = Some(value);
|
||||
seed.deserialize(Value::String(key)).map(Some)
|
||||
seed.deserialize(key.into_deserializer()).map(Some)
|
||||
}
|
||||
None => Ok(None),
|
||||
}
|
||||
|
@ -1556,6 +1867,298 @@ impl de::Deserializer for MapDeserializer {
|
|||
}
|
||||
}
|
||||
|
||||
impl<'a> de::Deserializer for &'a Value {
|
||||
type Error = Error;
|
||||
|
||||
fn deserialize<V>(self, visitor: V) -> Result<V::Value, Error>
|
||||
where V: de::Visitor,
|
||||
{
|
||||
match *self {
|
||||
Value::Null => visitor.visit_unit(),
|
||||
Value::Bool(v) => visitor.visit_bool(v),
|
||||
Value::Number(ref n) => n.deserialize(visitor),
|
||||
Value::String(ref v) => visitor.visit_str(v),
|
||||
Value::Array(ref v) => {
|
||||
let len = v.len();
|
||||
let mut deserializer = SeqRefDeserializer::new(v);
|
||||
let seq = try!(visitor.visit_seq(&mut deserializer));
|
||||
let remaining = deserializer.iter.len();
|
||||
if remaining == 0 {
|
||||
Ok(seq)
|
||||
} else {
|
||||
Err(de::Error::invalid_length(len, &"fewer elements in array"))
|
||||
}
|
||||
}
|
||||
Value::Object(ref v) => {
|
||||
let len = v.len();
|
||||
let mut deserializer = MapRefDeserializer::new(v);
|
||||
let map = try!(visitor.visit_map(&mut deserializer));
|
||||
let remaining = deserializer.iter.len();
|
||||
if remaining == 0 {
|
||||
Ok(map)
|
||||
} else {
|
||||
Err(de::Error::invalid_length(len, &"fewer elements in map"))
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fn deserialize_option<V>(
|
||||
self,
|
||||
visitor: V
|
||||
) -> Result<V::Value, Error>
|
||||
where V: de::Visitor,
|
||||
{
|
||||
match *self {
|
||||
Value::Null => visitor.visit_none(),
|
||||
_ => visitor.visit_some(self),
|
||||
}
|
||||
}
|
||||
|
||||
fn deserialize_enum<V>(
|
||||
self,
|
||||
_name: &str,
|
||||
_variants: &'static [&'static str],
|
||||
visitor: V
|
||||
) -> Result<V::Value, Error>
|
||||
where V: de::Visitor,
|
||||
{
|
||||
let (variant, value) = match *self {
|
||||
Value::Object(ref value) => {
|
||||
let mut iter = value.into_iter();
|
||||
let (variant, value) = match iter.next() {
|
||||
Some(v) => v,
|
||||
None => {
|
||||
return Err(de::Error::invalid_value(Unexpected::Map, &"map with a single key"));
|
||||
}
|
||||
};
|
||||
// enums are encoded in json as maps with a single key:value pair
|
||||
if iter.next().is_some() {
|
||||
return Err(de::Error::invalid_value(Unexpected::Map, &"map with a single key"));
|
||||
}
|
||||
(variant, Some(value))
|
||||
}
|
||||
Value::String(ref variant) => (variant, None),
|
||||
ref other => {
|
||||
return Err(de::Error::invalid_type(other.unexpected(), &"string or map"));
|
||||
}
|
||||
};
|
||||
|
||||
visitor.visit_enum(EnumRefDeserializer {
|
||||
variant: variant,
|
||||
value: value,
|
||||
})
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn deserialize_newtype_struct<V>(
|
||||
self,
|
||||
_name: &'static str,
|
||||
visitor: V
|
||||
) -> Result<V::Value, Self::Error>
|
||||
where V: de::Visitor,
|
||||
{
|
||||
visitor.visit_newtype_struct(self)
|
||||
}
|
||||
|
||||
forward_to_deserialize! {
|
||||
bool u8 u16 u32 u64 i8 i16 i32 i64 f32 f64 char str string unit seq
|
||||
seq_fixed_size bytes byte_buf map unit_struct tuple_struct struct
|
||||
struct_field tuple ignored_any
|
||||
}
|
||||
}
|
||||
|
||||
struct EnumRefDeserializer<'a> {
|
||||
variant: &'a str,
|
||||
value: Option<&'a Value>,
|
||||
}
|
||||
|
||||
impl<'a> de::EnumVisitor for EnumRefDeserializer<'a> {
|
||||
type Error = Error;
|
||||
type Variant = VariantRefDeserializer<'a>;
|
||||
|
||||
fn visit_variant_seed<V>(self, seed: V) -> Result<(V::Value, Self::Variant), Error>
|
||||
where V: de::DeserializeSeed,
|
||||
{
|
||||
let variant = self.variant.into_deserializer();
|
||||
let visitor = VariantRefDeserializer { value: self.value };
|
||||
seed.deserialize(variant).map(|v| (v, visitor))
|
||||
}
|
||||
}
|
||||
|
||||
struct VariantRefDeserializer<'a> {
|
||||
value: Option<&'a Value>,
|
||||
}
|
||||
|
||||
impl<'a> de::VariantVisitor for VariantRefDeserializer<'a> {
|
||||
type Error = Error;
|
||||
|
||||
fn visit_unit(self) -> Result<(), Error> {
|
||||
match self.value {
|
||||
Some(value) => de::Deserialize::deserialize(value),
|
||||
None => Ok(()),
|
||||
}
|
||||
}
|
||||
|
||||
fn visit_newtype_seed<T>(self, seed: T) -> Result<T::Value, Error>
|
||||
where T: de::DeserializeSeed,
|
||||
{
|
||||
match self.value {
|
||||
Some(value) => seed.deserialize(value),
|
||||
None => Err(de::Error::invalid_type(Unexpected::UnitVariant, &"newtype variant")),
|
||||
}
|
||||
}
|
||||
|
||||
fn visit_tuple<V>(
|
||||
self,
|
||||
_len: usize,
|
||||
visitor: V
|
||||
) -> Result<V::Value, Error>
|
||||
where V: de::Visitor,
|
||||
{
|
||||
match self.value {
|
||||
Some(&Value::Array(ref v)) => {
|
||||
de::Deserializer::deserialize(SeqRefDeserializer::new(v), visitor)
|
||||
}
|
||||
Some(other) => Err(de::Error::invalid_type(other.unexpected(), &"tuple variant")),
|
||||
None => Err(de::Error::invalid_type(Unexpected::UnitVariant, &"tuple variant"))
|
||||
}
|
||||
}
|
||||
|
||||
fn visit_struct<V>(
|
||||
self,
|
||||
_fields: &'static [&'static str],
|
||||
visitor: V
|
||||
) -> Result<V::Value, Error>
|
||||
where V: de::Visitor,
|
||||
{
|
||||
match self.value {
|
||||
Some(&Value::Object(ref v)) => {
|
||||
de::Deserializer::deserialize(MapRefDeserializer::new(v), visitor)
|
||||
}
|
||||
Some(other) => Err(de::Error::invalid_type(other.unexpected(), &"struct variant")),
|
||||
_ => Err(de::Error::invalid_type(Unexpected::UnitVariant, &"struct variant"))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
struct SeqRefDeserializer<'a> {
|
||||
iter: slice::Iter<'a, Value>,
|
||||
}
|
||||
|
||||
impl<'a> SeqRefDeserializer<'a> {
|
||||
fn new(slice: &'a [Value]) -> Self {
|
||||
SeqRefDeserializer {
|
||||
iter: slice.iter(),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl<'a> de::Deserializer for SeqRefDeserializer<'a> {
|
||||
type Error = Error;
|
||||
|
||||
#[inline]
|
||||
fn deserialize<V>(mut self, visitor: V) -> Result<V::Value, Error>
|
||||
where V: de::Visitor,
|
||||
{
|
||||
let len = self.iter.len();
|
||||
if len == 0 {
|
||||
visitor.visit_unit()
|
||||
} else {
|
||||
let ret = try!(visitor.visit_seq(&mut self));
|
||||
let remaining = self.iter.len();
|
||||
if remaining == 0 {
|
||||
Ok(ret)
|
||||
} else {
|
||||
Err(de::Error::invalid_length(len, &"fewer elements in array"))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
forward_to_deserialize! {
|
||||
bool u8 u16 u32 u64 i8 i16 i32 i64 f32 f64 char str string unit option
|
||||
seq seq_fixed_size bytes byte_buf map unit_struct newtype_struct
|
||||
tuple_struct struct struct_field tuple enum ignored_any
|
||||
}
|
||||
}
|
||||
|
||||
impl<'a> de::SeqVisitor for SeqRefDeserializer<'a> {
|
||||
type Error = Error;
|
||||
|
||||
fn visit_seed<T>(&mut self, seed: T) -> Result<Option<T::Value>, Error>
|
||||
where T: de::DeserializeSeed,
|
||||
{
|
||||
match self.iter.next() {
|
||||
Some(value) => seed.deserialize(value).map(Some),
|
||||
None => Ok(None),
|
||||
}
|
||||
}
|
||||
|
||||
fn size_hint(&self) -> (usize, Option<usize>) {
|
||||
self.iter.size_hint()
|
||||
}
|
||||
}
|
||||
|
||||
struct MapRefDeserializer<'a> {
|
||||
iter: <&'a Map<String, Value> as IntoIterator>::IntoIter,
|
||||
value: Option<&'a Value>,
|
||||
}
|
||||
|
||||
impl<'a> MapRefDeserializer<'a> {
|
||||
fn new(map: &'a Map<String, Value>) -> Self {
|
||||
MapRefDeserializer {
|
||||
iter: map.into_iter(),
|
||||
value: None,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl<'a> de::MapVisitor for MapRefDeserializer<'a> {
|
||||
type Error = Error;
|
||||
|
||||
fn visit_key_seed<T>(&mut self, seed: T) -> Result<Option<T::Value>, Error>
|
||||
where T: de::DeserializeSeed,
|
||||
{
|
||||
match self.iter.next() {
|
||||
Some((key, value)) => {
|
||||
self.value = Some(value);
|
||||
seed.deserialize((&**key).into_deserializer()).map(Some)
|
||||
}
|
||||
None => Ok(None),
|
||||
}
|
||||
}
|
||||
|
||||
fn visit_value_seed<T>(&mut self, seed: T) -> Result<T::Value, Error>
|
||||
where T: de::DeserializeSeed,
|
||||
{
|
||||
match self.value.take() {
|
||||
Some(value) => seed.deserialize(value),
|
||||
None => Err(de::Error::custom("value is missing")),
|
||||
}
|
||||
}
|
||||
|
||||
fn size_hint(&self) -> (usize, Option<usize>) {
|
||||
self.iter.size_hint()
|
||||
}
|
||||
}
|
||||
|
||||
impl<'a> de::Deserializer for MapRefDeserializer<'a> {
|
||||
type Error = Error;
|
||||
|
||||
#[inline]
|
||||
fn deserialize<V>(self, visitor: V) -> Result<V::Value, Error>
|
||||
where V: de::Visitor,
|
||||
{
|
||||
visitor.visit_map(self)
|
||||
}
|
||||
|
||||
forward_to_deserialize! {
|
||||
bool u8 u16 u32 u64 i8 i16 i32 i64 f32 f64 char str string unit option
|
||||
seq seq_fixed_size bytes byte_buf map unit_struct newtype_struct
|
||||
tuple_struct struct struct_field tuple enum ignored_any
|
||||
}
|
||||
}
|
||||
|
||||
impl Value {
|
||||
fn unexpected(&self) -> Unexpected {
|
||||
match *self {
|
||||
|
|
|
@ -1 +1 @@
|
|||
{"files":{".cargo-ok":"e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855","Cargo.toml":"8e2151edfcef10949bbda036a8f636ad3af9fc31b98a830e282ddbc74dbd60c3","LICENSE-APACHE":"a60eea817514531668d7e00765731449fe14d059d3249e0bc93b36de45f759f2","LICENSE-MIT":"c9a75f18b9ab2927829a208fc6aa2cf4e63b8420887ba29cdb265d6619ae82d5","README.md":"b2d43372ff5db084b4f2ef5178e1fbdba83e0f05a9cfc298f188cc130e8de794","src/aster/generics.rs":"77eb19443af0dff5debb18d064733cc8721a42ad7e993a33352cdeff2b5f9f85","src/aster/ident.rs":"e9d082664f008a56bd854011310b4258ab072740ba82e57495b6e8a868a5f36b","src/aster/invoke.rs":"2b1b993973ab4f5c8fa6d6a286576b2542edce21fe9904f5133c470c072e6d3f","src/aster/lifetime.rs":"d83f4c1a48e3580caa028cfabde6ace232efc95d70af6dc9cfcca48317db9ad7","src/aster/mod.rs":"12220f73b0021e72b4c50f6a513cff174b9c7267209aa23f183043d96ccc9ab7","src/aster/path.rs":"60865b0f952077307c1a66810a4b6dafde43e76a417a433a8343960e7de474e4","src/aster/qpath.rs":"5ba33af56ccf74f5c516ed542d117d1f6ca9f7dfd1a74d08b4ac50d95666c497","src/aster/ty.rs":"03e5e631f1e04d6fafb24698b4d0529a6154a83d7ffb0a8268a1e5edf849ac55","src/aster/ty_param.rs":"7ced1e6ca0c98ef468d507d3f07bfcb1171395cd66ff5c3e1b091fe7e8b9a562","src/aster/where_predicate.rs":"5fb8ec3fcb67bcc1d9bb7b64cf2f5beb601aac6502d6db30c0cdf8641fa248d1","src/attr.rs":"efe29daa36cebee492101cbbbcb2bcdc629e30cc3122b6046c11a6ee5363cbc4","src/constant.rs":"90535a2320e0dc8ab623a9bffa770bdf697baef2884a7d9224b31daf422ea5a0","src/data.rs":"0119c67821f846e67d792bea638ae7f7f5d7e2f5e5a0c145d8ba8766d6ddb0f9","src/derive.rs":"eca81a0d38d275d7700a683022c4cf8e7ea4469f854ef99a79dc1671831941f3","src/escape.rs":"b474c52ee1b0b7577134b37ab9e57009f4ae4d445363ff54fa40df0f13a4f1d2","src/expr.rs":"ef5ca0168d763ae5043c21586d12bc086ff6fa890f6a6a014d10e138b26df780","src/fold.rs":"68e4bf844aa5bcff0325958a6d1ea235c9c697887a3ef0a2819e0e26ab59d0fc","src/generics.rs":"9d1b16001c5711d092a9fc587b7701ab025b408ce3abc0ea2c5e1ba4d45e36ed","src/ident.rs":"da8e419b0ff6ee4b9e978224795a43d5451d9aeea392ad162b5f32cd43a77df8","src/item.rs":"c91ec1b423877590acd3fa01b094f452ef6b177db6c177056f33caf61f3fe92d","src/krate.rs":"78f89e1f12f5b790d99d88a3a013178585f6715a27eb26f604e72e763a47dfdf","src/lib.rs":"4803728d6f6782c0c7414fe04b8a3522c99e9266cde886ad510f185b871d20d4","src/lit.rs":"c332899502f5d1a9e35300ef5f8173c7c54c288fc1183d56035df68b4c943c70","src/mac.rs":"b3ba8e7531980abecec4a9f86f68ae136c5982617e0e37aaa823d288ba6f5e4e","src/op.rs":"232f84ba605ed50e70ee02169dd551548872135cf56f155637917ec3bf810ce1","src/ty.rs":"88d9eb8a9a2e6cf0ddcff18d7ff76dca4e06e2a14e602bb845e438100baebef0","src/visit.rs":"c949e2414e6299ed976c3e55da58627e430e7657aed00a8a31e9480f1f7340e2"},"package":"0e28da8d02d75d1e58b89258e0741128f0b0d8a8309fb5c627be0fbd37a76c67"}
|
||||
{"files":{".cargo-ok":"e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855","Cargo.toml":"89888c3025c7ce1879bb1aeb0f50850f70f621ed3e6cb8e861808e8a9ed07ed0","LICENSE-APACHE":"a60eea817514531668d7e00765731449fe14d059d3249e0bc93b36de45f759f2","LICENSE-MIT":"c9a75f18b9ab2927829a208fc6aa2cf4e63b8420887ba29cdb265d6619ae82d5","README.md":"b2d43372ff5db084b4f2ef5178e1fbdba83e0f05a9cfc298f188cc130e8de794","src/aster/generics.rs":"77eb19443af0dff5debb18d064733cc8721a42ad7e993a33352cdeff2b5f9f85","src/aster/ident.rs":"e9d082664f008a56bd854011310b4258ab072740ba82e57495b6e8a868a5f36b","src/aster/invoke.rs":"2b1b993973ab4f5c8fa6d6a286576b2542edce21fe9904f5133c470c072e6d3f","src/aster/lifetime.rs":"d83f4c1a48e3580caa028cfabde6ace232efc95d70af6dc9cfcca48317db9ad7","src/aster/mod.rs":"12220f73b0021e72b4c50f6a513cff174b9c7267209aa23f183043d96ccc9ab7","src/aster/path.rs":"60865b0f952077307c1a66810a4b6dafde43e76a417a433a8343960e7de474e4","src/aster/qpath.rs":"5ba33af56ccf74f5c516ed542d117d1f6ca9f7dfd1a74d08b4ac50d95666c497","src/aster/ty.rs":"03e5e631f1e04d6fafb24698b4d0529a6154a83d7ffb0a8268a1e5edf849ac55","src/aster/ty_param.rs":"7ced1e6ca0c98ef468d507d3f07bfcb1171395cd66ff5c3e1b091fe7e8b9a562","src/aster/where_predicate.rs":"5fb8ec3fcb67bcc1d9bb7b64cf2f5beb601aac6502d6db30c0cdf8641fa248d1","src/attr.rs":"efe29daa36cebee492101cbbbcb2bcdc629e30cc3122b6046c11a6ee5363cbc4","src/constant.rs":"86dabf934d7ad8e81480a0abb65f863010c0d582ad1e716b9c1659ca224e5c52","src/data.rs":"f62fd874e54a439f80a9edbaa466072233098ee2483ac8fa9dafef0e8cc21f4e","src/derive.rs":"eca81a0d38d275d7700a683022c4cf8e7ea4469f854ef99a79dc1671831941f3","src/escape.rs":"b474c52ee1b0b7577134b37ab9e57009f4ae4d445363ff54fa40df0f13a4f1d2","src/expr.rs":"8a19f9390b077afc0248657bfad9d66a5c7c369aba7574c190f6e4b39f5fdece","src/fold.rs":"68e4bf844aa5bcff0325958a6d1ea235c9c697887a3ef0a2819e0e26ab59d0fc","src/generics.rs":"9d1b16001c5711d092a9fc587b7701ab025b408ce3abc0ea2c5e1ba4d45e36ed","src/ident.rs":"da8e419b0ff6ee4b9e978224795a43d5451d9aeea392ad162b5f32cd43a77df8","src/item.rs":"c91ec1b423877590acd3fa01b094f452ef6b177db6c177056f33caf61f3fe92d","src/krate.rs":"78f89e1f12f5b790d99d88a3a013178585f6715a27eb26f604e72e763a47dfdf","src/lib.rs":"dd6ee2070a138fa63522b9fb1fb2b6c8c42168bc14d64d263176ec6dec0e4eea","src/lit.rs":"c332899502f5d1a9e35300ef5f8173c7c54c288fc1183d56035df68b4c943c70","src/mac.rs":"b3ba8e7531980abecec4a9f86f68ae136c5982617e0e37aaa823d288ba6f5e4e","src/op.rs":"232f84ba605ed50e70ee02169dd551548872135cf56f155637917ec3bf810ce1","src/ty.rs":"c0e9c061e1b15b9fb17251ea9bd49364aab775c82afd72d205093679d2881da8","src/visit.rs":"c949e2414e6299ed976c3e55da58627e430e7657aed00a8a31e9480f1f7340e2"},"package":"37c279fb816210c9bb28b2c292664581e7b87b4561e86b94df462664d8620bb8"}
|
|
@ -1,6 +1,6 @@
|
|||
[package]
|
||||
name = "syn"
|
||||
version = "0.11.6" # don't forget to update version in readme for breaking changes
|
||||
version = "0.11.8" # don't forget to update version in readme for breaking changes
|
||||
authors = ["David Tolnay <dtolnay@gmail.com>"]
|
||||
license = "MIT/Apache-2.0"
|
||||
description = "Nom parser for Rust source code"
|
||||
|
@ -19,7 +19,7 @@ visit = []
|
|||
fold = []
|
||||
|
||||
[dependencies]
|
||||
quote = { version = "0.3", optional = true }
|
||||
quote = { version = "0.3.7", optional = true }
|
||||
unicode-xid = { version = "0.0.4", optional = true }
|
||||
synom = { version = "0.11", path = "synom", optional = true }
|
||||
|
||||
|
|
Некоторые файлы не были показаны из-за слишком большого количества измененных файлов Показать больше
Загрузка…
Ссылка в новой задаче