macro_rules! pattern {
() => {};
(!!**!! A) => { b'a' | b'A' };
(!!**!! C) => { b'c' | b'C' };
(!!**!! I) => { b'i' | b'I' };
(!!**!! L) => { b'l' | b'L' };
(!!**!! M) => { b'm' | b'M' };
(!!**!! N) => { b'n' | b'N' };
(!!**!! O) => { b'o' | b'O' };
(!!**!! P) => { b'p' | b'P' };
(!!**!! R) => { b'r' | b'R' };
(!!**!! T) => { b't' | b'T' };
(!!**!! U) => { b'u' | b'U' };
(!!**!! X) => { b'x' | b'X' };
(!!**!! /) => { b'\\' | b'/' };
(!!**!! '.') => { b'.' | b'?' };
(!!**!! '$') => { b'$' };
(!!**!! ':') => { b':' };
(!!**!! $pat:pat) => { $pat };
([$($tt:tt$(@$pat:pat)?),+]) => {
[$(pattern!(!!**!! $tt$(@$pat)?)),+]
};
([$($tt:tt$(|$pat:pat)?),+]) => {
[$(pattern!(!!**!! $tt)$(|$pat)?),+]
};
($($tt:tt)|+) => {
$(pattern!($tt))|+
};
}
macro_rules! match_pattern {
($match:expr; $([$($tt:tt)+]$(|[$($tt2:tt)*])* => $expr:expr),+, _ => $final:expr) => {
match $match {
$(
pattern!([$($tt)+]$(|[$($tt2)*])*) => $expr
),+,
_ => $final,
}
};
}
pub const fn trim_start(bytes: &[u8], len: u8) -> &[u8] {
if len == 0 {
return bytes;
}
match bytes {
[_, bytes @ ..] => trim_start(bytes, len - 1),
[] => bytes,
}
}
pub const unsafe fn trim_start_str(s: &str, len: usize) -> &str {
core::str::from_utf8_unchecked(trim_start(s.as_bytes(), len as u8))
}
pub const fn utf8_len(first_byte: u8) -> u8 {
match first_byte.leading_ones() as u8 {
0 => 1,
n => n,
}
}
pub const fn bmp_utf8_to_utf16(bytes: &[u8]) -> u16 {
debug_assert!(matches!(utf8_len(bytes[0]), 1 | 2 | 3));
match utf8_len(bytes[0]) {
3.. => {
let a = (bytes[0] & 0b1111) as u16;
let b = (bytes[1] & 0b111111) as u16;
let c = (bytes[2] & 0b111111) as u16;
(a << 12) | (b << 6) | c
}
2.. => {
let a = (bytes[0] & 0b11111) as u16;
let b = (bytes[1] & 0b111111) as u16;
(a << 6) | b
}
_ => bytes[0] as u16,
}
}