add Header trait with shared bytes impl

This commit is contained in:
yggverse 2025-02-22 06:06:31 +02:00
parent 25e3ebb243
commit 21ac900576
3 changed files with 29 additions and 19 deletions

View file

@ -3,3 +3,29 @@ pub mod response;
pub use request::Request;
pub use response::Response;
pub const HEADER_MAX_LEN: usize = 1024;
pub trait Header {
fn header_bytes(&self) -> Result<&[u8]>;
}
impl Header for &[u8] {
fn header_bytes(&self) -> Result<&[u8]> {
match self.iter().position(|&b| b == b'\r') {
Some(n) => {
if n > HEADER_MAX_LEN {
bail!("Header bytes length reached")
}
if self.get(n + 1).is_some_and(|&b| b == b'\n') {
Ok(&self[..n])
} else {
bail!("LF byte not found")
}
}
None => bail!("CR byte not found"),
}
}
}
use anyhow::{bail, Result};

View file

@ -4,8 +4,7 @@ pub mod titan;
pub use gemini::Gemini;
pub use titan::Titan;
pub const HEADER_MAX_LEN: usize = 1024;
use super::Header;
use anyhow::{bail, Result};
/// https://geminiprotocol.net/docs/protocol-specification.gmi#requests
@ -32,19 +31,3 @@ impl<'a> Request<'a> {
}
}
}
pub fn header_bytes(buffer: &[u8]) -> Result<&[u8]> {
match buffer.iter().position(|&b| b == b'\r') {
Some(n) => {
if n > HEADER_MAX_LEN {
bail!("Header bytes length reached")
}
if buffer.get(n + 1).is_some_and(|&b| b == b'\n') {
Ok(&buffer[..n])
} else {
bail!("LF byte not found")
}
}
None => bail!("CR byte not found"),
}
}

View file

@ -8,8 +8,9 @@ pub struct Gemini {
impl Gemini {
pub fn from_bytes(buffer: &[u8]) -> Result<Self> {
use super::Header;
Ok(Self {
url: Url::parse(std::str::from_utf8(crate::request::header_bytes(buffer)?)?)?,
url: Url::parse(std::str::from_utf8(buffer.header_bytes()?)?)?,
})
}
pub fn into_bytes(self) -> Vec<u8> {