perma-core 0.1.0

Shared types and parsers for permalink service
Documentation
mod redirects;
mod uri;

pub use self::redirects::{Redirect, RedirectParseError, RedirectTo, StatusCode};
pub use self::uri::{RelativeRef, Uri};

use serde::{Deserialize, Serialize};

mod http_serde {
    use serde::{Deserialize, Deserializer, Serialize, Serializer};

    pub mod status_code {
        use super::*;
        use http::StatusCode;
        use serde::de::Error;

        pub fn serialize<S: Serializer>(
            value: &StatusCode,
            serializer: S,
        ) -> Result<S::Ok, S::Error> {
            value.as_u16().serialize(serializer)
        }

        pub fn deserialize<'de, D: Deserializer<'de>>(
            deserializer: D,
        ) -> Result<StatusCode, D::Error> {
            let code = u16::deserialize(deserializer)?;
            Ok(StatusCode::from_u16(code).map_err(D::Error::custom)?)
        }
    }
}

#[derive(Deserialize, Serialize, Debug, Clone)]
pub struct PermaLink {
    #[serde(with = "crate::http_serde::status_code")]
    code: StatusCode,

    to: Uri,
}

#[cfg(test)]
mod tests {
    use super::*;

    #[test]
    fn parse_redirect_to() {
        assert_eq!(
            "https://www.example.com".parse::<RedirectTo>().unwrap(),
            RedirectTo::Uri(Uri::parse("https://www.example.com").unwrap()),
        );
        assert_eq!(
            "https://www.example.com/:splat"
                .parse::<RedirectTo>()
                .unwrap(),
            RedirectTo::Uri(Uri::parse("https://www.example.com/:splat").unwrap()),
        );
        assert_eq!("/abc".parse::<RedirectTo>().unwrap().path(), "/abc");
        assert_eq!(
            "/abc/:splat".parse::<RedirectTo>().unwrap().path(),
            "/abc/:splat"
        );
    }
}