use crate::*;
impl<Kind: StringletKind, const SIZE: usize> StringletBase<Kind, SIZE> {
#[inline(always)]
pub const fn len(&self) -> usize {
if Kind::FIXED || SIZE == 0 {
return SIZE;
}
let last = self.last();
if Kind::VAR {
last as _
} else if SIZE == 1 {
(last < TAG) as _
} else if Kind::TRIM {
SIZE - (last > TAG) as usize
}
else if SIZE == 64 {
SIZE - (last == TAG) as usize * SIZE - (last > TAG) as usize * (last ^ TAG) as usize
} else {
SIZE - (last > TAG) as usize * (last ^ TAG) as usize
}
}
#[inline(always)]
pub const fn is_empty(&self) -> bool {
if SIZE == 0 {
return true;
}
let last = self.last();
if Kind::FIXED {
false
} else if Kind::TRIM {
SIZE == 1 && last > TAG
} else if Kind::VAR {
last == 0
}
else if SIZE == 64 {
last == TAG
} else {
last == TAG | SIZE as u8
}
}
#[inline(always)]
pub const fn as_bytes(&self) -> &[u8] {
if Kind::FIXED {
&self.str
} else {
unsafe { core::slice::from_raw_parts(self.str.as_ptr(), self.len()) }
}
}
#[inline(always)]
pub const fn as_str(&self) -> &str {
unsafe { str::from_utf8_unchecked(self.as_bytes()) }
}
pub(crate) fn type_name() -> String {
use core::fmt::Write;
let mut ret = String::with_capacity(20) + if Kind::FIXED {
"Stringlet"
} else if Kind::VAR {
"VarStringlet"
} else if Kind::TRIM {
"TrimStringlet"
} else {
"SlimStringlet"
};
if SIZE != 16 {
_ = write!(ret, "<{SIZE}>");
}
ret
}
#[inline(always)]
pub(crate) const fn last(&self) -> u8 {
if Kind::VAR {
self.var_last()
} else {
debug_assert!(SIZE != 0, "unchecked call");
self.str[SIZE - 1]
}
}
}
#[cfg(test)]
mod tests {
use core::convert::Into;
use super::*;
#[test]
fn test_big() {
let _f: Stringlet<1024>;
let _v: VarStringlet<255>;
let _s: SlimStringlet<64>;
}
#[test]
fn test_as_str() {
let f: Stringlet<7> = "A123456".into();
assert_eq!(f.as_str(), "A123456");
let v: VarStringlet = "A123456".into();
assert_eq!(v.as_str(), "A123456");
let s: SlimStringlet = "A123456".into();
assert_eq!(s.as_str(), "A123456");
}
fn test_all_lengths<const SIZE: usize>()
where
VarStringlet<SIZE>: VarConfig<SIZE>,
SlimStringlet<SIZE>: SlimConfig<SIZE>,
{
const STR64: &str = "0123456789_123456789_123456789_123456789_123456789_123456789_123";
for len in 0..=SIZE {
let str: VarStringlet<SIZE> = (&STR64[..len]).into();
assert_eq!(str.is_empty(), len == 0);
assert_eq!(str.len(), len);
let str: SlimStringlet<SIZE> = (&STR64[..len]).into();
assert_eq!(str.is_empty(), len == 0);
assert_eq!(str.len(), len);
}
let fixed: Stringlet<SIZE> = (&STR64[..SIZE]).into();
assert_eq!(fixed.is_empty(), SIZE == 0);
assert_eq!(fixed.len(), SIZE);
let trim: TrimStringlet<SIZE> = (&STR64[..SIZE]).into();
assert_eq!(trim.is_empty(), SIZE == 0);
assert_eq!(trim.len(), SIZE);
}
#[test]
fn test_len() {
macro_rules! test_all_lengths {
($($size:literal),+) => {
$(test_all_lengths::<$size>();)+
};
}
test_all_lengths![
0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23,
24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45,
46, 47, 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63, 64
];
}
#[test]
fn test_empty() {
assert!(stringlet!("").is_empty());
assert!(!stringlet!("a").is_empty());
assert!(!stringlet!("ab").is_empty());
assert!(stringlet!(trim: "").is_empty());
assert!(stringlet!(trim 1: "").is_empty());
assert!(!stringlet!(trim: "a").is_empty());
assert!(!stringlet!(trim 2: "a").is_empty());
assert!(!stringlet!(trim: "ab").is_empty());
assert!(!stringlet!(trim 3: "ab").is_empty());
assert!(stringlet!(var: "").is_empty());
assert!(stringlet!(var 1: "").is_empty());
assert!(stringlet!(var 2: "").is_empty());
assert!(!stringlet!(var: "a").is_empty());
assert!(!stringlet!(var: "ab").is_empty());
assert!(stringlet!(slim: "").is_empty());
assert!(stringlet!(slim 1: "").is_empty());
assert!(stringlet!(slim 2: "").is_empty());
assert!(!stringlet!(slim: "a").is_empty());
assert!(!stringlet!(slim: "ab").is_empty());
}
#[test]
fn test_all_type_names() {
macro_rules! test_it {
(1 $ty:ty) => {
assert_eq!(<$ty>::type_name(), stringify!($ty).replace(' ', ""));
};
([$($size:literal),+] $ty:tt) => {
$(
test_it!(1 $ty<$size>);
)+
};
($ty:tt) => {
test_it!(1 $ty); test_it!([
0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 17, 18, 19, 20, 21, 22, 23,
24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43,
44, 45, 46, 47, 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63, 64
] $ty);
};
}
test_it!(Stringlet);
test_it!(VarStringlet);
test_it!(TrimStringlet);
test_it!(SlimStringlet);
}
}