use crate::bytes::Data;
use crate::err;
use crate::error::Error;
use std::str::FromStr;
pub trait Parse
where
Self: Sized,
{
fn split_off(&mut self, pat: &[u8]) -> Option<Self>;
#[must_use]
fn trim(&self) -> Self;
fn parse<Type>(&self) -> Result<Type, Error>
where
Type: FromStr,
Type::Err: std::error::Error + Send + 'static;
}
impl Parse for Data {
fn split_off(&mut self, pat: &[u8]) -> Option<Self> {
for (offset, haystack) in self.windows(pat.len()).enumerate() {
if haystack == pat {
let split = self.subcopy(..offset).expect("invalid prefix offset");
*self = self.subcopy(offset + pat.len()..).expect("invalid suffix offset");
return Some(split);
}
}
None
}
fn trim(&self) -> Self {
let leading = self.iter().take_while(|byte| byte.is_ascii_whitespace()).count();
let trimmed = self.subcopy(leading..).expect("invalid segment range");
let trailing = trimmed.iter().rev().take_while(|byte| byte.is_ascii_whitespace()).count();
trimmed.subcopy(..trimmed.len() - trailing).expect("invalid segment range")
}
fn parse<Type>(&self) -> Result<Type, Error>
where
Type: FromStr,
Type::Err: std::error::Error + Send + 'static,
{
self.as_ref().parse()
}
}
impl Parse for &[u8] {
fn split_off(&mut self, pat: &[u8]) -> Option<Self> {
for (offset, haystack) in self.windows(pat.len()).enumerate() {
if haystack == pat {
let split = &self[..offset];
*self = &self[offset + pat.len()..];
return Some(split);
}
}
None
}
fn trim(&self) -> Self {
self.trim_ascii()
}
fn parse<Type>(&self) -> Result<Type, Error>
where
Type: FromStr,
Type::Err: std::error::Error + Send + 'static,
{
let str_ = str::from_utf8(self)?;
str_.parse::<Type>().map_err(|e| err!(with: e, "failed to parse data"))
}
}