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