rowan/
utility_types.rs

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) => NodeOrToken::Node(&*node),
47            NodeOrToken::Token(token) => 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) => 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)]
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) => 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)]
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);