use super::*;
#[derive(Debug, Clone, Copy, Eq, PartialEq, derive_more::Display)]
pub struct KeywordRef<'s>(&'s str);
#[derive(Error, Clone, Copy, Debug, Eq, PartialEq)]
#[non_exhaustive]
pub enum InvalidKeyword {
#[error("Keyword cannot be empty")]
Empty,
#[error("Keyword longer than {MAX_LEN} bytes")]
TooLong,
#[error("Keyword contains nul byte")]
ContainsNul,
}
pub const MAX_LEN: usize = 255;
impl<'s> KeywordRef<'s> {
pub const fn new_const(s: &'s str) -> Self {
match Self::new(s) {
Ok(y) => y,
Err(_e) => panic!("new_const failed"), }
}
pub const fn new(s: &'s str) -> Result<Self, InvalidKeyword> {
use InvalidKeyword as IK;
if s.is_empty() {
return Err(IK::Empty);
}
if s.len() > MAX_LEN {
return Err(IK::TooLong);
}
{
let mut unchecked = s.as_bytes();
while let Some((h, t)) = unchecked.split_first() {
if *h == b'\0' {
return Err(IK::ContainsNul);
}
unchecked = t;
}
}
Ok(KeywordRef(s))
}
pub unsafe fn new_unchecked(s: &'s str) -> Self {
KeywordRef(s)
}
pub fn as_str(&self) -> &str {
self.0
}
#[allow(clippy::len_without_is_empty)] pub fn len(&self) -> usize {
self.as_str().len()
}
}
impl<'s> AsRef<str> for KeywordRef<'s> {
fn as_ref(&self) -> &str {
self.as_str()
}
}
impl PartialEq<&str> for KeywordRef<'_> {
fn eq(&self, s: &&str) -> bool {
self.as_str() == *s
}
}