use std::collections::{HashMap, LinkedList};
use std::hash::Hash;
pub(crate) struct InvertedIndex<K, V> {
look_up_table: HashMap<K, LinkedList<V>>,
}
impl<K, V> InvertedIndex<K, V>
where
K: Hash + Eq,
{
pub(crate) fn new() -> InvertedIndex<K, V> {
InvertedIndex {
look_up_table: HashMap::new(),
}
}
pub(crate) fn insert_single(&mut self, key: K, value: V) {
match self.look_up_table.get_mut(&key) {
Some(values) => values.push_back(value),
None => {
let mut values = LinkedList::new();
values.push_back(value);
self.look_up_table.insert(key, values);
}
}
}
pub(crate) fn insert_multiple(&mut self, key: K, values: impl IntoIterator<Item = V>) {
match self.look_up_table.get_mut(&key) {
Some(stored_values) => {
values.into_iter().for_each(|v| stored_values.push_back(v));
}
None => {
self.look_up_table.insert(key, values.into_iter().collect());
}
}
}
pub(crate) fn peek_first(&self, key: &K) -> Option<&V> {
self.look_up_table.get(key)?.front()
}
pub(crate) fn peek_all(&self, key: &K) -> Option<&LinkedList<V>> {
self.look_up_table.get(key)
}
}
#[cfg(test)]
mod tests {
use super::*;
macro_rules! assert_matching {
( $x:expr, $y:expr ) => {{
let are_matching = $x.iter().zip(&$y).fold(true, |acc, (a, b)| acc && a == b);
assert!(are_matching);
}};
}
#[test]
fn test_new() {
let _index: InvertedIndex<char, i32> = InvertedIndex::new();
}
#[test]
fn test_insert_single_peek_first() {
let mut index: InvertedIndex<char, i32> = InvertedIndex::new();
index.insert_single('A', 65);
let actual = index.peek_first(&'A');
assert_eq!(65, *actual.unwrap());
}
#[test]
fn test_new_key_insert_multiple_peek_first() {
let mut index: InvertedIndex<char, i32> = InvertedIndex::new();
index.insert_multiple('A', vec![65, 66, 67]);
let actual = index.peek_first(&'A');
assert_eq!(65, *actual.unwrap());
}
#[test]
fn test_new_key_insert_multiple_peek_all() {
let mut index: InvertedIndex<char, i32> = InvertedIndex::new();
index.insert_multiple('A', vec![65, 66, 67]);
let actual = index.peek_all(&'A');
assert_matching!([65, 66, 67], *actual.unwrap());
}
#[test]
fn test_existing_key_insert_multiple_peek_first() {
let mut index: InvertedIndex<char, i32> = InvertedIndex::new();
index.insert_single('A', 64);
index.insert_multiple('A', vec![65, 66, 67]);
let actual = index.peek_first(&'A');
assert_eq!(64, *actual.unwrap());
}
#[test]
fn test_existing_key_insert_multiple_peek_all() {
let mut index: InvertedIndex<char, i32> = InvertedIndex::new();
index.insert_single('A', 64);
index.insert_multiple('A', vec![65, 66, 67]);
let actual = index.peek_all(&'A');
assert_matching!([64, 65, 66, 67], *actual.unwrap());
}
#[test]
fn test_multiple_same_key_insert_single_peek_all() {
let mut index: InvertedIndex<char, i32> = InvertedIndex::new();
index.insert_single('A', 65);
index.insert_single('A', 66);
index.insert_single('A', 67);
let actual = index.peek_all(&'A');
assert_matching!([65, 66, 67], *actual.unwrap());
}
#[test]
fn test_multiple_different_key_insert_single_peek_all() {
let mut index: InvertedIndex<char, i32> = InvertedIndex::new();
index.insert_single('A', 65);
index.insert_single('B', 66);
index.insert_single('C', 67);
let actual = index.peek_all(&'A');
assert_matching!([65], *actual.unwrap());
}
}