Skip to main content

leveldb/database/
slice.rs

1//! Core interface for exchanging data with LevelDB.
2//!
3//! It maintains a unified interface when reading from or writing to LevelDB instances.
4//! When creating new instance of Slice, no data copied at Rust layer.
5use super::bytes::Bytes;
6
7/// Slice is the core interface for exchanging data with LevelDB.
8///
9/// Slice can exist in one of two states:
10/// - Borrowed: References a byte array
11/// - Owned: Owns LevelDB-allocated byte data
12///
13/// # Data Access
14///
15/// Use the [`as_bytes()`](Slice::as_bytes) method to obtain a reference to the internal data.
16///
17/// # Important: Iterator Lifetime Warning
18///
19/// When a Slice is returned from an iterator, it **only holds a reference to LevelDB's internal data**.
20/// After the iterator continues iteration (calling next(), seek(), etc.),  the data references
21/// in previously returned Slices may become invalid. If longer ownership is required, consider copying the data:
22///
23/// # Memory Management
24///
25/// - Borrowed state: Slice does not own data, lifetime must not exceed original data
26/// - Owned state: Slice owns LevelDB-allocated memory and automatically frees it on Drop
27pub struct Slice<'a> {
28    inner: SliceInner<'a>,
29}
30
31enum SliceInner<'a> {
32    Borrowed(&'a [u8]),
33    Owned(Bytes),
34}
35
36impl<'a> From<&'a [u8]> for Slice<'a> {
37    /// Create a Slice from a byte slice.
38    ///
39    /// This constructor is intended for creating Slice instances from user owned data.
40    /// The Slice will borrow the data, so the original data must outlive the Slice.
41    ///
42    /// Use this when user owned byte data needs to be passed to LevelDB operations
43    /// like put(), delete(), or get(). The Slice will only hold a reference, avoiding data copying.
44    fn from(data: &'a [u8]) -> Self {
45        Slice {
46            inner: SliceInner::Borrowed(data),
47        }
48    }
49}
50
51impl From<Bytes> for Slice<'static> {
52    /// Create a Slice from LevelDB-allocated bytes.
53    ///
54    /// This is used internally to wrap data that LevelDB allocates and returns to the
55    /// Rust layer. The Slice becomes responsible for managing the memory and ensuring
56    /// it's properly freed when no longer needed.
57    fn from(bytes: Bytes) -> Self {
58        Slice {
59            inner: SliceInner::Owned(bytes),
60        }
61    }
62}
63
64impl<'a> std::fmt::Debug for Slice<'a> {
65    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
66        write!(f, "Slice({:?})", self.as_bytes())
67    }
68}
69
70impl<'a> PartialEq for Slice<'a> {
71    fn eq(&self, other: &Self) -> bool {
72        self.as_bytes() == other.as_bytes()
73    }
74}
75
76impl<'a> Eq for Slice<'a> {}
77
78impl<'a> PartialOrd for Slice<'a> {
79    fn partial_cmp(&self, other: &Self) -> Option<std::cmp::Ordering> {
80        Some(self.cmp(other))
81    }
82}
83
84impl<'a> Ord for Slice<'a> {
85    fn cmp(&self, other: &Self) -> std::cmp::Ordering {
86        self.as_bytes().cmp(other.as_bytes())
87    }
88}
89
90impl<'a> Slice<'a> {
91    /// Get a byte slice reference to the internal data.
92    ///
93    /// # Returns
94    ///
95    /// Returns a `&[u8]` reference to the internal data. Regardless of whether the Slice
96    /// is in Borrowed or Owned state, the actual data content can be accessed through this method.
97    ///
98    /// # Important Lifetime Warning
99    ///
100    /// **Critical**: If this Slice comes from an iterator, the returned reference's lifetime
101    /// is limited by the iterator's state. This reference may become invalid after the iterator
102    /// continues iteration.
103    pub fn as_bytes(&self) -> &[u8] {
104        match &self.inner {
105            SliceInner::Borrowed(data) => data,
106            SliceInner::Owned(bytes) => bytes.as_ref(),
107        }
108    }
109}
110
111//
112// Useful methods when comparing with other types of data
113//
114
115impl<'a> PartialEq<Vec<u8>> for Slice<'a> {
116    fn eq(&self, other: &Vec<u8>) -> bool {
117        self.as_bytes() == other.as_slice()
118    }
119}
120
121impl<'a> PartialEq<&[u8]> for Slice<'a> {
122    fn eq(&self, other: &&[u8]) -> bool {
123        self.as_bytes() == *other
124    }
125}
126
127impl<'a> PartialEq<Slice<'a>> for Vec<u8> {
128    fn eq(&self, other: &Slice<'a>) -> bool {
129        self.as_slice() == other.as_bytes()
130    }
131}
132
133impl<'a> PartialEq<Slice<'a>> for &[u8] {
134    fn eq(&self, other: &Slice<'a>) -> bool {
135        *self == other.as_bytes()
136    }
137}
138
139impl<const N: usize> PartialEq<[u8; N]> for Slice<'_> {
140    fn eq(&self, other: &[u8; N]) -> bool {
141        self.as_bytes() == other.as_slice()
142    }
143}
144
145impl<const N: usize> PartialEq<Slice<'_>> for [u8; N] {
146    fn eq(&self, other: &Slice<'_>) -> bool {
147        self.as_slice() == other.as_bytes()
148    }
149}