use std::sync::Arc;
use crate::{
encryption::{
indexer::{IndexerInit, IndexesForQuery, QueryOp},
EncryptionError, IndexTerm, JsonIndexer, MatchIndexer, OreIndexer, Plaintext, ScopedCipher,
UniqueIndexer,
},
zerokms::IndexKey,
};
use zerokms_protocol::cipherstash_config::column::{Index, IndexType};
#[derive(Debug)]
pub struct QueryBuilder<T, C> {
source: T,
scoped_cipher: Arc<ScopedCipher<C>>,
descriptor: Option<String>,
}
impl<T, C> QueryBuilder<T, C> {
pub fn new(source: T, scoped_cipher: Arc<ScopedCipher<C>>) -> Self {
Self {
source,
scoped_cipher,
descriptor: None,
}
}
pub fn query_with<I>(self, index: I, op: QueryOp) -> Result<IndexTerm, EncryptionError>
where
for<'t> I: IndexesForQuery<T, C>,
{
index.query_index(self, op)
}
pub fn with_descriptor(mut self, descriptor: impl Into<String>) -> Self {
self.descriptor = Some(descriptor.into());
self
}
pub(crate) fn plaintext(&self) -> &T {
&self.source
}
pub(crate) fn index_key(&self) -> &IndexKey {
self.scoped_cipher.index_key()
}
}
pub trait Queryable<C> {
type Output;
fn build_queryable(
self,
scoped_cipher: Arc<ScopedCipher<C>>,
op: QueryOp,
) -> Result<IndexTerm, EncryptionError>;
}
impl<C> Queryable<C> for (Index, Plaintext) {
type Output = Plaintext;
fn build_queryable(
self,
scoped_cipher: Arc<ScopedCipher<C>>,
op: QueryOp,
) -> Result<IndexTerm, EncryptionError> {
(&self.0, self.1).build_queryable(scoped_cipher, op)
}
}
impl<C> Queryable<C> for (&Index, Plaintext) {
type Output = Plaintext;
fn build_queryable(
self,
scoped_cipher: Arc<ScopedCipher<C>>,
op: QueryOp,
) -> Result<IndexTerm, EncryptionError> {
let (index, plaintext) = self;
let builder = QueryBuilder::new(plaintext, scoped_cipher);
match &index.index_type {
unique @ IndexType::Unique { .. } => {
let index = UniqueIndexer::try_init(unique)?;
builder.query_with(index, op)
}
match_ @ IndexType::Match { .. } => {
let index = MatchIndexer::try_init(match_)?;
builder.query_with(index, op)
}
ore @ IndexType::Ore => {
let index = OreIndexer::try_init(ore)?;
builder.query_with(index, op)
}
json @ IndexType::SteVec { .. } => {
let index = JsonIndexer::try_init(json)?;
builder.query_with(index, op)
}
}
}
}