1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
|
/*
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 <metamuffin.org>
*/
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<Box<dyn Index>>,
}
impl Table {
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: &mut dyn WriteTransaction, entry: ObjectBuffer) -> 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), 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<T: Index + Clone + 'static>(&mut self, index: T) -> T {
self.indices.push(Box::new(index.clone()));
index
}
pub fn get(&self, db: &dyn ReadTransaction, row: RowNum) -> Result<Option<ObjectBuffer>> {
Ok(db.get(&self.key(row))?.map(ObjectBuffer::from))
}
pub fn remove(&self, db: &mut dyn WriteTransaction, row: RowNum) -> Result<bool> {
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)
}
}
|