scuffle_bytes_util/cow/bytes/
mod.rs

1use std::borrow::Cow;
2use std::hash::Hash;
3
4use bytes::Bytes;
5
6#[cfg(feature = "serde")]
7pub(crate) mod serde;
8
9/// A [`Cow`] type for bytes.
10#[derive(Debug, Clone, Eq)]
11pub enum BytesCow<'a> {
12    /// A borrowed [`Bytes`] object.
13    Slice(&'a [u8]),
14    /// A staticly borrowed [`Bytes`] object.
15    StaticSlice(&'static [u8]),
16    /// An owned [`Vec`] of bytes.
17    Vec(Vec<u8>),
18    /// An owned [`Bytes`] object.
19    Bytes(Bytes),
20}
21
22impl Default for BytesCow<'_> {
23    fn default() -> Self {
24        Self::new()
25    }
26}
27
28impl<'a> BytesCow<'a> {
29    /// Creates an empty [`BytesCow`] object.
30    pub fn new() -> Self {
31        Self::from_static(b"")
32    }
33
34    /// Creates a new [`BytesCow`] from a static slice.
35    pub fn from_static(slice: &'static [u8]) -> Self {
36        Self::StaticSlice(slice)
37    }
38
39    /// Creates a new [`BytesCow`] from a slice of bytes.
40    pub fn from_slice(slice: &'a [u8]) -> Self {
41        Self::Slice(slice)
42    }
43
44    /// Creates a new [`BytesCow`] from a [`Bytes`] object.
45    pub fn from_bytes(bytes: Bytes) -> Self {
46        Self::Bytes(bytes)
47    }
48
49    /// Creates a new [`BytesCow`] from a [`Cow`] of a [`Bytes`] object.
50    pub fn from_cow(cow: Cow<'a, [u8]>) -> Self {
51        match cow {
52            Cow::Borrowed(slice) => Self::Slice(slice),
53            Cow::Owned(bytes) => Self::Vec(bytes),
54        }
55    }
56
57    /// Creates a new [`BytesCow`] from a [`Vec`] of bytes.
58    pub fn from_vec(bytes: Vec<u8>) -> Self {
59        Self::Vec(bytes)
60    }
61
62    /// Converts the object into a [`Bytes`] object.
63    pub fn into_bytes(self) -> Bytes {
64        match self {
65            Self::Slice(slice) => Bytes::copy_from_slice(slice),
66            Self::StaticSlice(slice) => Bytes::from_static(slice),
67            Self::Vec(bytes) => Bytes::from(bytes),
68            Self::Bytes(bytes) => bytes,
69        }
70    }
71
72    /// Returns a reference to the inner data as a slice.
73    pub fn as_bytes(&self) -> &[u8] {
74        match self {
75            Self::Slice(slice) => slice,
76            Self::StaticSlice(slice) => slice,
77            Self::Vec(bytes) => bytes.as_slice(),
78            Self::Bytes(bytes) => bytes.as_ref(),
79        }
80    }
81}
82
83impl<T> PartialEq<T> for BytesCow<'_>
84where
85    T: AsRef<[u8]>,
86{
87    fn eq(&self, other: &T) -> bool {
88        self.as_bytes() == other.as_ref()
89    }
90}
91
92impl Hash for BytesCow<'_> {
93    fn hash<H: std::hash::Hasher>(&self, state: &mut H) {
94        self.as_bytes().hash(state);
95    }
96}
97
98impl AsRef<[u8]> for BytesCow<'_> {
99    fn as_ref(&self) -> &[u8] {
100        self.as_bytes()
101    }
102}
103
104impl<'a> From<Cow<'a, [u8]>> for BytesCow<'a> {
105    fn from(cow: Cow<'a, [u8]>) -> Self {
106        BytesCow::from_cow(cow)
107    }
108}
109
110impl From<Bytes> for BytesCow<'_> {
111    fn from(bytes: Bytes) -> Self {
112        BytesCow::from_bytes(bytes)
113    }
114}
115
116impl<'a> From<&'a [u8]> for BytesCow<'a> {
117    fn from(bytes: &'a [u8]) -> Self {
118        BytesCow::from_slice(bytes)
119    }
120}
121
122impl From<Vec<u8>> for BytesCow<'_> {
123    fn from(bytes: Vec<u8>) -> Self {
124        BytesCow::from_vec(bytes)
125    }
126}
127
128#[cfg(test)]
129#[cfg_attr(all(test, coverage_nightly), coverage(off))]
130mod tests {
131    use super::BytesCow;
132
133    #[test]
134    fn constructors() {
135        let cow = BytesCow::default();
136        assert_eq!(cow.as_bytes(), b"");
137
138        let cow = BytesCow::from_static(b"hello");
139        assert_eq!(cow.as_bytes(), b"hello");
140
141        let cow = BytesCow::from_slice(b"world");
142        assert_eq!(cow.as_bytes(), b"world");
143
144        let cow = BytesCow::from_vec(vec![1, 2, 3]);
145        assert_eq!(cow.as_bytes(), &[1, 2, 3]);
146        let cow = BytesCow::from(vec![1, 2, 3]);
147        assert_eq!(cow.as_bytes(), &[1, 2, 3]);
148
149        let cow = BytesCow::from_bytes(bytes::Bytes::from_static(b"foo"));
150        assert_eq!(cow.as_bytes(), b"foo");
151        let cow = BytesCow::from(bytes::Bytes::from(vec![7, 8, 9]));
152        assert_eq!(cow.as_bytes(), &[7, 8, 9]);
153
154        let cow = BytesCow::from_cow(std::borrow::Cow::Borrowed(b"bar"));
155        assert_eq!(cow.as_bytes(), b"bar");
156        let cow = BytesCow::from_cow(std::borrow::Cow::Owned(vec![10, 11, 12]));
157        assert_eq!(cow.as_bytes(), &[10, 11, 12]);
158        let cow = BytesCow::from(std::borrow::Cow::Owned(vec![4, 5, 6]));
159        assert_eq!(cow.as_bytes(), &[4, 5, 6]);
160
161        let cow = BytesCow::from(&b"hello world"[..]);
162        assert_eq!(cow.as_bytes(), b"hello world");
163    }
164
165    #[test]
166    fn into_bytes() {
167        let cow = BytesCow::from_static(b"hello");
168        assert_eq!(cow.into_bytes(), bytes::Bytes::from_static(b"hello"));
169
170        let cow = BytesCow::from_slice(b"world");
171        assert_eq!(cow.into_bytes(), bytes::Bytes::from_static(b"world"));
172
173        let cow = BytesCow::from_vec(vec![1, 2, 3]);
174        assert_eq!(cow.into_bytes(), bytes::Bytes::from(vec![1, 2, 3]));
175
176        let cow = BytesCow::from_bytes(bytes::Bytes::from_static(b"foo"));
177        assert_eq!(cow.into_bytes(), bytes::Bytes::from_static(b"foo"));
178
179        let cow = BytesCow::from_cow(std::borrow::Cow::Borrowed(b"bar"));
180        assert_eq!(cow.into_bytes(), bytes::Bytes::from_static(b"bar"));
181
182        let cow = BytesCow::from_cow(std::borrow::Cow::Owned(vec![10, 11, 12]));
183        assert_eq!(cow.into_bytes(), bytes::Bytes::from(vec![10, 11, 12]));
184    }
185
186    #[test]
187    fn as_ref() {
188        let cow = BytesCow::from_static(b"hello");
189        assert_eq!(cow.as_ref(), b"hello");
190
191        let cow = BytesCow::from_slice(b"world");
192        assert_eq!(cow.as_ref(), b"world");
193
194        let cow = BytesCow::from_vec(vec![1, 2, 3]);
195        assert_eq!(cow.as_ref(), &[1, 2, 3]);
196
197        let cow = BytesCow::from_bytes(bytes::Bytes::from_static(b"foo"));
198        assert_eq!(cow.as_ref(), b"foo");
199    }
200
201    #[test]
202    fn partial_eq() {
203        let cow = BytesCow::from_static(b"hello");
204        assert!(cow == b"hello");
205        assert!(cow != b"world");
206
207        let cow = BytesCow::from_slice(b"world");
208        assert!(cow == b"world");
209        assert!(cow != b"hello");
210
211        let cow = BytesCow::from_vec(vec![1, 2, 3]);
212        assert!(cow == [1, 2, 3]);
213        assert!(cow != [4, 5, 6]);
214    }
215
216    #[test]
217    fn hash() {
218        use std::collections::hash_map::DefaultHasher;
219        use std::hash::{Hash, Hasher};
220
221        let mut hasher = DefaultHasher::new();
222        b"hello".hash(&mut hasher);
223        let expected_hash = hasher.finish();
224
225        let cow = BytesCow::from_static(b"hello");
226        let mut hasher = DefaultHasher::new();
227        cow.hash(&mut hasher);
228        assert_eq!(hasher.finish(), expected_hash);
229    }
230}