aboutsummaryrefslogtreecommitdiff
path: root/database/src/indices/key.rs
blob: ab38d716b4d41ed8d34b39ebf54a0cdd2d325dfc (plain)
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
// }