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