/* 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}, sort::Index, }; use anyhow::Result; use jellyobject::ObjectBuffer; pub type TableNum = u64; pub type RowNum = u64; pub struct Table { id: u32, pub(crate) indices: Vec>, } impl Table { pub fn new(id: u32) -> Self { Self { id, indices: Vec::new(), } } fn key(&self, row: RowNum) -> Vec { let mut key = Vec::new(); key.extend(self.id.to_be_bytes()); key.extend(row.to_be_bytes()); key } pub fn insert(&self, db: &mut dyn WriteTransaction, entry: ObjectBuffer) -> Result { let mut id_counter = db .get(&self.id.to_be_bytes())? .map(|k| k.as_slice().try_into().map(RowNum::from_be_bytes).ok()) .flatten() .unwrap_or(0); let row = id_counter; id_counter += 1; db.set(&self.id.to_be_bytes(), &id_counter.to_be_bytes())?; db.set(&self.key(row), bytemuck::cast_slice(entry.0.as_slice()))?; let ob = entry.as_object(); for idx in &self.indices { idx.add(db, row, ob)?; } Ok(id_counter) } pub fn add_index(&mut self, index: T) -> T { self.indices.push(Box::new(index.clone())); index } pub fn get(&self, db: &dyn ReadTransaction, row: RowNum) -> Result> { Ok(db.get(&self.key(row))?.map(ObjectBuffer::from)) } pub fn remove(&self, db: &mut dyn WriteTransaction, row: RowNum) -> Result { let Some(entry) = self.get(db, row)? else { return Ok(false); }; let ob = entry.as_object(); for idx in &self.indices { idx.remove(db, row, ob)?; } db.del(&self.key(row))?; Ok(true) } }