use anyhow::anyhow; use std::{fmt::Display, str::FromStr}; #[derive(Debug, Clone)] pub struct Uri { pub protocol: String, pub localpart: Option, pub addr: String, pub params: String, } impl Display for Uri { fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { let Self { protocol, localpart, addr, params, } = self; write!( f, "{protocol}:{}{addr}{}", if let Some(localpart) = localpart { format!("{localpart}@") } else { "".to_string() }, if params.is_empty() { "".to_string() } else { format!(";{params}") } )?; Ok(()) } } impl FromStr for Uri { type Err = anyhow::Error; fn from_str(s: &str) -> Result { let (pr, s) = s.split_once(":").ok_or(anyhow!("protocol sep"))?; let (lp, s) = s.split_once("@").unwrap_or(("", s)); let (addr, params) = s.split_once(";").unwrap_or((s, "")); Ok(Self { addr: addr.to_owned(), localpart: if lp.is_empty() { None } else { Some(lp.to_string()) }, params: params.to_string(), protocol: pr.to_string(), }) } }