pub struct Db { /* private fields */ }Implementations§
Source§impl Db
impl Db
Sourcepub async fn create_checkpoint(
&self,
scope: CheckpointScope,
options: &CheckpointOptions,
) -> Result<CheckpointCreateResult, Error>
pub async fn create_checkpoint( &self, scope: CheckpointScope, options: &CheckpointOptions, ) -> Result<CheckpointCreateResult, Error>
Creates a checkpoint of an opened db using the provided options. Returns the ID of the created checkpoint and the id of the referenced manifest.
Source§impl Db
impl Db
Sourcepub async fn open<P: Into<Path>>(
path: P,
object_store: Arc<dyn ObjectStore>,
) -> Result<Self, Error>
pub async fn open<P: Into<Path>>( path: P, object_store: Arc<dyn ObjectStore>, ) -> Result<Self, Error>
Open a new database with default options.
§Arguments
path: the path to the databaseobject_store: the object store to use for the database
§Returns
Db: the database
§Errors
Error: if there was an error opening the database
§Examples
use slatedb::{Db, Error};
use slatedb::object_store::memory::InMemory;
use std::sync::Arc;
#[tokio::main]
async fn main() -> Result<(), Error> {
let object_store = Arc::new(InMemory::new());
let db = Db::open("test_db", object_store).await?;
Ok(())
}Sourcepub fn builder<P: Into<Path>>(
path: P,
object_store: Arc<dyn ObjectStore>,
) -> DbBuilder<P>
pub fn builder<P: Into<Path>>( path: P, object_store: Arc<dyn ObjectStore>, ) -> DbBuilder<P>
Creates a new builder for a database at the given path.
§Arguments
path: the path to the databaseobject_store: the object store to use for the database
§Returns
DbBuilder: the builder to initialize the database
§Examples
use slatedb::{Db, Error};
use slatedb::object_store::memory::InMemory;
use std::sync::Arc;
#[tokio::main]
async fn main() -> Result<(), Error> {
let object_store = Arc::new(InMemory::new());
let db = Db::builder("/tmp/test_db", object_store)
.build()
.await?;
Ok(())
}Sourcepub async fn close(&self) -> Result<(), Error>
pub async fn close(&self) -> Result<(), Error>
Close the database.
§Returns
Result<(), Error>: if there was an error closing the database
§Examples
use slatedb::{Db, Error};
use slatedb::object_store::{ObjectStore, memory::InMemory};
use std::sync::Arc;
#[tokio::main]
async fn main() -> Result<(), Error> {
let object_store: Arc<dyn ObjectStore> = Arc::new(InMemory::new());
let db = Db::open("test_db", object_store).await?;
db.close().await?;
Ok(())
}Sourcepub async fn snapshot(&self) -> Result<Arc<DbSnapshot>, Error>
pub async fn snapshot(&self) -> Result<Arc<DbSnapshot>, Error>
Create a snapshot of the database.
§Returns
Result<Arc<DbSnapshot>, Error>: the snapshot of the database, it represents a consistent view of the database at the time of the snapshot.
§Examples
use slatedb::{Db, Error};
use slatedb::object_store::{ObjectStore, memory::InMemory};
use std::sync::Arc;
use bytes::Bytes;
#[tokio::main]
async fn main() -> Result<(), Error> {
let object_store = Arc::new(InMemory::new());
let db = Db::open("test_db", object_store).await?;
// Write some data and create a snapshot
db.put(b"key1", b"value1").await?;
let snapshot = db.snapshot().await?;
// Snapshot provides read-only access to database state
let value = snapshot.get(b"key1").await?;
assert_eq!(value, Some(Bytes::from(b"value1".as_ref())));
// Write more data to original database
db.put(b"key2", b"value2").await?;
// Snapshot still sees old state, original db sees new data
assert_eq!(snapshot.get(b"key2").await?, None);
assert_eq!(db.get(b"key2").await?, Some(Bytes::from(b"value2".as_ref())));
Ok(())
}Sourcepub async fn get<K: AsRef<[u8]> + Send>(
&self,
key: K,
) -> Result<Option<Bytes>, Error>
pub async fn get<K: AsRef<[u8]> + Send>( &self, key: K, ) -> Result<Option<Bytes>, Error>
Get a value from the database with default read options.
The Bytes object returned contains a slice of an entire
4 KiB block. The block will be held in memory as long as the
caller holds a reference to the Bytes object. Consider
copying the data if you need to hold it for a long time.
§Arguments
key: the key to get
§Returns
Result<Option<Bytes>, Error>:Some(Bytes): the value if it existsNone: if the value does not exist
§Errors
Error: if there was an error getting the value
§Examples
use slatedb::{Db, Error};
use slatedb::object_store::{ObjectStore, memory::InMemory};
use std::sync::Arc;
#[tokio::main]
async fn main() -> Result<(), Error> {
let object_store: Arc<dyn ObjectStore> = Arc::new(InMemory::new());
let db = Db::open("test_db", object_store).await?;
db.put(b"key", b"value").await?;
assert_eq!(db.get(b"key").await?, Some("value".into()));
Ok(())
}Sourcepub async fn get_with_options<K: AsRef<[u8]> + Send>(
&self,
key: K,
options: &ReadOptions,
) -> Result<Option<Bytes>, Error>
pub async fn get_with_options<K: AsRef<[u8]> + Send>( &self, key: K, options: &ReadOptions, ) -> Result<Option<Bytes>, Error>
Get a value from the database with custom read options.
The Bytes object returned contains a slice of an entire
4 KiB block. The block will be held in memory as long as the
caller holds a reference to the Bytes object. Consider
copying the data if you need to hold it for a long time.
§Arguments
key: the key to getoptions: the read options to use (Note that [ReadOptions::read_level] has no effect for readers, which can only observe committed state).
§Returns
Result<Option<Bytes>, Error>:Some(Bytes): the value if it existsNone: if the value does not exist
§Errors
Error: if there was an error getting the value
§Examples
use slatedb::{Db, config::ReadOptions, Error};
use slatedb::object_store::{ObjectStore, memory::InMemory};
use std::sync::Arc;
#[tokio::main]
async fn main() -> Result<(), Error> {
let object_store: Arc<dyn ObjectStore> = Arc::new(InMemory::new());
let db = Db::open("test_db", object_store).await?;
db.put(b"key", b"value").await?;
assert_eq!(db.get_with_options(b"key", &ReadOptions::default()).await?, Some("value".into()));
Ok(())
}Sourcepub async fn get_key_value<K: AsRef<[u8]> + Send>(
&self,
key: K,
) -> Result<Option<KeyValue>, Error>
pub async fn get_key_value<K: AsRef<[u8]> + Send>( &self, key: K, ) -> Result<Option<KeyValue>, Error>
Get a key-value pair from the database with default read options.
Returns the key along with its value and metadata (sequence number,
creation timestamp, expiration timestamp). Unlike get,
which returns only the value bytes, this method returns a KeyValue
that includes row metadata.
§Arguments
key: the key to look up
§Returns
Ok(Some(KeyValue)): if the key exists and is not deleted/expiredOk(None): if the key does not exist or is deleted/expired
§Errors
Error: if there was an error reading from the database
Sourcepub async fn get_key_value_with_options<K: AsRef<[u8]> + Send>(
&self,
key: K,
options: &ReadOptions,
) -> Result<Option<KeyValue>, Error>
pub async fn get_key_value_with_options<K: AsRef<[u8]> + Send>( &self, key: K, options: &ReadOptions, ) -> Result<Option<KeyValue>, Error>
Get a key-value pair from the database with custom read options.
Returns the key along with its value and metadata (sequence number,
creation timestamp, expiration timestamp). Unlike
get_with_options, which returns only the
value bytes, this method returns a KeyValue that includes row
metadata.
§Arguments
key: the key to look upoptions: the read options to use
§Returns
Ok(Some(KeyValue)): if the key exists and is not deleted/expiredOk(None): if the key does not exist or is deleted/expired
§Errors
Error: if there was an error reading from the database
Sourcepub async fn scan<T>(&self, range: T) -> Result<DbIterator, Error>where
T: ByteRangeBounds + Send,
pub async fn scan<T>(&self, range: T) -> Result<DbIterator, Error>where
T: ByteRangeBounds + Send,
Scan a range of keys using the default scan options.
returns a DbIterator
§Errors
Error: if there was an error scanning the range of keys
§Returns
Result<DbIterator, Error>: An iterator with the results of the scan
§Examples
use slatedb::{Db, Error};
use slatedb::object_store::{ObjectStore, memory::InMemory};
use std::sync::Arc;
#[tokio::main]
async fn main() -> Result<(), Error> {
let object_store: Arc<dyn ObjectStore> = Arc::new(InMemory::new());
let db = Db::open("test_db", object_store).await?;
db.put(b"a", b"a_value").await?;
db.put(b"b", b"b_value").await?;
let mut iter = db.scan("a".."b").await?;
let kv = iter.next().await?.unwrap();
assert_eq!(kv.key.as_ref(), b"a");
assert_eq!(kv.value.as_ref(), b"a_value");
assert_eq!(None, iter.next().await?);
Ok(())
}Sourcepub async fn scan_with_options<T>(
&self,
range: T,
options: &ScanOptions,
) -> Result<DbIterator, Error>where
T: ByteRangeBounds + Send,
pub async fn scan_with_options<T>(
&self,
range: T,
options: &ScanOptions,
) -> Result<DbIterator, Error>where
T: ByteRangeBounds + Send,
Scan a range of keys with the provided options.
returns a DbIterator
§Errors
Error: if there was an error scanning the range of keys
§Examples
use slatedb::{Db, config::ScanOptions, config::DurabilityLevel, Error};
use slatedb::object_store::{ObjectStore, memory::InMemory};
use std::sync::Arc;
#[tokio::main]
async fn main() -> Result<(), Error> {
let object_store: Arc<dyn ObjectStore> = Arc::new(InMemory::new());
let db = Db::open("test_db", object_store).await?;
db.put(b"a", b"a_value").await?;
db.put(b"b", b"b_value").await?;
let mut iter = db.scan_with_options("a".."b", &ScanOptions {
durability_filter: DurabilityLevel::Memory,
..ScanOptions::default()
}).await?;
let kv = iter.next().await?.unwrap();
assert_eq!(kv.key.as_ref(), b"a");
assert_eq!(kv.value.as_ref(), b"a_value");
assert_eq!(None, iter.next().await?);
Ok(())
}Sourcepub async fn scan_prefix<P, T>(
&self,
prefix: P,
subrange: T,
) -> Result<DbIterator, Error>
pub async fn scan_prefix<P, T>( &self, prefix: P, subrange: T, ) -> Result<DbIterator, Error>
Scan keys that share the provided prefix, restricted to subrange,
using the default scan options.
The subrange bounds are key suffixes interpreted relative to the
prefix: a bound s selects the full key prefix ++ s. Pass .. to
scan the prefix’s entire keyspace. When a prefix extractor is
configured, prefix bloom filters are consulted to skip SSTs that
contain no matching keys.
§Arguments
prefix: the key prefix to scansubrange: the range of key suffixes (relative toprefix) to scan;..scans all keys with the prefix
§Returns
Result<DbIterator, Error>: An iterator with the results of the scan
§Examples
use slatedb::{Db, Error};
use slatedb::object_store::{ObjectStore, memory::InMemory};
use std::sync::Arc;
#[tokio::main]
async fn main() -> Result<(), Error> {
let object_store: Arc<dyn ObjectStore> = Arc::new(InMemory::new());
let db = Db::open("test_db", object_store).await?;
db.put(b"ab", b"v0").await?;
db.put(b"aba", b"v1").await?;
db.put(b"b", b"v2").await?;
let mut iter = db.scan_prefix(b"ab", ..).await?;
let kv = iter.next().await?.unwrap();
assert_eq!(kv.key.as_ref(), b"ab");
assert_eq!(kv.value.as_ref(), b"v0");
let kv = iter.next().await?.unwrap();
assert_eq!(kv.key.as_ref(), b"aba");
assert_eq!(kv.value.as_ref(), b"v1");
assert_eq!(None, iter.next().await?);
// Restrict the scan to suffixes from b"a" onward.
// Ordinary Rust range syntax works here; `as_slice()` is optional.
let mut iter = db.scan_prefix(b"ab", b"a".as_slice()..).await?;
let kv = iter.next().await?.unwrap();
assert_eq!(kv.key.as_ref(), b"aba");
assert_eq!(None, iter.next().await?);
Ok(())
}Sourcepub async fn scan_prefix_with_options<P, T>(
&self,
prefix: P,
subrange: T,
options: &ScanOptions,
) -> Result<DbIterator, Error>
pub async fn scan_prefix_with_options<P, T>( &self, prefix: P, subrange: T, options: &ScanOptions, ) -> Result<DbIterator, Error>
Scan keys that share the provided prefix, restricted to subrange,
with custom options. See Self::scan_prefix for the subrange
semantics.
§Arguments
prefix: the key prefix to scansubrange: the range of key suffixes (relative toprefix) to scan;..scans all keys with the prefixoptions: the scan options to use
§Returns
Result<DbIterator, Error>: An iterator with the results of the scan
§Examples
use slatedb::{Db, Error};
use slatedb::config::ScanOptions;
use slatedb::object_store::{ObjectStore, memory::InMemory};
use std::sync::Arc;
#[tokio::main]
async fn main() -> Result<(), Error> {
let object_store: Arc<dyn ObjectStore> = Arc::new(InMemory::new());
let db = Db::open("test_db", object_store).await?;
db.put(b"x1", b"v1").await?;
db.put(b"x2", b"v2").await?;
db.put(b"y", b"v3").await?;
let options = ScanOptions {
cache_blocks: false,
..ScanOptions::default()
};
let mut iter = db.scan_prefix_with_options(b"x", .., &options).await?;
let kv = iter.next().await?.unwrap();
assert_eq!(kv.key.as_ref(), b"x1");
assert_eq!(kv.value.as_ref(), b"v1");
let kv = iter.next().await?.unwrap();
assert_eq!(kv.key.as_ref(), b"x2");
assert_eq!(kv.value.as_ref(), b"v2");
assert_eq!(None, iter.next().await?);
Ok(())
}Sourcepub async fn scan_prefix_by_recency<P>(
&self,
prefix: P,
) -> Result<DbRecencyIterator, Error>
pub async fn scan_prefix_by_recency<P>( &self, prefix: P, ) -> Result<DbRecencyIterator, Error>
Scan keys that share prefix, walking sources newest-first.
Warning: this is a low-level, unopinionated iterator. It does
no merging, no deduping, and no interpretation of
entries across sources, unlike Self::scan_prefix. The API
makes no assumptions about what duplicates, tombstones, or merge
operands should mean; every such decision is left to the caller.
Within each source, entries are emitted in the order requested by
options.order: ascending (the default) or descending. Across
sources, the walk is always newest-first, independent of
options.order. Each source restarts its own scan at its own
first matching key for that order, so the global emit sequence is
not a single sorted key stream and the within-source key order
resets at every source boundary. The same user key can appear
multiple times, both across sources (once per source that holds
it, newest source first) and within a single source (one entry
per stored sequence number, newest seq first within the key
group): nothing collapses versions. Tombstones and merge operands
are surfaced as raw crate::types::RowEntry values. The caller
is responsible for any dedup, delete handling, or merge
resolution. Callers that need a totally ordered, fully merged
view should use Self::scan_prefix instead; use this only when
you want freshest-first results with the option to early-stop and
are willing to interpret raw entries.
Sources are walked in this order: active memtable, immutable memtables, then within the single matching segment that segment’s L0 SSTs newest-first followed by its sorted runs newest-first. Each source is fully drained before moving to the next. Sources are lazily initialized: the filter check, index load, and first data block fetch only happen when the recency walk reaches that source. A prefix read whose data lives in the active memtable therefore performs zero I/O. When the walk does have to descend to SST sources, configuring prefix bloom filters lets the scan skip non-matching SSTs without a data-block fetch, which keeps I/O proportional to how recent the data is rather than to the size of the LSM.
Multi-segment prefixes are rejected. If the prefix overlaps
more than one segment, this returns an error with
crate::ErrorKind::Invalid. The recency guarantee is only
well-defined within a single segment: walking one segment’s oldest
data before touching another segment’s newest data would violate
freshest-first ordering. Callers that need cross-segment scans
should use Self::scan_prefix instead.
§Arguments
prefix: the key prefix to scan
§Returns
Result<RecencyIterator, Error>: an iterator that yields rawRowEntryvalues newest-first. Use [RecencyIterator::next_entry] to pull the next entry, and inspectentry.valuefor thecrate::types::ValueDeletablevariant (Value,Merge, orTombstone).
§Examples
Pull entries from the freshest source under the prefix and stop.
Because sources are walked newest-first and lazily initialized, an
early-return like this only touches the source that holds the
freshest data. Note that within a source the order is set by
options.order (ascending by default), so the first yielded entry
is the smallest key in the freshest source, not necessarily the
most recently written key. Across sources the same key may appear
more than once, so callers that want only the freshest value per
key should dedupe.
use slatedb::{Db, Error};
use slatedb::object_store::{ObjectStore, memory::InMemory};
use slatedb::ValueDeletable;
use std::sync::Arc;
#[tokio::main]
async fn main() -> Result<(), Error> {
let object_store: Arc<dyn ObjectStore> = Arc::new(InMemory::new());
let db = Db::open("test_db", object_store).await?;
db.put(b"user:42", b"alice").await?;
db.put(b"user:42", b"alice2").await?;
db.put(b"user:99", b"bob").await?;
let mut iter = db.scan_prefix_by_recency(b"user:").await?;
let entry = iter.next_entry().await?.unwrap();
// All three writes live in the active memtable (the freshest
// source). With ascending within-source order, "user:42" comes
// out first because it sorts before "user:99". Both writes to
// "user:42" are stored as separate sequence-numbered entries;
// within the "user:42" key group the newest seq is yielded
// first, so the first entry carries the latest write
// ("alice2"). A second pull would yield the older "user:42"
// entry ("alice") before advancing to "user:99".
assert_eq!(entry.key.as_ref(), b"user:42");
match entry.value {
ValueDeletable::Value(v) => assert_eq!(v.as_ref(), b"alice2"),
_ => panic!("expected a regular value"),
}
Ok(())
}Sourcepub async fn scan_prefix_by_recency_with_options<P>(
&self,
prefix: P,
options: &ScanOptions,
) -> Result<DbRecencyIterator, Error>
pub async fn scan_prefix_by_recency_with_options<P>( &self, prefix: P, options: &ScanOptions, ) -> Result<DbRecencyIterator, Error>
Recency-ordered prefix scan with custom options.
Same contract as Self::scan_prefix_by_recency (raw entries
emitted newest-source-first; caller handles dedupe, tombstones, and
merge operands).
§Arguments
prefix: the key prefix to scanoptions: the scan options to use
§Returns
Result<RecencyIterator, Error>: an iterator that yields rawRowEntryvalues newest-first.
§Examples
Use cache_blocks: false to scan recent data without polluting
the block cache, and stop after pulling enough entries from the
freshest source. Combined with the recency walk’s early-stop, this
is a cheap way to ask “is there a recent entry under this prefix?”
without warming the cache for cold blocks the answer doesn’t depend
on.
use slatedb::{Db, Error};
use slatedb::config::ScanOptions;
use slatedb::object_store::{ObjectStore, memory::InMemory};
use std::sync::Arc;
#[tokio::main]
async fn main() -> Result<(), Error> {
let object_store: Arc<dyn ObjectStore> = Arc::new(InMemory::new());
let db = Db::open("test_db", object_store).await?;
db.put(b"event:001", b"a").await?;
db.put(b"event:002", b"b").await?;
let options = ScanOptions {
cache_blocks: false,
..ScanOptions::default()
};
let mut iter = db
.scan_prefix_by_recency_with_options(b"event:", &options)
.await?;
let first = iter.next_entry().await?.unwrap();
// Within-source order is ascending by default, so "event:001"
// is yielded before "event:002" even though both live in the
// same (freshest) source. Stop here: we only needed to see
// that something fresh exists under the prefix.
assert_eq!(first.key.as_ref(), b"event:001");
Ok(())
}Sourcepub async fn put<K, V>(&self, key: K, value: V) -> Result<WriteHandle, Error>
pub async fn put<K, V>(&self, key: K, value: V) -> Result<WriteHandle, Error>
Write a value into the database with default WriteOptions.
§Arguments
key: the key to writevalue: the value to write
§Errors
Error: if there was an error writing the value.
§Examples
use slatedb::{Db, Error};
use slatedb::object_store::{ObjectStore, memory::InMemory};
use std::sync::Arc;
#[tokio::main]
async fn main() -> Result<(), Error> {
let object_store: Arc<dyn ObjectStore> = Arc::new(InMemory::new());
let db = Db::open("test_db", object_store).await?;
let handle = db.put(b"key", b"value").await?;
Ok(())
}Sourcepub async fn put_with_options<K, V>(
&self,
key: K,
value: V,
put_opts: &PutOptions,
write_opts: &WriteOptions,
) -> Result<WriteHandle, Error>
pub async fn put_with_options<K, V>( &self, key: K, value: V, put_opts: &PutOptions, write_opts: &WriteOptions, ) -> Result<WriteHandle, Error>
Write a value into the database with custom PutOptions and WriteOptions.
§Arguments
key: the key to writevalue: the value to writeput_opts: the put options to usewrite_opts: the write options to use
§Errors
Error: if there was an error writing the value.
§Examples
use slatedb::{Db, config::{PutOptions, WriteOptions}, Error};
use slatedb::object_store::{ObjectStore, memory::InMemory};
use std::sync::Arc;
#[tokio::main]
async fn main() -> Result<(), Error> {
let object_store: Arc<dyn ObjectStore> = Arc::new(InMemory::new());
let db = Db::open("test_db", object_store).await?;
let handle = db.put_with_options(b"key", b"value", &PutOptions::default(), &WriteOptions::default()).await?;
Ok(())
}Sourcepub async fn put_bytes_with_options(
&self,
key: Bytes,
value: Bytes,
put_opts: &PutOptions,
write_opts: &WriteOptions,
) -> Result<WriteHandle, Error>
pub async fn put_bytes_with_options( &self, key: Bytes, value: Bytes, put_opts: &PutOptions, write_opts: &WriteOptions, ) -> Result<WriteHandle, Error>
Write a value into the database using owned Bytes with custom
PutOptions and WriteOptions. See Db::put_bytes for why this
form exists.
Sourcepub async fn delete<K: AsRef<[u8]>>(&self, key: K) -> Result<WriteHandle, Error>
pub async fn delete<K: AsRef<[u8]>>(&self, key: K) -> Result<WriteHandle, Error>
Delete a key from the database with default WriteOptions.
§Arguments
key: the key to delete
§Errors
Error: if there was an error deleting the key.
§Examples
use slatedb::{Db, Error};
use slatedb::object_store::{ObjectStore, memory::InMemory};
use std::sync::Arc;
#[tokio::main]
async fn main() -> Result<(), Error> {
let object_store: Arc<dyn ObjectStore> = Arc::new(InMemory::new());
let db = Db::open("test_db", object_store).await?;
let handle = db.delete(b"key").await?;
Ok(())
}Sourcepub async fn delete_with_options<K: AsRef<[u8]>>(
&self,
key: K,
options: &WriteOptions,
) -> Result<WriteHandle, Error>
pub async fn delete_with_options<K: AsRef<[u8]>>( &self, key: K, options: &WriteOptions, ) -> Result<WriteHandle, Error>
Delete a key from the database with custom WriteOptions.
§Arguments
key: the key to deleteoptions: the write options to use
§Errors
Error: if there was an error deleting the key.
§Examples
use slatedb::{Db, config::WriteOptions, Error};
use slatedb::object_store::{ObjectStore, memory::InMemory};
use std::sync::Arc;
#[tokio::main]
async fn main() -> Result<(), Error> {
let object_store: Arc<dyn ObjectStore> = Arc::new(InMemory::new());
let db = Db::open("test_db", object_store).await?;
let handle = db.delete_with_options(b"key", &WriteOptions::default()).await?;
Ok(())
}Sourcepub async fn merge<K, V>(&self, key: K, value: V) -> Result<WriteHandle, Error>
pub async fn merge<K, V>(&self, key: K, value: V) -> Result<WriteHandle, Error>
Merge a value into the database with default MergeOptions and WriteOptions.
Merge operations allow applications to bypass the traditional read/modify/write cycle by expressing partial updates using an associative operator. The merge operator must be configured when opening the database.
§Arguments
key: the key to merge intovalue: the merge operand to apply
§Errors
Error: if there was an error merging the value, or if no merge operator is configured.
§Examples
use slatedb::{Db, Error, MergeOperator, MergeOperatorError};
use slatedb::object_store::{ObjectStore, memory::InMemory};
use std::sync::Arc;
use bytes::Bytes;
struct StringConcatMergeOperator;
impl MergeOperator for StringConcatMergeOperator {
fn merge(&self, _key: &Bytes, existing_value: Option<Bytes>, value: Bytes) -> Result<Bytes, MergeOperatorError> {
let mut result = existing_value.unwrap_or_default().as_ref().to_vec();
result.extend_from_slice(&value);
Ok(Bytes::from(result))
}
}
#[tokio::main]
async fn main() -> Result<(), Error> {
let object_store: Arc<dyn ObjectStore> = Arc::new(InMemory::new());
let db = Db::builder("test_db", object_store)
.with_merge_operator(Arc::new(StringConcatMergeOperator))
.build()
.await?;
let handle = db.merge(b"key", b"value").await?;
Ok(())
}Sourcepub async fn merge_with_options<K, V>(
&self,
key: K,
value: V,
merge_opts: &MergeOptions,
write_opts: &WriteOptions,
) -> Result<WriteHandle, Error>
pub async fn merge_with_options<K, V>( &self, key: K, value: V, merge_opts: &MergeOptions, write_opts: &WriteOptions, ) -> Result<WriteHandle, Error>
Merge a value into the database with custom MergeOptions and WriteOptions.
Merge operations allow applications to bypass the traditional read/modify/write cycle by expressing partial updates using an associative operator. The merge operator must be configured when opening the database.
§Arguments
key: the key to merge intovalue: the merge operand to applymerge_opts: the merge options to usewrite_opts: the write options to use
§Errors
Error: if there was an error merging the value, or if no merge operator is configured.
§Examples
use slatedb::{Db, Error, MergeOperator, MergeOperatorError, config::{MergeOptions, WriteOptions}};
use slatedb::object_store::{ObjectStore, memory::InMemory};
use std::sync::Arc;
use bytes::Bytes;
struct StringConcatMergeOperator;
impl MergeOperator for StringConcatMergeOperator {
fn merge(&self, _key: &Bytes, existing_value: Option<Bytes>, value: Bytes) -> Result<Bytes, MergeOperatorError> {
let mut result = existing_value.unwrap_or_default().as_ref().to_vec();
result.extend_from_slice(&value);
Ok(Bytes::from(result))
}
}
#[tokio::main]
async fn main() -> Result<(), Error> {
let object_store: Arc<dyn ObjectStore> = Arc::new(InMemory::new());
let db = Db::builder("test_db", object_store)
.with_merge_operator(Arc::new(StringConcatMergeOperator))
.build()
.await?;
let handle = db.merge_with_options(
b"key",
b"value",
&MergeOptions::default(),
&WriteOptions::default()
).await?;
Ok(())
}Sourcepub async fn write(&self, batch: WriteBatch) -> Result<WriteHandle, Error>
pub async fn write(&self, batch: WriteBatch) -> Result<WriteHandle, Error>
Write a batch of put/delete operations atomically to the database. Batch writes block other gets and writes until the batch is written to the WAL (or memtable if WAL is disabled).
§Arguments
batch: the batch of put/delete operations to write
§Errors
Error: if there was an error writing the batch.
§Examples
use slatedb::{WriteBatch, Db, Error};
use slatedb::object_store::{ObjectStore, memory::InMemory};
use std::sync::Arc;
#[tokio::main]
async fn main() -> Result<(), Error> {
let object_store: Arc<dyn ObjectStore> = Arc::new(InMemory::new());
let db = Db::open("test_db", object_store).await?;
let mut batch = WriteBatch::new();
batch.put(b"key1", b"value1");
batch.put(b"key2", b"value2");
batch.delete(b"key1");
let handle = db.write(batch).await?;
Ok(())
}Sourcepub async fn write_with_options(
&self,
batch: WriteBatch,
options: &WriteOptions,
) -> Result<WriteHandle, Error>
pub async fn write_with_options( &self, batch: WriteBatch, options: &WriteOptions, ) -> Result<WriteHandle, Error>
Write a batch of put/delete operations atomically to the database. Batch writes block other gets and writes until the batch is written to the WAL (or memtable if WAL is disabled).
§Arguments
batch: the batch of put/delete operations to writeoptions: the write options to use
§Errors
Error: if there was an error writing the batch.
§Examples
use slatedb::{WriteBatch, Db, config::WriteOptions, Error};
use slatedb::object_store::{ObjectStore, memory::InMemory};
use std::sync::Arc;
#[tokio::main]
async fn main() -> Result<(), Error> {
let object_store: Arc<dyn ObjectStore> = Arc::new(InMemory::new());
let db = Db::open("test_db", object_store).await?;
let mut batch = WriteBatch::new();
batch.put(b"key1", b"value1");
batch.put(b"key2", b"value2");
batch.delete(b"key1");
let handle = db.write_with_options(batch, &WriteOptions::default()).await?;
Ok(())
}Sourcepub async fn flush(&self) -> Result<(), Error>
pub async fn flush(&self) -> Result<(), Error>
Flush in-memory writes to disk. This function blocks until the in-memory data has been durably written to object storage.
If WAL is enabled, this method is equivalent to:
flush_with_options(FlushOptions { flush_type: FlushType::Wal })
If WAL is disabled, this method is equivalent to:
flush_with_options(FlushOptions { flush_type: FlushType::Memtable }).
§Errors
Error: if there was an error flushing the database
§Examples
use slatedb::{Db, Error};
use slatedb::object_store::{ObjectStore, memory::InMemory};
use std::sync::Arc;
#[tokio::main]
async fn main() -> Result<(), Error> {
let object_store: Arc<dyn ObjectStore> = Arc::new(InMemory::new());
let db = Db::open("test_db", object_store).await?;
db.flush().await?;
Ok(())
}Sourcepub async fn flush_with_options(
&self,
options: FlushOptions,
) -> Result<(), Error>
pub async fn flush_with_options( &self, options: FlushOptions, ) -> Result<(), Error>
Flush in-memory writes to disk with custom options.
An error will be returned if options.flush_type is FlushType::Wal and the WAL
is disabled.
FlushType::Memtable is allowed even if WAL is enabled.
§Arguments
options: the flush options
§Returns
Result<(), crate::Error>: the result of the flush operation.
§Errors
Error: if there was an error flushing the database
§Examples
use slatedb::{Db, Error};
use slatedb::config::{FlushOptions, FlushType};
use slatedb::object_store::{ObjectStore, memory::InMemory};
use std::sync::Arc;
#[tokio::main]
async fn main() -> Result<(), Error> {
let object_store: Arc<dyn ObjectStore> = Arc::new(InMemory::new());
let db = Db::open("test_db", object_store).await?;
db.flush_with_options(FlushOptions {
flush_type: FlushType::Wal,
})
.await?;
Ok(())
}Sourcepub async fn refresh_manifest(&self) -> Result<(), Error>
pub async fn refresh_manifest(&self) -> Result<(), Error>
Refresh the manifest immediately and wait for it to complete.
The database normally refreshes its manifest on a background timer
controlled by Settings::manifest_poll_interval. This method
bypasses that timer, triggering an immediate refresh and waiting
for it to finish.
Use this when you know the manifest has changed externally and want to ensure the database has observed the update before proceeding — for example, after a compaction completes and you need to confirm that a compaction filter has been applied.
§Errors
- Returns [
Error] if the database is closed before the refresh completes.
Sourcepub async fn begin(
&self,
isolation_level: IsolationLevel,
) -> Result<DbTransaction, Error>
pub async fn begin( &self, isolation_level: IsolationLevel, ) -> Result<DbTransaction, Error>
Begin a new transaction with the specified isolation level.
§Arguments
isolation_level: the isolation level for the transaction
§Returns
Result<DbTransaction, crate::Error>: the transaction handle
§Examples
use slatedb::{Db, IsolationLevel};
use slatedb::object_store::memory::InMemory;
use std::sync::Arc;
#[tokio::main]
async fn main() -> Result<(), slatedb::Error> {
let object_store = Arc::new(InMemory::new());
let db = Db::open("test_db", object_store).await?;
let txn = db.begin(IsolationLevel::SerializableSnapshot).await?;
Ok(())
}Sourcepub fn resolve_object_store(url: &str) -> Result<Arc<dyn ObjectStore>, Error>
pub fn resolve_object_store(url: &str) -> Result<Arc<dyn ObjectStore>, Error>
Resolve an object store from a URL.
URL must not have a path component. This is an artifact of the way object_store
handles URL parsing. Paths should be provided in the various *Builder::new
methods that take path arguments, not in the URL passed to this method.
§Arguments
url: the URL to resolve with no trailing path, for examples3://my-bucket.
§Returns
Result<Arc<dyn ObjectStore>, crate::Error>: the resolved object store
§Errors
Error: if the URL is unparseable, if the URL contains a path component, or if there was an error initializing the object store.
Trait Implementations§
Source§impl DbCacheManagerOps for Db
impl DbCacheManagerOps for Db
Source§fn warm_sst<'life0, 'life1, 'async_trait>(
&'life0 self,
sst_id: SsTableId,
targets: &'life1 [CacheTarget],
) -> Pin<Box<dyn Future<Output = Result<(), Error>> + Send + 'async_trait>>where
Self: 'async_trait,
'life0: 'async_trait,
'life1: 'async_trait,
fn warm_sst<'life0, 'life1, 'async_trait>(
&'life0 self,
sst_id: SsTableId,
targets: &'life1 [CacheTarget],
) -> Pin<Box<dyn Future<Output = Result<(), Error>> + Send + 'async_trait>>where
Self: 'async_trait,
'life0: 'async_trait,
'life1: 'async_trait,
Source§impl DbMetadataOps for Db
impl DbMetadataOps for Db
Source§impl DbReadOps for Db
impl DbReadOps for Db
Source§fn get_with_options<'life0, 'life1, 'async_trait, K>(
&'life0 self,
key: K,
options: &'life1 ReadOptions,
) -> Pin<Box<dyn Future<Output = Result<Option<Bytes>, Error>> + Send + 'async_trait>>
fn get_with_options<'life0, 'life1, 'async_trait, K>( &'life0 self, key: K, options: &'life1 ReadOptions, ) -> Pin<Box<dyn Future<Output = Result<Option<Bytes>, Error>> + Send + 'async_trait>>
Source§fn get_key_value_with_options<'life0, 'life1, 'async_trait, K>(
&'life0 self,
key: K,
options: &'life1 ReadOptions,
) -> Pin<Box<dyn Future<Output = Result<Option<KeyValue>, Error>> + Send + 'async_trait>>
fn get_key_value_with_options<'life0, 'life1, 'async_trait, K>( &'life0 self, key: K, options: &'life1 ReadOptions, ) -> Pin<Box<dyn Future<Output = Result<Option<KeyValue>, Error>> + Send + 'async_trait>>
Source§fn scan_with_options<'life0, 'life1, 'async_trait, T>(
&'life0 self,
range: T,
options: &'life1 ScanOptions,
) -> Pin<Box<dyn Future<Output = Result<DbIterator, Error>> + Send + 'async_trait>>where
T: ByteRangeBounds + Send + 'async_trait,
Self: 'async_trait,
'life0: 'async_trait,
'life1: 'async_trait,
fn scan_with_options<'life0, 'life1, 'async_trait, T>(
&'life0 self,
range: T,
options: &'life1 ScanOptions,
) -> Pin<Box<dyn Future<Output = Result<DbIterator, Error>> + Send + 'async_trait>>where
T: ByteRangeBounds + Send + 'async_trait,
Self: 'async_trait,
'life0: 'async_trait,
'life1: 'async_trait,
Source§fn scan_prefix_with_options<'life0, 'life1, 'async_trait, P, T>(
&'life0 self,
prefix: P,
subrange: T,
options: &'life1 ScanOptions,
) -> Pin<Box<dyn Future<Output = Result<DbIterator, Error>> + Send + 'async_trait>>where
P: AsRef<[u8]> + Send + 'async_trait,
T: ByteRangeBounds + Send + 'async_trait,
Self: 'async_trait,
'life0: 'async_trait,
'life1: 'async_trait,
fn scan_prefix_with_options<'life0, 'life1, 'async_trait, P, T>(
&'life0 self,
prefix: P,
subrange: T,
options: &'life1 ScanOptions,
) -> Pin<Box<dyn Future<Output = Result<DbIterator, Error>> + Send + 'async_trait>>where
P: AsRef<[u8]> + Send + 'async_trait,
T: ByteRangeBounds + Send + 'async_trait,
Self: 'async_trait,
'life0: 'async_trait,
'life1: 'async_trait,
subrange,
with custom options. See Self::scan_prefix for the subrange
semantics. Read moreSource§fn get<'life0, 'async_trait, K>(
&'life0 self,
key: K,
) -> Pin<Box<dyn Future<Output = Result<Option<Bytes>, Error>> + Send + 'async_trait>>
fn get<'life0, 'async_trait, K>( &'life0 self, key: K, ) -> Pin<Box<dyn Future<Output = Result<Option<Bytes>, Error>> + Send + 'async_trait>>
Source§fn get_key_value<'life0, 'async_trait, K>(
&'life0 self,
key: K,
) -> Pin<Box<dyn Future<Output = Result<Option<KeyValue>, Error>> + Send + 'async_trait>>
fn get_key_value<'life0, 'async_trait, K>( &'life0 self, key: K, ) -> Pin<Box<dyn Future<Output = Result<Option<KeyValue>, Error>> + Send + 'async_trait>>
Source§fn scan<'life0, 'async_trait, T>(
&'life0 self,
range: T,
) -> Pin<Box<dyn Future<Output = Result<DbIterator, Error>> + Send + 'async_trait>>
fn scan<'life0, 'async_trait, T>( &'life0 self, range: T, ) -> Pin<Box<dyn Future<Output = Result<DbIterator, Error>> + Send + 'async_trait>>
Source§impl DbWriteOps for Db
impl DbWriteOps for Db
Source§type Transaction = DbTransaction
type Transaction = DbTransaction
Self::begin. Stub
implementations supply their own DbTransactionOps type, while
the real Db returns a DbTransaction.Source§fn put_with_options<'life0, 'life1, 'life2, 'async_trait, K, V>(
&'life0 self,
key: K,
value: V,
put_opts: &'life1 PutOptions,
write_opts: &'life2 WriteOptions,
) -> Pin<Box<dyn Future<Output = Result<WriteHandle, Error>> + Send + 'async_trait>>
fn put_with_options<'life0, 'life1, 'life2, 'async_trait, K, V>( &'life0 self, key: K, value: V, put_opts: &'life1 PutOptions, write_opts: &'life2 WriteOptions, ) -> Pin<Box<dyn Future<Output = Result<WriteHandle, Error>> + Send + 'async_trait>>
Source§fn delete_with_options<'life0, 'life1, 'async_trait, K>(
&'life0 self,
key: K,
options: &'life1 WriteOptions,
) -> Pin<Box<dyn Future<Output = Result<WriteHandle, Error>> + Send + 'async_trait>>
fn delete_with_options<'life0, 'life1, 'async_trait, K>( &'life0 self, key: K, options: &'life1 WriteOptions, ) -> Pin<Box<dyn Future<Output = Result<WriteHandle, Error>> + Send + 'async_trait>>
WriteOptions. Read moreSource§fn merge_with_options<'life0, 'life1, 'life2, 'async_trait, K, V>(
&'life0 self,
key: K,
value: V,
merge_opts: &'life1 MergeOptions,
write_opts: &'life2 WriteOptions,
) -> Pin<Box<dyn Future<Output = Result<WriteHandle, Error>> + Send + 'async_trait>>
fn merge_with_options<'life0, 'life1, 'life2, 'async_trait, K, V>( &'life0 self, key: K, value: V, merge_opts: &'life1 MergeOptions, write_opts: &'life2 WriteOptions, ) -> Pin<Box<dyn Future<Output = Result<WriteHandle, Error>> + Send + 'async_trait>>
Source§fn write_with_options<'life0, 'life1, 'async_trait>(
&'life0 self,
batch: WriteBatch,
options: &'life1 WriteOptions,
) -> Pin<Box<dyn Future<Output = Result<WriteHandle, Error>> + Send + 'async_trait>>where
Self: 'async_trait,
'life0: 'async_trait,
'life1: 'async_trait,
fn write_with_options<'life0, 'life1, 'async_trait>(
&'life0 self,
batch: WriteBatch,
options: &'life1 WriteOptions,
) -> Pin<Box<dyn Future<Output = Result<WriteHandle, Error>> + Send + 'async_trait>>where
Self: 'async_trait,
'life0: 'async_trait,
'life1: 'async_trait,
WriteOptions. Read moreSource§fn flush<'life0, 'async_trait>(
&'life0 self,
) -> Pin<Box<dyn Future<Output = Result<(), Error>> + Send + 'async_trait>>where
Self: 'async_trait,
'life0: 'async_trait,
fn flush<'life0, 'async_trait>(
&'life0 self,
) -> Pin<Box<dyn Future<Output = Result<(), Error>> + Send + 'async_trait>>where
Self: 'async_trait,
'life0: 'async_trait,
Source§fn flush_with_options<'life0, 'async_trait>(
&'life0 self,
options: FlushOptions,
) -> Pin<Box<dyn Future<Output = Result<(), Error>> + Send + 'async_trait>>where
Self: 'async_trait,
'life0: 'async_trait,
fn flush_with_options<'life0, 'async_trait>(
&'life0 self,
options: FlushOptions,
) -> Pin<Box<dyn Future<Output = Result<(), Error>> + Send + 'async_trait>>where
Self: 'async_trait,
'life0: 'async_trait,
Source§fn begin<'life0, 'async_trait>(
&'life0 self,
isolation_level: IsolationLevel,
) -> Pin<Box<dyn Future<Output = Result<DbTransaction, Error>> + Send + 'async_trait>>where
Self: 'async_trait,
'life0: 'async_trait,
fn begin<'life0, 'async_trait>(
&'life0 self,
isolation_level: IsolationLevel,
) -> Pin<Box<dyn Future<Output = Result<DbTransaction, Error>> + Send + 'async_trait>>where
Self: 'async_trait,
'life0: 'async_trait,
Source§fn put<'life0, 'async_trait, K, V>(
&'life0 self,
key: K,
value: V,
) -> Pin<Box<dyn Future<Output = Result<WriteHandle, Error>> + Send + 'async_trait>>
fn put<'life0, 'async_trait, K, V>( &'life0 self, key: K, value: V, ) -> Pin<Box<dyn Future<Output = Result<WriteHandle, Error>> + Send + 'async_trait>>
Source§fn delete<'life0, 'async_trait, K>(
&'life0 self,
key: K,
) -> Pin<Box<dyn Future<Output = Result<WriteHandle, Error>> + Send + 'async_trait>>
fn delete<'life0, 'async_trait, K>( &'life0 self, key: K, ) -> Pin<Box<dyn Future<Output = Result<WriteHandle, Error>> + Send + 'async_trait>>
WriteOptions. Read moreAuto Trait Implementations§
impl !RefUnwindSafe for Db
impl !UnwindSafe for Db
impl Freeze for Db
impl Send for Db
impl Sync for Db
impl Unpin for Db
impl UnsafeUnpin for Db
Blanket Implementations§
Source§impl<T> BorrowMut<T> for Twhere
T: ?Sized,
impl<T> BorrowMut<T> for Twhere
T: ?Sized,
Source§fn borrow_mut(&mut self) -> &mut T
fn borrow_mut(&mut self) -> &mut T
Source§impl<T> CloneToUninit for Twhere
T: Clone,
impl<T> CloneToUninit for Twhere
T: Clone,
Source§impl<T> Instrument for T
impl<T> Instrument for T
Source§fn instrument(self, span: Span) -> Instrumented<Self>
fn instrument(self, span: Span) -> Instrumented<Self>
Source§fn in_current_span(self) -> Instrumented<Self>
fn in_current_span(self) -> Instrumented<Self>
Source§impl<T> IntoEither for T
impl<T> IntoEither for T
Source§fn into_either(self, into_left: bool) -> Either<Self, Self>
fn into_either(self, into_left: bool) -> Either<Self, Self>
self into a Left variant of Either<Self, Self>
if into_left is true.
Converts self into a Right variant of Either<Self, Self>
otherwise. Read moreSource§fn into_either_with<F>(self, into_left: F) -> Either<Self, Self>
fn into_either_with<F>(self, into_left: F) -> Either<Self, Self>
self into a Left variant of Either<Self, Self>
if into_left(&self) returns true.
Converts self into a Right variant of Either<Self, Self>
otherwise. Read moreSource§impl<T> Paint for Twhere
T: ?Sized,
impl<T> Paint for Twhere
T: ?Sized,
Source§fn fg(&self, value: Color) -> Painted<&T>
fn fg(&self, value: Color) -> Painted<&T>
Returns a styled value derived from self with the foreground set to
value.
This method should be used rarely. Instead, prefer to use color-specific
builder methods like red() and
green(), which have the same functionality but are
pithier.
§Example
Set foreground color to white using fg():
use yansi::{Paint, Color};
painted.fg(Color::White);Set foreground color to white using white().
use yansi::Paint;
painted.white();Source§fn bright_black(&self) -> Painted<&T>
fn bright_black(&self) -> Painted<&T>
Source§fn bright_red(&self) -> Painted<&T>
fn bright_red(&self) -> Painted<&T>
Source§fn bright_green(&self) -> Painted<&T>
fn bright_green(&self) -> Painted<&T>
Source§fn bright_yellow(&self) -> Painted<&T>
fn bright_yellow(&self) -> Painted<&T>
Source§fn bright_blue(&self) -> Painted<&T>
fn bright_blue(&self) -> Painted<&T>
Source§fn bright_magenta(&self) -> Painted<&T>
fn bright_magenta(&self) -> Painted<&T>
Source§fn bright_cyan(&self) -> Painted<&T>
fn bright_cyan(&self) -> Painted<&T>
Source§fn bright_white(&self) -> Painted<&T>
fn bright_white(&self) -> Painted<&T>
Source§fn bg(&self, value: Color) -> Painted<&T>
fn bg(&self, value: Color) -> Painted<&T>
Returns a styled value derived from self with the background set to
value.
This method should be used rarely. Instead, prefer to use color-specific
builder methods like on_red() and
on_green(), which have the same functionality but
are pithier.
§Example
Set background color to red using fg():
use yansi::{Paint, Color};
painted.bg(Color::Red);Set background color to red using on_red().
use yansi::Paint;
painted.on_red();Source§fn on_primary(&self) -> Painted<&T>
fn on_primary(&self) -> Painted<&T>
Source§fn on_magenta(&self) -> Painted<&T>
fn on_magenta(&self) -> Painted<&T>
Source§fn on_bright_black(&self) -> Painted<&T>
fn on_bright_black(&self) -> Painted<&T>
Source§fn on_bright_red(&self) -> Painted<&T>
fn on_bright_red(&self) -> Painted<&T>
Source§fn on_bright_green(&self) -> Painted<&T>
fn on_bright_green(&self) -> Painted<&T>
Source§fn on_bright_yellow(&self) -> Painted<&T>
fn on_bright_yellow(&self) -> Painted<&T>
Source§fn on_bright_blue(&self) -> Painted<&T>
fn on_bright_blue(&self) -> Painted<&T>
Source§fn on_bright_magenta(&self) -> Painted<&T>
fn on_bright_magenta(&self) -> Painted<&T>
Source§fn on_bright_cyan(&self) -> Painted<&T>
fn on_bright_cyan(&self) -> Painted<&T>
Source§fn on_bright_white(&self) -> Painted<&T>
fn on_bright_white(&self) -> Painted<&T>
Source§fn attr(&self, value: Attribute) -> Painted<&T>
fn attr(&self, value: Attribute) -> Painted<&T>
Enables the styling Attribute value.
This method should be used rarely. Instead, prefer to use
attribute-specific builder methods like bold() and
underline(), which have the same functionality
but are pithier.
§Example
Make text bold using attr():
use yansi::{Paint, Attribute};
painted.attr(Attribute::Bold);Make text bold using using bold().
use yansi::Paint;
painted.bold();Source§fn rapid_blink(&self) -> Painted<&T>
fn rapid_blink(&self) -> Painted<&T>
Source§fn quirk(&self, value: Quirk) -> Painted<&T>
fn quirk(&self, value: Quirk) -> Painted<&T>
Enables the yansi Quirk value.
This method should be used rarely. Instead, prefer to use quirk-specific
builder methods like mask() and
wrap(), which have the same functionality but are
pithier.
§Example
Enable wrapping using .quirk():
use yansi::{Paint, Quirk};
painted.quirk(Quirk::Wrap);Enable wrapping using wrap().
use yansi::Paint;
painted.wrap();Source§fn clear(&self) -> Painted<&T>
👎Deprecated since 1.0.1: renamed to resetting() due to conflicts with Vec::clear().
The clear() method will be removed in a future release.
fn clear(&self) -> Painted<&T>
renamed to resetting() due to conflicts with Vec::clear().
The clear() method will be removed in a future release.
Source§fn whenever(&self, value: Condition) -> Painted<&T>
fn whenever(&self, value: Condition) -> Painted<&T>
Conditionally enable styling based on whether the Condition value
applies. Replaces any previous condition.
See the crate level docs for more details.
§Example
Enable styling painted only when both stdout and stderr are TTYs:
use yansi::{Paint, Condition};
painted.red().on_yellow().whenever(Condition::STDOUTERR_ARE_TTY);