Skip to main content

reth_libmdbx/
codec.rs

1use crate::{Error, TransactionKind};
2use derive_more::{Debug, Deref, DerefMut};
3use std::{borrow::Cow, slice};
4
5/// Implement this to be able to decode data values
6pub trait TableObject: Sized {
7    /// Decodes the object from the given bytes.
8    fn decode(data_val: &[u8]) -> Result<Self, Error>;
9
10    /// Decodes the value directly from the given MDBX_val pointer.
11    ///
12    /// # Safety
13    ///
14    /// This should only in the context of an MDBX transaction.
15    #[doc(hidden)]
16    unsafe fn decode_val<K: TransactionKind>(
17        _: *const ffi::MDBX_txn,
18        data_val: ffi::MDBX_val,
19    ) -> Result<Self, Error> {
20        let s = unsafe { slice::from_raw_parts(data_val.iov_base as *const u8, data_val.iov_len) };
21        Self::decode(s)
22    }
23}
24
25impl TableObject for Cow<'_, [u8]> {
26    fn decode(_: &[u8]) -> Result<Self, Error> {
27        unreachable!()
28    }
29
30    #[doc(hidden)]
31    unsafe fn decode_val<K: TransactionKind>(
32        _txn: *const ffi::MDBX_txn,
33        data_val: ffi::MDBX_val,
34    ) -> Result<Self, Error> {
35        let s = unsafe { slice::from_raw_parts(data_val.iov_base as *const u8, data_val.iov_len) };
36
37        #[cfg(feature = "return-borrowed")]
38        {
39            Ok(Cow::Borrowed(s))
40        }
41
42        #[cfg(not(feature = "return-borrowed"))]
43        {
44            let is_dirty = (!K::IS_READ_ONLY) &&
45                crate::error::mdbx_result(unsafe {
46                    ffi::mdbx_is_dirty(_txn, data_val.iov_base)
47                })?;
48
49            Ok(if is_dirty { Cow::Owned(s.to_vec()) } else { Cow::Borrowed(s) })
50        }
51    }
52}
53
54impl TableObject for Vec<u8> {
55    fn decode(data_val: &[u8]) -> Result<Self, Error> {
56        Ok(data_val.to_vec())
57    }
58}
59
60impl TableObject for () {
61    fn decode(_: &[u8]) -> Result<Self, Error> {
62        Ok(())
63    }
64
65    unsafe fn decode_val<K: TransactionKind>(
66        _: *const ffi::MDBX_txn,
67        _: ffi::MDBX_val,
68    ) -> Result<Self, Error> {
69        Ok(())
70    }
71}
72
73/// If you don't need the data itself, just its length.
74#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash, PartialOrd, Ord, Deref, DerefMut)]
75pub struct ObjectLength(pub usize);
76
77impl TableObject for ObjectLength {
78    fn decode(data_val: &[u8]) -> Result<Self, Error> {
79        Ok(Self(data_val.len()))
80    }
81}
82
83impl<const LEN: usize> TableObject for [u8; LEN] {
84    fn decode(data_val: &[u8]) -> Result<Self, Error> {
85        if data_val.len() != LEN {
86            return Err(Error::DecodeErrorLenDiff)
87        }
88        let mut a = [0; LEN];
89        a[..].copy_from_slice(data_val);
90        Ok(a)
91    }
92}