lsm_tree/slice/
mod.rs

1// Copyright (c) 2024-present, fjall-rs
2// This source code is licensed under both the Apache 2.0 and MIT License
3// (found in the LICENSE-* files in the repository)
4
5// Using tokio bytes
6#[cfg(feature = "bytes_1")]
7mod slice_bytes;
8
9// Using byteview
10#[cfg(not(feature = "bytes_1"))]
11mod slice_default;
12
13use std::{
14    path::{Path, PathBuf},
15    sync::Arc,
16};
17
18#[cfg(not(feature = "bytes_1"))]
19pub use slice_default::{Builder, Slice};
20
21#[cfg(feature = "bytes_1")]
22pub use slice_bytes::{Builder, Slice};
23
24impl AsRef<[u8]> for Slice {
25    fn as_ref(&self) -> &[u8] {
26        &self.0
27    }
28}
29
30impl From<&[u8]> for Slice {
31    fn from(value: &[u8]) -> Self {
32        #[cfg(not(feature = "bytes_1"))]
33        {
34            Self(byteview::ByteView::new(value))
35        }
36
37        #[cfg(feature = "bytes_1")]
38        {
39            Self(bytes::Bytes::from(value.to_vec()))
40        }
41    }
42}
43
44impl From<Arc<[u8]>> for Slice {
45    fn from(value: Arc<[u8]>) -> Self {
46        Self::from(&*value)
47    }
48}
49
50impl From<&Vec<u8>> for Slice {
51    fn from(value: &Vec<u8>) -> Self {
52        Self::from(value.as_slice())
53    }
54}
55
56impl From<&str> for Slice {
57    fn from(value: &str) -> Self {
58        Self::from(value.as_bytes())
59    }
60}
61
62impl From<&String> for Slice {
63    fn from(value: &String) -> Self {
64        Self::from(value.as_str())
65    }
66}
67
68impl From<&Path> for Slice {
69    fn from(value: &Path) -> Self {
70        Self::from(value.as_os_str().as_encoded_bytes())
71    }
72}
73
74impl From<PathBuf> for Slice {
75    fn from(value: PathBuf) -> Self {
76        Self::from(value.as_os_str().as_encoded_bytes())
77    }
78}
79
80impl From<Arc<str>> for Slice {
81    fn from(value: Arc<str>) -> Self {
82        Self::from(&*value)
83    }
84}
85
86impl<const N: usize> From<[u8; N]> for Slice {
87    fn from(value: [u8; N]) -> Self {
88        Self::from(value.as_slice())
89    }
90}
91
92impl<const N: usize> From<&[u8; N]> for Slice {
93    fn from(value: &[u8; N]) -> Self {
94        Self::from(value.as_slice())
95    }
96}
97
98impl FromIterator<u8> for Slice {
99    fn from_iter<T>(iter: T) -> Self
100    where
101        T: IntoIterator<Item = u8>,
102    {
103        Vec::from_iter(iter).into()
104    }
105}
106
107impl std::ops::Deref for Slice {
108    type Target = [u8];
109
110    fn deref(&self) -> &Self::Target {
111        self.as_ref()
112    }
113}
114
115impl std::borrow::Borrow<[u8]> for Slice {
116    fn borrow(&self) -> &[u8] {
117        self
118    }
119}
120
121impl<T> PartialEq<T> for Slice
122where
123    T: AsRef<[u8]>,
124{
125    fn eq(&self, other: &T) -> bool {
126        self.as_ref() == other.as_ref()
127    }
128}
129
130impl PartialEq<Slice> for &[u8] {
131    fn eq(&self, other: &Slice) -> bool {
132        *self == other.as_ref()
133    }
134}
135
136impl<T> PartialOrd<T> for Slice
137where
138    T: AsRef<[u8]>,
139{
140    fn partial_cmp(&self, other: &T) -> Option<std::cmp::Ordering> {
141        self.as_ref().partial_cmp(other.as_ref())
142    }
143}
144
145impl PartialOrd<Slice> for &[u8] {
146    fn partial_cmp(&self, other: &Slice) -> Option<std::cmp::Ordering> {
147        (*self).partial_cmp(other.as_ref())
148    }
149}
150
151#[cfg(test)]
152#[allow(clippy::expect_used)]
153mod tests {
154    use super::Slice;
155    use std::{fmt::Debug, sync::Arc};
156    use test_log::test;
157
158    fn assert_slice_handles<T>(v: T)
159    where
160        T: Clone + Debug,
161        Slice: From<T> + PartialEq<T> + PartialOrd<T>,
162    {
163        // verify slice arc roundtrips
164        let slice: Slice = v.clone().into();
165        assert_eq!(slice, v, "slice_arc: {slice:?}, v: {v:?}");
166        assert!(slice >= v, "slice_arc: {slice:?}, v: {v:?}");
167    }
168
169    #[test]
170    fn slice_empty() {
171        assert_eq!(Slice::empty(), []);
172    }
173
174    #[test]
175    fn slice_fuse_empty() {
176        let bytes = Slice::fused(&[], &[]);
177        assert_eq!(&*bytes, &[] as &[u8]);
178    }
179
180    #[test]
181    fn slice_fuse_one() {
182        let bytes = Slice::fused(b"abc", &[]);
183        assert_eq!(&*bytes, b"abc");
184    }
185
186    #[test]
187    fn slice_fuse_two() {
188        let bytes = Slice::fused(b"abc", b"def");
189        assert_eq!(&*bytes, b"abcdef");
190    }
191
192    #[test]
193    #[allow(unsafe_code)]
194    fn slice_with_size() {
195        assert_eq!(
196            &*unsafe {
197                let mut b = Slice::builder_unzeroed(5);
198                b.fill(0);
199                b.freeze()
200            },
201            [0; 5],
202        );
203        assert_eq!(
204            &*unsafe {
205                let mut b = Slice::builder_unzeroed(50);
206                b.fill(0);
207                b.freeze()
208            },
209            [0; 50],
210        );
211        assert_eq!(
212            &*unsafe {
213                let mut b = Slice::builder_unzeroed(50);
214                b.fill(77);
215                b.freeze()
216            },
217            [77; 50],
218        );
219    }
220
221    /// This test verifies that we can create a `Slice` from various types and compare a `Slice` with them.
222    #[test]
223    fn test_slice_instantiation() {
224        // - &[u8]
225        assert_slice_handles::<&[u8]>(&[1, 2, 3, 4]);
226        // - Arc<u8>
227        assert_slice_handles::<Arc<[u8]>>(Arc::new([1, 2, 3, 4]));
228        // - Vec<u8>
229        assert_slice_handles::<Vec<u8>>(vec![1, 2, 3, 4]);
230        // - &str
231        assert_slice_handles::<&str>("hello");
232        // - String
233        assert_slice_handles::<String>("hello".to_string());
234        // - [u8; N]
235        assert_slice_handles::<[u8; 4]>([1, 2, 3, 4]);
236
237        // Special case for these types
238        // - Iterator<Item = u8>
239        let slice = Slice::from_iter(vec![1, 2, 3, 4]);
240        assert_eq!(slice, vec![1, 2, 3, 4]);
241
242        // - Arc<str>
243        let arc_str: Arc<str> = Arc::from("hello");
244        let slice = Slice::from(arc_str.clone());
245        assert_eq!(slice.as_ref(), arc_str.as_bytes());
246
247        // - io::Read
248        let mut reader = std::io::Cursor::new(vec![1, 2, 3, 4]);
249        let slice = Slice::from_reader(&mut reader, 4).expect("read");
250        assert_eq!(slice, vec![1, 2, 3, 4]);
251    }
252}