1use std::iter::FromIterator;
2
3pub fn simple_lowercase(c: char) -> char {
4 c.to_lowercase().next().unwrap_or(c)
5}
6
7#[derive(Copy, Clone, Debug, Default, PartialEq, Eq, Hash)]
8pub struct CharBag(u64);
9
10impl CharBag {
11 pub fn is_superset(self, other: CharBag) -> bool {
12 self.0 & other.0 == other.0
13 }
14
15 fn insert(&mut self, c: char) {
16 let c = simple_lowercase(c);
17 if c.is_ascii_lowercase() {
18 let mut count = self.0;
19 let idx = c as u8 - b'a';
20 count >>= idx * 2;
21 count = ((count << 1) | 1) & 3;
22 count <<= idx * 2;
23 self.0 |= count;
24 } else if c.is_ascii_digit() {
25 let idx = c as u8 - b'0';
26 self.0 |= 1 << (idx + 52);
27 } else if c == '-' {
28 self.0 |= 1 << 62;
29 }
30 }
31}
32
33impl Extend<char> for CharBag {
34 fn extend<T: IntoIterator<Item = char>>(&mut self, iter: T) {
35 for c in iter {
36 self.insert(c);
37 }
38 }
39}
40
41impl FromIterator<char> for CharBag {
42 fn from_iter<T: IntoIterator<Item = char>>(iter: T) -> Self {
43 let mut result = Self::default();
44 result.extend(iter);
45 result
46 }
47}
48
49impl From<&str> for CharBag {
50 fn from(s: &str) -> Self {
51 let mut bag = Self(0);
52 for c in s.chars() {
53 bag.insert(c);
54 }
55 bag
56 }
57}
58
59impl From<&[char]> for CharBag {
60 fn from(chars: &[char]) -> Self {
61 let mut bag = Self(0);
62 for c in chars {
63 bag.insert(*c);
64 }
65 bag
66 }
67}