use anyhow::{bail, Result}; pub const CODE: &[u8] = b"53"; /// [Proxy request refused](https://geminiprotocol.net/docs/protocol-specification.gmi#status-53-proxy-request-refused) pub struct ProxyRequestRefused { pub message: Option, } impl ProxyRequestRefused { /// Build `Self` from UTF-8 header bytes /// * expected buffer includes leading status code, message, CRLF pub fn from_bytes(buffer: &[u8]) -> Result { use crate::Header; let h = buffer.header_bytes()?; if h.get(..2) .is_none_or(|c| c[0] != CODE[0] || c[1] != CODE[1]) { bail!("Invalid status code") } Ok(Self { message: String::from_utf8((h[3..]).to_vec()).map(|m| { if m.is_empty() { None } else { Some(m) } })?, }) } /// Convert `Self` into UTF-8 bytes presentation pub fn into_bytes(self) -> Vec { match self.message { Some(message) => { let mut bytes = Vec::with_capacity(message.len() + 5); bytes.extend(CODE); bytes.push(b' '); bytes.extend(message.into_bytes()); bytes.extend([b'\r', b'\n']); bytes } None => { let mut bytes = Vec::with_capacity(4); bytes.extend(CODE); bytes.extend([b'\r', b'\n']); bytes } } } } #[test] fn test() { let request = format!("53 message\r\n"); let source = ProxyRequestRefused::from_bytes(request.as_bytes()).unwrap(); assert_eq!(source.message, Some("message".to_string())); assert_eq!(source.into_bytes(), request.as_bytes()); }