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 type KeyValueDBPinBoxFuture<'a, T> = Pin<Box<dyn Future<Output = T> + Send + 'a>>;
151
152pub trait KeyValueDB: Sync + Send + Clone + 'static {
163 fn transaction(&self) -> DBTransaction {
165 DBTransaction::new()
166 }
167
168 fn get<'a>(
170 &'a self,
171 col: u32,
172 key: &'a [u8],
173 ) -> KeyValueDBPinBoxFuture<'a, io::Result<Option<DBValue>>>;
174
175 fn delete<'a>(
177 &'a self,
178 col: u32,
179 key: &'a [u8],
180 ) -> KeyValueDBPinBoxFuture<'a, io::Result<Option<DBValue>>>;
181
182 fn write(
184 &self,
185 transaction: DBTransaction,
186 ) -> KeyValueDBPinBoxFuture<'_, Result<(), DBTransactionError>>;
187
188 fn iter<
192 'a,
193 T: Send + 'static,
194 C: Send + 'static,
195 F: FnMut(&mut C, DBKeyValueRef) -> io::Result<Option<T>> + Send + Sync + 'static,
196 >(
197 &'a self,
198 col: u32,
199 prefix: Option<&'a [u8]>,
200 context: C,
201 f: F,
202 ) -> KeyValueDBPinBoxFuture<'a, io::Result<(C, Option<T>)>>;
203
204 fn iter_keys<
208 'a,
209 T: Send + 'static,
210 C: Send + 'static,
211 F: FnMut(&mut C, DBKeyRef) -> io::Result<Option<T>> + Send + Sync + 'static,
212 >(
213 &'a self,
214 col: u32,
215 prefix: Option<&'a [u8]>,
216 context: C,
217 f: F,
218 ) -> KeyValueDBPinBoxFuture<'a, io::Result<(C, Option<T>)>>;
219
220 fn io_stats(&self, _kind: IoStatsKind) -> IoStats {
227 IoStats::empty()
228 }
229
230 fn num_columns(&self) -> io::Result<u32>;
232
233 fn num_keys(&self, col: u32) -> KeyValueDBPinBoxFuture<'_, io::Result<u64>>;
235
236 fn has_key<'a>(
238 &'a self,
239 col: u32,
240 key: &'a [u8],
241 ) -> KeyValueDBPinBoxFuture<'a, io::Result<bool>> {
242 let this = self.clone();
243 Box::pin(async move { Ok(this.get(col, key).await?.is_some()) })
244 }
245
246 fn has_prefix<'a>(
248 &'a self,
249 col: u32,
250 prefix: &'a [u8],
251 ) -> KeyValueDBPinBoxFuture<'a, io::Result<bool>> {
252 let this = self.clone();
253 Box::pin(async move {
254 let (_, out) = this
255 .iter_keys(col, Some(prefix), (), |_, _| Ok(Some(())))
256 .await?;
257 Ok(out.is_some())
258 })
259 }
260
261 fn first_with_prefix<'a>(
263 &'a self,
264 col: u32,
265 prefix: &'a [u8],
266 ) -> KeyValueDBPinBoxFuture<'a, io::Result<Option<DBKeyValue>>> {
267 let this = self.clone();
268 Box::pin(async move {
269 let (_, out) = this
270 .iter(col, Some(prefix), (), |_, (k, v)| {
271 Ok(Some((k.to_vec(), v.to_vec())))
272 })
273 .await?;
274 Ok(out)
275 })
276 }
277
278 fn cleanup(&self) -> KeyValueDBPinBoxFuture<'_, io::Result<()>> {
280 Box::pin(async { Ok(()) })
281 }
282}
283
284pub fn end_prefix(prefix: &[u8]) -> Option<Vec<u8>> {
289 let mut end_range = prefix.to_vec();
290 while let Some(0xff) = end_range.last() {
291 end_range.pop();
292 }
293 if let Some(byte) = end_range.last_mut() {
294 *byte += 1;
295 Some(end_range)
296 } else {
297 None
298 }
299}
300
301#[cfg(test)]
302mod test {
303 use super::end_prefix;
304
305 #[test]
306 fn end_prefix_test() {
307 assert_eq!(end_prefix(&[5, 6, 7]), Some(vec![5, 6, 8]));
308 assert_eq!(end_prefix(&[5, 6, 255]), Some(vec![5, 7]));
309 assert_ne!(end_prefix(&[5, 255, 255]), Some(vec![5, 255]));
311 assert_eq!(end_prefix(&[5, 255, 255]), Some(vec![6]));
314 assert_eq!(end_prefix(&[255, 255, 255]), None);
315
316 assert_eq!(end_prefix(&[0x00, 0xff]), Some(vec![0x01]));
317 assert_eq!(end_prefix(&[0xff]), None);
318 assert_eq!(end_prefix(&[]), None);
319 assert_eq!(end_prefix(b"0"), Some(b"1".to_vec()));
320 }
321}