use serde::de::{self, Deserializer, Error as DeError, Visitor}; use httprequest::HttpRequest; use param::ParamsIter; macro_rules! unsupported_type { ($trait_fn:ident, $name:expr) => { fn $trait_fn(self, _: V) -> Result where V: Visitor<'de> { Err(de::value::Error::custom(concat!("unsupported type: ", $name))) } }; } macro_rules! parse_single_value { ($trait_fn:ident, $visit_fn:ident, $tp:tt) => { fn $trait_fn(self, visitor: V) -> Result where V: Visitor<'de> { if self.req.match_info().len() != 1 { Err(de::value::Error::custom( format!("wrong number of parameters: {} expected 1", self.req.match_info().len()).as_str())) } else { let v = self.req.match_info()[0].parse().map_err( |_| de::value::Error::custom( format!("can not parse {:?} to a {}", &self.req.match_info()[0], $tp)))?; visitor.$visit_fn(v) } } } } pub struct PathDeserializer<'de, S: 'de> { req: &'de HttpRequest, } impl<'de, S: 'de> PathDeserializer<'de, S> { pub fn new(req: &'de HttpRequest) -> Self { PathDeserializer { req } } } impl<'de, S: 'de> Deserializer<'de> for PathDeserializer<'de, S> { type Error = de::value::Error; fn deserialize_map(self, visitor: V) -> Result where V: Visitor<'de>, { visitor.visit_map(ParamsDeserializer { params: self.req.match_info().iter(), current: None, }) } fn deserialize_struct( self, _: &'static str, _: &'static [&'static str], visitor: V, ) -> Result where V: Visitor<'de>, { self.deserialize_map(visitor) } fn deserialize_unit(self, visitor: V) -> Result where V: Visitor<'de>, { visitor.visit_unit() } fn deserialize_unit_struct( self, _: &'static str, visitor: V, ) -> Result where V: Visitor<'de>, { self.deserialize_unit(visitor) } fn deserialize_newtype_struct( self, _: &'static str, visitor: V, ) -> Result where V: Visitor<'de>, { visitor.visit_newtype_struct(self) } fn deserialize_tuple( self, len: usize, visitor: V, ) -> Result where V: Visitor<'de>, { if self.req.match_info().len() < len { Err(de::value::Error::custom( format!( "wrong number of parameters: {} expected {}", self.req.match_info().len(), len ).as_str(), )) } else { visitor.visit_seq(ParamsSeq { params: self.req.match_info().iter(), }) } } fn deserialize_tuple_struct( self, _: &'static str, len: usize, visitor: V, ) -> Result where V: Visitor<'de>, { if self.req.match_info().len() < len { Err(de::value::Error::custom( format!( "wrong number of parameters: {} expected {}", self.req.match_info().len(), len ).as_str(), )) } else { visitor.visit_seq(ParamsSeq { params: self.req.match_info().iter(), }) } } fn deserialize_enum( self, _: &'static str, _: &'static [&'static str], _: V, ) -> Result where V: Visitor<'de>, { Err(de::value::Error::custom("unsupported type: enum")) } fn deserialize_str(self, visitor: V) -> Result where V: Visitor<'de>, { if self.req.match_info().len() != 1 { Err(de::value::Error::custom( format!( "wrong number of parameters: {} expected 1", self.req.match_info().len() ).as_str(), )) } else { visitor.visit_str(&self.req.match_info()[0]) } } fn deserialize_seq(self, visitor: V) -> Result where V: Visitor<'de>, { visitor.visit_seq(ParamsSeq { params: self.req.match_info().iter(), }) } unsupported_type!(deserialize_any, "'any'"); unsupported_type!(deserialize_bytes, "bytes"); unsupported_type!(deserialize_option, "Option"); unsupported_type!(deserialize_identifier, "identifier"); unsupported_type!(deserialize_ignored_any, "ignored_any"); parse_single_value!(deserialize_bool, visit_bool, "bool"); parse_single_value!(deserialize_i8, visit_i8, "i8"); parse_single_value!(deserialize_i16, visit_i16, "i16"); parse_single_value!(deserialize_i32, visit_i32, "i16"); parse_single_value!(deserialize_i64, visit_i64, "i64"); parse_single_value!(deserialize_u8, visit_u8, "u8"); parse_single_value!(deserialize_u16, visit_u16, "u16"); parse_single_value!(deserialize_u32, visit_u32, "u32"); parse_single_value!(deserialize_u64, visit_u64, "u64"); parse_single_value!(deserialize_f32, visit_f32, "f32"); parse_single_value!(deserialize_f64, visit_f64, "f64"); parse_single_value!(deserialize_string, visit_string, "String"); parse_single_value!(deserialize_byte_buf, visit_string, "String"); parse_single_value!(deserialize_char, visit_char, "char"); } struct ParamsDeserializer<'de> { params: ParamsIter<'de>, current: Option<(&'de str, &'de str)>, } impl<'de> de::MapAccess<'de> for ParamsDeserializer<'de> { type Error = de::value::Error; fn next_key_seed(&mut self, seed: K) -> Result, Self::Error> where K: de::DeserializeSeed<'de>, { self.current = self.params.next().map(|ref item| (item.0, item.1)); match self.current { Some((key, _)) => Ok(Some(seed.deserialize(Key { key })?)), None => Ok(None), } } fn next_value_seed(&mut self, seed: V) -> Result where V: de::DeserializeSeed<'de>, { if let Some((_, value)) = self.current.take() { seed.deserialize(Value { value }) } else { Err(de::value::Error::custom("unexpected item")) } } } struct Key<'de> { key: &'de str, } impl<'de> Deserializer<'de> for Key<'de> { type Error = de::value::Error; fn deserialize_identifier(self, visitor: V) -> Result where V: Visitor<'de>, { visitor.visit_str(self.key) } fn deserialize_any(self, _visitor: V) -> Result where V: Visitor<'de>, { Err(de::value::Error::custom("Unexpected")) } forward_to_deserialize_any! { bool i8 i16 i32 i64 u8 u16 u32 u64 f32 f64 char str string bytes byte_buf option unit unit_struct newtype_struct seq tuple tuple_struct map struct enum ignored_any } } macro_rules! parse_value { ($trait_fn:ident, $visit_fn:ident, $tp:tt) => { fn $trait_fn(self, visitor: V) -> Result where V: Visitor<'de> { let v = self.value.parse().map_err( |_| de::value::Error::custom( format!("can not parse {:?} to a {}", self.value, $tp)))?; visitor.$visit_fn(v) } } } struct Value<'de> { value: &'de str, } impl<'de> Deserializer<'de> for Value<'de> { type Error = de::value::Error; parse_value!(deserialize_bool, visit_bool, "bool"); parse_value!(deserialize_i8, visit_i8, "i8"); parse_value!(deserialize_i16, visit_i16, "i16"); parse_value!(deserialize_i32, visit_i32, "i16"); parse_value!(deserialize_i64, visit_i64, "i64"); parse_value!(deserialize_u8, visit_u8, "u8"); parse_value!(deserialize_u16, visit_u16, "u16"); parse_value!(deserialize_u32, visit_u32, "u32"); parse_value!(deserialize_u64, visit_u64, "u64"); parse_value!(deserialize_f32, visit_f32, "f32"); parse_value!(deserialize_f64, visit_f64, "f64"); parse_value!(deserialize_string, visit_string, "String"); parse_value!(deserialize_byte_buf, visit_string, "String"); parse_value!(deserialize_char, visit_char, "char"); fn deserialize_ignored_any(self, visitor: V) -> Result where V: Visitor<'de>, { visitor.visit_unit() } fn deserialize_unit(self, visitor: V) -> Result where V: Visitor<'de>, { visitor.visit_unit() } fn deserialize_unit_struct( self, _: &'static str, visitor: V, ) -> Result where V: Visitor<'de>, { visitor.visit_unit() } fn deserialize_bytes(self, visitor: V) -> Result where V: Visitor<'de>, { visitor.visit_borrowed_bytes(self.value.as_bytes()) } fn deserialize_str(self, visitor: V) -> Result where V: Visitor<'de>, { visitor.visit_borrowed_str(self.value) } fn deserialize_option(self, visitor: V) -> Result where V: Visitor<'de>, { visitor.visit_some(self) } fn deserialize_enum( self, _: &'static str, _: &'static [&'static str], visitor: V, ) -> Result where V: Visitor<'de>, { visitor.visit_enum(ValueEnum { value: self.value }) } fn deserialize_newtype_struct( self, _: &'static str, visitor: V, ) -> Result where V: Visitor<'de>, { visitor.visit_newtype_struct(self) } fn deserialize_tuple(self, _: usize, _: V) -> Result where V: Visitor<'de>, { Err(de::value::Error::custom("unsupported type: tuple")) } fn deserialize_struct( self, _: &'static str, _: &'static [&'static str], _: V, ) -> Result where V: Visitor<'de>, { Err(de::value::Error::custom("unsupported type: struct")) } fn deserialize_tuple_struct( self, _: &'static str, _: usize, _: V, ) -> Result where V: Visitor<'de>, { Err(de::value::Error::custom("unsupported type: tuple struct")) } unsupported_type!(deserialize_any, "any"); unsupported_type!(deserialize_seq, "seq"); unsupported_type!(deserialize_map, "map"); unsupported_type!(deserialize_identifier, "identifier"); } struct ParamsSeq<'de> { params: ParamsIter<'de>, } impl<'de> de::SeqAccess<'de> for ParamsSeq<'de> { type Error = de::value::Error; fn next_element_seed(&mut self, seed: T) -> Result, Self::Error> where T: de::DeserializeSeed<'de>, { match self.params.next() { Some(item) => Ok(Some(seed.deserialize(Value { value: item.1 })?)), None => Ok(None), } } } struct ValueEnum<'de> { value: &'de str, } impl<'de> de::EnumAccess<'de> for ValueEnum<'de> { type Error = de::value::Error; type Variant = UnitVariant; fn variant_seed(self, seed: V) -> Result<(V::Value, Self::Variant), Self::Error> where V: de::DeserializeSeed<'de>, { Ok((seed.deserialize(Key { key: self.value })?, UnitVariant)) } } struct UnitVariant; impl<'de> de::VariantAccess<'de> for UnitVariant { type Error = de::value::Error; fn unit_variant(self) -> Result<(), Self::Error> { Ok(()) } fn newtype_variant_seed(self, _seed: T) -> Result where T: de::DeserializeSeed<'de>, { Err(de::value::Error::custom("not supported")) } fn tuple_variant(self, _len: usize, _visitor: V) -> Result where V: Visitor<'de>, { Err(de::value::Error::custom("not supported")) } fn struct_variant( self, _: &'static [&'static str], _: V, ) -> Result where V: Visitor<'de>, { Err(de::value::Error::custom("not supported")) } }