use crate::{check_len, Error, Result, TryRead, TryWrite};
#[derive(Debug, PartialEq, Eq, Copy, Clone)]
pub enum Bytes {
Len(usize),
Pattern(&'static [u8]),
PatternUntil(&'static [u8], usize),
}
impl<'a> TryRead<'a, Bytes> for &'a [u8] {
#[inline]
fn try_read(bytes: &'a [u8], ctx: Bytes) -> Result<(Self, usize)> {
let len = match ctx {
Bytes::Len(len) => check_len(bytes, len)?,
Bytes::Pattern(pattern) => {
if pattern.is_empty() {
return Err(Error::BadInput {
err: "Pattern is empty",
});
}
check_len(bytes, pattern.len())?;
(0..bytes.len() - pattern.len() + 1)
.map(|n| bytes[n..].starts_with(pattern))
.position(|p| p)
.map(|len| len + pattern.len())
.ok_or(Error::Incomplete)?
}
Bytes::PatternUntil(pattern, len) => {
if pattern.is_empty() {
return Err(Error::BadInput {
err: "Pattern is empty",
});
}
if pattern.len() > len {
return Err(Error::BadInput {
err: "Pattern is longer than restricted length",
});
}
check_len(bytes, pattern.len())?;
(0..bytes.len() - pattern.len() + 1)
.map(|n| bytes[n..].starts_with(pattern))
.take(len - pattern.len())
.position(|p| p)
.map(|position| position + pattern.len())
.unwrap_or(check_len(bytes, len)?)
}
};
Ok((&bytes[..len], len))
}
}
impl<'a> TryWrite for &'a [u8] {
#[inline]
fn try_write(self, bytes: &mut [u8], _ctx: ()) -> Result<usize> {
check_len(bytes, self.len())?;
bytes[..self.len()].clone_from_slice(self);
Ok(self.len())
}
}