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