Skip to main content

miden_rowan/
utility_types.rs

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