1#![deny(clippy::all)]
4
5mod io_stats;
6
7pub use io_stats::{IoStats, Kind as IoStatsKind};
8use std::future::Future;
9use std::io;
10use std::pin::Pin;
11
12pub const PREFIX_LEN: usize = 12;
14
15pub type DBValue = Vec<u8>;
17pub type DBKey = Vec<u8>;
18pub type DBKeyValue = (DBKey, DBValue);
19pub type DBKeyRef<'a> = &'a DBKey;
20pub type DBKeyValueRef<'a> = (&'a DBKey, &'a DBValue);
21
22#[derive(Default, Debug, Clone, Eq, PartialEq)]
24pub struct DBTransaction {
25 pub ops: Vec<DBOp>,
27}
28
29#[derive(Clone, Debug, PartialEq, Eq)]
31pub enum DBOp {
32 Insert {
33 col: u32,
34 key: DBKey,
35 value: DBValue,
36 },
37 Delete {
38 col: u32,
39 key: DBKey,
40 },
41 DeletePrefix {
42 col: u32,
43 prefix: DBKey,
44 },
45}
46
47impl DBOp {
48 pub fn key(&self) -> &DBKey {
50 match *self {
51 DBOp::Insert { ref key, .. } => key,
52 DBOp::Delete { ref key, .. } => key,
53 DBOp::DeletePrefix { ref prefix, .. } => prefix,
54 }
55 }
56 pub fn value(&self) -> Option<&DBValue> {
58 match *self {
59 DBOp::Insert { ref value, .. } => Some(value),
60 DBOp::Delete { .. } => None,
61 DBOp::DeletePrefix { .. } => None,
62 }
63 }
64 pub fn col(&self) -> u32 {
66 match *self {
67 DBOp::Insert { col, .. } => col,
68 DBOp::Delete { col, .. } => col,
69 DBOp::DeletePrefix { col, .. } => col,
70 }
71 }
72}
73
74impl DBTransaction {
75 pub fn new() -> DBTransaction {
77 DBTransaction::with_capacity(256)
78 }
79
80 pub fn with_capacity(cap: usize) -> DBTransaction {
82 DBTransaction {
83 ops: Vec::with_capacity(cap),
84 }
85 }
86
87 pub fn put<K, V>(&mut self, col: u32, key: K, value: V)
89 where
90 K: AsRef<[u8]>,
91 V: AsRef<[u8]>,
92 {
93 self.ops.push(DBOp::Insert {
94 col,
95 key: DBKey::from(key.as_ref()),
96 value: DBValue::from(value.as_ref()),
97 })
98 }
99 pub fn put_owned(&mut self, col: u32, key: Vec<u8>, value: Vec<u8>) {
100 self.ops.push(DBOp::Insert { col, key, value })
101 }
102
103 pub fn delete<K>(&mut self, col: u32, key: K)
105 where
106 K: AsRef<[u8]>,
107 {
108 self.ops.push(DBOp::Delete {
109 col,
110 key: DBKey::from(key.as_ref()),
111 });
112 }
113 pub fn delete_owned(&mut self, col: u32, key: Vec<u8>) {
114 self.ops.push(DBOp::Delete { col, key });
115 }
116
117 pub fn delete_prefix<K>(&mut self, col: u32, prefix: K)
121 where
122 K: AsRef<[u8]>,
123 {
124 self.ops.push(DBOp::DeletePrefix {
125 col,
126 prefix: DBKey::from(prefix.as_ref()),
127 });
128 }
129 pub fn delete_prefix_owned(&mut self, col: u32, prefix: Vec<u8>) {
130 self.ops.push(DBOp::DeletePrefix { col, prefix });
131 }
132}
133
134#[derive(Debug)]
136pub struct DBTransactionError {
137 pub error: io::Error,
138 pub transaction: DBTransaction,
139}
140
141impl std::fmt::Display for DBTransactionError {
142 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
143 f.debug_struct("TransactionError")
144 .field("error", &self.error)
145 .finish()
146 }
147}
148impl std::error::Error for DBTransactionError {}
149
150pub trait KeyValueDB: Sync + Send + Clone + 'static {
161 fn transaction(&self) -> DBTransaction {
163 DBTransaction::new()
164 }
165
166 fn get<'a>(
168 &self,
169 col: u32,
170 key: &'a [u8],
171 ) -> Pin<Box<dyn Future<Output = io::Result<Option<DBValue>>> + Send + 'a>>;
172
173 fn delete<'a>(
175 &self,
176 col: u32,
177 key: &'a [u8],
178 ) -> Pin<Box<dyn Future<Output = io::Result<Option<DBValue>>> + Send + 'a>>;
179
180 fn write(
182 &self,
183 transaction: DBTransaction,
184 ) -> Pin<Box<dyn Future<Output = Result<(), DBTransactionError>> + Send>>;
185
186 fn iter<'a, T: 'a, F: FnMut(DBKeyValueRef) -> io::Result<Option<T>> + Send + Sync + 'a>(
190 &self,
191 col: u32,
192 prefix: Option<&'a [u8]>,
193 f: F,
194 ) -> Pin<Box<dyn Future<Output = io::Result<Option<T>>> + Send + 'a>>;
195
196 fn iter_keys<'a, T: 'a, F: FnMut(DBKeyRef) -> io::Result<Option<T>> + Send + Sync + 'a>(
200 &self,
201 col: u32,
202 prefix: Option<&'a [u8]>,
203 f: F,
204 ) -> Pin<Box<dyn Future<Output = io::Result<Option<T>>> + Send + 'a>>;
205
206 fn restore(&self, new_db: &str) -> io::Result<()>;
208
209 fn io_stats(&self, _kind: IoStatsKind) -> IoStats {
216 IoStats::empty()
217 }
218
219 fn num_columns(&self) -> io::Result<u32>;
221
222 fn num_keys(&self, col: u32) -> Pin<Box<dyn Future<Output = io::Result<u64>> + Send>>;
224
225 fn has_key<'a>(
227 &self,
228 col: u32,
229 key: &'a [u8],
230 ) -> Pin<Box<dyn Future<Output = io::Result<bool>> + Send + 'a>> {
231 let this = self.clone();
232 Box::pin(async move { Ok(this.get(col, key).await?.is_some()) })
233 }
234
235 fn has_prefix<'a>(
237 &self,
238 col: u32,
239 prefix: &'a [u8],
240 ) -> Pin<Box<dyn Future<Output = io::Result<bool>> + Send + 'a>> {
241 let this = self.clone();
242 Box::pin(async move {
243 Ok(this
244 .iter_keys(col, Some(prefix), |_| Ok(Some(())))
245 .await?
246 .is_some())
247 })
248 }
249
250 fn first_with_prefix<'a>(
252 &self,
253 col: u32,
254 prefix: &'a [u8],
255 ) -> Pin<Box<dyn Future<Output = io::Result<Option<DBKeyValue>>> + Send + 'a>> {
256 let this = self.clone();
257 Box::pin(async move {
258 let out = this
259 .iter(col, Some(prefix), |(k, v)| {
260 Ok(Some((k.to_vec(), v.to_vec())))
261 })
262 .await?;
263 Ok(out)
264 })
265 }
266}
267
268pub fn end_prefix(prefix: &[u8]) -> Option<Vec<u8>> {
273 let mut end_range = prefix.to_vec();
274 while let Some(0xff) = end_range.last() {
275 end_range.pop();
276 }
277 if let Some(byte) = end_range.last_mut() {
278 *byte += 1;
279 Some(end_range)
280 } else {
281 None
282 }
283}
284
285#[cfg(test)]
286mod test {
287 use super::end_prefix;
288
289 #[test]
290 fn end_prefix_test() {
291 assert_eq!(end_prefix(&[5, 6, 7]), Some(vec![5, 6, 8]));
292 assert_eq!(end_prefix(&[5, 6, 255]), Some(vec![5, 7]));
293 assert_ne!(end_prefix(&[5, 255, 255]), Some(vec![5, 255]));
295 assert_eq!(end_prefix(&[5, 255, 255]), Some(vec![6]));
298 assert_eq!(end_prefix(&[255, 255, 255]), None);
299
300 assert_eq!(end_prefix(&[0x00, 0xff]), Some(vec![0x01]));
301 assert_eq!(end_prefix(&[0xff]), None);
302 assert_eq!(end_prefix(&[]), None);
303 assert_eq!(end_prefix(b"0"), Some(b"1".to_vec()));
304 }
305}