Skip to content

Commit e817683

Browse files
committed
add tests for deserialize_any
1 parent 703e79e commit e817683

File tree

1 file changed

+98
-0
lines changed

1 file changed

+98
-0
lines changed

actix-router/src/de.rs

Lines changed: 98 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -722,6 +722,104 @@ mod tests {
722722
assert_eq!(vals.value, "/");
723723
}
724724

725+
#[test]
726+
fn deserialize_path_decode_any() {
727+
#[derive(Debug, PartialEq)]
728+
pub enum AnyEnumCustom {
729+
String(String),
730+
Int(u32),
731+
Other,
732+
}
733+
734+
impl<'de> Deserialize<'de> for AnyEnumCustom {
735+
fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
736+
where
737+
D: serde::Deserializer<'de>,
738+
{
739+
struct Vis;
740+
impl<'de> Visitor<'de> for Vis {
741+
type Value = AnyEnumCustom;
742+
743+
fn expecting<'a>(
744+
&self,
745+
f: &mut std::fmt::Formatter<'a>,
746+
) -> std::fmt::Result {
747+
write!(f, "my thing")
748+
}
749+
750+
fn visit_u32<E>(self, v: u32) -> Result<Self::Value, E>
751+
where
752+
E: serde::de::Error,
753+
{
754+
Ok(AnyEnumCustom::Int(v))
755+
}
756+
757+
fn visit_str<E: serde::de::Error>(self, v: &str) -> Result<Self::Value, E> {
758+
v.parse().map(AnyEnumCustom::Int).or_else(|_| {
759+
Ok(match v {
760+
"other" => AnyEnumCustom::Other,
761+
_ => AnyEnumCustom::String(format!("some str: {v}")),
762+
})
763+
})
764+
}
765+
}
766+
767+
deserializer.deserialize_any(Vis)
768+
}
769+
}
770+
771+
#[derive(Debug, Deserialize, PartialEq)]
772+
#[serde(untagged)]
773+
pub enum AnyEnumDerive {
774+
String(String),
775+
Int(u32),
776+
Other,
777+
}
778+
779+
// single
780+
let rdef = ResourceDef::new("/{key}");
781+
782+
let mut path = Path::new("/%25");
783+
rdef.capture_match_info(&mut path);
784+
let de = PathDeserializer::new(&path);
785+
let segment: AnyEnumCustom = serde::Deserialize::deserialize(de).unwrap();
786+
assert_eq!(segment, AnyEnumCustom::String("some str: %".to_string()));
787+
788+
let mut path = Path::new("/%25");
789+
rdef.capture_match_info(&mut path);
790+
let de = PathDeserializer::new(&path);
791+
let segment: AnyEnumDerive = serde::Deserialize::deserialize(de).unwrap();
792+
assert_eq!(segment, AnyEnumDerive::String("%".to_string()));
793+
794+
// seq
795+
let rdef = ResourceDef::new("/{key}/{value}");
796+
797+
let mut path = Path::new("/other/123");
798+
rdef.capture_match_info(&mut path);
799+
let de = PathDeserializer::new(&path);
800+
let segment: (AnyEnumCustom, AnyEnumDerive) =
801+
serde::Deserialize::deserialize(de).unwrap();
802+
assert_eq!(segment.0, AnyEnumCustom::Other);
803+
// Deserializes to `String` instead of `Int` because deserializing defaults to `str` and serde doesn't automatically implement parsing numbers from `&str`s
804+
assert_eq!(segment.1, AnyEnumDerive::String("123".to_string()));
805+
806+
// map
807+
#[derive(Deserialize)]
808+
struct Vals {
809+
key: AnyEnumCustom,
810+
value: AnyEnumDerive,
811+
}
812+
813+
let rdef = ResourceDef::new("/{key}/{value}");
814+
815+
let mut path = Path::new("/123/%2F");
816+
rdef.capture_match_info(&mut path);
817+
let de = PathDeserializer::new(&path);
818+
let vals: Vals = serde::Deserialize::deserialize(de).unwrap();
819+
assert_eq!(vals.key, AnyEnumCustom::Int(123));
820+
assert_eq!(vals.value, AnyEnumDerive::String("/".to_string()));
821+
}
822+
725823
#[test]
726824
fn deserialize_borrowed() {
727825
#[derive(Debug, Deserialize)]

0 commit comments

Comments
 (0)