1use crate::{Leaf, Subtree, TokenTree, TokenTreesView, dispatch_ref};
5
6pub struct Cursor<'a> {
7 buffer: TokenTreesView<'a>,
8 index: usize,
9 subtrees_stack: Vec<usize>,
10}
11
12impl<'a> Cursor<'a> {
13 pub fn new(buffer: TokenTreesView<'a>) -> Self {
14 Self { buffer, index: 0, subtrees_stack: Vec::new() }
15 }
16
17 pub fn eof(&self) -> bool {
19 self.index == self.buffer.len() && self.subtrees_stack.is_empty()
20 }
21
22 pub fn is_root(&self) -> bool {
23 self.subtrees_stack.is_empty()
24 }
25
26 fn at(&self, idx: usize) -> Option<TokenTree> {
27 dispatch_ref! {
28 match self.buffer.repr => tt => Some(tt.get(idx)?.to_api(self.buffer.span_parts))
29 }
30 }
31
32 fn last_subtree(&self) -> Option<(usize, Subtree)> {
33 self.subtrees_stack.last().map(|&subtree_idx| {
34 let Some(TokenTree::Subtree(subtree)) = self.at(subtree_idx) else {
35 panic!("subtree pointing to non-subtree");
36 };
37 (subtree_idx, subtree)
38 })
39 }
40
41 pub fn end(&mut self) -> Subtree {
42 let (last_subtree_idx, last_subtree) =
43 self.last_subtree().expect("called `Cursor::end()` without an open subtree");
44 assert_eq!(
46 last_subtree_idx + last_subtree.usize_len() + 1,
47 self.index,
48 "called `Cursor::end()` without finishing a subtree"
49 );
50 self.subtrees_stack.pop();
51 last_subtree
52 }
53
54 pub fn token_tree(&self) -> Option<TokenTree> {
56 if let Some((last_subtree_idx, last_subtree)) = self.last_subtree() {
57 if last_subtree_idx + last_subtree.usize_len() + 1 == self.index {
59 return None;
60 }
61 }
62 self.at(self.index)
63 }
64
65 pub fn bump(&mut self) {
67 if let Some((last_subtree_idx, last_subtree)) = self.last_subtree() {
68 assert_ne!(
70 last_subtree_idx + last_subtree.usize_len() + 1,
71 self.index,
72 "called `Cursor::bump()` when at the end of a subtree"
73 );
74 }
75 if let Some(TokenTree::Subtree(_)) = self.at(self.index) {
76 self.subtrees_stack.push(self.index);
77 }
78 self.index += 1;
79 }
80
81 pub fn bump_or_end(&mut self) {
82 if let Some((last_subtree_idx, last_subtree)) = self.last_subtree() {
83 if last_subtree_idx + last_subtree.usize_len() + 1 == self.index {
85 self.subtrees_stack.pop();
86 return;
87 }
88 }
89 if let Some(TokenTree::Subtree(_)) = self.at(self.index) {
91 self.subtrees_stack.push(self.index);
92 }
93 self.index += 1;
94 }
95
96 pub fn peek_two_leaves(&self) -> Option<[Leaf; 2]> {
97 if let Some((last_subtree_idx, last_subtree)) = self.last_subtree() {
98 let last_end = last_subtree_idx + last_subtree.usize_len() + 1;
100 if last_end == self.index || last_end == self.index + 1 {
101 return None;
102 }
103 }
104 self.at(self.index).zip(self.at(self.index + 1)).and_then(|it| match it {
105 (TokenTree::Leaf(a), TokenTree::Leaf(b)) => Some([a, b]),
106 _ => None,
107 })
108 }
109
110 pub fn crossed(&self) -> TokenTreesView<'a> {
111 assert!(self.is_root());
112 TokenTreesView {
113 repr: self.buffer.repr.get(..self.index).unwrap(),
114 span_parts: self.buffer.span_parts,
115 }
116 }
117}