use super::{headermap::HeaderMap, method::Method, uri::Uri}; use anyhow::{anyhow, bail}; use std::{fmt::Display, str::FromStr}; #[derive(Debug, Clone)] pub struct Request { pub method: Method, pub uri: Uri, pub headers: HeaderMap, pub body: String, } impl Display for Request { fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { let Self { headers, method, uri, body, } = self; write!(f, "{method} {uri} SIP/2.0\r\n")?; write!(f, "{headers}\r\n")?; write!(f, "{body}")?; Ok(()) } } impl FromStr for Request { type Err = anyhow::Error; fn from_str(s: &str) -> Result { let mut lines = s.lines(); let statusline = lines.next().ok_or(anyhow!("status line missing"))?; let (method, rest) = statusline .split_once(" ") .ok_or(anyhow!("status line malformed"))?; let (uri, sipver) = rest .split_once(" ") .ok_or(anyhow!("status line malformed"))?; let Some(ver) = sipver.strip_prefix("SIP/") else { bail!("sip version malformed"); }; if ver != "2.0" { bail!("sip version {ver:?} is not supported"); } let uri = Uri::from_str(uri)?; let headers = HeaderMap::parse(&mut lines)?; let method = Method::from_str(method)?; Ok(Self { body: String::new(), headers, method, uri, }) } }