use {TryRead, TryWrite, Error, Result, check_len};
#[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.len() == 0 {
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.len() == 0 {
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())
}
}