pub struct IsAscii<T>(pub T);
impl IsAscii<&[u8]> {
pub const fn const_eval(&self) -> bool {
let bytes = self.0;
let mut i = 0;
while i < bytes.len() {
if !bytes[i].is_ascii() {
return false;
}
i += 1;
}
true
}
}
impl IsAscii<&str> {
pub const fn const_eval(&self) -> bool {
IsAscii(self.0.as_bytes()).const_eval()
}
}
impl<const N: usize> IsAscii<&[u8; N]> {
pub const fn const_eval(&self) -> bool {
IsAscii(self.0.as_slice()).const_eval()
}
}
#[macro_export]
macro_rules! is_ascii {
($s:expr) => {
$crate::__ctfe::IsAscii($s).const_eval()
};
}
#[cfg(test)]
mod tests {
#[test]
fn test_is_ascii() {
const S1: &str = "hello!\n";
const S2: &str = "你好!";
const S3: &str = "";
const S4: &str = "ASCII123";
let r1 = is_ascii!(S1);
let r2 = is_ascii!(S2);
let r3 = is_ascii!(S3);
let r4 = is_ascii!(S4);
assert!(r1);
assert!(!r2);
assert!(r3); assert!(r4);
const B1: &[u8] = b"hello";
const B2: &[u8] = b"\x80\x00";
let rb1 = is_ascii!(B1);
let rb2 = is_ascii!(B2);
assert!(rb1);
assert!(!rb2);
const A1: &[u8; 5] = b"hello";
const A2: &[u8; 2] = b"\x80\x00";
let ra1 = is_ascii!(A1);
let ra2 = is_ascii!(A2);
assert!(ra1);
assert!(!ra2);
}
}