diff options
Diffstat (limited to 'vendor/rowan/src/utility_types.rs')
-rw-r--r-- | vendor/rowan/src/utility_types.rs | 180 |
1 files changed, 180 insertions, 0 deletions
diff --git a/vendor/rowan/src/utility_types.rs b/vendor/rowan/src/utility_types.rs new file mode 100644 index 000000000..817add72e --- /dev/null +++ b/vendor/rowan/src/utility_types.rs @@ -0,0 +1,180 @@ +use std::{ + fmt, + ops::{AddAssign, Deref}, +}; +use text_size::TextSize; + +#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash)] +pub enum NodeOrToken<N, T> { + Node(N), + Token(T), +} + +impl<N, T> NodeOrToken<N, T> { + pub fn into_node(self) -> Option<N> { + match self { + NodeOrToken::Node(node) => Some(node), + NodeOrToken::Token(_) => None, + } + } + + pub fn into_token(self) -> Option<T> { + match self { + NodeOrToken::Node(_) => None, + NodeOrToken::Token(token) => Some(token), + } + } + + pub fn as_node(&self) -> Option<&N> { + match self { + NodeOrToken::Node(node) => Some(node), + NodeOrToken::Token(_) => None, + } + } + + pub fn as_token(&self) -> Option<&T> { + match self { + NodeOrToken::Node(_) => None, + NodeOrToken::Token(token) => Some(token), + } + } +} + +impl<N: Deref, T: Deref> NodeOrToken<N, T> { + pub(crate) fn as_deref(&self) -> NodeOrToken<&N::Target, &T::Target> { + match self { + NodeOrToken::Node(node) => NodeOrToken::Node(&*node), + NodeOrToken::Token(token) => NodeOrToken::Token(&*token), + } + } +} + +impl<N: fmt::Display, T: fmt::Display> fmt::Display for NodeOrToken<N, T> { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + match self { + NodeOrToken::Node(node) => fmt::Display::fmt(node, f), + NodeOrToken::Token(token) => fmt::Display::fmt(token, f), + } + } +} + +#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash)] +pub enum Direction { + Next, + Prev, +} + +/// `WalkEvent` describes tree walking process. +#[derive(Debug, Copy, Clone)] +pub enum WalkEvent<T> { + /// Fired before traversing the node. + Enter(T), + /// Fired after the node is traversed. + Leave(T), +} + +impl<T> WalkEvent<T> { + pub fn map<F: FnOnce(T) -> U, U>(self, f: F) -> WalkEvent<U> { + match self { + WalkEvent::Enter(it) => WalkEvent::Enter(f(it)), + WalkEvent::Leave(it) => WalkEvent::Leave(f(it)), + } + } +} + +/// There might be zero, one or two leaves at a given offset. +#[derive(Clone, Debug)] +pub enum TokenAtOffset<T> { + /// No leaves at offset -- possible for the empty file. + None, + /// Only a single leaf at offset. + Single(T), + /// Offset is exactly between two leaves. + Between(T, T), +} + +impl<T> TokenAtOffset<T> { + pub fn map<F: Fn(T) -> U, U>(self, f: F) -> TokenAtOffset<U> { + match self { + TokenAtOffset::None => TokenAtOffset::None, + TokenAtOffset::Single(it) => TokenAtOffset::Single(f(it)), + TokenAtOffset::Between(l, r) => TokenAtOffset::Between(f(l), f(r)), + } + } + + /// Convert to option, preferring the right leaf in case of a tie. + pub fn right_biased(self) -> Option<T> { + match self { + TokenAtOffset::None => None, + TokenAtOffset::Single(node) => Some(node), + TokenAtOffset::Between(_, right) => Some(right), + } + } + + /// Convert to option, preferring the left leaf in case of a tie. + pub fn left_biased(self) -> Option<T> { + match self { + TokenAtOffset::None => None, + TokenAtOffset::Single(node) => Some(node), + TokenAtOffset::Between(left, _) => Some(left), + } + } +} + +impl<T> Iterator for TokenAtOffset<T> { + type Item = T; + + fn next(&mut self) -> Option<T> { + match std::mem::replace(self, TokenAtOffset::None) { + TokenAtOffset::None => None, + TokenAtOffset::Single(node) => { + *self = TokenAtOffset::None; + Some(node) + } + TokenAtOffset::Between(left, right) => { + *self = TokenAtOffset::Single(right); + Some(left) + } + } + } + + fn size_hint(&self) -> (usize, Option<usize>) { + match self { + TokenAtOffset::None => (0, Some(0)), + TokenAtOffset::Single(_) => (1, Some(1)), + TokenAtOffset::Between(_, _) => (2, Some(2)), + } + } +} + +impl<T> ExactSizeIterator for TokenAtOffset<T> {} + +macro_rules! _static_assert { + ($expr:expr) => { + const _: i32 = 0 / $expr as i32; + }; +} + +pub(crate) use _static_assert as static_assert; + +#[derive(Copy, Clone, Debug)] +pub(crate) enum Delta<T> { + Add(T), + Sub(T), +} + +// This won't be coherent :-( +// impl<T: AddAssign + SubAssign> AddAssign<Delta<T>> for T +macro_rules! impls { + ($($ty:ident)*) => {$( + impl AddAssign<Delta<$ty>> for $ty { + fn add_assign(&mut self, rhs: Delta<$ty>) { + match rhs { + Delta::Add(amt) => *self += amt, + Delta::Sub(amt) => *self -= amt, + } + } + } + )*}; +} +impls!(u32 TextSize); |