safe_uri 0.1.0-beta.4

Simple and safe URI types.
Documentation
use crate::*;
use std::fmt;

pub(crate) struct UriRefDisplay<'a> {
    scheme: Option<&'a Scheme>,
    authority: Option<&'a Authority>,
    resource: &'a Resource,
}

impl fmt::Display for UriRefDisplay<'_> {
    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
        let uri = self;
        if let Some(s) = &uri.scheme {
            write!(f, "{}:", s.as_str())?;
        }
        if let Some(authority) = &uri.authority {
            f.write_str("//")?;
            if let Some(user_info) = &authority.user_info {
                write!(f, "{}@", user_info.as_str())?;
            }
            write!(f, "{}", &authority.host)?;
            if let Some(port) = &authority.port {
                write!(f, ":{}", port)?;
            }
        }
        f.write_str(uri.resource.path.as_str())?;
        if let Some(query) = &uri.resource.query {
            write!(f, "?{}", query.as_str())?;
        }
        if let Some(fragment) = &uri.resource.fragment {
            write!(f, "#{}", fragment.as_str())?;
        }
        Ok(())
    }
}

impl<'a> From<&'a Uri> for UriRefDisplay<'a> {
    fn from(uri: &'a Uri) -> Self {
        Self {
            scheme: Some(&uri.scheme),
            authority: uri.authority.as_ref(),
            resource: &uri.resource,
        }
    }
}

impl<'a> From<&'a UriRef> for UriRefDisplay<'a> {
    fn from(uri: &'a UriRef) -> Self {
        Self {
            scheme: uri.scheme.as_ref(),
            authority: uri.authority.as_ref(),
            resource: &uri.resource,
        }
    }
}

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

    #[test]
    fn parse_is_inverse_of_display() {
        test_parse_is_inverse_of_display(
            "https://ferris@www.example.com/my/resource?search=rust#headline".into(),
        );
    }

    fn test_parse_is_inverse_of_display(input: SharedStr) {
        let uri = UriRef::parse(input.clone()).unwrap();
        assert_eq!(input, UriRefDisplay::from(&uri).to_string());
    }
}