pub type AsciiSet = u128;
pub const UNRESERVED: AsciiSet = alphanumerics() | chars_to_ascii_set(b"-._~");
pub const SUBDELIMS: AsciiSet = chars_to_ascii_set(b"!$&'()*+,;=");
pub const GENDELIMS: AsciiSet = chars_to_ascii_set(b":/?#[]@");
pub const RESERVED: AsciiSet = GENDELIMS | SUBDELIMS;
pub const HOST_UE: AsciiSet = UNRESERVED | SUBDELIMS;
pub const PATH_UE: AsciiSet = UNRESERVED | SUBDELIMS | chars_to_ascii_set(b":@");
pub const QUERY_UE: AsciiSet = (UNRESERVED | SUBDELIMS | chars_to_ascii_set(b":@/?")) & !chars_to_ascii_set(b"&");
pub const FRAGMENT_UE: AsciiSet = UNRESERVED | SUBDELIMS | chars_to_ascii_set(b":@/?");
const fn chars_to_ascii_set(s: &[u8]) -> AsciiSet {
let mut result = 0;
let mut i = 0;
while i < s.len() {
let c = s[i];
if c < 128 {
result |= 1u128 << c;
} else {
panic!("High characters can not be part in an ASCII set");
}
i += 1;
}
result
}
const fn alphanumerics() -> AsciiSet {
let mut result = 0;
let mut i = 0u8;
while i < 128 {
if i.is_ascii_alphanumeric() {
result |= 1u128 << i;
}
i += 1;
}
result
}
pub const fn contains(s: AsciiSet, c: char) -> bool {
let c = c as u32;
if c < 128 {
s & (1 << c) != 0
} else {
false
}
}
pub const fn contains_byte(s: AsciiSet, c: u8) -> bool {
if c < 128 {
s & (1 << c) != 0
} else {
false
}
}
#[test]
fn asciiset_examples() {
assert!(contains(UNRESERVED, 'a'));
assert!(contains(UNRESERVED, 'A'));
assert!(contains(UNRESERVED, '9'));
assert!(contains(UNRESERVED, '~'));
assert!(!contains(UNRESERVED, '@'));
assert!(contains(RESERVED, '['));
assert!(!contains(RESERVED, 'A'));
assert!(!contains_byte(RESERVED, b'A'));
assert!(!contains_byte(QUERY_UE, b'&'));
}