pub struct Db { /* private fields */ }Expand description
The sled embedded database!
Implementations§
Source§impl Db
impl Db
Sourcepub fn open<P>(path: P) -> Result<Db, Error>
pub fn open<P>(path: P) -> Result<Db, Error>
Load existing or create a new Db with a default configuration.
§Examples
use sled::Db;
let t = Db::open("my_db").unwrap();Sourcepub fn open_tree<V>(&self, name: V) -> Result<Tree, Error>
pub fn open_tree<V>(&self, name: V) -> Result<Tree, Error>
Open or create a new disk-backed Tree with its own keyspace,
accessible from the Db via the provided identifier.
Sourcepub fn tree_names(&self) -> Vec<Vec<u8>>
pub fn tree_names(&self) -> Vec<Vec<u8>>
Returns the trees names saved in this Db.
Sourcepub fn was_recovered(&self) -> bool
pub fn was_recovered(&self) -> bool
Returns true if the database was
recovered from a previous process.
Note that database state is only
guaranteed to be present up to the
last call to flush! Otherwise state
is synced to disk periodically if the
sync_every_ms configuration option
is set to Some(number_of_ms_between_syncs)
or if the IO buffer gets filled to
capacity before being rotated.
Sourcepub fn generate_id(&self) -> Result<u64, Error>
pub fn generate_id(&self) -> Result<u64, Error>
Generate a monotonic ID. Not guaranteed to be
contiguous. Written to disk every idgen_persist_interval
operations, followed by a blocking flush. During recovery, we
take the last recovered generated ID and add 2x
the idgen_persist_interval to it. While persisting, if the
previous persisted counter wasn’t synced to disk yet, we will do
a blocking flush to fsync the latest counter, ensuring
that we will never give out the same counter twice.
Sourcepub fn export(
&self,
) -> Vec<(Vec<u8>, Vec<u8>, impl Iterator<Item = Vec<Vec<u8>>>)>
pub fn export( &self, ) -> Vec<(Vec<u8>, Vec<u8>, impl Iterator<Item = Vec<Vec<u8>>>)>
A database export method for all collections in the Db,
for use in sled version upgrades. Can be used in combination
with the import method below on a database running a later
version.
§Panics
Panics if any IO problems occur while trying to perform the export.
Methods from Deref<Target = Tree>§
Sourcepub fn insert<K, V>(&self, key: K, value: V) -> Result<Option<IVec>, Error>
pub fn insert<K, V>(&self, key: K, value: V) -> Result<Option<IVec>, Error>
Insert a key to a new value, returning the last value if it was set.
§Examples
use sled::{Config, IVec};
let config = Config::new().temporary(true);
let t = config.open().unwrap();
assert_eq!(t.insert(&[1, 2, 3], vec![0]), Ok(None));
assert_eq!(t.insert(&[1, 2, 3], vec![1]), Ok(Some(IVec::from(&[0]))));Sourcepub fn transaction<F, A, E>(&self, f: F) -> Result<A, TransactionError<E>>
pub fn transaction<F, A, E>(&self, f: F) -> Result<A, TransactionError<E>>
Perform a multi-key serializable transaction.
§Examples
let config = Config::new().temporary(true);
let db = config.open().unwrap();
// Use write-only transactions as a writebatch:
db.transaction(|db| {
db.insert(b"k1", b"cats")?;
db.insert(b"k2", b"dogs")?;
Ok(())
})?;
// Atomically swap two items:
db.transaction(|db| {
let v1_option = db.remove(b"k1")?;
let v1 = v1_option.unwrap();
let v2_option = db.remove(b"k2")?;
let v2 = v2_option.unwrap();
db.insert(b"k1", v2)?;
db.insert(b"k2", v1)?;
Ok(())
})?;
assert_eq!(&db.get(b"k1")?.unwrap(), b"dogs");
assert_eq!(&db.get(b"k2")?.unwrap(), b"cats");A transaction may return information from an intentionally-cancelled transaction by using the abort function inside the closure in combination with the try operator.
use sled::{TransactionError, TransactionResult, Config, abort};
#[derive(Debug, PartialEq)]
struct MyBullshitError;
fn main() -> TransactionResult<(), MyBullshitError> {
let config = Config::new().temporary(true);
let db = config.open().unwrap();
// Use write-only transactions as a writebatch:
let res = db.transaction(|db| {
db.insert(b"k1", b"cats")?;
db.insert(b"k2", b"dogs")?;
// aborting will cause all writes to roll-back.
if true {
abort(MyBullshitError)?;
}
Ok(42)
}).unwrap_err();
assert_eq!(res, TransactionError::Abort(MyBullshitError));
assert_eq!(db.get(b"k1")?, None);
assert_eq!(db.get(b"k2")?, None);
Ok(())
}Transactions also work on tuples of Trees,
preserving serializable ACID semantics!
In this example, we treat two trees like a
work queue, atomically apply updates to
data and move them from the unprocessed Tree
to the processed Tree.
use sled::{Config, Transactional};
let config = Config::new().temporary(true);
let db = config.open().unwrap();
let unprocessed = db.open_tree(b"unprocessed items").unwrap();
let processed = db.open_tree(b"processed items").unwrap();
// An update somehow gets into the tree, which we
// later trigger the atomic processing of.
unprocessed.insert(b"k3", b"ligers").unwrap();
// Atomically process the new item and move it
// between `Tree`s.
(&unprocessed, &processed)
.transaction(|(unprocessed, processed)| {
let unprocessed_item = unprocessed.remove(b"k3")?.unwrap();
let mut processed_item = b"yappin' ".to_vec();
processed_item.extend_from_slice(&unprocessed_item);
processed.insert(b"k3", processed_item)?;
Ok(())
})
.unwrap();
assert_eq!(unprocessed.get(b"k3").unwrap(), None);
assert_eq!(&processed.get(b"k3").unwrap().unwrap(), b"yappin' ligers");Sourcepub fn apply_batch(&self, batch: Batch) -> Result<(), Error>
pub fn apply_batch(&self, batch: Batch) -> Result<(), Error>
Create a new batched update that can be atomically applied.
It is possible to apply a Batch in a transaction
as well, which is the way you can apply a Batch
to multiple Trees atomically.
§Examples
use sled::{Batch, Db};
let db = Db::open("batch_db").unwrap();
db.insert("key_0", "val_0").unwrap();
let mut batch = Batch::default();
batch.insert("key_a", "val_a");
batch.insert("key_b", "val_b");
batch.insert("key_c", "val_c");
batch.remove("key_0");
db.apply_batch(batch).unwrap();
// key_0 no longer exists, and key_a, key_b, and key_c
// now do exist.Sourcepub fn get<K>(&self, key: K) -> Result<Option<IVec>, Error>
pub fn get<K>(&self, key: K) -> Result<Option<IVec>, Error>
Retrieve a value from the Tree if it exists.
§Examples
use sled::{Config, IVec};
let config = Config::new().temporary(true);
let t = config.open().unwrap();
t.insert(&[0], vec![0]).unwrap();
assert_eq!(t.get(&[0]), Ok(Some(IVec::from(vec![0]))));
assert_eq!(t.get(&[1]), Ok(None));Sourcepub fn remove<K>(&self, key: K) -> Result<Option<IVec>, Error>
pub fn remove<K>(&self, key: K) -> Result<Option<IVec>, Error>
Delete a value, returning the old value if it existed.
§Examples
let config = sled::Config::new().temporary(true);
let t = config.open().unwrap();
t.insert(&[1], vec![1]);
assert_eq!(t.remove(&[1]), Ok(Some(sled::IVec::from(vec![1]))));
assert_eq!(t.remove(&[1]), Ok(None));Sourcepub fn compare_and_swap<K, OV, NV>(
&self,
key: K,
old: Option<OV>,
new: Option<NV>,
) -> Result<Result<(), CompareAndSwapError>, Error>
pub fn compare_and_swap<K, OV, NV>( &self, key: K, old: Option<OV>, new: Option<NV>, ) -> Result<Result<(), CompareAndSwapError>, Error>
Compare and swap. Capable of unique creation, conditional modification,
or deletion. If old is None, this will only set the value if it
doesn’t exist yet. If new is None, will delete the value if old is
correct. If both old and new are Some, will modify the value if
old is correct.
It returns Ok(Ok(())) if operation finishes successfully.
If it fails it returns:
- Ok(Err(CompareAndSwapError(current, proposed))) if operation
failed to setup a new value. CompareAndSwapError contains
current and proposed values.
- Err(Error::Unsupported) if the database is opened in read-only
mode.
§Examples
let config = sled::Config::new().temporary(true);
let t = config.open().unwrap();
// unique creation
assert_eq!(
t.compare_and_swap(&[1], None as Option<&[u8]>, Some(&[10])),
Ok(Ok(()))
);
// conditional modification
assert_eq!(
t.compare_and_swap(&[1], Some(&[10]), Some(&[20])),
Ok(Ok(()))
);
// failed conditional modification -- the current value is returned in
// the error variant
let operation = t.compare_and_swap(&[1], Some(&[30]), Some(&[40]));
assert!(operation.is_ok()); // the operation succeeded
let modification = operation.unwrap();
assert!(modification.is_err());
let actual_value = modification.unwrap_err();
assert_eq!(actual_value.current.map(|ivec| ivec.to_vec()), Some(vec![20]));
// conditional deletion
assert_eq!(
t.compare_and_swap(&[1], Some(&[20]), None as Option<&[u8]>),
Ok(Ok(()))
);
assert_eq!(t.get(&[1]), Ok(None));Sourcepub fn update_and_fetch<K, V, F>(
&self,
key: K,
f: F,
) -> Result<Option<IVec>, Error>
pub fn update_and_fetch<K, V, F>( &self, key: K, f: F, ) -> Result<Option<IVec>, Error>
Fetch the value, apply a function to it and return the result.
§Note
This may call the function multiple times if the value has been changed from other threads in the meantime.
§Examples
use sled::{Config, Error, IVec};
use std::convert::TryInto;
let config = Config::new().temporary(true);
let tree = config.open().unwrap();
fn u64_to_ivec(number: u64) -> IVec {
IVec::from(number.to_be_bytes().to_vec())
}
let zero = u64_to_ivec(0);
let one = u64_to_ivec(1);
let two = u64_to_ivec(2);
let three = u64_to_ivec(3);
fn increment(old: Option<&[u8]>) -> Option<Vec<u8>> {
let number = match old {
Some(bytes) => {
let array: [u8; 8] = bytes.try_into().unwrap();
let number = u64::from_be_bytes(array);
number + 1
}
None => 0,
};
Some(number.to_be_bytes().to_vec())
}
assert_eq!(tree.update_and_fetch("counter", increment), Ok(Some(zero)));
assert_eq!(tree.update_and_fetch("counter", increment), Ok(Some(one)));
assert_eq!(tree.update_and_fetch("counter", increment), Ok(Some(two)));
assert_eq!(tree.update_and_fetch("counter", increment), Ok(Some(three)));Sourcepub fn fetch_and_update<K, V, F>(
&self,
key: K,
f: F,
) -> Result<Option<IVec>, Error>
pub fn fetch_and_update<K, V, F>( &self, key: K, f: F, ) -> Result<Option<IVec>, Error>
Fetch the value, apply a function to it and return the previous value.
§Note
This may call the function multiple times if the value has been changed from other threads in the meantime.
§Examples
use sled::{Config, Error, IVec};
use std::convert::TryInto;
let config = Config::new().temporary(true);
let tree = config.open().unwrap();
fn u64_to_ivec(number: u64) -> IVec {
IVec::from(number.to_be_bytes().to_vec())
}
let zero = u64_to_ivec(0);
let one = u64_to_ivec(1);
let two = u64_to_ivec(2);
fn increment(old: Option<&[u8]>) -> Option<Vec<u8>> {
let number = match old {
Some(bytes) => {
let array: [u8; 8] = bytes.try_into().unwrap();
let number = u64::from_be_bytes(array);
number + 1
}
None => 0,
};
Some(number.to_be_bytes().to_vec())
}
assert_eq!(tree.fetch_and_update("counter", increment), Ok(None));
assert_eq!(tree.fetch_and_update("counter", increment), Ok(Some(zero)));
assert_eq!(tree.fetch_and_update("counter", increment), Ok(Some(one)));
assert_eq!(tree.fetch_and_update("counter", increment), Ok(Some(two)));Sourcepub fn watch_prefix<P>(&self, prefix: P) -> Subscriber
pub fn watch_prefix<P>(&self, prefix: P) -> Subscriber
Subscribe to Events that happen to keys that have
the specified prefix. Events for particular keys are
guaranteed to be witnessed in the same order by all
threads, but threads may witness different interleavings
of Events across different keys. If subscribers don’t
keep up with new writes, they will cause new writes
to block. There is a buffer of 1024 items per
Subscriber. This can be used to build reactive
and replicated systems.
§Examples
use sled::{Config, Event};
let config = Config::new().temporary(true);
let tree = config.open().unwrap();
// watch all events by subscribing to the empty prefix
let mut events = tree.watch_prefix(vec![]);
let tree_2 = tree.clone();
let thread = std::thread::spawn(move || {
tree.insert(vec![0], vec![1]).unwrap();
});
// events is a blocking `Iterator` over `Event`s
for event in events.take(1) {
match event {
Event::Insert(key, value) => assert_eq!(key.as_ref(), &[0]),
Event::Remove(key) => {}
}
}
thread.join().unwrap();Sourcepub fn flush(&self) -> Result<usize, Error>
pub fn flush(&self) -> Result<usize, Error>
Synchronously flushes all dirty IO buffers and calls fsync. If this succeeds, it is guaranteed that all previous writes will be recovered if the system crashes. Returns the number of bytes flushed during this call.
Flushing can take quite a lot of time, and you should measure the performance impact of using it on realistic sustained workloads running on realistic hardware.
Sourcepub fn flush_async(&self) -> impl Future<Output = Result<usize, Error>>
pub fn flush_async(&self) -> impl Future<Output = Result<usize, Error>>
Asynchronously flushes all dirty IO buffers and calls fsync. If this succeeds, it is guaranteed that all previous writes will be recovered if the system crashes. Returns the number of bytes flushed during this call.
Flushing can take quite a lot of time, and you should measure the performance impact of using it on realistic sustained workloads running on realistic hardware.
Sourcepub fn contains_key<K>(&self, key: K) -> Result<bool, Error>
pub fn contains_key<K>(&self, key: K) -> Result<bool, Error>
Returns true if the Tree contains a value for
the specified key.
§Examples
let config = sled::Config::new().temporary(true);
let t = config.open().unwrap();
t.insert(&[0], vec![0]).unwrap();
assert!(t.contains_key(&[0]).unwrap());
assert!(!t.contains_key(&[1]).unwrap());Sourcepub fn get_lt<K>(&self, key: K) -> Result<Option<(IVec, IVec)>, Error>
pub fn get_lt<K>(&self, key: K) -> Result<Option<(IVec, IVec)>, Error>
Retrieve the key and value before the provided key, if one exists.
§Examples
use sled::{Config, IVec};
let config = Config::new().temporary(true);
let tree = config.open().unwrap();
for i in 0..10 {
tree.insert(&[i], vec![i])
.expect("should write successfully");
}
assert_eq!(tree.get_lt(&[]), Ok(None));
assert_eq!(tree.get_lt(&[0]), Ok(None));
assert_eq!(
tree.get_lt(&[1]),
Ok(Some((IVec::from(&[0]), IVec::from(&[0]))))
);
assert_eq!(
tree.get_lt(&[9]),
Ok(Some((IVec::from(&[8]), IVec::from(&[8]))))
);
assert_eq!(
tree.get_lt(&[10]),
Ok(Some((IVec::from(&[9]), IVec::from(&[9]))))
);
assert_eq!(
tree.get_lt(&[255]),
Ok(Some((IVec::from(&[9]), IVec::from(&[9]))))
);Sourcepub fn get_gt<K>(&self, key: K) -> Result<Option<(IVec, IVec)>, Error>
pub fn get_gt<K>(&self, key: K) -> Result<Option<(IVec, IVec)>, Error>
Retrieve the next key and value from the Tree after the
provided key.
§Note
The order follows the Ord implementation for Vec<u8>:
[] < [0] < [255] < [255, 0] < [255, 255] ...
To retain the ordering of numerical types use big endian reprensentation
§Examples
use sled::{Config, IVec};
let config = Config::new().temporary(true);
let tree = config.open().unwrap();
for i in 0..10 {
tree.insert(&[i], vec![i])
.expect("should write successfully");
}
assert_eq!(
tree.get_gt(&[]),
Ok(Some((IVec::from(&[0]), IVec::from(&[0]))))
);
assert_eq!(
tree.get_gt(&[0]),
Ok(Some((IVec::from(&[1]), IVec::from(&[1]))))
);
assert_eq!(
tree.get_gt(&[1]),
Ok(Some((IVec::from(&[2]), IVec::from(&[2]))))
);
assert_eq!(
tree.get_gt(&[8]),
Ok(Some((IVec::from(&[9]), IVec::from(&[9]))))
);
assert_eq!(tree.get_gt(&[9]), Ok(None));
tree.insert(500u16.to_be_bytes(), vec![10]);
assert_eq!(
tree.get_gt(&499u16.to_be_bytes()),
Ok(Some((IVec::from(&500u16.to_be_bytes()), IVec::from(&[10]))))
);Sourcepub fn merge<K, V>(&self, key: K, value: V) -> Result<Option<IVec>, Error>
pub fn merge<K, V>(&self, key: K, value: V) -> Result<Option<IVec>, Error>
Merge state directly into a given key’s value using the configured merge operator. This allows state to be written into a value directly, without any read-modify-write steps. Merge operators can be used to implement arbitrary data structures.
§Panics
Calling merge will panic if no merge operator has been
configured.
§Examples
use sled::{Config, IVec};
fn concatenate_merge(
_key: &[u8], // the key being merged
old_value: Option<&[u8]>, // the previous value, if one existed
merged_bytes: &[u8] // the new bytes being merged in
) -> Option<Vec<u8>> { // set the new value, return None to delete
let mut ret = old_value
.map(|ov| ov.to_vec())
.unwrap_or_else(|| vec![]);
ret.extend_from_slice(merged_bytes);
Some(ret)
}
let config = Config::new()
.temporary(true);
let tree = config.open().unwrap();
tree.set_merge_operator(concatenate_merge);
let k = b"k1";
tree.insert(k, vec![0]);
tree.merge(k, vec![1]);
tree.merge(k, vec![2]);
assert_eq!(tree.get(k), Ok(Some(IVec::from(vec![0, 1, 2]))));
// Replace previously merged data. The merge function will not be called.
tree.insert(k, vec![3]);
assert_eq!(tree.get(k), Ok(Some(IVec::from(vec![3]))));
// Merges on non-present values will cause the merge function to be called
// with `old_value == None`. If the merge function returns something (which it
// does, in this case) a new value will be inserted.
tree.remove(k);
tree.merge(k, vec![4]);
assert_eq!(tree.get(k), Ok(Some(IVec::from(vec![4]))));Sourcepub fn set_merge_operator(
&self,
merge_operator: fn(&[u8], Option<&[u8]>, &[u8]) -> Option<Vec<u8>>,
)
pub fn set_merge_operator( &self, merge_operator: fn(&[u8], Option<&[u8]>, &[u8]) -> Option<Vec<u8>>, )
Sets a merge operator for use with the merge function.
Merge state directly into a given key’s value using the configured merge operator. This allows state to be written into a value directly, without any read-modify-write steps. Merge operators can be used to implement arbitrary data structures.
§Panics
Calling merge will panic if no merge operator has been
configured.
§Examples
use sled::{Config, IVec};
fn concatenate_merge(
_key: &[u8], // the key being merged
old_value: Option<&[u8]>, // the previous value, if one existed
merged_bytes: &[u8] // the new bytes being merged in
) -> Option<Vec<u8>> { // set the new value, return None to delete
let mut ret = old_value
.map(|ov| ov.to_vec())
.unwrap_or_else(|| vec![]);
ret.extend_from_slice(merged_bytes);
Some(ret)
}
let config = Config::new()
.temporary(true);
let tree = config.open().unwrap();
tree.set_merge_operator(concatenate_merge);
let k = b"k1";
tree.insert(k, vec![0]);
tree.merge(k, vec![1]);
tree.merge(k, vec![2]);
assert_eq!(tree.get(k), Ok(Some(IVec::from(vec![0, 1, 2]))));
// Replace previously merged data. The merge function will not be called.
tree.insert(k, vec![3]);
assert_eq!(tree.get(k), Ok(Some(IVec::from(vec![3]))));
// Merges on non-present values will cause the merge function to be called
// with `old_value == None`. If the merge function returns something (which it
// does, in this case) a new value will be inserted.
tree.remove(k);
tree.merge(k, vec![4]);
assert_eq!(tree.get(k), Ok(Some(IVec::from(vec![4]))));Sourcepub fn iter(&self) -> Iter
pub fn iter(&self) -> Iter
Create a double-ended iterator over the tuples of keys and values in this tree.
§Examples
use sled::{Config, IVec};
let config = Config::new().temporary(true);
let t = config.open().unwrap();
t.insert(&[1], vec![10]);
t.insert(&[2], vec![20]);
t.insert(&[3], vec![30]);
let mut iter = t.iter();
assert_eq!(
iter.next().unwrap(),
Ok((IVec::from(&[1]), IVec::from(&[10])))
);
assert_eq!(
iter.next().unwrap(),
Ok((IVec::from(&[2]), IVec::from(&[20])))
);
assert_eq!(
iter.next().unwrap(),
Ok((IVec::from(&[3]), IVec::from(&[30])))
);
assert_eq!(iter.next(), None);Sourcepub fn range<K, R>(&self, range: R) -> Iter
pub fn range<K, R>(&self, range: R) -> Iter
Create a double-ended iterator over tuples of keys and values, where the keys fall within the specified range.
§Examples
use sled::{Config, IVec};
let config = Config::new().temporary(true);
let t = config.open().unwrap();
t.insert(&[0], vec![0]).unwrap();
t.insert(&[1], vec![10]).unwrap();
t.insert(&[2], vec![20]).unwrap();
t.insert(&[3], vec![30]).unwrap();
t.insert(&[4], vec![40]).unwrap();
t.insert(&[5], vec![50]).unwrap();
let start: &[u8] = &[2];
let end: &[u8] = &[4];
let mut r = t.range(start..end);
assert_eq!(r.next().unwrap(), Ok((IVec::from(&[2]), IVec::from(&[20]))));
assert_eq!(r.next().unwrap(), Ok((IVec::from(&[3]), IVec::from(&[30]))));
assert_eq!(r.next(), None);
let mut r = t.range(start..end).rev();
assert_eq!(r.next().unwrap(), Ok((IVec::from(&[3]), IVec::from(&[30]))));
assert_eq!(r.next().unwrap(), Ok((IVec::from(&[2]), IVec::from(&[20]))));
assert_eq!(r.next(), None);Sourcepub fn scan_prefix<P>(&self, prefix: P) -> Iter
pub fn scan_prefix<P>(&self, prefix: P) -> Iter
Create an iterator over tuples of keys and values, where the all the keys starts with the given prefix.
§Examples
use sled::{Config, IVec};
let config = Config::new().temporary(true);
let t = config.open().unwrap();
t.insert(&[0, 0, 0], vec![0, 0, 0]).unwrap();
t.insert(&[0, 0, 1], vec![0, 0, 1]).unwrap();
t.insert(&[0, 0, 2], vec![0, 0, 2]).unwrap();
t.insert(&[0, 0, 3], vec![0, 0, 3]).unwrap();
t.insert(&[0, 1, 0], vec![0, 1, 0]).unwrap();
t.insert(&[0, 1, 1], vec![0, 1, 1]).unwrap();
let prefix: &[u8] = &[0, 0];
let mut r = t.scan_prefix(prefix);
assert_eq!(
r.next(),
Some(Ok((IVec::from(&[0, 0, 0]), IVec::from(&[0, 0, 0]))))
);
assert_eq!(
r.next(),
Some(Ok((IVec::from(&[0, 0, 1]), IVec::from(&[0, 0, 1]))))
);
assert_eq!(
r.next(),
Some(Ok((IVec::from(&[0, 0, 2]), IVec::from(&[0, 0, 2]))))
);
assert_eq!(
r.next(),
Some(Ok((IVec::from(&[0, 0, 3]), IVec::from(&[0, 0, 3]))))
);
assert_eq!(r.next(), None);Sourcepub fn pop_max(&self) -> Result<Option<(IVec, IVec)>, Error>
pub fn pop_max(&self) -> Result<Option<(IVec, IVec)>, Error>
Atomically removes the maximum item in the Tree instance.
§Examples
use sled::{Config, IVec};
let config = Config::new().temporary(true);
let t = config.open().unwrap();
t.insert(&[0], vec![0]).unwrap();
t.insert(&[1], vec![10]).unwrap();
t.insert(&[2], vec![20]).unwrap();
t.insert(&[3], vec![30]).unwrap();
t.insert(&[4], vec![40]).unwrap();
t.insert(&[5], vec![50]).unwrap();
assert_eq!(&t.pop_max().unwrap().unwrap().0, &[5]);
assert_eq!(&t.pop_max().unwrap().unwrap().0, &[4]);
assert_eq!(&t.pop_max().unwrap().unwrap().0, &[3]);
assert_eq!(&t.pop_max().unwrap().unwrap().0, &[2]);
assert_eq!(&t.pop_max().unwrap().unwrap().0, &[1]);
assert_eq!(&t.pop_max().unwrap().unwrap().0, &[0]);
assert_eq!(t.pop_max().unwrap(), None);Sourcepub fn pop_min(&self) -> Result<Option<(IVec, IVec)>, Error>
pub fn pop_min(&self) -> Result<Option<(IVec, IVec)>, Error>
Atomically removes the minimum item in the Tree instance.
§Examples
use sled::{Config, IVec};
let config = Config::new().temporary(true);
let t = config.open().unwrap();
t.insert(&[0], vec![0]).unwrap();
t.insert(&[1], vec![10]).unwrap();
t.insert(&[2], vec![20]).unwrap();
t.insert(&[3], vec![30]).unwrap();
t.insert(&[4], vec![40]).unwrap();
t.insert(&[5], vec![50]).unwrap();
assert_eq!(&t.pop_min().unwrap().unwrap().0, &[0]);
assert_eq!(&t.pop_min().unwrap().unwrap().0, &[1]);
assert_eq!(&t.pop_min().unwrap().unwrap().0, &[2]);
assert_eq!(&t.pop_min().unwrap().unwrap().0, &[3]);
assert_eq!(&t.pop_min().unwrap().unwrap().0, &[4]);
assert_eq!(&t.pop_min().unwrap().unwrap().0, &[5]);
assert_eq!(t.pop_min().unwrap(), None);Sourcepub fn len(&self) -> usize
pub fn len(&self) -> usize
Returns the number of elements in this tree.
Beware: performs a full O(n) scan under the hood.
§Examples
let config = sled::Config::new().temporary(true);
let t = config.open().unwrap();
t.insert(b"a", vec![0]);
t.insert(b"b", vec![1]);
assert_eq!(t.len(), 2);