frozenlib / parse-display

Procedural macro to implement Display and FromStr using common settings.
Apache License 2.0
182 stars 14 forks source link

Automatically implement serde Deserialize and Serialize using the FromStr and Display impls #6

Closed rossmacarthur closed 4 years ago

rossmacarthur commented 4 years ago

This might be out of scope for this crate, but it would be a cool feature to be able to automatically implement serde serialization and deserialization using the Display and FromStr implementations.

Some thing like this maybe?

#[derive(Display, FromStr, PartialEq, Debug)]
#[display(serde, style = "snake_case")]
enum MyEnum {
  VarA,
  VarB,
}

And this would implement the following type of serde Deserialize implementation

mod ... {
    struct Visitor;

    impl<'de> de::Visitor<'de> for Visitor {
        type Value = MyEnum;

        fn expecting(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
            formatter.write_str($expecting)
        }

        fn visit_str<E>(self, value: &str) -> result::Result<Self::Value, E>
        where
            E: de::Error,
        {
            MyEnum::from_str(value).map_err(|e| de::Error::custom(e.to_string()))
        }
    }

    impl<'de> Deserialize<'de> for MyEnum {
        fn deserialize<D>(deserializer: D) -> result::Result<Self, D::Error>
        where
            D: Deserializer<'de>,
        {
            deserializer.deserialize_str(Visitor)
        }
    }
}

I am aware things like serde_with can do something similar, but then I have to annotate all the places I'm using it.

frozenlib commented 4 years ago

I also considered supporting serde, but I didn't implement it because the amount of code is almost the same even if I use serde_with as below.

use serde_with::{DeserializeFromStr, SerializeDisplay};

#[derive(Display, FromStr, PartialEq, Debug, SerializeDisplay, DeserializeFromStr)]
#[display(style = "snake_case")]
pub enum MyType {
    A,
    B,
}
rossmacarthur commented 4 years ago

Ah, I think I must have missed those derives in the serde_with docs.