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
|
/*
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},
indices::Index,
prefix_iterator::PrefixIterator,
table::{RowNum, Table, TableNum},
};
use anyhow::Result;
pub struct KeyIndex<T> {
id: TableNum,
key: fn(&T) -> &[u8],
}
impl<T: 'static> KeyIndex<T> {
pub fn new(table: &mut Table<T>, id: TableNum, key: fn(&T) -> &[u8]) -> Self {
table.indices.push(Box::new(Self { id, key }));
Self { id, key }
}
pub fn key(&self, id: RowNum, key: &[u8]) -> Vec<u8> {
let mut v = Vec::new();
v.extend(self.id.to_be_bytes());
v.extend(key);
v.extend(id.to_be_bytes());
v
}
pub fn lookup<'a>(
&self,
db: &'a dyn ReadTransaction,
key: &[u8],
) -> Result<PrefixIterator<'a>> {
let mut prefix = Vec::new();
prefix.extend(self.id.to_be_bytes());
prefix.extend(key);
Ok(PrefixIterator {
inner: db.iter(&prefix, false)?,
prefix: prefix.into(),
})
}
}
impl<T: 'static> Index<T> for KeyIndex<T> {
fn add(&self, db: &mut dyn WriteTransaction, id: RowNum, val: &T) -> Result<()> {
db.set(&self.key(id, (self.key)(val)), &[])
}
fn remove(&self, db: &mut dyn WriteTransaction, id: RowNum, val: &T) -> Result<()> {
db.del(&self.key(id, (self.key)(val)))
}
fn compare(&self, before: &T, after: &T) -> bool {
(self.key)(before) == (self.key)(after)
}
}
// fn inc_key(key: &[u8]) -> Vec<u8> {
// let mut key = key.to_owned();
// for i in (0..key.len()).rev() {
// let (nv, carry) = key[i].overflowing_add(1);
// key[i] = nv;
// if !carry {
// break;
// }
// }
// key
// }
|