1use crate::bit::BitIterator;
4use std::fmt::{Debug, Display, Formatter};
5
6#[derive(Copy, Clone, Eq, PartialEq, Default)]
25#[repr(transparent)]
26#[must_use]
27pub struct AsciiSet {
28 set: u128,
29}
30
31impl AsciiSet {
32 pub const fn new(set: u128) -> Self {
34 Self { set }
35 }
36
37 #[must_use]
38 pub const fn is_empty(&self) -> bool {
39 self.set == 0
40 }
41
42 #[must_use]
43 pub const fn len(&self) -> usize {
44 self.set.count_ones() as usize
45 }
46
47 #[expect(clippy::cast_possible_truncation)]
48 fn write_next_entry(&mut self, f: &mut Formatter<'_>) -> std::fmt::Result {
49 let b = self.set.trailing_zeros() as u8;
50 let run = (self.set >> b).trailing_ones() as u8;
51
52 let class_end = match b {
53 b'0'..=b'9' => b'9',
54 b'a'..=b'z' => b'z',
55 b'A'..=b'Z' => b'Z',
56 _ => b,
57 };
58 let range_len = (class_end - b + 1).min(run);
59
60 if range_len >= 4 {
61 self.set &= !(((1 << range_len) - 1) << b);
62 write!(f, "{:?}-{:?}", b as char, (b + range_len - 1) as char)
63 } else {
64 self.set &= !(1 << b);
65 write!(f, "{:?}", b as char)
66 }
67 }
68}
69
70impl Display for AsciiSet {
98 fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
99 if self.is_empty() {
100 return write!(f, "(empty)");
101 }
102 let mut set = *self;
103 set.write_next_entry(f)?;
104 while !set.is_empty() {
105 write!(f, ", ")?;
106 set.write_next_entry(f)?;
107 }
108 Ok(())
109 }
110}
111
112impl Debug for AsciiSet {
113 #[expect(clippy::cast_possible_truncation)]
114 fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
115 f.debug_set()
116 .entries(BitIterator::ones(self.set).map(|(c, _)| c as u8 as char))
117 .finish()
118 }
119}
120
121impl From<u128> for AsciiSet {
122 fn from(set: u128) -> Self {
123 Self { set }
124 }
125}
126
127impl From<[bool; 128]> for AsciiSet {
128 fn from(value: [bool; 128]) -> Self {
129 Self {
130 set: value
131 .iter()
132 .enumerate()
133 .fold(0, |s, (i, &b)| s | u128::from(b) << i),
134 }
135 }
136}
137
138impl<F: Fn(u8) -> bool> From<F> for AsciiSet {
139 fn from(value: F) -> Self {
140 Self {
141 set: (0u8..=127).fold(0, |s, i| s | u128::from(value(i)) << i),
142 }
143 }
144}