use std::{fmt::Display, str::FromStr}; macro_rules! header { ($hname:literal, struct $name:ident($type:ty)) => { pub struct $name(pub $type); impl Header for $name { const NAME: &'static str = $hname; } impl Display for $name { fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { write!(f, "{}", self.0) } } impl FromStr for $name { type Err = anyhow::Error; fn from_str(s: &str) -> Result { Ok($name(<$type>::from_str(s)?)) } } }; } pub trait Header: FromStr + Display { const NAME: &'static str; } header!("Content-Length", struct ContentLength(usize)); header!("Call-ID", struct CallID(String)); header!("CSeq", struct CSeq(String)); header!("Via", struct Via(String)); header!("Contact", struct Contact(String)); header!("Max-Forwards", struct MaxForwards(usize)); header!("From", struct From(String)); header!("To", struct To(String)); header!("User-Agent", struct UserAgent(String)); header!("Allow", struct Allow(String));