Skip to main content

tuwunel_database/
handle.rs

1//! Pinned database values returned by point queries.
2//!
3//! A handle keeps the RocksDB slice pin alive while exposing the stored bytes
4//! through standard reference traits. Callers can deserialize directly from the
5//! pinned bytes or copy them into owned storage.
6
7use std::{fmt, fmt::Debug, ops::Deref};
8
9use rocksdb::DBPinnableSlice;
10use serde::{Deserialize, Serialize, Serializer};
11use tuwunel_core::Result;
12
13use crate::{Deserialized, Slice, keyval::deserialize_val};
14
15/// Pinned view of a value returned by RocksDB.
16///
17/// The handle keeps its underlying [`DBPinnableSlice`] alive and dereferences
18/// to [`Slice`] without an additional copy. Convert it into `Vec<u8>` when the
19/// bytes must outlive the pin.
20pub struct Handle<'a> {
21	val: DBPinnableSlice<'a>,
22}
23
24impl<'a> From<DBPinnableSlice<'a>> for Handle<'a> {
25	fn from(val: DBPinnableSlice<'a>) -> Self { Self { val } }
26}
27
28impl Debug for Handle<'_> {
29	// The pinned slice's address is the informative content here.
30	#[expect(clippy::pointer_format)]
31	fn fmt(&self, out: &mut fmt::Formatter<'_>) -> fmt::Result {
32		let val: &Slice = self;
33		let ptr = val.as_ptr();
34		let len = val.len();
35		write!(out, "Handle {{val: {{ptr: {ptr:?}, len: {len}}}}}")
36	}
37}
38
39impl Serialize for Handle<'_> {
40	#[inline]
41	fn serialize<S: Serializer>(&self, serializer: S) -> Result<S::Ok, S::Error> {
42		let bytes: &Slice = self;
43		serializer.serialize_bytes(bytes)
44	}
45}
46
47impl Deserialized for Result<Handle<'_>> {
48	#[inline]
49	fn map_de<T, U, F>(self, f: F) -> Result<U>
50	where
51		F: FnOnce(T) -> U,
52		T: for<'de> Deserialize<'de>,
53	{
54		self?.map_de(f)
55	}
56}
57
58impl<'a> Deserialized for Result<&'a Handle<'a>> {
59	#[inline]
60	fn map_de<T, U, F>(self, f: F) -> Result<U>
61	where
62		F: FnOnce(T) -> U,
63		T: for<'de> Deserialize<'de>,
64	{
65		self.and_then(|handle| handle.map_de(f))
66	}
67}
68
69impl<'a> Deserialized for &'a Handle<'a> {
70	#[inline]
71	fn map_de<T, U, F>(self, f: F) -> Result<U>
72	where
73		F: FnOnce(T) -> U,
74		T: for<'de> Deserialize<'de>,
75	{
76		deserialize_val(self.as_ref()).map(f)
77	}
78}
79
80impl From<Handle<'_>> for Vec<u8> {
81	fn from(handle: Handle<'_>) -> Self { handle.deref().to_vec() }
82}
83
84impl Deref for Handle<'_> {
85	type Target = Slice;
86
87	#[inline]
88	fn deref(&self) -> &Self::Target { &self.val }
89}
90
91impl AsRef<Slice> for Handle<'_> {
92	#[inline]
93	fn as_ref(&self) -> &Slice { &self.val }
94}