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 65 66 67
pub struct EqIgnoreAsciiCase<T1, T2>(pub T1, pub T2);
const fn eq_ignore_ascii_case(lhs: &[u8], rhs: &[u8]) -> bool {
if lhs.len() != rhs.len() {
return false;
}
let mut i = 0;
while i < lhs.len() {
let l = lhs[i].to_ascii_lowercase();
let r = rhs[i].to_ascii_lowercase();
if l != r {
return false;
}
i += 1;
}
true
}
impl EqIgnoreAsciiCase<&[u8], &[u8]> {
pub const fn const_eval(&self) -> bool {
eq_ignore_ascii_case(self.0, self.1)
}
}
impl EqIgnoreAsciiCase<&str, &str> {
pub const fn const_eval(&self) -> bool {
eq_ignore_ascii_case(self.0.as_bytes(), self.1.as_bytes())
}
}
impl<const N1: usize, const N2: usize> EqIgnoreAsciiCase<&[u8; N1], &[u8; N2]> {
pub const fn const_eval(&self) -> bool {
eq_ignore_ascii_case(self.0.as_slice(), self.1.as_slice())
}
}
/// Checks that two (string) slices are an ASCII case-insensitive match.
///
/// The input type must be one of:
/// + [`&str`](str)
/// + [`&[u8]`](slice)
/// + [`&[u8; N]`](array)
///
/// The output type is [`bool`].
///
/// # Examples
///
/// ```
/// use const_str::eq_ignore_ascii_case;
///
/// const _: () = {
/// assert!(eq_ignore_ascii_case!("Ferris", "FERRIS")); // true
/// assert!(!eq_ignore_ascii_case!(b"Ferris", b"FERRI")); // false
///
/// assert!(eq_ignore_ascii_case!("Ferrös", "FERRöS")); // true
/// // ^^^ ^ ^^^ ^
///
/// assert!(!eq_ignore_ascii_case!("Ferrös", "FERRÖS")); // false
/// // ^ ^
/// };
/// ```
#[macro_export]
macro_rules! eq_ignore_ascii_case {
($lhs:expr, $rhs:expr) => {
$crate::__ctfe::EqIgnoreAsciiCase($lhs, $rhs).const_eval()
};
}