/* 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::{ReadTransaction, WriteTransaction}, indices::Index, prefix_iterator::PrefixIterator, table::{RowNum, Table, TableNum}, }; use anyhow::Result; pub struct KeyIndex { id: TableNum, key: fn(&T) -> &[u8], } impl KeyIndex { pub fn new(table: &mut Table, id: TableNum, key: fn(&T) -> &[u8]) -> Self { table.indices.push(Box::new(Self { id, key })); Self { id, key } } pub fn key(&self, id: RowNum, key: &[u8]) -> Vec { let mut v = Vec::new(); v.extend(self.id.to_be_bytes()); v.extend(key); v.extend(id.to_be_bytes()); v } pub fn lookup<'a>( &self, db: &'a dyn ReadTransaction, key: &[u8], ) -> Result> { let mut prefix = Vec::new(); prefix.extend(self.id.to_be_bytes()); prefix.extend(key); Ok(PrefixIterator { inner: db.iter(&prefix, false)?, prefix: prefix.into(), }) } } impl Index for KeyIndex { fn add(&self, db: &mut dyn WriteTransaction, id: RowNum, val: &T) -> Result<()> { db.set(&self.key(id, (self.key)(val)), &[]) } fn remove(&self, db: &mut dyn WriteTransaction, id: RowNum, val: &T) -> Result<()> { db.del(&self.key(id, (self.key)(val))) } fn compare(&self, before: &T, after: &T) -> bool { (self.key)(before) == (self.key)(after) } } // fn inc_key(key: &[u8]) -> Vec { // let mut key = key.to_owned(); // for i in (0..key.len()).rev() { // let (nv, carry) = key[i].overflowing_add(1); // key[i] = nv; // if !carry { // break; // } // } // key // }