Repository: actix/actix-web
File: actix-router/src/de.rs (Rust)

Code before:
        // single
        let rdef = ResourceDef::new("/{key}");

        let mut path = Path::new("/%25");
        rdef.capture_match_info(&mut path);
        let de = PathDeserializer::new(&path);
        let segment: AnyEnumCustom = serde::Deserialize::deserialize(de).unwrap();
        assert_eq!(segment, AnyEnumCustom::String("some str: %".to_string()));

        let mut path = Path::new("/%25");
        rdef.capture_match_info(&mut path);
        let de = PathDeserializer::new(&path);
        let segment: AnyEnumDerive = serde::Deserialize::deserialize(de).unwrap();
        assert_eq!(segment, AnyEnumDerive::String("%".to_string()));

        // seq
        let rdef = ResourceDef::new("/{key}/{value}");

        let mut path = Path::new("/other/123");
        rdef.capture_match_info(&mut path);
        let de = PathDeserializer::new(&path);
        let segment: (AnyEnumCustom, AnyEnumDerive) =
            serde::Deserialize::deserialize(de).unwrap();
        assert_eq!(segment.0, AnyEnumCustom::Other);
        // Deserializes to `String` instead of `Int` because deserializing defaults to `str` and serde doesn't automatically implement parsing numbers from `&str`s
        assert_eq!(segment.1, AnyEnumDerive::String("123".to_string()));

        // map
        #[derive(Deserialize)]
        struct Vals {
            key: AnyEnumCustom,
            value: AnyEnumDerive,
        }

        let rdef = ResourceDef::new("/{key}/{value}");

        let mut path = Path::new("/123/%2F");
        rdef.capture_match_info(&mut path);
        let de = PathDeserializer::new(&path);
        let vals: Vals = serde::Deserialize::deserialize(de).unwrap();
        assert_eq!(vals.key, AnyEnumCustom::Int(123));
        assert_eq!(vals.value, AnyEnumDerive::String("/".to_string()));
    }

    #[test]
    fn deserialize_borrowed() {
        #[derive(Debug, Deserialize)]
        struct Params<'a> {
            val: &'a str,
        }


Review comment (suggestion):
This is my current hold-up. Ideally, if the `AnyEnumDerive` enum had `Int` variant before `String` then it should be able to deserialize to `Int` here. It's good that we can support it with a custom deserialize but I feel it's more distruptive to change this behavior later if it can be done at all.

Code after:
                    }

                    fn visit_i64<E>(self, v: i64) -> Result<Self::Value, E>
                    where
                        E: serde::de::Error,
                    {
                        match u32::try_from(v) {
                            Ok(v) => Ok(AnyEnumCustom::Int(v)),
                            Err(_) => Ok(AnyEnumCustom::String(format!("some str: {v}"))),
                        }
                    }

                    fn visit_str<E: serde::de::Error>(self, v: &str) -> Result<Self::Value, E> {
                        v.parse().map(AnyEnumCustom::Int).or_else(|_| {
                            Ok(match v {
                                "other" => AnyEnumCustom::Other,
                                _ => AnyEnumCustom::String(format!("some str: {v}")),
                            })
                        })
                    }
                }

                deserializer.deserialize_any(Vis)
            }
        }

        #[derive(Debug, Deserialize, PartialEq)]
        #[serde(untagged)]
        pub enum AnyEnumDerive {
            String(String),
            Int(u32),
            Other,
        }

        // single
        let rdef = ResourceDef::new("/{key}");

        let mut path = Path::new("/%25");
        rdef.capture_match_info(&mut path);
        let de = PathDeserializer::new(&path);
        let segment: AnyEnumCustom = serde::Deserialize::deserialize(de).unwrap();
        assert_eq!(segment, AnyEnumCustom::String("some str: %".to_string()));

        let mut path = Path::new("/%25");
        rdef.capture_match_info(&mut path);
        let de = PathDeserializer::new(&path);
        let segment: AnyEnumDerive = serde::Deserialize::deserialize(de).unwrap();
        assert_eq!(segment, AnyEnumDerive::String("%".to_string()));

        // seq
        let rdef = ResourceDef::new("/{key}/{value}");