Lines
97.03 %
Functions
83.33 %
Branches
100 %
use std::marker::PhantomData;
use futures::{Future, FutureExt};
use super::{BuilderState, Command, KeyOperation, KeyValue, Output};
use crate::keyvalue::{AsyncKeyValue, IncompatibleTypeError, Numeric, Value};
use crate::Error;
/// Executes a [`Command::Increment`] or [`Command::Decrement`] key-value operation.
#[must_use = "the key-value operation is not performed until execute() is called"]
pub struct Builder<'a, KeyValue, V> {
kv: &'a KeyValue,
namespace: Option<String>,
key: String,
increment: bool,
amount: Numeric,
saturating: bool,
_value: PhantomData<V>,
}
impl<'a, K, V> Builder<'a, K, V>
where
K: KeyValue,
V: TryFrom<Numeric, Error = IncompatibleTypeError>,
{
pub(crate) const fn new(
kv: &'a K,
) -> Self {
Self {
key,
kv,
namespace,
increment,
amount,
saturating: true,
_value: PhantomData,
/// Allows overflowing the value.
pub const fn allow_overflow(mut self) -> Self {
self.saturating = false;
self
/// Executes the operation using the configured options.
#[allow(clippy::missing_panics_doc)]
pub fn execute(self) -> Result<V, Error> {
let Self {
saturating,
..
} = self;
let result = kv.execute_key_operation(KeyOperation {
command: if increment {
Command::Increment { amount, saturating }
} else {
Command::Decrement { amount, saturating }
},
})?;
if let Output::Value(Some(Value::Numeric(value))) = result {
Ok(V::try_from(value).expect("server should send back identical type"))
unreachable!("Unexpected result from key value operation")
/// Executes a [`Command::Increment`] or [`Command::Decrement`] key-value operation when awaited.
#[must_use = "futures do nothing unless you `.await` or poll them"]
pub struct AsyncBuilder<'a, KeyValue, V> {
state: BuilderState<'a, Options<'a, KeyValue>, Result<V, Error>>,
struct Options<'a, KeyValue> {
impl<'a, K, V> AsyncBuilder<'a, K, V>
K: AsyncKeyValue,
state: BuilderState::Pending(Some(Options {
})),
fn options(&mut self) -> &mut Options<'a, K> {
if let BuilderState::Pending(Some(options)) = &mut self.state {
options
panic!("Attempted to use after retrieving the result")
pub fn allow_overflow(mut self) -> Self {
self.options().saturating = false;
impl<'a, K, V> Future for AsyncBuilder<'a, K, V>
type Output = Result<V, Error>;
fn poll(
mut self: std::pin::Pin<&mut Self>,
cx: &mut std::task::Context<'_>,
) -> std::task::Poll<Self::Output> {
match &mut self.state {
BuilderState::Executing(future) => future.as_mut().poll(cx),
BuilderState::Pending(builder) => {
let Options {
} = builder.take().expect("expected builder to have options");
let future = async move {
let result = kv
.execute_key_operation(KeyOperation {
})
.await?;
.boxed();
self.state = BuilderState::Executing(future);
self.poll(cx)