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}