rune/compile/
names.rs

1#[cfg(test)]
2mod tests;
3
4use core::mem::replace;
5
6use crate::alloc;
7use crate::alloc::btree_map::{self, BTreeMap};
8use crate::alloc::prelude::*;
9use crate::item::{Component, ComponentRef, IntoComponent};
10
11/// A tree of names.
12#[derive(Default, Debug)]
13pub struct Names {
14    root: Node,
15}
16
17impl TryClone for Names {
18    #[inline]
19    fn try_clone(&self) -> alloc::Result<Self> {
20        Ok(Self {
21            root: self.root.try_clone()?,
22        })
23    }
24}
25
26impl Names {
27    /// Insert the given item as an import.
28    pub(crate) fn insert(
29        &mut self,
30        iter: impl IntoIterator<Item: IntoComponent>,
31    ) -> alloc::Result<bool> {
32        let mut current = &mut self.root;
33
34        for c in iter {
35            current = current
36                .children
37                .entry(c.into_component()?)
38                .or_try_default()?;
39        }
40
41        Ok(replace(&mut current.term, true))
42    }
43
44    /// Test if the given import exists.
45    pub(crate) fn contains(
46        &self,
47        iter: impl IntoIterator<Item: IntoComponent>,
48    ) -> alloc::Result<bool> {
49        Ok(self.find_node(iter)?.map(|n| n.term).unwrap_or_default())
50    }
51
52    /// Test if we contain the given prefix.
53    pub(crate) fn contains_prefix(
54        &self,
55        iter: impl IntoIterator<Item: IntoComponent>,
56    ) -> alloc::Result<bool> {
57        Ok(self.find_node(iter)?.is_some())
58    }
59
60    /// Iterate over all known components immediately under the specified `iter`
61    /// path.
62    pub(crate) fn iter_components<'a>(
63        &'a self,
64        iter: impl IntoIterator<Item: IntoComponent> + 'a,
65    ) -> alloc::Result<impl Iterator<Item = ComponentRef<'a>> + 'a> {
66        let iter = if let Some(current) = self.find_node(iter)? {
67            current.children.keys()
68        } else {
69            btree_map::Keys::default()
70        };
71
72        Ok(iter.map(|c| c.as_component_ref()))
73    }
74
75    /// Find the node corresponding to the given path.
76    fn find_node(
77        &self,
78        iter: impl IntoIterator<Item: IntoComponent>,
79    ) -> alloc::Result<Option<&Node>> {
80        let mut current = &self.root;
81
82        for c in iter {
83            let c = c.into_component()?;
84
85            let Some(c) = current.children.get(&c) else {
86                return Ok(None);
87            };
88
89            current = c;
90        }
91
92        Ok(Some(current))
93    }
94}
95
96#[derive(Default, Debug)]
97struct Node {
98    /// If the node is terminating.
99    term: bool,
100    /// The children of this node.
101    children: BTreeMap<Component, Node>,
102}
103
104impl TryClone for Node {
105    fn try_clone(&self) -> alloc::Result<Self> {
106        Ok(Self {
107            term: self.term,
108            children: self.children.try_clone()?,
109        })
110    }
111}