Skip to main content

vsdb/basic/orphan/
mod.rs

1//!
2//! A storage type for various kinds of single, non-collection values.
3//!
4//! `Orphan` is designed to store single values, such as integers, enums, or other
5//! simple data types, on disk. It provides a convenient way to manage individual
6//! pieces of data that are not part of a larger collection.
7//!
8//! # Examples
9//!
10//! ```
11//! use vsdb::basic::orphan::Orphan;
12//! use vsdb::{vsdb_set_base_dir, vsdb_get_base_dir};
13//! use std::fs;
14//!
15//! // It's recommended to use a temporary directory for testing
16//! let dir = format!("/tmp/vsdb_testing/{}", rand::random::<u128>());
17//! vsdb_set_base_dir(&dir).unwrap();
18//!
19//! let mut o = Orphan::new(10);
20//! assert_eq!(o.get_value(), 10);
21//!
22//! *o.get_mut() += 5;
23//! assert_eq!(o.get_value(), 15);
24//!
25//! // Clean up the directory
26//! fs::remove_dir_all(vsdb_get_base_dir()).unwrap();
27//! ```
28
29#[cfg(test)]
30mod test;
31
32use crate::{ValueEnDe, basic::mapx_ord_rawkey::MapxOrdRawKey};
33use ruc::*;
34use serde::{Deserialize, Serialize};
35use std::{
36    cmp::Ordering,
37    ops::{
38        Add, AddAssign, BitAnd, BitAndAssign, BitOr, BitOrAssign, BitXor, BitXorAssign,
39        Deref, DerefMut, Div, DivAssign, Mul, MulAssign, Neg, Not, Rem, RemAssign, Shl,
40        ShlAssign, Shr, ShrAssign, Sub, SubAssign,
41    },
42};
43
44////////////////////////////////////////////////////////////////////
45////////////////////////////////////////////////////////////////////
46
47/// A container for a single, non-collection value stored on disk.
48///
49/// `Orphan` is suitable for storing simple data types like integers, enums, etc.
50#[derive(Debug)]
51pub struct Orphan<T> {
52    inner: MapxOrdRawKey<T>,
53}
54
55impl<T> Serialize for Orphan<T> {
56    fn serialize<S>(&self, serializer: S) -> std::result::Result<S::Ok, S::Error>
57    where
58        S: serde::Serializer,
59    {
60        self.inner.serialize(serializer)
61    }
62}
63
64impl<'de, T> Deserialize<'de> for Orphan<T> {
65    fn deserialize<D>(deserializer: D) -> std::result::Result<Self, D::Error>
66    where
67        D: serde::Deserializer<'de>,
68    {
69        MapxOrdRawKey::deserialize(deserializer).map(|inner| Self { inner })
70    }
71}
72
73////////////////////////////////////////////////////////////////////
74////////////////////////////////////////////////////////////////////
75
76impl<T> Orphan<T>
77where
78    T: ValueEnDe,
79{
80    /// Creates a "shadow" copy of the `Orphan` instance.
81    ///
82    /// # Safety
83    ///
84    /// This API breaks Rust's semantic safety guarantees. Use only in a race-free environment.
85    #[inline(always)]
86    pub unsafe fn shadow(&self) -> Self {
87        unsafe {
88            Self {
89                inner: self.inner.shadow(),
90            }
91        }
92    }
93
94    /// Creates an `Orphan` from a byte slice.
95    ///
96    /// # Safety
97    ///
98    /// This function is unsafe and assumes the byte slice is a valid representation.
99    #[inline(always)]
100    pub unsafe fn from_bytes(s: impl AsRef<[u8]>) -> Self {
101        unsafe {
102            Self {
103                inner: MapxOrdRawKey::from_bytes(s),
104            }
105        }
106    }
107
108    /// Returns the byte representation of the `Orphan`.
109    #[inline(always)]
110    pub fn as_bytes(&self) -> &[u8] {
111        self.inner.as_bytes()
112    }
113
114    /// Creates a new `Orphan` with an initial value.
115    pub fn new(v: T) -> Self {
116        let mut hdr = MapxOrdRawKey::new();
117        hdr.insert([], &v);
118        Self { inner: hdr }
119    }
120
121    /// Retrieves a clone of the inner value.
122    pub fn get_value(&self) -> T {
123        self.inner.get([]).unwrap()
124    }
125
126    /// Sets the inner value.
127    pub fn set_value(&mut self, v: &T) {
128        self.inner.set_value([], v);
129    }
130
131    /// Checks if the `Orphan` is uninitialized.
132    pub fn is_uninitialized(&self) -> bool {
133        self.inner.get([]).is_none()
134    }
135
136    /// Initializes the `Orphan` with a value if it is currently empty.
137    pub fn initialize_if_empty(&mut self, v: T) {
138        if self.is_uninitialized() {
139            self.set_value(&v)
140        }
141    }
142
143    /// Retrieves a mutable handler for the value.
144    ///
145    /// This is the recommended way to modify the value.
146    ///
147    /// # Example
148    ///
149    /// ```
150    /// # use vsdb::basic::orphan::Orphan;
151    /// # use vsdb::{vsdb_set_base_dir, vsdb_get_base_dir};
152    /// # use std::fs;
153    /// # let dir = format!("/tmp/vsdb_testing/{}", rand::random::<u128>());
154    /// # vsdb_set_base_dir(&dir).unwrap();
155    /// let mut o = Orphan::new(10);
156    /// *o.get_mut() = 20;
157    /// assert_eq!(o.get_value(), 20);
158    /// # fs::remove_dir_all(vsdb_get_base_dir()).unwrap();
159    /// ```
160    pub fn get_mut(&mut self) -> ValueMut<'_, T> {
161        let value = self.get_value();
162        ValueMut { hdr: self, value }
163    }
164
165    /// Checks if this `Orphan` instance is the same as another.
166    #[inline(always)]
167    pub fn is_the_same_instance(&self, other_hdr: &Self) -> bool {
168        self.inner.is_the_same_instance(&other_hdr.inner)
169    }
170
171    /// Returns the unique instance ID of this `Orphan`.
172    #[inline(always)]
173    pub fn instance_id(&self) -> u64 {
174        self.inner.instance_id()
175    }
176
177    /// Persists this instance's metadata to disk so that it can be
178    /// recovered later via [`from_meta`](Self::from_meta).
179    ///
180    /// Returns the `instance_id` that should be passed to `from_meta`.
181    pub fn save_meta(&self) -> ruc::Result<u64> {
182        let id = self.instance_id();
183        crate::common::save_instance_meta(id, self).c(d!())?;
184        Ok(id)
185    }
186
187    /// Recovers an `Orphan` instance from previously saved metadata.
188    ///
189    /// The caller must ensure that the underlying VSDB database still
190    /// contains the data referenced by this instance ID.
191    pub fn from_meta(instance_id: u64) -> ruc::Result<Self> {
192        crate::common::load_instance_meta(instance_id).c(d!())
193    }
194}
195
196impl<T> Clone for Orphan<T> {
197    fn clone(&self) -> Self {
198        Self {
199            inner: self.inner.clone(),
200        }
201    }
202}
203
204impl<T: Default + ValueEnDe> Default for Orphan<T> {
205    fn default() -> Self {
206        let mut hdr = MapxOrdRawKey::new();
207        hdr.insert([], &T::default());
208        Self { inner: hdr }
209    }
210}
211
212////////////////////////////////////////////////////////////////////
213////////////////////////////////////////////////////////////////////
214
215impl<T> Eq for Orphan<T> where T: ValueEnDe + PartialEq {}
216
217impl<T> PartialEq for Orphan<T>
218where
219    T: ValueEnDe + PartialEq,
220{
221    fn eq(&self, other: &Self) -> bool {
222        self.get_value() == other.get_value()
223    }
224}
225
226impl<T> PartialEq<T> for Orphan<T>
227where
228    T: ValueEnDe + PartialEq,
229{
230    fn eq(&self, other: &T) -> bool {
231        self.get_value() == *other
232    }
233}
234
235////////////////////////////////////////////////////////////////////
236////////////////////////////////////////////////////////////////////
237
238impl<T> Ord for Orphan<T>
239where
240    T: ValueEnDe + Ord,
241{
242    fn cmp(&self, other: &Self) -> Ordering {
243        self.get_value().cmp(&other.get_value())
244    }
245}
246
247impl<T> PartialOrd for Orphan<T>
248where
249    T: ValueEnDe + Ord,
250{
251    fn partial_cmp(&self, other: &Self) -> Option<Ordering> {
252        Some(self.cmp(other))
253    }
254}
255
256impl<T> PartialOrd<T> for Orphan<T>
257where
258    T: ValueEnDe + Ord,
259{
260    fn partial_cmp(&self, other: &T) -> Option<Ordering> {
261        self.get_value().partial_cmp(other)
262    }
263}
264
265////////////////////////////////////////////////////////////////////
266////////////////////////////////////////////////////////////////////
267
268macro_rules! impl_ops {
269    ($ops: tt, $fn: tt, $op: tt) => {
270        impl<T> $ops for Orphan<T>
271        where
272            T: ValueEnDe + Ord + Eq + $ops<Output = T>,
273        {
274            type Output = T;
275            fn $fn(self, other: Self) -> Self::Output {
276                self.get_value() $op other.get_value()
277            }
278        }
279
280        impl<T> $ops<T> for Orphan<T>
281        where
282            T: ValueEnDe + Ord + Eq + $ops<Output = T>,
283        {
284            type Output = T;
285            fn $fn(self, other: T) -> Self::Output {
286                self.get_value() $op other
287            }
288        }
289    };
290    ($ops: tt, $fn: tt, $op: tt, $ops_assign: tt, $fn_assign: tt, $op_assign: tt) => {
291        impl_ops!($ops, $fn, $op);
292
293        impl<T> $ops_assign for Orphan<T>
294        where
295            T: ValueEnDe + Ord + Eq + $ops_assign,
296        {
297            fn $fn_assign(&mut self, other: Self) {
298                *self.get_mut() $op_assign other.get_value();
299            }
300        }
301
302        impl<T> $ops_assign<T> for Orphan<T>
303        where
304            T: ValueEnDe + Ord + Eq + $ops_assign,
305        {
306            fn $fn_assign(&mut self, other: T) {
307                *self.get_mut() $op_assign other;
308            }
309        }
310    };
311    (@$ops: tt, $fn: tt, $op: tt) => {
312        impl<T> $ops for Orphan<T>
313        where
314            T: ValueEnDe + Ord + Eq + $ops<Output = T>,
315        {
316            type Output = T;
317            fn $fn(self) -> Self::Output {
318                $op self.get_value()
319            }
320        }
321    };
322}
323
324impl_ops!(Add, add, +, AddAssign, add_assign, +=);
325impl_ops!(Sub, sub, -, SubAssign, sub_assign, -=);
326impl_ops!(Mul, mul, *, MulAssign, mul_assign, *=);
327impl_ops!(Div, div, /, DivAssign, div_assign, /=);
328impl_ops!(Rem, rem, %, RemAssign, rem_assign, %=);
329
330impl_ops!(BitAnd, bitand, &, BitAndAssign, bitand_assign, &=);
331impl_ops!(BitOr, bitor, |, BitOrAssign, bitor_assign, |=);
332impl_ops!(BitXor, bitxor, ^, BitXorAssign, bitxor_assign, ^=);
333impl_ops!(Shl, shl, <<, ShlAssign, shl_assign, <<=);
334impl_ops!(Shr, shr, >>, ShrAssign, shr_assign, >>=);
335
336impl_ops!(@Not, not, !);
337impl_ops!(@Neg, neg, -);
338
339////////////////////////////////////////////////////////////////////
340////////////////////////////////////////////////////////////////////
341
342/// A mutable reference to the value of an `Orphan`.
343///
344/// This struct is returned by `get_mut()` and ensures that any changes to the
345/// value are written back to disk when it is dropped.
346pub struct ValueMut<'a, T>
347where
348    T: ValueEnDe,
349{
350    hdr: &'a mut Orphan<T>,
351    value: T,
352}
353
354impl<T> Drop for ValueMut<'_, T>
355where
356    T: ValueEnDe,
357{
358    fn drop(&mut self) {
359        self.hdr.set_value(&self.value);
360    }
361}
362
363impl<T> Deref for ValueMut<'_, T>
364where
365    T: ValueEnDe,
366{
367    type Target = T;
368    fn deref(&self) -> &Self::Target {
369        &self.value
370    }
371}
372
373impl<T> DerefMut for ValueMut<'_, T>
374where
375    T: ValueEnDe,
376{
377    fn deref_mut(&mut self) -> &mut Self::Target {
378        &mut self.value
379    }
380}
381
382////////////////////////////////////////////////////////////////////
383////////////////////////////////////////////////////////////////////