dbless/lib.rs
1#![deny(missing_docs)]
2#![doc = include_str!("../README.md")]
3//! ## About the default table
4//! Using methods from [`TableReadInterface`](trait.TableReadInterface.html) and [`TableWriteInterface`](trait.TableWriteInterface.html) directly on [`Database`](struct.Database.html) \
5//! uses a default table named `#_#_main_dbless_table_#_#`.
6//!
7//! calling [`clear()`](struct.Database.html#method.clear) or [`reset()`](struct.Database.html#method.reset) will only clear this table, not the entire database, \
8//! to clear the entire database, use [`delete_all_tables()`](struct.Database.html#method.delete_all_tables)
9//!
10//! similarly, calling [`len()`](struct.Database.html#method.len) or [`size()`](struct.Database.html#method.size) will only count the number of entries in this table, \
11//! to count the number of entries in the entire database, use [`len_all_tables()`](struct.Database.html#method.len_all_tables) or [`size_all_tables()`](struct.Database.html#method.size_all_tables).
12
13mod store;
14use std::path::Path;
15
16use store::Store;
17
18mod table;
19
20#[cfg(test)]
21mod tests;
22
23pub use table::{Table, TableMut, TableReadInterface, TableWriteInterface};
24
25use anyhow::Result;
26use serde::{de::DeserializeOwned, Serialize};
27
28const MAIN_TABLE: &str = "#_#_main_dbless_table_#_#";
29
30/// A Database
31pub struct Database {
32 store: Store,
33}
34
35impl Database {
36 /// Opens a file at the given path and uses it as the database. \
37 /// If the file doesn't exist, it will be created.
38 /// ```no_run
39 /// # use dbless::Database;
40 /// let db = Database::open("my_database.db")?;
41 /// # Ok::<(), Box<dyn std::error::Error>>(())
42 /// ```
43 pub fn open(path: impl AsRef<Path>) -> Result<Self> {
44 Ok(Database {
45 store: Store::file(path)?,
46 })
47 }
48
49 /// Opens an in-memory database. \
50 /// Useful for tests and as a stub for a database that doesn't need to be saved to disk.
51 /// ```no_run
52 /// # use dbless::Database;
53 /// let db = Database::in_memory()?;
54 /// # Ok::<(), Box<dyn std::error::Error>>(())
55 /// ```
56 pub fn in_memory() -> Result<Self> {
57 Ok(Database {
58 store: Store::in_memory()?,
59 })
60 }
61
62 /// Closes the databas
63 /// ```no_run
64 /// # use dbless::Database;
65 /// let db = Database::open("my_database.db")?;
66 /// db.close();
67 /// // why ?
68 /// # Ok::<(), Box<dyn std::error::Error>>(())
69 /// ```
70 pub fn close(self) {
71 drop(self);
72 }
73
74 /// Get a read-only handle to a table with the given name.
75 /// ```no_run
76 /// # use dbless::Database;
77 /// # use dbless::TableReadInterface;
78 /// let db = Database::open("my_database.db")?;
79 /// let value = db.table("my_table").get("key")?;
80 /// # let tmp: Option<String> = value;
81 /// # Ok::<(), Box<dyn std::error::Error>>(())
82 /// ```
83 pub fn table<'a>(&'a self, name: &'a str) -> Table<'a> {
84 Table {
85 store: &self.store,
86 name,
87 }
88 }
89
90 /// Get a read-write handle to a table with the given name.
91 /// ```no_run
92 /// # use dbless::Database;
93 /// # use dbless::TableWriteInterface;
94 /// let mut db = Database::open("my_database.db")?;
95 /// db.table_mut("my_table").set("key", &"value")?;
96 /// # Ok::<(), Box<dyn std::error::Error>>(())
97 /// ```
98 pub fn table_mut<'a>(&'a mut self, name: &'a str) -> TableMut<'a> {
99 TableMut {
100 store: &mut self.store,
101 name,
102 }
103 }
104
105 /// Returns a list of the names of all tables in the database.
106 /// ```no_run
107 /// # use dbless::Database;
108 /// let db = Database::open("my_database.db")?;
109 /// let tables = db.list_tables()?;
110 /// for table in tables {
111 /// println!("{}", table);
112 /// }
113 /// # Ok::<(), Box<dyn std::error::Error>>(())
114 /// ```
115 pub fn list_tables(&self) -> Result<Vec<String>> {
116 Ok(self
117 .store
118 .list_tables()?
119 .into_iter()
120 .filter(|t| t != MAIN_TABLE)
121 .collect())
122 }
123
124 /// Deletes a table from the database.
125 /// ```no_run
126 /// # use dbless::Database;
127 /// let mut db = Database::open("my_database.db")?;
128 /// db.delete_table("my_table")?;
129 /// # Ok::<(), Box<dyn std::error::Error>>(())
130 /// ```
131 pub fn delete_table(&mut self, name: &str) -> Result<()> {
132 self.store.delete_table(name)
133 }
134
135 /// Returns the number of entries in all tables in the database. \
136 /// aliases: [`size_all_tables()`](#method.size_all_tables)
137 /// ```no_run
138 /// # use dbless::Database;
139 /// let db = Database::open("my_database.db")?;
140 /// let len = db.len_all_tables()?;
141 /// println!("the database has {} entries across all tables", len);
142 /// # Ok::<(), Box<dyn std::error::Error>>(())
143 /// ```
144 pub fn len_all_tables(&self) -> Result<usize> {
145 self.store.len_all_tables()
146 }
147
148 /// Returns the number of entries in all tables in the database. \
149 /// aliases: [`len_all_tables()`](#method.len_all_tables)
150 /// ```no_run
151 /// # use dbless::Database;
152 /// let db = Database::open("my_database.db")?;
153 /// let size = db.size_all_tables()?;
154 /// println!("the database has {} entries across all tables", size);
155 /// # Ok::<(), Box<dyn std::error::Error>>(())
156 /// ```
157 pub fn size_all_tables(&self) -> Result<usize> {
158 self.len_all_tables()
159 }
160
161 /// Deletes all tables in the database. \
162 /// ```no_run
163 /// # use dbless::Database;
164 /// let mut db = Database::open("my_database.db")?;
165 /// db.delete_all_tables()?;
166 /// assert!(db.list_tables()?.is_empty());
167 /// # Ok::<(), Box<dyn std::error::Error>>(())
168 /// ```
169 pub fn delete_all_tables(&mut self) -> Result<()> {
170 self.store.delete_all_tables()
171 }
172}
173
174macro_rules! mirror_methods_with {
175 {self.$fn:ident($arg:expr); $(fn $name:ident$(<$($gname:ident: $gty1:ident $(+$gtyr:ident)*),+>)?(&self $(,$pname:ident: $pty:ty)*) -> $ret:ty;)*} => {
176 $(
177 fn $name$(<$($gname: $gty1$(+$gtyr)*),+>)?(&self, $($pname: $pty),*) -> $ret {
178 self.$fn($arg).$name($($pname),*)
179 }
180 )*
181 }
182}
183
184macro_rules! mirror_methods_mut_with {
185 {self.$fn:ident($arg:expr); $(fn $name:ident$(<$($gname:ident: $gty1:ident $(+$gtyr:ident)*),+>)?(&mut self $(,$pname:ident: $pty:ty)*) -> $ret:ty;)*} => {
186 $(
187 fn $name$(<$($gname: $gty1$(+$gtyr)*),+>)?(&mut self, $($pname: $pty),*) -> $ret {
188 self.$fn($arg).$name($($pname),*)
189 }
190 )*
191 }
192}
193
194impl TableReadInterface for Database {
195 mirror_methods_with! {
196 self.table(MAIN_TABLE);
197 fn get<T: DeserializeOwned>(&self, key: &str) -> Result<Option<T>>;
198 fn keys(&self) -> Result<Vec<String>> ;
199 fn values<T: DeserializeOwned>(&self) -> Result<Vec<T>> ;
200 fn entries<T: DeserializeOwned>(&self) -> Result<Vec<(String, T)>> ;
201 fn len(&self) -> Result<usize> ;
202 fn is_empty(&self) -> Result<bool> ;
203 fn contains_key(&self, key: &str) -> Result<bool> ;
204 fn size(&self) -> Result<usize> ;
205 fn contains(&self, key: &str) -> Result<bool> ;
206 fn has(&self, key: &str) -> Result<bool> ;
207 fn get_or<T: DeserializeOwned>(&self, key: &str, default: T) -> Result<T> ;
208 fn get_or_default<T: DeserializeOwned + Default>(&self, key: &str) -> Result<T> ;
209 }
210
211 // current macro can't handle FnOnce() -> T
212 fn get_or_else<T: DeserializeOwned, F: FnOnce() -> T>(
213 &self,
214 key: &str,
215 default: F,
216 ) -> Result<T> {
217 self.table(MAIN_TABLE).get_or_else(key, default)
218 }
219}
220
221impl TableWriteInterface for Database {
222 mirror_methods_mut_with! {
223 self.table_mut(MAIN_TABLE);
224 fn insert<T: Serialize>(&mut self, key: &str, value: &T) -> Result<()>;
225 fn remove(&mut self, key: &str) -> Result<()>;
226 fn clear(&mut self) -> Result<()>;
227 fn set<T: Serialize>(&mut self, key: &str, value: &T) -> Result<()>;
228 fn delete(&mut self, key: &str) -> Result<()>;
229 fn reset(&mut self) -> Result<()>;
230 fn get_or_insert<T: Serialize + DeserializeOwned>(&mut self, key: &str, default: T) -> Result<T>;
231 fn get_or_insert_default<T: Serialize + DeserializeOwned + Default>(&mut self, key: &str) -> Result<T>;
232 }
233
234 // current macro can't handle FnOnce() -> T
235 fn get_or_insert_with<T: Serialize + DeserializeOwned, F: FnOnce() -> T>(
236 &mut self,
237 key: &str,
238 default: F,
239 ) -> Result<T> {
240 self.table_mut(MAIN_TABLE).get_or_insert_with(key, default)
241 }
242}