/* 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) 2025 metamuffin */ use crate::{ backends::{ReadTransaction, WriteTransaction}, indices::Index, }; use anyhow::Result; use serde::{Serialize, de::DeserializeOwned}; 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: T) -> 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), &serde_json::to_vec(&entry)?)?; for idx in &self.indices { idx.add(db, row, &entry)?; } Ok(id_counter) } pub fn get(&self, db: &dyn ReadTransaction, row: RowNum) -> Result> { Ok(db .get(&self.key(row))? .map(|v| serde_json::from_slice(&v)) .transpose()?) } pub fn remove(&self, db: &mut dyn WriteTransaction, row: RowNum) -> Result { let Some(entry) = self.get(db, row)? else { return Ok(false); }; for idx in &self.indices { idx.remove(db, row, &entry)?; } db.del(&self.key(row))?; Ok(true) } }