1 unstable release
0.3.0 | May 25, 2022 |
---|---|
0.2.0 |
|
0.1.1 |
|
0.1.0 |
|
#2813 in Database interfaces
150KB
4.5K
SLoC
Husky
Husky is an abstraction around sled that allows for the creation of views with an API similar to iterators. Its aim is to make cache and indexing easier.
Below is a list of features. For examples, check the documentation.
Sections
Getting Started
Add Dependency
To use husky with rkyv
husky = "0.2"
To use husky with serde
husky = { version = "0.2", default-features = false, features = ["serde"] }
Open a Database
Open a database with
let db = husky::open("db_name").unwrap();
or
let db = husky::open_temp().unwrap();
Open a Tree
You can open a single entry in the database
let single = db.open_single("key").unwrap();
A key-value tree on disk
let tree = db.open_tree("name").unwrap();
Or a temporary key-value tree
let temp = db.open_temp();
Viewing
Through the View trait you can query entries in the tree.
use husky::View;
Check if a view is empty
assert_eq!(tree.is_empty(), Some(false));
Check if a key exists
assert_eq!(tree.contains_key(1), Ok(true));
assert_eq!(tree.contains_key(2), Ok(true));
Get individual values
assert_eq!(tree.get(1), Ok(Some("first value")));
assert_eq!(tree.get(2), Ok(Some("last value")));
Get entries before and after
assert_eq!(tree.get_lt(2), Ok(Some("first value"));
assert_eq!(tree.get_gt(1), Ok(Some("last value"));
Get a range of entries
let mut range = tree.range(..).unwrap();
assert_eq!(range.next(), Ok(Some((1, "first value"))));
assert_eq!(range.next(), Ok(Some((2, "last value"))));
Get all the entries
let mut iter = tree.iter();
assert_eq!(iter.next(), Ok(Some((1, "first value"))));
assert_eq!(iter.next(), Ok(Some((2, "last value"))));
Get the first and last entries
assert_eq!(tree.first(), Ok(Some((1, "first value"))));
assert_eq!(tree.last() , Ok(Some((2, "last value"))));
Changing
Through the Change trait you can manipulate the entries in the tree
use husky::Change;
Insert an entry
let previous = tree.insert("key", "value").unwrap();
Remove an entry
let previous = tree.remove("key").unwrap();
Clear all entries
tree.clear().unwrap();
Insert with auto increment
If the key type has the AutoInc trait implemented, you can push values. By default it is implemented for all unsigned integers and usize.
tree.push("value").unwrap()
Operating
Through the Operate trait you can create new views. They are lazy wrappers around the original, but you can store their results.
use husky::Operate;
Map entries
let map = tree.map(|key, value| "new_value");
Transform entries
let transform = tree.map(|key, value| vec![
("first key", "first value"),
("second key", "second value")
]);
Reindex entries
let index = tree.map(|key, value| vec![
"first key",
"second key"
]);
Chain two views
let chain = tree.chain(&other_tree);
Zip two views
let zip = tree.zip(&other_tree);
let (a, b) = zip.unzip();
Filter entries
let filter = tree.filter(|key, value| false);
let filter = tree.filter_map(|key, value| Some(value));
Reduce inserts
let reducer = tree.reducer(|value, add| value.unwrap_or(0) + add);
Filter and reduce inserts
let reducer = tree.filter_reducer(|value, add| value.map(|v| v + add));
Parse inserts
let inserter = tree.inserter(|insert| insert);
Filter and parse inserts
let inserter = tree.filter_inserter(|insert| Some(insert));
Pipe changes to another tree
tree.pipe(&other_tree);
Note that transform and index will also change the value type to a vector, because overwrites can happen. To further operate a transform or index, you must store or load them, as they require a key map.
Storing
You can store a view on the database through the Store trait
use husky::Store;
let stored = tree.store("tree name").unwrap();
Or load it in memory through the Load trait
use husky::Load;
let loaded = tree.load().unwrap();
Once you load or store a tree its results will be cached, and it will spawn new threads on each operation to propagate events from the original tree.
Listening
The Watch trait provides you with access to a BusReader that listens to events in a view.
use husky::Watch.
let reader = tree.watch();
A function to get the original tree's database.
let db = tree.db();
And methods to synchronize changes.
let sync = tree.sync();
assert_eq!(sync.incoming(), 0);
assert_eq!(sync.is_sync(), true);
sync.wait();
tree.wait();
Dependencies
~4–9.5MB
~106K SLoC