1use std::{
2 fmt,
3 ops::{AddAssign, Deref},
4};
5use text_size::TextSize;
6
7#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash)]
8pub enum NodeOrToken<N, T> {
9 Node(N),
10 Token(T),
11}
12
13impl<N, T> NodeOrToken<N, T> {
14 pub fn into_node(self) -> Option<N> {
15 match self {
16 NodeOrToken::Node(node) => Some(node),
17 NodeOrToken::Token(_) => None,
18 }
19 }
20
21 pub fn into_token(self) -> Option<T> {
22 match self {
23 NodeOrToken::Node(_) => None,
24 NodeOrToken::Token(token) => Some(token),
25 }
26 }
27
28 pub fn as_node(&self) -> Option<&N> {
29 match self {
30 NodeOrToken::Node(node) => Some(node),
31 NodeOrToken::Token(_) => None,
32 }
33 }
34
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
43impl<N: Deref, T: Deref> NodeOrToken<N, T> {
44 pub(crate) fn as_deref(&self) -> NodeOrToken<&N::Target, &T::Target> {
45 match self {
46 NodeOrToken::Node(node: &N) => NodeOrToken::Node(&*node),
47 NodeOrToken::Token(token: &T) => NodeOrToken::Token(&*token),
48 }
49 }
50}
51
52impl<N: fmt::Display, T: fmt::Display> fmt::Display for NodeOrToken<N, T> {
53 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
54 match self {
55 NodeOrToken::Node(node: &N) => fmt::Display::fmt(self:node, f),
56 NodeOrToken::Token(token: &T) => fmt::Display::fmt(self:token, f),
57 }
58 }
59}
60
61#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash)]
62pub enum Direction {
63 Next,
64 Prev,
65}
66
67/// `WalkEvent` describes tree walking process.
68#[derive(Debug, Copy, Clone)]
69pub enum WalkEvent<T> {
70 /// Fired before traversing the node.
71 Enter(T),
72 /// Fired after the node is traversed.
73 Leave(T),
74}
75
76impl<T> WalkEvent<T> {
77 pub fn map<F: FnOnce(T) -> U, U>(self, f: F) -> WalkEvent<U> {
78 match self {
79 WalkEvent::Enter(it: T) => WalkEvent::Enter(f(it)),
80 WalkEvent::Leave(it: T) => 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)]
87pub 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
96impl<T> TokenAtOffset<T> {
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.
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.
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
124impl<T> Iterator for TokenAtOffset<T> {
125 type Item = T;
126
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
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
150impl<T> ExactSizeIterator for TokenAtOffset<T> {}
151
152macro_rules! _static_assert {
153 ($expr:expr) => {
154 const _: i32 = 0 / $expr as i32;
155 };
156}
157
158pub(crate) use _static_assert as static_assert;
159
160#[derive(Copy, Clone, Debug)]
161pub(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
168macro_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}
180impls!(u32 TextSize);
181