use anyhow::{anyhow, Result}; pub struct ParsedMessage<'a> { pub headers: Vec>, pub body: &'a [u8], } impl<'a> ParsedMessage<'a> { pub fn from_bytes(data: &'a [u8]) -> Result { let (mut raw_headers, body) = match data.windows(4).position(|w| w == b"\r\n\r\n") { Some(body_index) => (&data[..body_index + 2], &data[body_index + 4..]), None => return Err(anyhow!("message body not found")), }; let mut headers = Vec::with_capacity(128); while !raw_headers.is_empty() { let end_index = header_end_pos(raw_headers)?; let h = ParsedHeader::from_bytes(&raw_headers[..end_index])?; headers.push(h); raw_headers = &raw_headers[end_index..]; } headers.shrink_to_fit(); Ok(Self { headers, body }) } } fn is_wsp(c: u8) -> bool { c == b' ' || c == b'\t' } fn header_end_pos(data: &[u8]) -> Result { let mut ret = 0; let max_len = data.len(); loop { ret += data[ret..] .windows(2) .position(|w| w == b"\r\n") .ok_or(anyhow!("end of header not found"))? + 2; if ret >= max_len { return Ok(max_len); } if !is_wsp(data[ret]) { return Ok(ret); } } } pub struct ParsedHeader<'a> { pub name: &'a [u8], pub name_lower: String, pub value: &'a [u8], pub raw: &'a [u8], } impl<'a> ParsedHeader<'a> { fn from_bytes(data: &'a [u8]) -> Result { let colon_pos = data .iter() .position(|&w| w == b':') .ok_or(anyhow!("colon not found in header"))?; let name = &data[..colon_pos]; let value = &data[colon_pos + 1..]; Ok(Self { name, name_lower: String::from_utf8(name.to_vec())?.to_lowercase(), value, raw: data, }) } }