Skip to main content

tuwunel_database/map/
contains.rs

1use std::{fmt::Debug, io::Write, sync::Arc};
2
3use futures::FutureExt;
4use serde::Serialize;
5use tuwunel_core::{
6	Result,
7	arrayvec::ArrayVec,
8	err, implement,
9	utils::{future::TryExtExt, result::FlatOk},
10};
11
12use crate::{keyval::KeyBuf, ser};
13
14/// Checks whether a serialized key exists.
15///
16/// The key is encoded into an owned buffer before asynchronous raw-key lookup.
17/// Missing keys and database errors are folded into `false`.
18///
19/// # Panics
20///
21/// Panics if the key cannot be serialized.
22#[inline]
23#[implement(super::Map)]
24pub fn contains<K>(
25	self: &Arc<Self>,
26	key: &K,
27) -> impl Future<Output = bool> + Send + '_ + use<'_, K>
28where
29	K: Serialize + ?Sized + Debug,
30{
31	let mut buf = KeyBuf::new();
32	self.bcontains(key, &mut buf)
33}
34
35/// Checks whether a serialized key exists using fixed-capacity storage.
36///
37/// `MAX` bounds the complete encoded key without a heap fallback. Missing keys
38/// and database errors are folded into `false`.
39///
40/// # Panics
41///
42/// Panics if the encoded key exceeds `MAX` or serialization otherwise fails.
43#[inline]
44#[implement(super::Map)]
45pub fn acontains<const MAX: usize, K>(
46	self: &Arc<Self>,
47	key: &K,
48) -> impl Future<Output = bool> + Send + '_ + use<'_, MAX, K>
49where
50	K: Serialize + ?Sized + Debug,
51{
52	let mut buf = ArrayVec::<u8, MAX>::new();
53	self.bcontains(key, &mut buf)
54}
55
56/// Checks whether a serialized key exists using a caller-supplied buffer.
57///
58/// Serialization appends to the supplied buffer, and lookup uses its full
59/// resulting contents. Missing keys and database errors are folded into
60/// `false`.
61///
62/// # Panics
63///
64/// Panics if the key cannot be serialized.
65#[implement(super::Map)]
66#[tracing::instrument(skip(self, buf), fields(%self), level = "trace")]
67pub fn bcontains<K, B>(
68	self: &Arc<Self>,
69	key: &K,
70	buf: &mut B,
71) -> impl Future<Output = bool> + Send + '_ + use<'_, K, B>
72where
73	K: Serialize + ?Sized + Debug,
74	B: Write + AsRef<[u8]>,
75{
76	let key = ser::serialize(buf, key).expect("failed to serialize query key");
77	self.exists(key).is_ok()
78}
79
80/// Checks whether a raw key exists asynchronously.
81///
82/// Success returns unit, while missing keys and database failures remain
83/// errors. The lookup uses the same cache-first path as `get`.
84#[inline]
85#[implement(super::Map)]
86pub fn exists<'a, K>(
87	self: &'a Arc<Self>,
88	key: &K,
89) -> impl Future<Output = Result> + Send + 'a + use<'a, K>
90where
91	K: AsRef<[u8]> + ?Sized + Debug + 'a,
92{
93	self.get(key).map(|res| res.map(|_| ()))
94}
95
96/// Checks synchronously whether a raw key exists.
97///
98/// A cache-tier existence hint can avoid a point read when absence is certain.
99/// Missing keys return the map's not-found error, while database failures
100/// remain errors.
101#[implement(super::Map)]
102#[tracing::instrument(skip(self, key), fields(%self), level = "trace")]
103pub fn exists_blocking<K>(&self, key: &K) -> Result
104where
105	K: AsRef<[u8]> + ?Sized + Debug,
106{
107	self.maybe_exists(key)
108		.then(|| self.get_blocking(key))
109		.flat_ok()
110		.map(|_| ())
111		.ok_or_else(|| err!(Request(NotFound("Not found in database"))))
112}
113
114/// Tests whether RocksDB can rule out a raw key without storage I/O.
115///
116/// A `false` result proves absence, while `true` still requires a point read.
117/// The configured read options restrict the probe to block cache.
118#[implement(super::Map)]
119pub(crate) fn maybe_exists<K>(&self, key: &K) -> bool
120where
121	K: AsRef<[u8]> + ?Sized,
122{
123	self.engine
124		.db
125		.key_may_exist_cf_opt(&self.cf(), key, &self.cache_read_options)
126}