diff options
| author | metamuffin <metamuffin@disroot.org> | 2025-12-16 04:30:42 +0100 |
|---|---|---|
| committer | metamuffin <metamuffin@disroot.org> | 2025-12-16 04:30:42 +0100 |
| commit | fc7f3ae8e39a0398ceba7b9c44f58679c01a98da (patch) | |
| tree | 77eef4d5e5ccb733b15ac4039e0a966f88ee8380 /database/src/table.rs | |
| parent | 0e48299889c3c2b81bf351ffe5da71e0bcd4c22a (diff) | |
| download | jellything-fc7f3ae8e39a0398ceba7b9c44f58679c01a98da.tar jellything-fc7f3ae8e39a0398ceba7b9c44f58679c01a98da.tar.bz2 jellything-fc7f3ae8e39a0398ceba7b9c44f58679c01a98da.tar.zst | |
tables
Diffstat (limited to 'database/src/table.rs')
| -rw-r--r-- | database/src/table.rs | 64 |
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) + } +} |