/* This file is part of jellything (https://codeberg.org/metamuffin/jellything) which is licensed under the GNU Affero General Public License (version 3); see /COPYING. Copyright (C) 2026 metamuffin */ use crate::{ backends::WriteTransaction, filter::binning::Binning, query::{MultiBehaviour, ValueSortComponent}, sort::Index, table::{RowNum, TableNum}, }; use anyhow::Result; use jellyobject::Object; pub struct ValueIndex { id: TableNum, binning: Binning, sort: ValueSortComponent, } impl ValueIndex { pub fn new(id: TableNum, binning: Binning, sort: ValueSortComponent) -> Self { Self { id, binning, sort } } fn keys(&self, id: RowNum, ob: Object) -> Vec> { let mut keys = vec![self.id.to_be_bytes().to_vec()]; self.binning.apply(ob, &mut keys); self.sort.apply(ob, &mut keys); for k in &mut keys { k.extend(id.to_ne_bytes()); } keys } } impl Index for ValueIndex { fn add(&self, db: &mut dyn WriteTransaction, id: RowNum, ob: Object) -> Result<()> { for key in self.keys(id, ob) { db.set(&key, &[])?; } Ok(()) } fn remove(&self, db: &mut dyn WriteTransaction, id: RowNum, ob: Object) -> Result<()> { for key in self.keys(id, ob) { db.del(&key)?; } Ok(()) } fn compare(&self, before: Object, after: Object) -> bool { self.keys(0, before) == self.keys(0, after) } } impl ValueSortComponent { fn apply(&self, ob: Object, keys: &mut Vec>) { match self.multi { MultiBehaviour::First => { if let Some(val) = self.path.get_matching_value(ob) { for k in keys.iter_mut() { k.extend(val); } } else { keys.clear(); } } MultiBehaviour::ForEach => { let mut keys_out = Vec::new(); for val in self.path.get_matching_values(ob) { for mut k in keys.clone() { k.extend(val); keys_out.push(k); } } *keys = keys_out } MultiBehaviour::Max => todo!(), MultiBehaviour::Min => todo!(), MultiBehaviour::Count => { let count = self.path.get_matching_values(ob).len() as u32; for k in keys.iter_mut() { k.extend(count.to_be_bytes()); } } } } }