Skip to main content

kermit_algos/
trie_iter_kind.rs

1//! Dispatch wrapper letting LFTJ hold a heterogeneous set of trie
2//! iterators — both real relations (borrowed) and synthetic singletons
3//! produced by the [Const-view rewrite](crate::const_rewrite).
4
5use {
6    crate::singleton::SingletonTrieIter,
7    kermit_iters::{JoinIterable, LinearIterator, TrieIterable, TrieIterator, TrieIteratorWrapper},
8};
9
10/// Either borrows a real relation or owns a synthetic singleton.
11///
12/// [`TrieIterable::trie_iter`] dispatches to the appropriate inner
13/// variant. Lifetime `'a` borrows the real relation; singletons carry
14/// no reference.
15pub enum TrieIterKind<'a, R: TrieIterable> {
16    /// A real relation borrowed from the database.
17    Relation(&'a R),
18    /// A synthetic `Const_<id>` singleton introduced by the rewrite.
19    Singleton(SingletonTrieIter),
20}
21
22/// Iterator produced by [`TrieIterKind::trie_iter`]; dispatches all
23/// `TrieIterator` / `LinearIterator` methods to the inner variant.
24pub enum KindIter<IT>
25where
26    IT: TrieIterator,
27{
28    /// Iterator from a real relation.
29    Relation(IT),
30    /// Iterator from a synthetic singleton.
31    Singleton(SingletonTrieIter),
32}
33
34impl<IT> LinearIterator for KindIter<IT>
35where
36    IT: TrieIterator,
37{
38    fn key(&self) -> Option<usize> {
39        match self {
40            | Self::Relation(it) => it.key(),
41            | Self::Singleton(it) => it.key(),
42        }
43    }
44
45    fn next(&mut self) -> Option<usize> {
46        match self {
47            | Self::Relation(it) => it.next(),
48            | Self::Singleton(it) => it.next(),
49        }
50    }
51
52    fn seek(&mut self, seek_key: usize) -> bool {
53        match self {
54            | Self::Relation(it) => it.seek(seek_key),
55            | Self::Singleton(it) => it.seek(seek_key),
56        }
57    }
58
59    fn at_end(&self) -> bool {
60        match self {
61            | Self::Relation(it) => it.at_end(),
62            | Self::Singleton(it) => it.at_end(),
63        }
64    }
65}
66
67impl<IT> TrieIterator for KindIter<IT>
68where
69    IT: TrieIterator,
70{
71    fn open(&mut self) -> bool {
72        match self {
73            | Self::Relation(it) => it.open(),
74            | Self::Singleton(it) => it.open(),
75        }
76    }
77
78    fn up(&mut self) -> bool {
79        match self {
80            | Self::Relation(it) => it.up(),
81            | Self::Singleton(it) => it.up(),
82        }
83    }
84}
85
86impl<IT> IntoIterator for KindIter<IT>
87where
88    IT: TrieIterator,
89{
90    type IntoIter = TrieIteratorWrapper<Self>;
91    type Item = Vec<usize>;
92
93    fn into_iter(self) -> Self::IntoIter { TrieIteratorWrapper::new(self) }
94}
95
96impl<R: TrieIterable> JoinIterable for TrieIterKind<'_, R> {}
97
98impl<R: TrieIterable> TrieIterable for TrieIterKind<'_, R> {
99    fn trie_iter(&self) -> impl TrieIterator + IntoIterator<Item = Vec<usize>> {
100        match self {
101            | Self::Relation(r) => KindIter::Relation(r.trie_iter()),
102            | Self::Singleton(s) => KindIter::Singleton(s.clone()),
103        }
104    }
105}
106
107#[cfg(test)]
108mod tests {
109    use {
110        super::*,
111        kermit_ds::{Relation, TreeTrie},
112    };
113
114    fn tree_from(tuples: Vec<Vec<usize>>) -> TreeTrie { TreeTrie::from_tuples(2.into(), tuples) }
115
116    #[test]
117    fn kind_relation_delegates_to_inner() {
118        let trie = tree_from(vec![vec![1, 2], vec![3, 4]]);
119        let kind: TrieIterKind<TreeTrie> = TrieIterKind::Relation(&trie);
120        let mut it = kind.trie_iter();
121        assert!(it.open());
122        assert_eq!(it.key(), Some(1));
123    }
124
125    #[test]
126    fn kind_singleton_delegates_to_inner() {
127        let kind: TrieIterKind<TreeTrie> = TrieIterKind::Singleton(SingletonTrieIter::new(7));
128        let mut it = kind.trie_iter();
129        assert!(it.open());
130        assert_eq!(it.key(), Some(7));
131    }
132
133    #[test]
134    fn kind_singleton_seek_behaves_like_bare_singleton() {
135        let kind: TrieIterKind<TreeTrie> = TrieIterKind::Singleton(SingletonTrieIter::new(7));
136        let mut it = kind.trie_iter();
137        it.open();
138        assert!(!it.seek(8));
139        assert!(it.at_end());
140    }
141
142    #[test]
143    fn wrapper_on_kind_iter_yields_tuples() {
144        let trie = tree_from(vec![vec![1, 2]]);
145        let kind: TrieIterKind<TreeTrie> = TrieIterKind::Relation(&trie);
146        let tuples: Vec<Vec<usize>> = kind.trie_iter().into_iter().collect();
147        assert_eq!(tuples, vec![vec![1, 2]]);
148    }
149
150    #[test]
151    fn wrapper_on_kind_singleton_yields_one_tuple() {
152        let kind: TrieIterKind<TreeTrie> = TrieIterKind::Singleton(SingletonTrieIter::new(42));
153        let tuples: Vec<Vec<usize>> = kind.trie_iter().into_iter().collect();
154        assert_eq!(tuples, vec![vec![42]]);
155    }
156}