diff --git a/src/database/map.rs b/src/database/map.rs index cac20d6a..d6b8bf38 100644 --- a/src/database/map.rs +++ b/src/database/map.rs @@ -1,3 +1,4 @@ +mod contains; mod count; mod get; mod insert; diff --git a/src/database/map/contains.rs b/src/database/map/contains.rs new file mode 100644 index 00000000..a98fe7c5 --- /dev/null +++ b/src/database/map/contains.rs @@ -0,0 +1,88 @@ +use std::{convert::AsRef, fmt::Debug, future::Future, io::Write}; + +use arrayvec::ArrayVec; +use conduit::{implement, utils::TryFutureExtExt, Err, Result}; +use futures::future::ready; +use serde::Serialize; + +use crate::{ser, util}; + +/// Returns true if the map contains the key. +/// - key is serialized into allocated buffer +/// - harder errors may not be reported +#[implement(super::Map)] +pub fn contains(&self, key: &K) -> impl Future + Send +where + K: Serialize + ?Sized + Debug, +{ + let mut buf = Vec::::with_capacity(64); + self.bcontains(key, &mut buf) +} + +/// Returns true if the map contains the key. +/// - key is serialized into stack-buffer +/// - harder errors will panic +#[implement(super::Map)] +pub fn acontains(&self, key: &K) -> impl Future + Send +where + K: Serialize + ?Sized + Debug, +{ + let mut buf = ArrayVec::::new(); + self.bcontains(key, &mut buf) +} + +/// Returns true if the map contains the key. +/// - key is serialized into provided buffer +/// - harder errors will panic +#[implement(super::Map)] +#[tracing::instrument(skip(self, buf), fields(%self), level = "trace")] +pub fn bcontains(&self, key: &K, buf: &mut B) -> impl Future + Send +where + K: Serialize + ?Sized + Debug, + B: Write + AsRef<[u8]>, +{ + let key = ser::serialize(buf, key).expect("failed to serialize query key"); + self.exists(key).is_ok() +} + +/// Returns Ok if the map contains the key. +/// - key is raw +#[implement(super::Map)] +pub fn exists(&self, key: &K) -> impl Future> + Send +where + K: AsRef<[u8]> + ?Sized + Debug, +{ + ready(self.exists_blocking(key)) +} + +/// Returns Ok if the map contains the key; NotFound otherwise. Harder errors +/// may not always be reported properly. +#[implement(super::Map)] +#[tracing::instrument(skip(self, key), fields(%self), level = "trace")] +pub fn exists_blocking(&self, key: &K) -> Result<()> +where + K: AsRef<[u8]> + ?Sized + Debug, +{ + if self.maybe_exists_blocking(key) + && self + .db + .db + .get_pinned_cf_opt(&self.cf(), key, &self.read_options) + .map_err(util::map_err)? + .is_some() + { + Ok(()) + } else { + Err!(Request(NotFound("Not found in database"))) + } +} + +#[implement(super::Map)] +fn maybe_exists_blocking(&self, key: &K) -> bool +where + K: AsRef<[u8]> + ?Sized, +{ + self.db + .db + .key_may_exist_cf_opt(&self.cf(), key, &self.read_options) +}