diff --git a/src/green.rs b/src/green.rs index ba04e61..57b3e98 100644 --- a/src/green.rs +++ b/src/green.rs @@ -5,6 +5,7 @@ mod builder; mod element; mod interner; +mod iter; mod node; mod token; @@ -14,7 +15,8 @@ use self::element::{GreenElement, PackedGreenElement}; pub use self::{ builder::{Checkpoint, GreenNodeBuilder, NodeCache}, interner::TokenInterner, - node::{Children, GreenNode}, + iter::GreenNodeChildren, + node::GreenNode, token::GreenToken, }; diff --git a/src/green/iter.rs b/src/green/iter.rs new file mode 100644 index 0000000..ca78c8f --- /dev/null +++ b/src/green/iter.rs @@ -0,0 +1,92 @@ +//! Green tree iterators. + +use std::{iter::FusedIterator, slice}; + +use super::{element::PackedGreenElement, GreenElementRef}; + +/// An iterator over a [`GreenNode`](crate::GreenNode)'s children. +#[derive(Debug, Clone)] +pub struct GreenNodeChildren<'a> { + pub(super) inner: slice::Iter<'a, PackedGreenElement>, +} + +// NB: forward everything stable that iter::Slice specializes as of Rust 1.39.0 +impl ExactSizeIterator for GreenNodeChildren<'_> { + #[inline(always)] + fn len(&self) -> usize { + self.inner.len() + } +} + +impl<'a> Iterator for GreenNodeChildren<'a> { + type Item = GreenElementRef<'a>; + + #[inline] + fn next(&mut self) -> Option> { + self.inner.next().map(PackedGreenElement::as_ref) + } + + #[inline] + fn size_hint(&self) -> (usize, Option) { + self.inner.size_hint() + } + + #[inline] + fn count(self) -> usize + where + Self: Sized, + { + self.inner.count() + } + + #[inline] + fn nth(&mut self, n: usize) -> Option { + self.inner.nth(n).map(PackedGreenElement::as_ref) + } + + #[inline] + fn last(mut self) -> Option + where + Self: Sized, + { + self.next_back() + } + + #[inline] + fn fold(self, init: Acc, mut f: Fold) -> Acc + where + Fold: FnMut(Acc, Self::Item) -> Acc, + { + let mut accum = init; + for x in self { + accum = f(accum, x); + } + accum + } +} + +impl<'a> DoubleEndedIterator for GreenNodeChildren<'a> { + #[inline] + fn next_back(&mut self) -> Option { + self.inner.next_back().map(PackedGreenElement::as_ref) + } + + #[inline] + fn nth_back(&mut self, n: usize) -> Option { + self.inner.nth_back(n).map(PackedGreenElement::as_ref) + } + + #[inline] + fn rfold(mut self, init: Acc, mut f: Fold) -> Acc + where + Fold: FnMut(Acc, Self::Item) -> Acc, + { + let mut accum = init; + while let Some(x) = self.next_back() { + accum = f(accum, x); + } + accum + } +} + +impl FusedIterator for GreenNodeChildren<'_> {} diff --git a/src/green/node.rs b/src/green/node.rs index 6f0a1c6..6eb119e 100644 --- a/src/green/node.rs +++ b/src/green/node.rs @@ -1,13 +1,12 @@ use std::{ hash::{Hash, Hasher}, - iter::FusedIterator, slice, }; use fxhash::FxHasher32; use crate::{ - green::{GreenElement, GreenElementRef, PackedGreenElement, SyntaxKind}, + green::{iter::GreenNodeChildren, GreenElement, PackedGreenElement, SyntaxKind}, TextSize, }; use triomphe::{Arc, HeaderWithLength, ThinArc}; @@ -135,8 +134,8 @@ impl GreenNode { /// Iterator over all children of this node. #[inline] - pub fn children(&self) -> Children<'_> { - Children { + pub fn children(&self) -> GreenNodeChildren<'_> { + GreenNodeChildren { inner: self.data.slice.iter(), } } @@ -156,90 +155,3 @@ impl PartialEq for GreenNode { } impl Eq for GreenNode {} - -/// An iterator over a [`GreenNode`]'s children. -#[derive(Debug, Clone)] -pub struct Children<'a> { - inner: slice::Iter<'a, PackedGreenElement>, -} - -// NB: forward everything stable that iter::Slice specializes as of Rust 1.39.0 -impl ExactSizeIterator for Children<'_> { - #[inline(always)] - fn len(&self) -> usize { - self.inner.len() - } -} - -impl<'a> Iterator for Children<'a> { - type Item = GreenElementRef<'a>; - - #[inline] - fn next(&mut self) -> Option> { - self.inner.next().map(PackedGreenElement::as_ref) - } - - #[inline] - fn size_hint(&self) -> (usize, Option) { - self.inner.size_hint() - } - - #[inline] - fn count(self) -> usize - where - Self: Sized, - { - self.inner.count() - } - - #[inline] - fn nth(&mut self, n: usize) -> Option { - self.inner.nth(n).map(PackedGreenElement::as_ref) - } - - #[inline] - fn last(mut self) -> Option - where - Self: Sized, - { - self.next_back() - } - - #[inline] - fn fold(self, init: Acc, mut f: Fold) -> Acc - where - Fold: FnMut(Acc, Self::Item) -> Acc, - { - let mut accum = init; - for x in self { - accum = f(accum, x); - } - accum - } -} - -impl<'a> DoubleEndedIterator for Children<'a> { - #[inline] - fn next_back(&mut self) -> Option { - self.inner.next_back().map(PackedGreenElement::as_ref) - } - - #[inline] - fn nth_back(&mut self, n: usize) -> Option { - self.inner.nth_back(n).map(PackedGreenElement::as_ref) - } - - #[inline] - fn rfold(mut self, init: Acc, mut f: Fold) -> Acc - where - Fold: FnMut(Acc, Self::Item) -> Acc, - { - let mut accum = init; - while let Some(x) = self.next_back() { - accum = f(accum, x); - } - accum - } -} - -impl FusedIterator for Children<'_> {} diff --git a/src/lib.rs b/src/lib.rs index 775fcd0..2af1005 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -65,7 +65,7 @@ pub use text_size::{TextLen, TextRange, TextSize}; #[doc(inline)] pub use crate::syntax::*; pub use crate::{ - green::{Checkpoint, Children, GreenNode, GreenNodeBuilder, GreenToken, NodeCache, SyntaxKind}, + green::{Checkpoint, GreenNode, GreenNodeBuilder, GreenNodeChildren, GreenToken, NodeCache, SyntaxKind}, utility_types::{Direction, NodeOrToken, TokenAtOffset, WalkEvent}, }; pub use triomphe::Arc; diff --git a/src/syntax/node.rs b/src/syntax/node.rs index 922c65f..247c402 100644 --- a/src/syntax/node.rs +++ b/src/syntax/node.rs @@ -975,7 +975,7 @@ where #[derive(Clone, Debug)] struct Iter<'n> { - green: Children<'n>, + green: GreenNodeChildren<'n>, offset: TextSize, index: usize, } @@ -983,7 +983,7 @@ struct Iter<'n> { impl<'n> Iter<'n> { fn new(parent: &'n SyntaxNode) -> Self { let offset = parent.text_range().start(); - let green: Children<'_> = parent.green().children(); + let green: GreenNodeChildren<'_> = parent.green().children(); Iter { green, offset,