1 use std::{
2     fmt,
3     ops::{AddAssign, Deref},
4 };
5 use text_size::TextSize;
6 
7 #[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash)]
8 pub enum NodeOrToken<N, T> {
9     Node(N),
10     Token(T),
11 }
12 
13 impl<N, T> NodeOrToken<N, T> {
into_node(self) -> Option<N>14     pub fn into_node(self) -> Option<N> {
15         match self {
16             NodeOrToken::Node(node) => Some(node),
17             NodeOrToken::Token(_) => None,
18         }
19     }
20 
into_token(self) -> Option<T>21     pub fn into_token(self) -> Option<T> {
22         match self {
23             NodeOrToken::Node(_) => None,
24             NodeOrToken::Token(token) => Some(token),
25         }
26     }
27 
as_node(&self) -> Option<&N>28     pub fn as_node(&self) -> Option<&N> {
29         match self {
30             NodeOrToken::Node(node) => Some(node),
31             NodeOrToken::Token(_) => None,
32         }
33     }
34 
as_token(&self) -> Option<&T>35     pub fn as_token(&self) -> Option<&T> {
36         match self {
37             NodeOrToken::Node(_) => None,
38             NodeOrToken::Token(token) => Some(token),
39         }
40     }
41 }
42 
43 impl<N: Deref, T: Deref> NodeOrToken<N, T> {
as_deref(&self) -> NodeOrToken<&N::Target, &T::Target>44     pub(crate) fn as_deref(&self) -> NodeOrToken<&N::Target, &T::Target> {
45         match self {
46             NodeOrToken::Node(node) => NodeOrToken::Node(&*node),
47             NodeOrToken::Token(token) => NodeOrToken::Token(&*token),
48         }
49     }
50 }
51 
52 impl<N: fmt::Display, T: fmt::Display> fmt::Display for NodeOrToken<N, T> {
fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result53     fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
54         match self {
55             NodeOrToken::Node(node) => fmt::Display::fmt(node, f),
56             NodeOrToken::Token(token) => fmt::Display::fmt(token, f),
57         }
58     }
59 }
60 
61 #[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash)]
62 pub enum Direction {
63     Next,
64     Prev,
65 }
66 
67 /// `WalkEvent` describes tree walking process.
68 #[derive(Debug, Copy, Clone)]
69 pub enum WalkEvent<T> {
70     /// Fired before traversing the node.
71     Enter(T),
72     /// Fired after the node is traversed.
73     Leave(T),
74 }
75 
76 impl<T> WalkEvent<T> {
map<F: FnOnce(T) -> U, U>(self, f: F) -> WalkEvent<U>77     pub fn map<F: FnOnce(T) -> U, U>(self, f: F) -> WalkEvent<U> {
78         match self {
79             WalkEvent::Enter(it) => WalkEvent::Enter(f(it)),
80             WalkEvent::Leave(it) => WalkEvent::Leave(f(it)),
81         }
82     }
83 }
84 
85 /// There might be zero, one or two leaves at a given offset.
86 #[derive(Clone, Debug)]
87 pub enum TokenAtOffset<T> {
88     /// No leaves at offset -- possible for the empty file.
89     None,
90     /// Only a single leaf at offset.
91     Single(T),
92     /// Offset is exactly between two leaves.
93     Between(T, T),
94 }
95 
96 impl<T> TokenAtOffset<T> {
map<F: Fn(T) -> U, U>(self, f: F) -> TokenAtOffset<U>97     pub fn map<F: Fn(T) -> U, U>(self, f: F) -> TokenAtOffset<U> {
98         match self {
99             TokenAtOffset::None => TokenAtOffset::None,
100             TokenAtOffset::Single(it) => TokenAtOffset::Single(f(it)),
101             TokenAtOffset::Between(l, r) => TokenAtOffset::Between(f(l), f(r)),
102         }
103     }
104 
105     /// Convert to option, preferring the right leaf in case of a tie.
right_biased(self) -> Option<T>106     pub fn right_biased(self) -> Option<T> {
107         match self {
108             TokenAtOffset::None => None,
109             TokenAtOffset::Single(node) => Some(node),
110             TokenAtOffset::Between(_, right) => Some(right),
111         }
112     }
113 
114     /// Convert to option, preferring the left leaf in case of a tie.
left_biased(self) -> Option<T>115     pub fn left_biased(self) -> Option<T> {
116         match self {
117             TokenAtOffset::None => None,
118             TokenAtOffset::Single(node) => Some(node),
119             TokenAtOffset::Between(left, _) => Some(left),
120         }
121     }
122 }
123 
124 impl<T> Iterator for TokenAtOffset<T> {
125     type Item = T;
126 
next(&mut self) -> Option<T>127     fn next(&mut self) -> Option<T> {
128         match std::mem::replace(self, TokenAtOffset::None) {
129             TokenAtOffset::None => None,
130             TokenAtOffset::Single(node) => {
131                 *self = TokenAtOffset::None;
132                 Some(node)
133             }
134             TokenAtOffset::Between(left, right) => {
135                 *self = TokenAtOffset::Single(right);
136                 Some(left)
137             }
138         }
139     }
140 
size_hint(&self) -> (usize, Option<usize>)141     fn size_hint(&self) -> (usize, Option<usize>) {
142         match self {
143             TokenAtOffset::None => (0, Some(0)),
144             TokenAtOffset::Single(_) => (1, Some(1)),
145             TokenAtOffset::Between(_, _) => (2, Some(2)),
146         }
147     }
148 }
149 
150 impl<T> ExactSizeIterator for TokenAtOffset<T> {}
151 
152 macro_rules! _static_assert {
153     ($expr:expr) => {
154         const _: i32 = 0 / $expr as i32;
155     };
156 }
157 
158 pub(crate) use _static_assert as static_assert;
159 
160 #[derive(Copy, Clone, Debug)]
161 pub(crate) enum Delta<T> {
162     Add(T),
163     Sub(T),
164 }
165 
166 // This won't be coherent :-(
167 // impl<T: AddAssign + SubAssign> AddAssign<Delta<T>> for T
168 macro_rules! impls {
169     ($($ty:ident)*) => {$(
170         impl AddAssign<Delta<$ty>> for $ty {
171             fn add_assign(&mut self, rhs: Delta<$ty>) {
172                 match rhs {
173                     Delta::Add(amt) => *self += amt,
174                     Delta::Sub(amt) => *self -= amt,
175                 }
176             }
177         }
178     )*};
179 }
180 impls!(u32 TextSize);
181