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
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
#[cfg(feature = "json")]
mod json;
#[cfg(feature = "proto")]
mod proto;

pub use async_trait::async_trait;
use bytes::Bytes;
use smol_str::SmolStr;
use std::collections::HashMap;

#[cfg(feature = "json")]
pub use json::KvdbJsonExt;
#[cfg(feature = "proto")]
pub use proto::KvdbProtoExt;

pub type Key = SmolStr;
pub type Value = Bytes;
pub type KeyValue = (Key, Value);
pub type Filter = dyn Fn(&Key) -> bool + Send + Sync;

pub enum DbOp {
    Insert { key: Key, value: Value },
    InsertMany { data: HashMap<Key, Value> },
    Delete { key: Key },
    DeleteMany { keys: Vec<Key> },
    DeleteAll,
}

#[derive(Default)]
pub struct DbOps {
    pub clear: bool,
    pub insert: HashMap<Key, Value>,
    pub delete: Vec<Key>,
}

#[derive(Default)]
pub struct DbOpMerger {
    need_clear: bool,
    ops: HashMap<Key, Option<Value>>,
}
impl DbOpMerger {
    pub fn new() -> Self {
        Self {
            need_clear: false,
            ops: HashMap::new(),
        }
    }
    pub fn is_empty(&self) -> bool {
        !self.need_clear && self.ops.is_empty()
    }
    pub fn merge(&mut self, op: DbOp) {
        match op {
            DbOp::Insert { key, value } => {
                self.ops.insert(key, Some(value));
            }
            DbOp::InsertMany { data } => {
                for (key, value) in data {
                    self.ops.insert(key, Some(value));
                }
            }
            DbOp::Delete { key } => {
                self.ops.insert(key, None);
            }
            DbOp::DeleteMany { keys } => {
                for key in keys {
                    self.ops.insert(key, None);
                }
            }
            DbOp::DeleteAll => {
                self.need_clear = true;
                self.ops.clear();
            }
        }
    }
    pub fn into_ops(self) -> DbOps {
        let mut ops = DbOps::default();
        for (k, v) in self.ops {
            if let Some(v) = v {
                ops.insert.insert(k, v);
            } else {
                ops.delete.push(k);
            }
        }
        ops.clear = self.need_clear;
        ops
    }
}

#[async_trait]
pub trait Kvdb {
    async fn scan_keys(&self, filter: &Filter) -> Vec<Key>;
    async fn get(&self, key: Key) -> Option<Value> {
        let keys = Vec::from([key]);
        self.get_many(keys).await.into_values().next()
    }
    async fn get_many(&self, keys: Vec<Key>) -> HashMap<Key, Value>;
    async fn set(&self, key: Key, value: Value) {
        let data = HashMap::from([(key, value)]);
        self.set_many(data).await
    }
    async fn set_many(&self, data: HashMap<Key, Value>);
    async fn delete(&self, key: Key) {
        let keys = Vec::from([key]);
        self.delete_many(keys).await
    }
    async fn delete_many(&self, keys: Vec<Key>);
    async fn delete_all(&self);
}

#[test]
fn empty(){
    let op_merger = DbOpMerger::default();
    assert!(op_merger.is_empty());
}