diff --git a/router/src/de.rs b/router/src/de.rs index 81796348..aedf9395 100644 --- a/router/src/de.rs +++ b/router/src/de.rs @@ -1,3 +1,5 @@ +use std::fmt; + use serde::de::{self, Deserializer, Error as DeError, Visitor}; use serde::forward_to_deserialize_any; @@ -42,17 +44,24 @@ macro_rules! parse_single_value { }; } -pub struct PathDeserializer<'de, T: ResourcePath> { +#[derive(Debug)] +pub struct PathDeserializer<'de, T: ResourcePath + fmt::Debug> { path: &'de Path, } -impl<'de, T: ResourcePath + 'de> PathDeserializer<'de, T> { +impl<'de, T> PathDeserializer<'de, T> +where + T: ResourcePath + fmt::Debug + 'de, +{ pub fn new(path: &'de Path) -> Self { PathDeserializer { path } } } -impl<'de, T: ResourcePath + 'de> Deserializer<'de> for PathDeserializer<'de, T> { +impl<'de, T> Deserializer<'de> for PathDeserializer<'de, T> +where + T: ResourcePath + fmt::Debug + 'de, +{ type Error = de::value::Error; fn deserialize_map(self, visitor: V) -> Result @@ -103,6 +112,7 @@ impl<'de, T: ResourcePath + 'de> Deserializer<'de> for PathDeserializer<'de, T> where V: Visitor<'de>, { + eprintln!("heres my newtype"); visitor.visit_newtype_struct(self) } @@ -154,15 +164,19 @@ impl<'de, T: ResourcePath + 'de> Deserializer<'de> for PathDeserializer<'de, T> fn deserialize_enum( self, _: &'static str, - _: &'static [&'static str], + variants: &'static [&'static str], visitor: V, ) -> Result where V: Visitor<'de>, { + eprintln!("variants: {:?}", &variants); + if self.path.is_empty() { Err(de::value::Error::custom("expected at least one parameters")) } else { + eprintln!("{:?}", &self.path[0]); + visitor.visit_enum(ValueEnum { value: &self.path[0], }) @@ -191,7 +205,16 @@ impl<'de, T: ResourcePath + 'de> Deserializer<'de> for PathDeserializer<'de, T> }) } - unsupported_type!(deserialize_any, "'any'"); + fn deserialize_any(self, visitor: V) -> Result + where + V: Visitor<'de>, + { + match self.path[0].parse::() { + Ok(int) => visitor.visit_u64(int), + Err(_) => visitor.visit_str(&self.path[0]), + } + } + unsupported_type!(deserialize_bytes, "bytes"); unsupported_type!(deserialize_option, "Option"); unsupported_type!(deserialize_identifier, "identifier"); @@ -218,7 +241,10 @@ struct ParamsDeserializer<'de, T: ResourcePath> { current: Option<(&'de str, &'de str)>, } -impl<'de, T: ResourcePath> de::MapAccess<'de> for ParamsDeserializer<'de, T> { +impl<'de, T> de::MapAccess<'de> for ParamsDeserializer<'de, T> +where + T: ResourcePath + fmt::Debug, +{ type Error = de::value::Error; fn next_key_seed(&mut self, seed: K) -> Result, Self::Error> @@ -262,6 +288,7 @@ impl<'de> Deserializer<'de> for Key<'de> { where V: Visitor<'de>, { + eprintln!("Key::deserialize_any"); Err(de::value::Error::custom("Unexpected")) } @@ -312,6 +339,7 @@ impl<'de> Deserializer<'de> for Value<'de> { where V: Visitor<'de>, { + eprintln!("Value::deserialize_ignored_any"); visitor.visit_unit() } @@ -418,7 +446,10 @@ struct ParamsSeq<'de, T: ResourcePath> { params: PathIter<'de, T>, } -impl<'de, T: ResourcePath> de::SeqAccess<'de> for ParamsSeq<'de, T> { +impl<'de, T> de::SeqAccess<'de> for ParamsSeq<'de, T> +where + T: ResourcePath + fmt::Debug, +{ type Error = de::value::Error; fn next_element_seed(&mut self, seed: U) -> Result, Self::Error> @@ -432,8 +463,10 @@ impl<'de, T: ResourcePath> de::SeqAccess<'de> for ParamsSeq<'de, T> { } } +#[derive(Debug)] struct ValueEnum<'de> { value: &'de str, + // todo there maybe must be some state here to decide on which variant to use } impl<'de> de::EnumAccess<'de> for ValueEnum<'de> { @@ -444,6 +477,9 @@ impl<'de> de::EnumAccess<'de> for ValueEnum<'de> { where V: de::DeserializeSeed<'de>, { + // eprintln!("seed: {:?}", &seed); + eprintln!("value: {:?}", &self.value); + Ok((seed.deserialize(Key { key: self.value })?, UnitVariant)) } } @@ -454,6 +490,7 @@ impl<'de> de::VariantAccess<'de> for UnitVariant { type Error = de::value::Error; fn unit_variant(self) -> Result<(), Self::Error> { + eprintln!("try unit variant"); Ok(()) } @@ -461,6 +498,7 @@ impl<'de> de::VariantAccess<'de> for UnitVariant { where T: de::DeserializeSeed<'de>, { + eprintln!("try newtype variant"); Err(de::value::Error::custom("not supported")) } @@ -468,6 +506,7 @@ impl<'de> de::VariantAccess<'de> for UnitVariant { where V: Visitor<'de>, { + eprintln!("try tuple variant"); Err(de::value::Error::custom("not supported")) } @@ -479,6 +518,7 @@ impl<'de> de::VariantAccess<'de> for UnitVariant { where V: Visitor<'de>, { + eprintln!("try struct variant"); Err(de::value::Error::custom("not supported")) } } @@ -512,6 +552,11 @@ mod tests { value: u32, } + #[derive(Debug, Deserialize)] + struct Test3 { + val: TestEnum, + } + #[derive(Debug, Deserialize, PartialEq)] #[serde(rename_all = "lowercase")] enum TestEnum { @@ -519,9 +564,72 @@ mod tests { Val2, } - #[derive(Debug, Deserialize)] - struct Test3 { - val: TestEnum, + #[derive(Clone, Debug, PartialEq, Eq)] + pub enum TestEnum2 { + Int(u32), + String(String), + } + + #[allow(non_snake_case)] + mod __TestEnum2 { + use std::fmt; + + use serde::{ + export::{Err as SErr, Ok as SOk, Result as SResult}, + private::de::{Content, ContentRefDeserializer}, + Deserialize, + }; + + use super::TestEnum2; + + impl<'de> serde::Deserialize<'de> for TestEnum2 { + fn deserialize(deserializer: D) -> SResult + where + D: serde::Deserializer<'de>, + { + eprintln!( + "!!derive!! deserializer: {:?}", + &deserializer.is_human_readable() + ); + + let content = match as Deserialize>::deserialize(deserializer) { + SOk(val) => { + eprintln!("!!derive!! content val: {:?}", &val); + val + } + SErr(err) => { + eprintln!("!!derive!! content err: {:?}", &err); + return SErr(err); + } + }; + + let cnt1 = ContentRefDeserializer::::new(&content); + let de1 = ::deserialize(cnt1); + + // eprintln!("!!derive!! cnt1: {:?}", &cnt1); + eprintln!("!!derive!! de1: {:?}", &de1); + + if let SOk(ok) = SResult::map(de1, TestEnum2::Int) { + eprintln!("!!derive!! de1 map ok: {:?}", &ok); + return SOk(ok); + } + + let cnt2 = ContentRefDeserializer::::new(&content); + let de2 = ::deserialize(cnt2); + + // eprintln!("!!derive!! cnt2: {:?}", &cnt2); + eprintln!("!!derive!! de2: {:?}", &de2); + + if let SOk(ok) = SResult::map(de2, TestEnum2::String) { + eprintln!("!!derive!! de2 map ok: {:?}", &ok); + return SOk(ok); + } + + SErr(serde::de::Error::custom( + "data did not match any variant of untagged enum TestEnum2", + )) + } + } } #[test] @@ -591,6 +699,16 @@ mod tests { let i: TestEnum = de::Deserialize::deserialize(PathDeserializer::new(&path)).unwrap(); assert_eq!(i, TestEnum::Val1); + let mut path = Path::new("/22/"); + assert!(router.recognize(&mut path).is_some()); + let i: TestEnum2 = de::Deserialize::deserialize(PathDeserializer::new(&path)).unwrap(); + assert_eq!(i, TestEnum2::Int(22)); + + let mut path = Path::new("/abc/"); + assert!(router.recognize(&mut path).is_some()); + let i: TestEnum2 = de::Deserialize::deserialize(PathDeserializer::new(&path)).unwrap(); + assert_eq!(i, TestEnum2::String("abc".to_owned())); + let mut router = Router::<()>::build(); router.path("/{val1}/{val2}/", ()); let router = router.finish(); diff --git a/router/src/path.rs b/router/src/path.rs index 0998c614..474d049d 100644 --- a/router/src/path.rs +++ b/router/src/path.rs @@ -1,4 +1,4 @@ -use std::ops::Index; +use std::{fmt, ops::Index}; use serde::de; @@ -41,7 +41,10 @@ impl Clone for Path { } } -impl Path { +impl Path +where + T: ResourcePath + fmt::Debug, +{ pub fn new(path: T) -> Path { Path { path, @@ -177,7 +180,10 @@ pub struct PathIter<'a, T> { params: &'a Path, } -impl<'a, T: ResourcePath> Iterator for PathIter<'a, T> { +impl<'a, T> Iterator for PathIter<'a, T> +where + T: ResourcePath + fmt::Debug, +{ type Item = (&'a str, &'a str); #[inline] @@ -195,7 +201,10 @@ impl<'a, T: ResourcePath> Iterator for PathIter<'a, T> { } } -impl<'a, T: ResourcePath> Index<&'a str> for Path { +impl<'a, T> Index<&'a str> for Path +where + T: ResourcePath + fmt::Debug, +{ type Output = str; fn index(&self, name: &'a str) -> &str { diff --git a/router/src/resource.rs b/router/src/resource.rs index 2ab4ceb5..cb3cf9be 100644 --- a/router/src/resource.rs +++ b/router/src/resource.rs @@ -1,6 +1,6 @@ -use std::cmp::min; use std::collections::HashMap; use std::hash::{Hash, Hasher}; +use std::{cmp::min, fmt}; use regex::{escape, Regex, RegexSet}; @@ -241,7 +241,7 @@ impl ResourceDef { } /// Is the given path and parameters a match against this pattern. - pub fn match_path(&self, path: &mut Path) -> bool { + pub fn match_path(&self, path: &mut Path) -> bool { match self.tp { PatternType::Static(ref s) => { if s == path.path() { @@ -345,7 +345,7 @@ impl ResourceDef { user_data: &Option, ) -> bool where - T: ResourcePath, + T: ResourcePath + fmt::Debug, R: Resource, F: Fn(&R, &Option) -> bool, { diff --git a/router/src/router.rs b/router/src/router.rs index bcbe61f9..a39608d9 100644 --- a/router/src/router.rs +++ b/router/src/router.rs @@ -1,3 +1,5 @@ +use std::fmt; + use crate::{IntoPattern, Resource, ResourceDef, ResourcePath}; #[derive(Debug, Copy, Clone, PartialEq)] @@ -22,7 +24,7 @@ impl Router { pub fn recognize(&self, resource: &mut R) -> Option<(&T, ResourceId)> where R: Resource

, - P: ResourcePath, + P: ResourcePath + fmt::Debug, { for item in self.0.iter() { if item.0.match_path(resource.resource_path()) { @@ -35,7 +37,7 @@ impl Router { pub fn recognize_mut(&mut self, resource: &mut R) -> Option<(&mut T, ResourceId)> where R: Resource

, - P: ResourcePath, + P: ResourcePath + fmt::Debug, { for item in self.0.iter_mut() { if item.0.match_path(resource.resource_path()) { @@ -53,7 +55,7 @@ impl Router { where F: Fn(&R, &Option) -> bool, R: Resource

, - P: ResourcePath, + P: ResourcePath + fmt::Debug, { for item in self.0.iter_mut() { if item.0.match_path_checked(resource, &check, &item.2) {