From e24f52d3aed8abaaf4c1042abc6ae52450fc84c1 Mon Sep 17 00:00:00 2001 From: Patrick Walton Date: Fri, 10 Jul 2015 15:08:59 -0700 Subject: [PATCH] Implement serialization for `Result`. Servo wants this. --- serde/src/de/impls.rs | 129 +++++++++++++++++++++++++++++++++++++++++ serde/src/ser/impls.rs | 90 ++++++++++++++++++++++++++++ 2 files changed, 219 insertions(+) diff --git a/serde/src/de/impls.rs b/serde/src/de/impls.rs index 3f6cbf80..bc1d9b57 100644 --- a/serde/src/de/impls.rs +++ b/serde/src/de/impls.rs @@ -12,9 +12,11 @@ use num::FromPrimitive; use de::{ Deserialize, Deserializer, + EnumVisitor, Error, MapVisitor, SeqVisitor, + VariantVisitor, Visitor, }; @@ -865,3 +867,130 @@ impl<'a, T: ?Sized> Deserialize for Cow<'a, T> where T: ToOwned, T::Owned: Deser Ok(Cow::Owned(val)) } } + +/////////////////////////////////////////////////////////////////////////////// + +impl Deserialize for Result where T: Deserialize, E: Deserialize { + fn deserialize(deserializer: &mut D) -> Result, D::Error> + where D: Deserializer { + enum Field { + Field0, + Field1, + } + + impl Deserialize for Field { + #[inline] + fn deserialize(deserializer: &mut D) -> Result + where D: Deserializer { + struct FieldVisitor { + phantom: PhantomData, + } + + impl ::de::Visitor for FieldVisitor where D: Deserializer { + type Value = Field; + + fn visit_str(&mut self, value: &str) -> Result where E: Error { + match value { + "Ok" => Ok(Field::Field0), + "Err" => Ok(Field::Field1), + _ => Err(Error::unknown_field_error(value)), + } + } + + fn visit_bytes(&mut self, value: &[u8]) -> Result where E: Error { + match str::from_utf8(value) { + Ok(s) => self.visit_str(s), + _ => Err(Error::syntax_error()), + } + } + } + + deserializer.visit(FieldVisitor:: { + phantom: PhantomData, + }) + } + } + + struct Visitor(PhantomData, PhantomData, PhantomData) + where D: Deserializer, T: Deserialize, E: Deserialize; + + impl EnumVisitor for Visitor where D: Deserializer, + T: Deserialize, + E: Deserialize { + type Value = Result; + + fn visit(&mut self, mut visitor: V) -> Result, V::Error> + where V: VariantVisitor { + match match visitor.visit_variant() { + Ok(val) => val, + Err(err) => return Err(From::from(err)), + } { + Field::Field0 => { + struct Visitor(PhantomData, PhantomData, PhantomData) + where D: Deserializer, + T: Deserialize, + E: Deserialize; + impl ::de::Visitor for Visitor where D: Deserializer, + T: Deserialize, + E: Deserialize { + type Value = Result; + + fn visit_seq(&mut self, mut visitor: V) + -> Result, V::Error> where V: SeqVisitor { + let field0 = match match visitor.visit() { + Ok(val) => val, + Err(err) => return Err(From::from(err)), + } { + Some(value) => value, + None => return Err(Error::end_of_stream_error()), + }; + match visitor.end() { + Ok(val) => val, + Err(err) => return Err(From::from(err)), + }; + Ok(Result::Ok(field0)) + } + } + visitor.visit_seq(Visitor::(PhantomData, + PhantomData, + PhantomData)) + } + Field::Field1 => { + struct Visitor(PhantomData, PhantomData, PhantomData) + where D: Deserializer, + T: Deserialize, + E: Deserialize; + impl ::de::Visitor for Visitor where D: Deserializer, + T: Deserialize, + E: Deserialize { + type Value = Result; + + fn visit_seq(&mut self, mut visitor: V) + -> Result, V::Error> where V: SeqVisitor { + let field0 = match match visitor.visit() { + Ok(val) => val, + Err(err) => return Err(From::from(err)), + } { + Some(value) => value, + None => return Err(Error::end_of_stream_error()), + }; + match visitor.end() { + Ok(val) => val, + Err(err) => return Err(From::from(err)), + }; + Ok(Result::Err(field0)) + } + } + visitor.visit_seq(Visitor::(PhantomData, + PhantomData, + PhantomData)) + } + } + } + } + + deserializer.visit_enum("Result", + Visitor::(PhantomData, PhantomData, PhantomData)) + } +} + diff --git a/serde/src/ser/impls.rs b/serde/src/ser/impls.rs index 88183654..d0ffe8d6 100644 --- a/serde/src/ser/impls.rs +++ b/serde/src/ser/impls.rs @@ -1,6 +1,7 @@ use std::borrow::Cow; use std::collections::{BTreeMap, BTreeSet, HashMap, HashSet}; use std::hash::Hash; +use std::marker::PhantomData; use std::path; use std::rc::Rc; use std::sync::Arc; @@ -530,6 +531,95 @@ impl<'a, T: ?Sized> Serialize for Cow<'a, T> where T: Serialize + ToOwned, { /////////////////////////////////////////////////////////////////////////////// +impl Serialize for Result where T: Serialize, E: Serialize { + fn serialize(&self, serializer: &mut S) -> Result<(), S::Error> where S: Serializer { + match *self { + Result::Ok(ref field0) => { + struct Visitor<'a, T, E> where T: Serialize + 'a, E: Serialize + 'a { + state: usize, + value: (&'a T,), + _structure_ty: PhantomData<&'a Result>, + } + + impl<'a, T, E> SeqVisitor for Visitor<'a, T, E> where T: Serialize + 'a, + E: Serialize + 'a { + #[inline] + fn visit(&mut self, serializer: &mut S) -> Result, S::Error> + where S: Serializer { + match self.state { + 0 => { + self.state += 1; + let v = match serializer.visit_seq_elt(&self.value.0) { + Ok(val) => val, + Err(err) => return Err(From::from(err)), + }; + Ok(Some(v)) + } + _ => Ok(None), + } + } + + #[inline] + fn len(&self) -> Option { + Some(1) + } + } + + let field0: &T = field0; + let data: PhantomData<&Result<&T,E>> = PhantomData; + let visitor = Visitor { + value: (&field0,), + state: 0, + _structure_ty: data + }; + serializer.visit_enum_seq("Result", "Ok", visitor) + } + Result::Err(ref field0) => { + struct Visitor<'a, T, E> where T: Serialize + 'a, E: Serialize + 'a { + state: usize, + value: (&'a E,), + _structure_ty: PhantomData<&'a Result>, + } + + impl<'a, T, E> SeqVisitor for Visitor<'a, T, E> where T: Serialize + 'a, + E: Serialize + 'a { + #[inline] + fn visit(&mut self, serializer: &mut S) -> Result, S::Error> + where S: Serializer { + match self.state { + 0 => { + self.state += 1; + let v = match serializer.visit_seq_elt(&self.value.0) { + Ok(val) => val, + Err(err) => return Err(From::from(err)), + }; + Ok(Some(v)) + } + _ => Ok(None), + } + } + + #[inline] + fn len(&self) -> Option { + Some(1) + } + } + + let field0: &E = field0; + let data: PhantomData<&Result> = PhantomData; + let visitor = Visitor { + value: (&field0,), + state: 0, + _structure_ty: data + }; + serializer.visit_enum_seq("Result", "Err", visitor) + } + } + } +} + +/////////////////////////////////////////////////////////////////////////////// + impl Serialize for path::Path { fn serialize(&self, serializer: &mut S) -> Result<(), S::Error> where S: Serializer,