use crate::*;
use core::ops::Deref;
impl_for! {
Deref:
type Target = str;
#[inline]
fn deref(&self) -> &str {
self.as_str()
}
}
impl_for! {
AsRef<str>:
#[inline]
fn as_ref(&self) -> &str {
self
}
}
macro_rules! impl_ref {
($type:ty => $stringlet:ident $(: $conf:tt)?) => {
impl<const SIZE: usize> AsRef<$stringlet<SIZE>> for $type
$(where
$stringlet<SIZE>: $conf<SIZE>)?
{
#[doc = concat!("Cast a `", stringify!($type), "` as a shared reference to a [`", stringify!($stringlet), "`].")]
#[inline]
fn as_ref(&self) -> &$stringlet<SIZE> {
assert_eq!(
self.len(),
SIZE,
concat!("Cannot cast a len {} ", stringify!($type), " as &", stringify!($stringlet), "<SIZE>"),
self.len()
);
unsafe { core::mem::transmute(&*(self.as_ptr() as *const $stringlet<SIZE>)) }
}
}
};
}
impl_ref!(str => Stringlet);
impl_ref!(str => VarStringlet: VarConfig);
impl_ref!(str => TrimStringlet);
impl_ref!(str => SlimStringlet: SlimConfig);
impl_ref!(String => Stringlet);
impl_ref!(String => VarStringlet: VarConfig);
impl_ref!(String => TrimStringlet);
impl_ref!(String => SlimStringlet: SlimConfig);
impl_ref!(Box<str> => Stringlet);
impl_ref!(Box<str> => VarStringlet: VarConfig);
impl_ref!(Box<str> => TrimStringlet);
impl_ref!(Box<str> => SlimStringlet: SlimConfig);
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn test_deref() {
let s = Stringlet::<3>::from("Abc");
assert!(s.contains('b'));
let s = VarStringlet::<4>::from("Abc");
assert!(s.contains('b'));
let s = TrimStringlet::<4>::from("Abc");
assert!(s.contains('b'));
let s = SlimStringlet::<4>::from("Abc");
assert!(s.contains('b'));
}
#[test]
fn test_as_ref() {
let s = Stringlet::<1>::from("A");
let s: &str = s.as_ref();
assert_eq!(s, "A");
}
#[test]
fn test_borrow() {
macro_rules! test_borrow {
($a:ident = $in:expr, $size:literal) => {
let $a = $in;
let str: &str = $a.as_ref();
let slet: &Stringlet<$size> = $a.as_ref();
assert_eq!(str.as_ptr(), slet.as_ptr(), "fail {}", stringify!($in));
};
($a:expr) => {
test_borrow!(a = $a, 3);
test_borrow!(b = &a[1..], 2);
};
}
test_borrow!("aha");
test_borrow!(String::from("aha"));
test_borrow!(Box::<str>::from("aha"));
}
#[test]
#[should_panic]
fn test_panics_when_ref_too_long() {
let _: &Stringlet<4> = "abc".as_ref();
}
}