use std::{ collections::{BTreeMap, HashMap, HashSet}, path::Path, sync::Arc, }; use anyhow::Result; use uuid::Uuid; use crate::models::{Document, Project}; pub trait Filter = Fn(&Row) -> bool; pub trait Map = Fn(&Row) -> T; pub enum Row { Project(Box), Document(Box), //User(Box), } #[derive(Clone, Debug, Eq, Hash, PartialEq)] pub struct RowId(Uuid); // supports comparison operators #[derive(Clone, Debug, Eq, Hash, PartialEq)] pub struct IndexId(String); #[derive(Clone, Debug, Eq, Hash, PartialEq)] pub struct IndexValue(String); pub enum Index { BTree(BTreeMap>), Unique(HashMap), } pub struct Store { rows: HashMap>, indexes: HashMap, keyspace: fjall::Keyspace, data_partition: fjall::PartitionHandle, permissions_partition: fjall::PartitionHandle, } impl Store { pub fn new>(path: P) -> Result { let rows = HashMap::new(); let indexes = HashMap::new(); let kv_config = fjall::Config::new(path) .flush_workers(4) .compaction_workers(4); let keyspace = fjall::Keyspace::open(kv_config)?; let data_partition = keyspace.open_partition("data", fjall::PartitionCreateOptions::default())?; let permissions_partition = keyspace.open_partition("permissions", fjall::PartitionCreateOptions::default())?; Ok(Store { rows, indexes, keyspace, data_partition, permissions_partition, }) } pub fn set(&mut self, _item: &Row) -> Result<()> { todo!() } /// Retrieves an item from the store by id. This is always an in-memory /// operation and cannot fail. pub fn get(&self, id: RowId) -> Option> { self.rows.get(&id).cloned() } } #[derive(Clone, Debug, Eq, Hash, PartialEq)] pub struct Comparison { index: IndexId, value: IndexValue, operator: ComparisonOperator, } #[derive(Clone, Debug, Eq, Hash, PartialEq)] pub enum ComparisonOperator { Eq, Gt, Gte, Lt, Lte, } #[derive(Clone, Debug, Eq, Hash, PartialEq)] pub enum QueryOperation { All, Where(Comparison), Limit(usize), Offset(usize), OrderBy(IndexId), } /// Describes a set of operations to query for data in the database. To read the /// data, this gets transformed into a QuerySet, which contains the results. pub struct Query { operations: Vec, } impl Query { pub fn new() -> Query { Query { operations: Vec::new(), } } pub fn all(&mut self) -> &mut Self { self.operations.push(QueryOperation::All); self } /// Filters down the set of rows via comparison operators pub fn restrict( &mut self, index: IndexId, value: IndexValue, operator: ComparisonOperator, ) -> &mut Self { self.operations.push(QueryOperation::Where(Comparison { index, value, operator, })); self } pub fn limit(&mut self, limit: usize) -> &mut Self { self.operations.push(QueryOperation::Limit(limit)); self } pub fn offset(&mut self, offset: usize) -> &mut Self { self.operations.push(QueryOperation::Offset(offset)); self } pub fn order_by(&mut self, index: IndexId) -> &mut Self { self.operations.push(QueryOperation::OrderBy(index)); self } pub fn execute(&self) -> QuerySet { todo!() } } /// The results of a Query, this will contain the concrete Rows which have been /// retrieved. pub struct QuerySet {} impl QuerySet {} impl Iterator for QuerySet { type Item = Row; fn next(&mut self) -> Option { todo!() } } // How I'd like to do queries: // // store.query().via(OnlyProjects). // // //