ratproto-did 0.0.3

A highly-optimized library for atproto DIDs.
Documentation
use std::{fmt::Formatter, str::FromStr};

use serde::{
    de::{Deserialize, Deserializer, Error, Visitor},
    ser::{Serialize, Serializer},
};

use crate::Did;

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

struct DidVisitor;

impl<'de> Visitor<'de> for DidVisitor {
    type Value = Did;

    fn expecting(&self, formatter: &mut Formatter) -> std::fmt::Result {
        formatter.write_str("DID string")
    }

    fn visit_str<E>(self, value: &str) -> Result<Self::Value, E>
    where
        E: Error,
    {
        Did::from_str(value).map_err(Error::custom)
    }
}

impl Serialize for Did {
    fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
    where
        S: Serializer,
    {
        serializer.serialize_str(&self.to_string())
    }
}

#[cfg(test)]
mod tests {
    use serde_derive::{Deserialize, Serialize};
    use serde_json::{self, json};

    use super::*;

    #[derive(Debug, Serialize, Deserialize)]
    struct Container {
        did: Did,
    }

    #[test]
    fn deser_ok() {
        let json = json!({
            "did": "did:plc:c6te24qg5hx54qgegqylpqkx"
        });

        let c: Container = serde_json::from_value(json).unwrap();
        assert_eq!(c.did.to_string(), "did:plc:c6te24qg5hx54qgegqylpqkx")
    }

    #[test]
    fn deser_err() {
        let json = json!({
            "did": "did:plc:invalid"
        });

        serde_json::from_value::<Container>(json).unwrap_err();
    }

    #[test]
    fn ser_ok() {
        let c = Container { did: Did::from_str("did:plc:c6te24qg5hx54qgegqylpqkx").unwrap() };

        let json = serde_json::to_string(&c).unwrap();

        assert_eq!(
            json,
            json!({
                "did": "did:plc:c6te24qg5hx54qgegqylpqkx"
            })
            .to_string()
        )
    }
}