summaryrefslogtreecommitdiff
path: root/vendor/logos-codegen/src/graph/impls.rs
diff options
context:
space:
mode:
Diffstat (limited to 'vendor/logos-codegen/src/graph/impls.rs')
-rw-r--r--vendor/logos-codegen/src/graph/impls.rs220
1 files changed, 220 insertions, 0 deletions
diff --git a/vendor/logos-codegen/src/graph/impls.rs b/vendor/logos-codegen/src/graph/impls.rs
new file mode 100644
index 00000000..dc97bdf1
--- /dev/null
+++ b/vendor/logos-codegen/src/graph/impls.rs
@@ -0,0 +1,220 @@
+use std::fmt::{self, Debug, Display};
+use std::hash::{Hash, Hasher};
+
+use crate::graph::{Fork, Graph, Node, NodeId, Range, Rope};
+
+impl<T> From<Fork> for Node<T> {
+ fn from(fork: Fork) -> Self {
+ Node::Fork(fork)
+ }
+}
+impl<T> From<Rope> for Node<T> {
+ fn from(rope: Rope) -> Self {
+ Node::Rope(rope)
+ }
+}
+
+fn is_ascii(byte: u8) -> bool {
+ (0x20..0x7F).contains(&byte)
+}
+
+impl Hash for Fork {
+ fn hash<H: Hasher>(&self, state: &mut H) {
+ for branch in self.branches() {
+ branch.hash(state);
+ }
+ self.miss.hash(state);
+ }
+}
+
+impl<T> Hash for Node<T> {
+ fn hash<H: Hasher>(&self, state: &mut H) {
+ match self {
+ Node::Rope(rope) => {
+ b"ROPE".hash(state);
+ rope.hash(state);
+ }
+ Node::Fork(fork) => {
+ b"FORK".hash(state);
+ fork.hash(state);
+ }
+ Node::Leaf(_) => b"LEAF".hash(state),
+ }
+ }
+}
+
+impl Debug for NodeId {
+ fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
+ Debug::fmt(&self.0, f)
+ }
+}
+
+/// We don't need debug impls in release builds
+// #[cfg(test)]
+mod debug {
+ use super::*;
+ use crate::graph::rope::Miss;
+ use crate::graph::Disambiguate;
+ use std::cmp::{Ord, Ordering};
+
+ impl Disambiguate for &str {
+ fn cmp(left: &&str, right: &&str) -> Ordering {
+ Ord::cmp(left, right)
+ }
+ }
+
+ impl Debug for Range {
+ fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
+ let Range { start, end } = *self;
+
+ if start != end || !is_ascii(start) {
+ f.write_str("[")?;
+ }
+ match is_ascii(start) {
+ true => write!(f, "{}", start as char),
+ false => write!(f, "{:02X}", start),
+ }?;
+ if start != end {
+ match is_ascii(end) {
+ true => write!(f, "-{}]", end as char),
+ false => write!(f, "-{:02X}]", end),
+ }?;
+ } else if !is_ascii(start) {
+ f.write_str("]")?;
+ }
+ Ok(())
+ }
+ }
+
+ impl Display for Range {
+ fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
+ <Range as Debug>::fmt(self, f)
+ }
+ }
+
+ impl<T: Debug> Debug for Graph<T> {
+ fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
+ let entries = self
+ .nodes()
+ .iter()
+ .enumerate()
+ .filter_map(|(i, n)| n.as_ref().map(|n| (i, n)));
+
+ f.debug_map().entries(entries).finish()
+ }
+ }
+
+ struct Arm<T, U>(T, U);
+
+ impl<T, U> Debug for Arm<T, U>
+ where
+ T: Display,
+ U: Display,
+ {
+ fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
+ write!(f, "{} ⇒ {}", self.0, self.1)
+ }
+ }
+
+ impl Debug for Fork {
+ fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
+ let mut list = f.debug_set();
+
+ for (range, then) in self.branches() {
+ list.entry(&Arm(range, then));
+ }
+ if let Some(id) = self.miss {
+ list.entry(&Arm('_', id));
+ }
+
+ list.finish()
+ }
+ }
+
+ impl Display for Miss {
+ fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
+ match self {
+ Miss::First(id) => Display::fmt(id, f),
+ Miss::Any(id) => write!(f, "{}*", id),
+ Miss::None => f.write_str("n/a"),
+ }
+ }
+ }
+
+ impl Debug for Rope {
+ fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
+ use std::fmt::Write;
+
+ let mut rope = String::with_capacity(self.pattern.len());
+ for range in self.pattern.iter() {
+ write!(rope, "{}", range)?;
+ }
+
+ match self.miss.is_none() {
+ false => {
+ let mut list = f.debug_list();
+
+ list.entry(&Arm(rope, self.then));
+ list.entry(&Arm('_', self.miss));
+
+ list.finish()
+ }
+ true => Arm(rope, self.then).fmt(f),
+ }
+ }
+ }
+
+ impl PartialEq for Fork {
+ fn eq(&self, other: &Self) -> bool {
+ self.miss == other.miss && self.branches().eq(other.branches())
+ }
+ }
+
+ impl<T: Debug> Debug for Node<T> {
+ fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
+ match self {
+ Node::Fork(fork) => fork.fmt(f),
+ Node::Rope(rope) => rope.fmt(f),
+ Node::Leaf(leaf) => leaf.fmt(f),
+ }
+ }
+ }
+
+ use std::ops::RangeInclusive;
+
+ impl From<RangeInclusive<u8>> for Range {
+ fn from(range: RangeInclusive<u8>) -> Range {
+ Range {
+ start: *range.start(),
+ end: *range.end(),
+ }
+ }
+ }
+
+ impl From<RangeInclusive<char>> for Range {
+ fn from(range: RangeInclusive<char>) -> Range {
+ Range {
+ start: *range.start() as u8,
+ end: *range.end() as u8,
+ }
+ }
+ }
+
+ impl<T> PartialEq<Rope> for Node<T> {
+ fn eq(&self, other: &Rope) -> bool {
+ match self {
+ Node::Rope(rope) => rope == other,
+ _ => false,
+ }
+ }
+ }
+
+ impl<T> PartialEq<Fork> for Node<T> {
+ fn eq(&self, other: &Fork) -> bool {
+ match self {
+ Node::Fork(fork) => fork == other,
+ _ => false,
+ }
+ }
+ }
+}