Skip to main content

kermit_algos/
hash_trie_iter_kind.rs

1//! Mirror of [`crate::trie_iter_kind::TrieIterKind`] for the hash-trie
2//! algorithm family. Lets the `DatabaseEngine::join` machinery hold a
3//! heterogeneous mix of real `HashTrieIterable` relations and synthetic
4//! `Const_<id>` singletons under one type.
5
6use {
7    crate::hash_singleton::SingletonHashTrieIter,
8    kermit_iters::{HashTrieIterable, HashTrieIterator, JoinIterable},
9};
10
11/// Either borrows a real `HashTrieIterable` relation or owns a synthetic
12/// singleton.
13///
14/// [`HashTrieIterable::hash_trie_iter`] dispatches to the appropriate
15/// inner variant. Lifetime `'a` borrows the real relation; singletons
16/// carry no reference.
17pub enum HashTrieIterKind<'a, R: HashTrieIterable> {
18    /// A real relation borrowed from the database.
19    Relation(&'a R),
20    /// A synthetic `Const_<id>` singleton introduced by the rewrite.
21    Singleton(SingletonHashTrieIter),
22}
23
24/// Iterator produced by [`HashTrieIterKind::hash_trie_iter`]; dispatches
25/// all [`HashTrieIterator`] methods to the inner variant.
26pub enum HashKindIter<IT>
27where
28    IT: HashTrieIterator,
29{
30    /// Iterator from a real relation.
31    Relation(IT),
32    /// Iterator from a synthetic singleton.
33    Singleton(SingletonHashTrieIter),
34}
35
36impl<IT> HashTrieIterator for HashKindIter<IT>
37where
38    IT: HashTrieIterator,
39{
40    fn key(&self) -> Option<u64> {
41        match self {
42            | Self::Relation(it) => it.key(),
43            | Self::Singleton(it) => it.key(),
44        }
45    }
46
47    fn next(&mut self) -> Option<u64> {
48        match self {
49            | Self::Relation(it) => it.next(),
50            | Self::Singleton(it) => it.next(),
51        }
52    }
53
54    fn lookup(&mut self, hash: u64) -> bool {
55        match self {
56            | Self::Relation(it) => it.lookup(hash),
57            | Self::Singleton(it) => it.lookup(hash),
58        }
59    }
60
61    fn size(&self) -> usize {
62        match self {
63            | Self::Relation(it) => it.size(),
64            | Self::Singleton(it) => it.size(),
65        }
66    }
67
68    fn at_end(&self) -> bool {
69        match self {
70            | Self::Relation(it) => it.at_end(),
71            | Self::Singleton(it) => it.at_end(),
72        }
73    }
74
75    fn open(&mut self) -> bool {
76        match self {
77            | Self::Relation(it) => it.open(),
78            | Self::Singleton(it) => it.open(),
79        }
80    }
81
82    fn up(&mut self) -> bool {
83        match self {
84            | Self::Relation(it) => it.up(),
85            | Self::Singleton(it) => it.up(),
86        }
87    }
88
89    fn leaf_tuples(&self) -> Option<&[Vec<usize>]> {
90        match self {
91            | Self::Relation(it) => it.leaf_tuples(),
92            | Self::Singleton(it) => it.leaf_tuples(),
93        }
94    }
95}
96
97impl<R: HashTrieIterable> JoinIterable for HashTrieIterKind<'_, R> {}
98
99impl<R: HashTrieIterable> HashTrieIterable for HashTrieIterKind<'_, R> {
100    fn hash_trie_iter(&self) -> impl HashTrieIterator {
101        match self {
102            | Self::Relation(r) => HashKindIter::Relation(r.hash_trie_iter()),
103            | Self::Singleton(s) => HashKindIter::Singleton(s.clone()),
104        }
105    }
106}
107
108#[cfg(test)]
109mod tests {
110    use {
111        super::*,
112        kermit_ds::{HashTrie, Relation},
113    };
114
115    #[test]
116    fn relation_variant_delegates_open() {
117        let r = HashTrie::from_tuples(2.into(), vec![vec![1, 2]]);
118        let kind: HashTrieIterKind<HashTrie> = HashTrieIterKind::Relation(&r);
119        let mut it = kind.hash_trie_iter();
120        assert!(it.open());
121    }
122
123    #[test]
124    fn singleton_variant_delegates_key() {
125        use kermit_iters::{HashStrategy, SipHashStrategy};
126        let hash = SipHashStrategy::hash(7);
127        let kind: HashTrieIterKind<HashTrie> =
128            HashTrieIterKind::Singleton(SingletonHashTrieIter::new(7, hash));
129        let mut it = kind.hash_trie_iter();
130        assert!(it.open());
131        assert_eq!(it.key(), Some(hash));
132    }
133}