logos_codegen/graph/
impls.rs1use std::fmt::{self, Debug, Display};
2use std::hash::{Hash, Hasher};
3
4use crate::graph::{Fork, Graph, Node, NodeId, Range, Rope};
5
6impl<T> From<Fork> for Node<T> {
7 fn from(fork: Fork) -> Self {
8 Node::Fork(fork)
9 }
10}
11impl<T> From<Rope> for Node<T> {
12 fn from(rope: Rope) -> Self {
13 Node::Rope(rope)
14 }
15}
16
17fn is_ascii(byte: u8) -> bool {
18 (0x20..0x7F).contains(&byte)
19}
20
21impl Hash for Fork {
22 fn hash<H: Hasher>(&self, state: &mut H) {
23 for branch in self.branches() {
24 branch.hash(state);
25 }
26 self.miss.hash(state);
27 }
28}
29
30impl<T> Hash for Node<T> {
31 fn hash<H: Hasher>(&self, state: &mut H) {
32 match self {
33 Node::Rope(rope) => {
34 b"ROPE".hash(state);
35 rope.hash(state);
36 }
37 Node::Fork(fork) => {
38 b"FORK".hash(state);
39 fork.hash(state);
40 }
41 Node::Leaf(_) => b"LEAF".hash(state),
42 }
43 }
44}
45
46impl Debug for NodeId {
47 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
48 Debug::fmt(&self.0, f)
49 }
50}
51
52mod debug {
55 use super::*;
56 use crate::graph::rope::Miss;
57 use crate::graph::Disambiguate;
58 use std::cmp::{Ord, Ordering};
59
60 impl Disambiguate for &str {
61 fn cmp(left: &&str, right: &&str) -> Ordering {
62 Ord::cmp(left, right)
63 }
64 }
65
66 impl Debug for Range {
67 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
68 let Range { start, end } = *self;
69
70 if start != end || !is_ascii(start) {
71 f.write_str("[")?;
72 }
73 match is_ascii(start) {
74 true => write!(f, "{}", start as char),
75 false => write!(f, "{:02X}", start),
76 }?;
77 if start != end {
78 match is_ascii(end) {
79 true => write!(f, "-{}]", end as char),
80 false => write!(f, "-{:02X}]", end),
81 }?;
82 } else if !is_ascii(start) {
83 f.write_str("]")?;
84 }
85 Ok(())
86 }
87 }
88
89 impl Display for Range {
90 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
91 <Range as Debug>::fmt(self, f)
92 }
93 }
94
95 impl<T: Debug> Debug for Graph<T> {
96 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
97 let entries = self
98 .nodes()
99 .iter()
100 .enumerate()
101 .filter_map(|(i, n)| n.as_ref().map(|n| (i, n)));
102
103 f.debug_map().entries(entries).finish()
104 }
105 }
106
107 struct Arm<T, U>(T, U);
108
109 impl<T, U> Debug for Arm<T, U>
110 where
111 T: Display,
112 U: Display,
113 {
114 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
115 write!(f, "{} ⇒ {}", self.0, self.1)
116 }
117 }
118
119 impl Debug for Fork {
120 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
121 let mut list = f.debug_set();
122
123 for (range, then) in self.branches() {
124 list.entry(&Arm(range, then));
125 }
126 if let Some(id) = self.miss {
127 list.entry(&Arm('_', id));
128 }
129
130 list.finish()
131 }
132 }
133
134 impl Display for Miss {
135 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
136 match self {
137 Miss::First(id) => Display::fmt(id, f),
138 Miss::Any(id) => write!(f, "{}*", id),
139 Miss::None => f.write_str("n/a"),
140 }
141 }
142 }
143
144 impl Debug for Rope {
145 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
146 use std::fmt::Write;
147
148 let mut rope = String::with_capacity(self.pattern.len());
149 for range in self.pattern.iter() {
150 write!(rope, "{}", range)?;
151 }
152
153 match self.miss.is_none() {
154 false => {
155 let mut list = f.debug_list();
156
157 list.entry(&Arm(rope, self.then));
158 list.entry(&Arm('_', self.miss));
159
160 list.finish()
161 }
162 true => Arm(rope, self.then).fmt(f),
163 }
164 }
165 }
166
167 impl PartialEq for Fork {
168 fn eq(&self, other: &Self) -> bool {
169 self.miss == other.miss && self.branches().eq(other.branches())
170 }
171 }
172
173 impl<T: Debug> Debug for Node<T> {
174 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
175 match self {
176 Node::Fork(fork) => fork.fmt(f),
177 Node::Rope(rope) => rope.fmt(f),
178 Node::Leaf(leaf) => leaf.fmt(f),
179 }
180 }
181 }
182
183 use std::ops::RangeInclusive;
184
185 impl From<RangeInclusive<u8>> for Range {
186 fn from(range: RangeInclusive<u8>) -> Range {
187 Range {
188 start: *range.start(),
189 end: *range.end(),
190 }
191 }
192 }
193
194 impl From<RangeInclusive<char>> for Range {
195 fn from(range: RangeInclusive<char>) -> Range {
196 Range {
197 start: *range.start() as u8,
198 end: *range.end() as u8,
199 }
200 }
201 }
202
203 impl<T> PartialEq<Rope> for Node<T> {
204 fn eq(&self, other: &Rope) -> bool {
205 match self {
206 Node::Rope(rope) => rope == other,
207 _ => false,
208 }
209 }
210 }
211
212 impl<T> PartialEq<Fork> for Node<T> {
213 fn eq(&self, other: &Fork) -> bool {
214 match self {
215 Node::Fork(fork) => fork == other,
216 _ => false,
217 }
218 }
219 }
220}