aboutsummaryrefslogtreecommitdiff
path: root/database/src/table.rs
diff options
context:
space:
mode:
authormetamuffin <metamuffin@disroot.org>2025-12-16 04:30:42 +0100
committermetamuffin <metamuffin@disroot.org>2025-12-16 04:30:42 +0100
commitfc7f3ae8e39a0398ceba7b9c44f58679c01a98da (patch)
tree77eef4d5e5ccb733b15ac4039e0a966f88ee8380 /database/src/table.rs
parent0e48299889c3c2b81bf351ffe5da71e0bcd4c22a (diff)
downloadjellything-fc7f3ae8e39a0398ceba7b9c44f58679c01a98da.tar
jellything-fc7f3ae8e39a0398ceba7b9c44f58679c01a98da.tar.bz2
jellything-fc7f3ae8e39a0398ceba7b9c44f58679c01a98da.tar.zst
tables
Diffstat (limited to 'database/src/table.rs')
-rw-r--r--database/src/table.rs64
1 files changed, 64 insertions, 0 deletions
diff --git a/database/src/table.rs b/database/src/table.rs
new file mode 100644
index 0000000..8c6b724
--- /dev/null
+++ b/database/src/table.rs
@@ -0,0 +1,64 @@
+/*
+ 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 <metamuffin.org>
+*/
+
+use crate::{backends::KV, indices::Index};
+use anyhow::Result;
+use serde::{Serialize, de::DeserializeOwned};
+
+pub type RowNum = u64;
+
+pub struct Table<T> {
+ id: u32,
+ pub(crate) indices: Vec<Box<dyn Index<T>>>,
+}
+impl<T: Serialize + DeserializeOwned> Table<T> {
+ pub fn new(id: u32) -> Self {
+ Self {
+ id,
+ indices: Vec::new(),
+ }
+ }
+ fn key(&self, row: RowNum) -> Vec<u8> {
+ let mut key = Vec::new();
+ key.extend(self.id.to_be_bytes());
+ key.extend(row.to_be_bytes());
+ key
+ }
+ pub fn insert(&self, db: &dyn KV, entry: T) -> Result<RowNum> {
+ 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 KV, row: RowNum) -> Result<Option<T>> {
+ Ok(db
+ .get(&self.key(row))?
+ .map(|v| serde_json::from_slice(&v))
+ .transpose()?)
+ }
+ pub fn remove(&self, db: &dyn KV, row: RowNum) -> Result<bool> {
+ 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)
+ }
+}