summaryrefslogtreecommitdiffstats
path: root/vendor/rowan/src/utility_types.rs
diff options
context:
space:
mode:
Diffstat (limited to 'vendor/rowan/src/utility_types.rs')
-rw-r--r--vendor/rowan/src/utility_types.rs180
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);