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#[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 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 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 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 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 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 term: bool,
100 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}