scuffle_bytes_util/cow/bytes/
mod.rs

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