Crates.io | husky |
lib.rs | husky |
version | 0.3.0 |
source | src |
created_at | 2022-05-13 14:45:00.414625 |
updated_at | 2022-05-25 16:45:32.608183 |
description | Library for creating databases like iterators |
homepage | |
repository | |
max_upload_size | |
id | 585920 |
size | 149,245 |
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.
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 with
let db = husky::open("db_name").unwrap();
or
let db = husky::open_temp().unwrap();
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();
Through the View trait you can query entries in the tree.
use husky::View;
assert_eq!(tree.is_empty(), Some(false));
assert_eq!(tree.contains_key(1), Ok(true));
assert_eq!(tree.contains_key(2), Ok(true));
assert_eq!(tree.get(1), Ok(Some("first value")));
assert_eq!(tree.get(2), Ok(Some("last value")));
assert_eq!(tree.get_lt(2), Ok(Some("first value"));
assert_eq!(tree.get_gt(1), Ok(Some("last value"));
let mut range = tree.range(..).unwrap();
assert_eq!(range.next(), Ok(Some((1, "first value"))));
assert_eq!(range.next(), Ok(Some((2, "last value"))));
let mut iter = tree.iter();
assert_eq!(iter.next(), Ok(Some((1, "first value"))));
assert_eq!(iter.next(), Ok(Some((2, "last value"))));
assert_eq!(tree.first(), Ok(Some((1, "first value"))));
assert_eq!(tree.last() , Ok(Some((2, "last value"))));
Through the Change trait you can manipulate the entries in the tree
use husky::Change;
let previous = tree.insert("key", "value").unwrap();
let previous = tree.remove("key").unwrap();
tree.clear().unwrap();
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()
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;
let map = tree.map(|key, value| "new_value");
let transform = tree.map(|key, value| vec![
("first key", "first value"),
("second key", "second value")
]);
let index = tree.map(|key, value| vec![
"first key",
"second key"
]);
let chain = tree.chain(&other_tree);
let zip = tree.zip(&other_tree);
let (a, b) = zip.unzip();
let filter = tree.filter(|key, value| false);
let filter = tree.filter_map(|key, value| Some(value));
let reducer = tree.reducer(|value, add| value.unwrap_or(0) + add);
let reducer = tree.filter_reducer(|value, add| value.map(|v| v + add));
let inserter = tree.inserter(|insert| insert);
let inserter = tree.filter_inserter(|insert| Some(insert));
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.
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.
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();