scuffle_bytes_util/cow/bytes/
mod.rs1use 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#[derive(Debug, Clone, Eq)]
12pub enum BytesCow<'a> {
13 Slice(&'a [u8]),
15 StaticSlice(&'static [u8]),
17 Vec(Vec<u8>),
19 Bytes(Bytes),
21}
22
23impl Default for BytesCow<'_> {
24 fn default() -> Self {
25 Self::new()
26 }
27}
28
29impl<'a> BytesCow<'a> {
30 pub fn new() -> Self {
32 Self::from_static(b"")
33 }
34
35 pub fn from_static(slice: &'static [u8]) -> Self {
37 Self::StaticSlice(slice)
38 }
39
40 pub fn from_slice(slice: &'a [u8]) -> Self {
42 Self::Slice(slice)
43 }
44
45 pub fn from_bytes(bytes: Bytes) -> Self {
47 Self::Bytes(bytes)
48 }
49
50 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 pub fn from_vec(bytes: Vec<u8>) -> Self {
60 Self::Vec(bytes)
61 }
62
63 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 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}