mirror of
https://github.com/hinto-janai/cuprate.git
synced 2024-12-22 11:39:30 +00:00
docs, example
This commit is contained in:
parent
87de6de499
commit
80272e14e9
4 changed files with 103 additions and 32 deletions
|
@ -1,16 +1,26 @@
|
||||||
//! TODO
|
//! [`Entry`]
|
||||||
|
|
||||||
use crate::{
|
use crate::{
|
||||||
entry::{OccupiedEntry, VacantEntry},
|
entry::{OccupiedEntry, VacantEntry},
|
||||||
DatabaseRw, DbResult, Table,
|
DatabaseRw, DbResult, Table,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
/// A view into a single entry in a [`DatabaseRw`], which may either be vacant or occupied.
|
||||||
|
///
|
||||||
|
/// This enum is constructed from the [`DatabaseRw::entry`] method.
|
||||||
pub enum Entry<'a, T, D>
|
pub enum Entry<'a, T, D>
|
||||||
where
|
where
|
||||||
T: Table,
|
T: Table,
|
||||||
D: DatabaseRw<T>,
|
D: DatabaseRw<T>,
|
||||||
{
|
{
|
||||||
|
/// A vacant entry; this key did not exist.
|
||||||
|
///
|
||||||
|
/// [`crate::Runtime::KeyExists`] will never be returned from this type's operations.
|
||||||
Vacant(VacantEntry<'a, T, D>),
|
Vacant(VacantEntry<'a, T, D>),
|
||||||
|
|
||||||
|
/// An occupied entry; this key already exists.
|
||||||
|
///
|
||||||
|
/// [`crate::Runtime::KeyNotFound`] will never be returned from this type's operations.
|
||||||
Occupied(OccupiedEntry<'a, T, D>),
|
Occupied(OccupiedEntry<'a, T, D>),
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -19,7 +29,9 @@ where
|
||||||
T: Table,
|
T: Table,
|
||||||
D: DatabaseRw<T>,
|
D: DatabaseRw<T>,
|
||||||
{
|
{
|
||||||
/// TODO
|
/// Ensures a value is in the entry by inserting the `default` if empty.
|
||||||
|
///
|
||||||
|
/// This only inserts if the entry is [`VacantEntry`].
|
||||||
pub fn or_insert(self, default: &T::Value) -> DbResult<()> {
|
pub fn or_insert(self, default: &T::Value) -> DbResult<()> {
|
||||||
match self {
|
match self {
|
||||||
Self::Occupied(_) => Ok(()),
|
Self::Occupied(_) => Ok(()),
|
||||||
|
@ -27,7 +39,9 @@ where
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// TODO
|
/// Ensures a value is in the entry by inserting the result of the `default` function.
|
||||||
|
///
|
||||||
|
/// This only inserts if the entry is [`VacantEntry`].
|
||||||
pub fn or_insert_with<F>(self, default: F) -> DbResult<()>
|
pub fn or_insert_with<F>(self, default: F) -> DbResult<()>
|
||||||
where
|
where
|
||||||
F: FnOnce() -> &'a T::Value,
|
F: FnOnce() -> &'a T::Value,
|
||||||
|
@ -38,7 +52,7 @@ where
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// TODO
|
/// Same as [`Self::or_insert_with`] but gives access to the key.
|
||||||
pub fn or_insert_with_key<F>(self, default: F) -> DbResult<()>
|
pub fn or_insert_with_key<F>(self, default: F) -> DbResult<()>
|
||||||
where
|
where
|
||||||
F: FnOnce(&'a T::Key) -> &'a T::Value,
|
F: FnOnce(&'a T::Key) -> &'a T::Value,
|
||||||
|
@ -52,7 +66,7 @@ where
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// TODO
|
/// Returns a reference to this entry's key.
|
||||||
pub const fn key(&self) -> &T::Key {
|
pub const fn key(&self) -> &T::Key {
|
||||||
match self {
|
match self {
|
||||||
Self::Occupied(entry) => entry.key(),
|
Self::Occupied(entry) => entry.key(),
|
||||||
|
@ -60,7 +74,7 @@ where
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// TODO
|
/// Returns a reference to this entry's key (if the entry is [`OccupiedEntry`]).
|
||||||
pub const fn value(&self) -> Option<&T::Value> {
|
pub const fn value(&self) -> Option<&T::Value> {
|
||||||
match self {
|
match self {
|
||||||
Self::Occupied(entry) => Some(entry.value()),
|
Self::Occupied(entry) => Some(entry.value()),
|
||||||
|
@ -68,7 +82,7 @@ where
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// TODO
|
/// Provides in-place mutable access to an occupied entry before any potential inserts.
|
||||||
pub fn and_update<F>(self, f: F) -> DbResult<Self>
|
pub fn and_update<F>(self, f: F) -> DbResult<Self>
|
||||||
where
|
where
|
||||||
F: FnOnce(&mut T::Value),
|
F: FnOnce(&mut T::Value),
|
||||||
|
@ -83,14 +97,19 @@ where
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<'a, T, D> Entry<'a, T, D>
|
impl<T, D> Entry<'_, T, D>
|
||||||
where
|
where
|
||||||
T: Table,
|
T: Table,
|
||||||
<T as Table>::Value: Default,
|
<T as Table>::Value: Default,
|
||||||
D: DatabaseRw<T>,
|
D: DatabaseRw<T>,
|
||||||
{
|
{
|
||||||
/// TODO
|
/// Ensures a value is in the entry by inserting a [`Default`] value if empty.
|
||||||
pub fn or_default(self) -> &'a mut T::Value {
|
///
|
||||||
todo!()
|
/// This only inserts if the entry is [`VacantEntry`].
|
||||||
|
pub fn or_default(self) -> DbResult<()> {
|
||||||
|
match self {
|
||||||
|
Self::Occupied(_) => Ok(()),
|
||||||
|
Self::Vacant(entry) => entry.insert(&Default::default()),
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,4 +1,55 @@
|
||||||
//! TODO
|
//! `(key, value)` entry API for [`crate::DatabaseRw`].
|
||||||
|
//!
|
||||||
|
//! This module provides a [`std::collections::btree_map::Entry`]-like API for [`crate::DatabaseRw`].
|
||||||
|
//!
|
||||||
|
//! ## Example - modifying a value in place, or inserting it if it doesn't exist
|
||||||
|
//! ```rust
|
||||||
|
//! use cuprate_database::{
|
||||||
|
//! ConcreteEnv,
|
||||||
|
//! config::ConfigBuilder,
|
||||||
|
//! Env, EnvInner,
|
||||||
|
//! DatabaseRo, DatabaseRw, TxRo, TxRw, RuntimeError,
|
||||||
|
//! };
|
||||||
|
//!
|
||||||
|
//! # fn main() -> Result<(), Box<dyn std::error::Error>> {
|
||||||
|
//! # let tmp_dir = tempfile::tempdir()?;
|
||||||
|
//! # let db_dir = tmp_dir.path().to_owned();
|
||||||
|
//! # let config = ConfigBuilder::new(db_dir.into()).build();
|
||||||
|
//! #
|
||||||
|
//! # let env = ConcreteEnv::open(config)?;
|
||||||
|
//! #
|
||||||
|
//! # struct Table;
|
||||||
|
//! # impl cuprate_database::Table for Table {
|
||||||
|
//! # const NAME: &'static str = "table";
|
||||||
|
//! # type Key = u8;
|
||||||
|
//! # type Value = u64;
|
||||||
|
//! # }
|
||||||
|
//! #
|
||||||
|
//! # let env_inner = env.env_inner();
|
||||||
|
//! # let tx_rw = env_inner.tx_rw()?;
|
||||||
|
//! #
|
||||||
|
//! # env_inner.create_db::<Table>(&tx_rw)?;
|
||||||
|
//! # let mut table = env_inner.open_db_rw::<Table>(&tx_rw)?;
|
||||||
|
//! /// The key to use.
|
||||||
|
//! const KEY: u8 = u8::MAX;
|
||||||
|
//!
|
||||||
|
//! /// The update function applied if the value already exists.
|
||||||
|
//! fn f(value: &mut u64) {
|
||||||
|
//! *value += 1;
|
||||||
|
//! }
|
||||||
|
//!
|
||||||
|
//! // No entry exists.
|
||||||
|
//! assert!(matches!(table.first(), Err(RuntimeError::KeyNotFound)));
|
||||||
|
//!
|
||||||
|
//! // Increment the value by `1` or insert a `0` if it doesn't exist.
|
||||||
|
//! table.entry(&KEY)?.and_update(f)?.or_insert(&0)?;
|
||||||
|
//! assert_eq!(table.first()?, (KEY, 0));
|
||||||
|
//!
|
||||||
|
//! // Again.
|
||||||
|
//! table.entry(&KEY)?.and_update(f)?.or_insert(&0)?;
|
||||||
|
//! assert_eq!(table.first()?, (KEY, 1));
|
||||||
|
//! # Ok(()) }
|
||||||
|
//! ```
|
||||||
|
|
||||||
#[expect(clippy::module_inception)]
|
#[expect(clippy::module_inception)]
|
||||||
mod entry;
|
mod entry;
|
||||||
|
|
|
@ -1,7 +1,8 @@
|
||||||
//! TODO
|
//! [`OccupiedEntry`]
|
||||||
|
|
||||||
use crate::{DatabaseRw, DbResult, Table};
|
use crate::{DatabaseRw, DbResult, Table};
|
||||||
|
|
||||||
|
/// A view into an occupied entry in a [`DatabaseRw`]. It is part of [`crate::entry::Entry`].
|
||||||
pub struct OccupiedEntry<'a, T, D>
|
pub struct OccupiedEntry<'a, T, D>
|
||||||
where
|
where
|
||||||
T: Table,
|
T: Table,
|
||||||
|
@ -17,17 +18,26 @@ where
|
||||||
T: Table,
|
T: Table,
|
||||||
D: DatabaseRw<T>,
|
D: DatabaseRw<T>,
|
||||||
{
|
{
|
||||||
/// TODO
|
/// Gets a reference to the key that is used when [`Self::insert`]ing a value.
|
||||||
pub const fn key(&self) -> &T::Key {
|
pub const fn key(&self) -> &T::Key {
|
||||||
self.key
|
self.key
|
||||||
}
|
}
|
||||||
|
|
||||||
/// TODO
|
/// Gets a reference to the current value.
|
||||||
|
///
|
||||||
|
/// [`Self::update`] will modify this value.
|
||||||
pub const fn value(&self) -> &T::Value {
|
pub const fn value(&self) -> &T::Value {
|
||||||
&self.value
|
&self.value
|
||||||
}
|
}
|
||||||
|
|
||||||
/// TODO
|
/// Take ownership of the current value.
|
||||||
|
pub fn into_value(self) -> T::Value {
|
||||||
|
self.value
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Modify the current value and insert it.
|
||||||
|
///
|
||||||
|
/// Calling [`Self::value`] after this will return the modified value.
|
||||||
pub fn update<F>(&mut self, f: F) -> DbResult<()>
|
pub fn update<F>(&mut self, f: F) -> DbResult<()>
|
||||||
where
|
where
|
||||||
F: FnOnce(&mut T::Value),
|
F: FnOnce(&mut T::Value),
|
||||||
|
@ -36,23 +46,13 @@ where
|
||||||
DatabaseRw::put(self.db, self.key, &self.value)
|
DatabaseRw::put(self.db, self.key, &self.value)
|
||||||
}
|
}
|
||||||
|
|
||||||
/// TODO
|
/// Replace the current value with a new value.
|
||||||
pub fn insert(&mut self, value: &T::Value) -> DbResult<()> {
|
pub fn insert(self, value: &T::Value) -> DbResult<()> {
|
||||||
DatabaseRw::put(self.db, self.key, value)
|
DatabaseRw::put(self.db, self.key, value)
|
||||||
}
|
}
|
||||||
|
|
||||||
/// TODO
|
/// Remove this entry.
|
||||||
pub fn remove(self) -> DbResult<T::Value> {
|
pub fn remove(self) -> DbResult<T::Value> {
|
||||||
DatabaseRw::delete(self.db, self.key).map(|()| Ok(self.value))?
|
DatabaseRw::delete(self.db, self.key).map(|()| Ok(self.value))?
|
||||||
}
|
}
|
||||||
|
|
||||||
/// TODO
|
|
||||||
pub const fn get(&self) -> &T::Value {
|
|
||||||
&self.value
|
|
||||||
}
|
|
||||||
|
|
||||||
/// TODO
|
|
||||||
pub fn into_value(self) -> T::Value {
|
|
||||||
self.value
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,7 +1,8 @@
|
||||||
//! TODO
|
//! [`VacantEntry`]
|
||||||
|
|
||||||
use crate::{DatabaseRw, DbResult, RuntimeError, Table};
|
use crate::{DatabaseRw, DbResult, RuntimeError, Table};
|
||||||
|
|
||||||
|
/// A view into a vacant entry in a [`DatabaseRw`]. It is part of [`crate::entry::Entry`].
|
||||||
pub struct VacantEntry<'a, T, D>
|
pub struct VacantEntry<'a, T, D>
|
||||||
where
|
where
|
||||||
T: Table,
|
T: Table,
|
||||||
|
@ -16,12 +17,12 @@ where
|
||||||
T: Table,
|
T: Table,
|
||||||
D: DatabaseRw<T>,
|
D: DatabaseRw<T>,
|
||||||
{
|
{
|
||||||
/// TODO
|
/// Gets a reference to the key that is used when [`Self::insert`]ing a value.
|
||||||
pub const fn key(&self) -> &T::Key {
|
pub const fn key(&self) -> &T::Key {
|
||||||
self.key
|
self.key
|
||||||
}
|
}
|
||||||
|
|
||||||
/// TODO
|
/// [`DatabaseRw::put`] a new value with [`Self::key`] as the key.
|
||||||
pub fn insert(self, value: &T::Value) -> DbResult<()> {
|
pub fn insert(self, value: &T::Value) -> DbResult<()> {
|
||||||
match DatabaseRw::put(self.db, self.key, value) {
|
match DatabaseRw::put(self.db, self.key, value) {
|
||||||
Ok(()) => Ok(()),
|
Ok(()) => Ok(()),
|
||||||
|
|
Loading…
Reference in a new issue