Skip to main content

lsm_tree/slice/slice_bytes/
mod.rs

1// SPDX-License-Identifier: Apache-2.0
2// Copyright (c) 2024-present, fjall-rs
3// Copyright (c) 2026-present, Dmitry Prudnikov
4
5#[cfg(not(feature = "std"))]
6use alloc::{string::String, vec::Vec};
7use bytes::Bytes;
8
9pub use bytes::BytesMut as Builder;
10
11/// A [`Slice`] allocated and not written yet, for a read to fill.
12pub(crate) struct UnfilledSlice {
13    builder: Builder,
14    len: usize,
15}
16
17impl UnfilledSlice {
18    pub(crate) fn new(len: usize) -> Self {
19        Self {
20            builder: Builder::with_capacity(len),
21            len,
22        }
23    }
24
25    /// The whole allocation as a read target.
26    pub(crate) fn target(&mut self) -> crate::fs::ReadBuf<'_> {
27        let (target, _) = self.builder.spare_capacity_mut().split_at_mut(self.len);
28        crate::fs::ReadBuf::uninit(target)
29    }
30
31    /// The slice.
32    ///
33    /// # Safety
34    ///
35    /// Every byte must have been written.
36    pub(crate) unsafe fn assume_filled(mut self) -> Slice {
37        // SAFETY: the caller promises the first `len` bytes were written.
38        #[expect(unsafe_code, reason = "see safety")]
39        unsafe {
40            self.builder.set_len(self.len);
41        }
42        Slice(self.builder.freeze())
43    }
44}
45
46/// An immutable byte slice that can be cloned without additional heap allocation
47///
48/// There is no guarantee of any sort of alignment for zero-copy (de)serialization.
49#[derive(Debug, Clone, Eq, Hash, Ord)]
50pub struct Slice(pub(super) Bytes);
51
52impl Slice {
53    /// Construct a [`Slice`] from a byte slice.
54    #[must_use]
55    pub fn new(bytes: &[u8]) -> Self {
56        Self(Bytes::copy_from_slice(bytes))
57    }
58
59    #[doc(hidden)]
60    #[must_use]
61    pub fn empty() -> Self {
62        Self(Bytes::from_static(&[]))
63    }
64
65    #[doc(hidden)]
66    #[must_use]
67    pub unsafe fn builder_unzeroed(len: usize) -> Builder {
68        // Use `with_capacity` & `set_len`` to avoid zeroing the buffer
69        let mut builder = Builder::with_capacity(len);
70
71        // SAFETY: we just allocated `len` bytes, and `read_exact` will fail if
72        // it doesn't fill the buffer, subsequently dropping the uninitialized
73        // BytesMut object
74        #[expect(unsafe_code, reason = "see safety")]
75        unsafe {
76            builder.set_len(len);
77        }
78
79        builder
80    }
81
82    #[doc(hidden)]
83    #[must_use]
84    pub fn slice(&self, range: impl core::ops::RangeBounds<usize>) -> Self {
85        Self(self.0.slice(range))
86    }
87
88    /// Whether both hold the same bytes.
89    #[inline]
90    pub(crate) fn same_bytes(&self, other: &Self) -> bool {
91        self.0 == other.0
92    }
93
94    #[doc(hidden)]
95    #[must_use]
96    pub fn fused(left: &[u8], right: &[u8]) -> Self {
97        let mut builder = Builder::with_capacity(left.len() + right.len());
98        builder.extend_from_slice(left);
99        builder.extend_from_slice(right);
100        Self(builder.freeze())
101    }
102
103    /// Constructs a [`Slice`] from an I/O reader by pulling in `len` bytes.
104    ///
105    /// The buffer is zeroed: `R` is any safe reader, free to look at it.
106    #[doc(hidden)]
107    #[cfg(feature = "std")]
108    pub fn from_reader<R: std::io::Read>(reader: &mut R, len: usize) -> std::io::Result<Self> {
109        let mut builder = Builder::zeroed(len);
110        reader.read_exact(&mut builder)?;
111        Ok(Self(builder.freeze()))
112    }
113
114    /// `no_std` mirror of [`Slice::from_reader`] over [`crate::io::Read`].
115    ///
116    /// # Errors
117    ///
118    /// Returns an error if an I/O error occurred.
119    #[doc(hidden)]
120    #[cfg(not(feature = "std"))]
121    pub fn from_reader<R: crate::io::Read>(reader: &mut R, len: usize) -> crate::io::Result<Self> {
122        let mut builder = Builder::zeroed(len);
123        reader.read_exact(&mut builder)?;
124        Ok(Self(builder.freeze()))
125    }
126}
127
128impl From<Bytes> for Slice {
129    fn from(value: Bytes) -> Self {
130        Self(value)
131    }
132}
133
134impl From<Slice> for Bytes {
135    fn from(value: Slice) -> Self {
136        value.0
137    }
138}
139
140// Bytes::from<Vec<u8>> is zero-copy optimized
141impl From<Vec<u8>> for Slice {
142    fn from(value: Vec<u8>) -> Self {
143        Self(Bytes::from(value))
144    }
145}
146
147// Bytes::from<String> is zero-copy optimized
148impl From<String> for Slice {
149    fn from(value: String) -> Self {
150        Self(Bytes::from(value))
151    }
152}