summaryrefslogtreecommitdiff
path: root/vendor/logos-codegen/src/graph/range.rs
diff options
context:
space:
mode:
Diffstat (limited to 'vendor/logos-codegen/src/graph/range.rs')
-rw-r--r--vendor/logos-codegen/src/graph/range.rs144
1 files changed, 144 insertions, 0 deletions
diff --git a/vendor/logos-codegen/src/graph/range.rs b/vendor/logos-codegen/src/graph/range.rs
new file mode 100644
index 00000000..a4d23d3b
--- /dev/null
+++ b/vendor/logos-codegen/src/graph/range.rs
@@ -0,0 +1,144 @@
+use regex_syntax::hir::ClassBytesRange;
+use regex_syntax::hir::ClassUnicodeRange;
+use regex_syntax::utf8::Utf8Range;
+
+use std::cmp::{Ord, Ordering};
+
+#[derive(Clone, Copy, PartialEq, Eq, Hash)]
+pub struct Range {
+ pub start: u8,
+ pub end: u8,
+}
+
+impl Range {
+ pub fn as_byte(&self) -> Option<u8> {
+ if self.is_byte() {
+ Some(self.start)
+ } else {
+ None
+ }
+ }
+
+ pub fn is_byte(&self) -> bool {
+ self.start == self.end
+ }
+}
+
+impl From<u8> for Range {
+ fn from(byte: u8) -> Range {
+ Range {
+ start: byte,
+ end: byte,
+ }
+ }
+}
+
+impl From<&u8> for Range {
+ fn from(byte: &u8) -> Range {
+ Range::from(*byte)
+ }
+}
+
+impl Iterator for Range {
+ type Item = u8;
+
+ fn next(&mut self) -> Option<u8> {
+ match self.start.cmp(&self.end) {
+ std::cmp::Ordering::Less => {
+ let res = self.start;
+ self.start += 1;
+
+ Some(res)
+ }
+ std::cmp::Ordering::Equal => {
+ let res = self.start;
+
+ // Necessary so that range 0xFF-0xFF doesn't loop forever
+ self.start = 0xFF;
+ self.end = 0x00;
+
+ Some(res)
+ }
+ std::cmp::Ordering::Greater => None,
+ }
+ }
+}
+
+impl PartialOrd for Range {
+ fn partial_cmp(&self, other: &Range) -> Option<Ordering> {
+ Some(self.cmp(other))
+ }
+}
+
+impl Ord for Range {
+ fn cmp(&self, other: &Self) -> Ordering {
+ self.start.cmp(&other.start)
+ }
+}
+
+impl From<Utf8Range> for Range {
+ fn from(r: Utf8Range) -> Range {
+ Range {
+ start: r.start,
+ end: r.end,
+ }
+ }
+}
+
+impl From<ClassUnicodeRange> for Range {
+ fn from(r: ClassUnicodeRange) -> Range {
+ let start = r.start() as u32;
+ let end = r.end() as u32;
+
+ if start >= 128 || end >= 128 && end != 0x0010FFFF {
+ panic!("Casting non-ascii ClassUnicodeRange to Range")
+ }
+
+ Range {
+ start: start as u8,
+ end: end as u8,
+ }
+ }
+}
+
+impl From<ClassBytesRange> for Range {
+ fn from(r: ClassBytesRange) -> Range {
+ Range {
+ start: r.start(),
+ end: r.end(),
+ }
+ }
+}
+
+#[cfg(test)]
+mod tests {
+ use super::*;
+
+ #[test]
+ fn range_iter_one() {
+ let byte = Range::from(b'!');
+ let collected = byte.take(1000).collect::<Vec<_>>();
+
+ assert_eq!(b"!", &collected[..]);
+ }
+
+ #[test]
+ fn range_iter_few() {
+ let byte = Range {
+ start: b'a',
+ end: b'd',
+ };
+ let collected = byte.take(1000).collect::<Vec<_>>();
+
+ assert_eq!(b"abcd", &collected[..]);
+ }
+
+ #[test]
+ fn range_iter_bounds() {
+ let byte = Range::from(0xFA..=0xFF);
+
+ let collected = byte.take(1000).collect::<Vec<_>>();
+
+ assert_eq!(b"\xFA\xFB\xFC\xFD\xFE\xFF", &collected[..]);
+ }
+}