use std::collections::BTreeMap; use brk_computer::Computer; use brk_indexer::Indexer; use vecdb::AnyCollectableVec; use derive_deref::{Deref, DerefMut}; use crate::pagination::{PaginatedIndexParam, PaginationParam}; use super::index::Index; #[derive(Default)] pub struct Vecs<'a> { pub id_to_index_to_vec: BTreeMap<&'a str, IndexToVec<'a>>, pub index_to_id_to_vec: BTreeMap>, pub ids: Vec<&'a str>, pub indexes: Vec<&'static str>, pub accepted_indexes: BTreeMap<&'static str, &'static [&'static str]>, pub index_count: usize, pub id_count: usize, pub vec_count: usize, id_to_indexes: BTreeMap<&'a str, Vec<&'static str>>, indexes_to_ids: BTreeMap>, } impl<'a> Vecs<'a> { pub fn build(indexer: &'a Indexer, computer: &'a Computer) -> Self { let mut this = Vecs::default(); indexer .vecs .vecs() .into_iter() .for_each(|vec| this.insert(vec)); computer.vecs().into_iter().for_each(|vec| this.insert(vec)); let mut ids = this.id_to_index_to_vec.keys().cloned().collect::>(); let sort_ids = |ids: &mut Vec<&str>| { ids.sort_unstable_by(|a, b| { let len_cmp = a.len().cmp(&b.len()); if len_cmp == std::cmp::Ordering::Equal { a.cmp(b) } else { len_cmp } }) }; sort_ids(&mut ids); this.ids = ids; this.id_count = this.id_to_index_to_vec.keys().count(); this.index_count = this.index_to_id_to_vec.keys().count(); this.vec_count = this .index_to_id_to_vec .values() .map(|tree| tree.len()) .sum::(); this.indexes = this .index_to_id_to_vec .keys() .map(|i| i.serialize_long()) .collect::>(); this.accepted_indexes = this .index_to_id_to_vec .keys() .map(|i| (i.serialize_long(), i.possible_values())) .collect::>(); this.id_to_indexes = this .id_to_index_to_vec .iter() .map(|(id, index_to_vec)| { ( *id, index_to_vec .keys() .map(|i| i.serialize_long()) .collect::>(), ) }) .collect(); this.indexes_to_ids = this .index_to_id_to_vec .iter() .map(|(index, id_to_vec)| (*index, id_to_vec.keys().cloned().collect::>())) .collect(); this.indexes_to_ids .values_mut() .for_each(|ids| sort_ids(ids)); this } // Not the most performant or type safe but only built once so that's okay fn insert(&mut self, vec: &'a dyn AnyCollectableVec) { let name = vec.name(); let serialized_index = vec.index_type_to_string(); let index = Index::try_from(serialized_index) .inspect_err(|_| { dbg!(&serialized_index); }) .unwrap(); let prev = self .id_to_index_to_vec .entry(name) .or_default() .insert(index, vec); if prev.is_some() { dbg!(serialized_index, name); panic!() } let prev = self .index_to_id_to_vec .entry(index) .or_default() .insert(name, vec); if prev.is_some() { dbg!(serialized_index, name); panic!() } } pub fn ids(&self, pagination: PaginationParam) -> &[&'_ str] { let len = self.ids.len(); let start = pagination.start(len); let end = pagination.end(len); &self.ids[start..end] } pub fn id_to_indexes(&self, id: String) -> Option<&Vec<&'static str>> { self.id_to_indexes.get(id.as_str()) } pub fn index_to_ids( &self, PaginatedIndexParam { index, pagination }: PaginatedIndexParam, ) -> Vec<&'a str> { let vec = self.indexes_to_ids.get(&index).unwrap(); let len = vec.len(); let start = pagination.start(len); let end = pagination.end(len); vec.iter().skip(start).take(end).cloned().collect() } } #[derive(Default, Deref, DerefMut)] pub struct IndexToVec<'a>(BTreeMap); #[derive(Default, Deref, DerefMut)] pub struct IdToVec<'a>(BTreeMap<&'a str, &'a dyn AnyCollectableVec>);