use crate::{check_len, Error, Result, TryRead, TryWrite};
use core::str;
#[derive(Debug, PartialEq, Eq, Copy, Clone)]
pub enum Str {
Len(usize),
Delimiter(u8),
DelimiterUntil(u8, usize),
}
impl Default for Str {
#[inline]
fn default() -> Self {
Str::Delimiter(NULL)
}
}
pub const NULL: u8 = 0;
pub const SPACE: u8 = 0x20;
pub const RET: u8 = 0x0a;
pub const TAB: u8 = 0x09;
impl<'a> TryRead<'a, Str> for &'a str {
#[inline]
fn try_read(bytes: &'a [u8], ctx: Str) -> Result<(Self, usize)> {
let (bytes, size) = match ctx {
Str::Len(len) => {
let len = check_len(bytes, len)?;
(&bytes[..len], len)
}
Str::Delimiter(delimiter) => {
let position = bytes
.iter()
.position(|c| *c == delimiter)
.ok_or(Error::Incomplete)?;
(&bytes[..position], position + 1)
}
Str::DelimiterUntil(delimiter, len) => {
let position = bytes.iter().take(len).position(|c| *c == delimiter);
match position {
Some(position) => (&bytes[..position], position + 1),
None => {
let len = check_len(bytes, len)?;
(&bytes[..len], len)
}
}
}
};
match str::from_utf8(bytes) {
Ok(str) => Ok((str, size)),
Err(_) => Err(Error::BadInput { err: "UTF8 Error" }),
}
}
}
impl<'a> TryWrite for &'a str {
#[inline]
fn try_write(self, bytes: &mut [u8], _ctx: ()) -> Result<usize> {
let str_bytes = self.as_bytes();
check_len(bytes, str_bytes.len())?;
bytes[..str_bytes.len()].clone_from_slice(str_bytes);
Ok(str_bytes.len())
}
}