Implement Serialize and Deserialize for RangeInclusive
This commit is contained in:
parent
4e54aaf796
commit
8b2e6baf78
@ -2196,6 +2196,144 @@ where
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
#[cfg(feature = "std")]
|
||||
impl<'de, Idx> Deserialize<'de> for ops::RangeInclusive<Idx>
|
||||
where
|
||||
Idx: Deserialize<'de>,
|
||||
{
|
||||
fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
|
||||
where
|
||||
D: Deserializer<'de>,
|
||||
{
|
||||
enum Field {
|
||||
Start,
|
||||
End,
|
||||
};
|
||||
|
||||
impl<'de> Deserialize<'de> for Field {
|
||||
fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
|
||||
where
|
||||
D: Deserializer<'de>,
|
||||
{
|
||||
struct FieldVisitor;
|
||||
|
||||
impl<'de> Visitor<'de> for FieldVisitor {
|
||||
type Value = Field;
|
||||
|
||||
fn expecting(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
|
||||
formatter.write_str("`start` or `end`")
|
||||
}
|
||||
|
||||
fn visit_str<E>(self, value: &str) -> Result<Self::Value, E>
|
||||
where
|
||||
E: Error,
|
||||
{
|
||||
match value {
|
||||
"start" => Ok(Field::Start),
|
||||
"end" => Ok(Field::End),
|
||||
_ => Err(Error::unknown_field(value, FIELDS)),
|
||||
}
|
||||
}
|
||||
|
||||
fn visit_bytes<E>(self, value: &[u8]) -> Result<Self::Value, E>
|
||||
where
|
||||
E: Error,
|
||||
{
|
||||
match value {
|
||||
b"start" => Ok(Field::Start),
|
||||
b"end" => Ok(Field::End),
|
||||
_ => {
|
||||
let value = String::from_utf8_lossy(value);
|
||||
Err(Error::unknown_field(&value, FIELDS))
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
deserializer.deserialize_identifier(FieldVisitor)
|
||||
}
|
||||
}
|
||||
|
||||
struct RangeInclusiveVisitor<Idx> {
|
||||
phantom: PhantomData<Idx>,
|
||||
}
|
||||
|
||||
impl<'de, Idx> Visitor<'de> for RangeInclusiveVisitor<Idx>
|
||||
where
|
||||
Idx: Deserialize<'de>,
|
||||
{
|
||||
type Value = ops::RangeInclusive<Idx>;
|
||||
|
||||
fn expecting(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
|
||||
formatter.write_str("struct RangeInclusive")
|
||||
}
|
||||
|
||||
fn visit_seq<A>(self, mut seq: A) -> Result<Self::Value, A::Error>
|
||||
where
|
||||
A: SeqAccess<'de>,
|
||||
{
|
||||
let start: Idx = match try!(seq.next_element()) {
|
||||
Some(value) => value,
|
||||
None => {
|
||||
return Err(Error::invalid_length(0, &self));
|
||||
}
|
||||
};
|
||||
let end: Idx = match try!(seq.next_element()) {
|
||||
Some(value) => value,
|
||||
None => {
|
||||
return Err(Error::invalid_length(1, &self));
|
||||
}
|
||||
};
|
||||
Ok(start..=end)
|
||||
}
|
||||
|
||||
fn visit_map<A>(self, mut map: A) -> Result<Self::Value, A::Error>
|
||||
where
|
||||
A: MapAccess<'de>,
|
||||
{
|
||||
let mut start: Option<Idx> = None;
|
||||
let mut end: Option<Idx> = None;
|
||||
while let Some(key) = try!(map.next_key()) {
|
||||
match key {
|
||||
Field::Start => {
|
||||
if start.is_some() {
|
||||
return Err(<A::Error as Error>::duplicate_field("start"));
|
||||
}
|
||||
start = Some(try!(map.next_value()));
|
||||
}
|
||||
Field::End => {
|
||||
if end.is_some() {
|
||||
return Err(<A::Error as Error>::duplicate_field("end"));
|
||||
}
|
||||
end = Some(try!(map.next_value()));
|
||||
}
|
||||
}
|
||||
}
|
||||
let start = match start {
|
||||
Some(start) => start,
|
||||
None => return Err(<A::Error as Error>::missing_field("start")),
|
||||
};
|
||||
let end = match end {
|
||||
Some(end) => end,
|
||||
None => return Err(<A::Error as Error>::missing_field("end")),
|
||||
};
|
||||
Ok(start..=end)
|
||||
}
|
||||
}
|
||||
|
||||
const FIELDS: &'static [&'static str] = &["start", "end"];
|
||||
deserializer.deserialize_struct(
|
||||
"RangeInclusive",
|
||||
FIELDS,
|
||||
RangeInclusiveVisitor {
|
||||
phantom: PhantomData,
|
||||
},
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
macro_rules! nonzero_integers {
|
||||
( $( $T: ident, )+ ) => {
|
||||
$(
|
||||
|
@ -97,6 +97,7 @@
|
||||
//! - Path
|
||||
//! - PathBuf
|
||||
//! - Range\<T\>
|
||||
//! - RangeInclusive\<T\>
|
||||
//! - num::NonZero*
|
||||
//! - `!` *(unstable)*
|
||||
//! - **Net types**:
|
||||
|
@ -246,6 +246,25 @@ where
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
#[cfg(feature = "std")]
|
||||
impl<Idx> Serialize for ops::RangeInclusive<Idx>
|
||||
where
|
||||
Idx: Serialize,
|
||||
{
|
||||
fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
|
||||
where
|
||||
S: Serializer,
|
||||
{
|
||||
use super::SerializeStruct;
|
||||
let mut state = try!(serializer.serialize_struct("RangeInclusive", 2));
|
||||
try!(state.serialize_field("start", &self.start()));
|
||||
try!(state.serialize_field("end", &self.end()));
|
||||
state.end()
|
||||
}
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
impl Serialize for () {
|
||||
#[inline]
|
||||
fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
|
||||
|
@ -92,6 +92,7 @@
|
||||
//! - Path
|
||||
//! - PathBuf
|
||||
//! - Range\<T\>
|
||||
//! - RangeInclusive\<T\>
|
||||
//! - num::NonZero*
|
||||
//! - `!` *(unstable)*
|
||||
//! - **Net types**:
|
||||
|
@ -811,6 +811,23 @@ declare_tests! {
|
||||
Token::SeqEnd,
|
||||
],
|
||||
}
|
||||
test_range_inclusive {
|
||||
1u32..=2u32 => &[
|
||||
Token::Struct { name: "RangeInclusive", len: 2 },
|
||||
Token::Str("start"),
|
||||
Token::U32(1),
|
||||
|
||||
Token::Str("end"),
|
||||
Token::U32(2),
|
||||
Token::StructEnd,
|
||||
],
|
||||
1u32..=2u32 => &[
|
||||
Token::Seq { len: Some(2) },
|
||||
Token::U64(1),
|
||||
Token::U64(2),
|
||||
Token::SeqEnd,
|
||||
],
|
||||
}
|
||||
test_path {
|
||||
Path::new("/usr/local/lib") => &[
|
||||
Token::BorrowedStr("/usr/local/lib"),
|
||||
|
@ -377,6 +377,17 @@ declare_tests! {
|
||||
Token::StructEnd,
|
||||
],
|
||||
}
|
||||
test_range_inclusive {
|
||||
1u32..=2u32 => &[
|
||||
Token::Struct { name: "RangeInclusive", len: 2 },
|
||||
Token::Str("start"),
|
||||
Token::U32(1),
|
||||
|
||||
Token::Str("end"),
|
||||
Token::U32(2),
|
||||
Token::StructEnd,
|
||||
],
|
||||
}
|
||||
test_path {
|
||||
Path::new("/usr/local/lib") => &[
|
||||
Token::Str("/usr/local/lib"),
|
||||
|
Loading…
x
Reference in New Issue
Block a user