logos_codegen/graph/
range.rs1use regex_syntax::hir::ClassBytesRange;
2use regex_syntax::hir::ClassUnicodeRange;
3use regex_syntax::utf8::Utf8Range;
4
5use std::cmp::{Ord, Ordering};
6
7#[derive(Clone, Copy, PartialEq, Eq, Hash)]
8pub struct Range {
9 pub start: u8,
10 pub end: u8,
11}
12
13impl Range {
14 pub fn as_byte(&self) -> Option<u8> {
15 if self.is_byte() {
16 Some(self.start)
17 } else {
18 None
19 }
20 }
21
22 pub fn is_byte(&self) -> bool {
23 self.start == self.end
24 }
25}
26
27impl From<u8> for Range {
28 fn from(byte: u8) -> Range {
29 Range {
30 start: byte,
31 end: byte,
32 }
33 }
34}
35
36impl From<&u8> for Range {
37 fn from(byte: &u8) -> Range {
38 Range::from(*byte)
39 }
40}
41
42impl Iterator for Range {
43 type Item = u8;
44
45 fn next(&mut self) -> Option<u8> {
46 match self.start.cmp(&self.end) {
47 std::cmp::Ordering::Less => {
48 let res = self.start;
49 self.start += 1;
50
51 Some(res)
52 }
53 std::cmp::Ordering::Equal => {
54 let res = self.start;
55
56 self.start = 0xFF;
58 self.end = 0x00;
59
60 Some(res)
61 }
62 std::cmp::Ordering::Greater => None,
63 }
64 }
65}
66
67impl PartialOrd for Range {
68 fn partial_cmp(&self, other: &Range) -> Option<Ordering> {
69 Some(self.cmp(other))
70 }
71}
72
73impl Ord for Range {
74 fn cmp(&self, other: &Self) -> Ordering {
75 self.start.cmp(&other.start)
76 }
77}
78
79impl From<Utf8Range> for Range {
80 fn from(r: Utf8Range) -> Range {
81 Range {
82 start: r.start,
83 end: r.end,
84 }
85 }
86}
87
88impl From<ClassUnicodeRange> for Range {
89 fn from(r: ClassUnicodeRange) -> Range {
90 let start = r.start() as u32;
91 let end = r.end() as u32;
92
93 if start >= 128 || end >= 128 && end != 0x0010FFFF {
94 panic!("Casting non-ascii ClassUnicodeRange to Range")
95 }
96
97 Range {
98 start: start as u8,
99 end: end as u8,
100 }
101 }
102}
103
104impl From<ClassBytesRange> for Range {
105 fn from(r: ClassBytesRange) -> Range {
106 Range {
107 start: r.start(),
108 end: r.end(),
109 }
110 }
111}
112
113#[cfg(test)]
114mod tests {
115 use super::*;
116
117 #[test]
118 fn range_iter_one() {
119 let byte = Range::from(b'!');
120 let collected = byte.take(1000).collect::<Vec<_>>();
121
122 assert_eq!(b"!", &collected[..]);
123 }
124
125 #[test]
126 fn range_iter_few() {
127 let byte = Range {
128 start: b'a',
129 end: b'd',
130 };
131 let collected = byte.take(1000).collect::<Vec<_>>();
132
133 assert_eq!(b"abcd", &collected[..]);
134 }
135
136 #[test]
137 fn range_iter_bounds() {
138 let byte = Range::from(0xFA..=0xFF);
139
140 let collected = byte.take(1000).collect::<Vec<_>>();
141
142 assert_eq!(b"\xFA\xFB\xFC\xFD\xFE\xFF", &collected[..]);
143 }
144}