cairo_lang_syntax/node/
element_list.rs

1use std::marker::PhantomData;
2
3use salsa::Database;
4
5use crate::node::{SyntaxNode, TypedSyntaxNode};
6
7// A typed view of an element list node.
8// STEP=1 means a sequence of elements (e.g. sequence of trivia elements).
9// STEP=2 means a separated sequence (e.g. argument list separated by `,`).
10#[derive(Clone, Debug, Eq, Hash, PartialEq, salsa::Update)]
11pub struct ElementList<'db, T: TypedSyntaxNode<'db>, const STEP: usize> {
12    pub node: SyntaxNode<'db>,
13    phantom: PhantomData<T>,
14}
15impl<'db, T: TypedSyntaxNode<'db>, const STEP: usize> ElementList<'db, T, STEP> {
16    pub fn new(node: SyntaxNode<'db>) -> Self {
17        Self { node, phantom: PhantomData {} }
18    }
19}
20impl<'db, T: TypedSyntaxNode<'db>> ElementList<'db, T, 1> {
21    pub fn elements_vec(&self, db: &'db dyn Database) -> Vec<T> {
22        self.elements(db).collect()
23    }
24    pub fn elements<'a: 'db>(
25        &self,
26        db: &'db dyn Database,
27    ) -> impl ExactSizeIterator<Item = T> + DoubleEndedIterator + use<'db, T> {
28        self.node.get_children(db).iter().copied().map(move |x| T::from_syntax_node(db, x))
29    }
30    pub fn has_tail(&self, _db: &dyn Database) -> bool {
31        false
32    }
33}
34impl<'db, T: TypedSyntaxNode<'db>> ElementList<'db, T, 2> {
35    pub fn elements_vec(&self, db: &'db dyn Database) -> Vec<T> {
36        self.elements(db).collect()
37    }
38    pub fn elements(
39        &self,
40        db: &'db dyn Database,
41    ) -> impl ExactSizeIterator<Item = T> + DoubleEndedIterator + use<'db, T> {
42        self.node
43            .get_children(db)
44            .iter()
45            .copied()
46            .step_by(2)
47            .map(move |x| T::from_syntax_node(db, x))
48    }
49    pub fn has_tail(&self, db: &dyn Database) -> bool {
50        !self.node.get_children(db).len().is_multiple_of(2)
51    }
52}