1use std::borrow::Cow;
2use std::fmt::Debug;
3use std::hash::Hash;
4
5use bytes::Bytes;
6
7#[cfg(feature = "serde")]
8pub(crate) mod serde;
9
10#[derive(Clone, Eq)]
12pub enum BytesCow<'a> {
13 Slice(&'a [u8]),
15 StaticSlice(&'static [u8]),
17 Vec(Vec<u8>),
19 Bytes(Bytes),
21}
22
23impl Debug for BytesCow<'_> {
24 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
25 write!(f, "b\"")?;
28 for &b in self.as_bytes() {
29 if b == b'\n' {
31 write!(f, "\\n")?;
32 } else if b == b'\r' {
33 write!(f, "\\r")?;
34 } else if b == b'\t' {
35 write!(f, "\\t")?;
36 } else if b == b'\\' || b == b'"' {
37 write!(f, "\\{}", b as char)?;
38 } else if b == b'\0' {
39 write!(f, "\\0")?;
40 } else if (0x20..0x7f).contains(&b) {
42 write!(f, "{}", b as char)?;
43 } else {
44 write!(f, "\\x{b:02x}")?;
45 }
46 }
47 write!(f, "\"")?;
48 Ok(())
49 }
50}
51
52impl Default for BytesCow<'_> {
53 fn default() -> Self {
54 Self::new()
55 }
56}
57
58impl<'a> BytesCow<'a> {
59 pub fn new() -> Self {
61 Self::from_static(b"")
62 }
63
64 pub fn from_static(slice: &'static [u8]) -> Self {
66 Self::StaticSlice(slice)
67 }
68
69 pub fn from_slice(slice: &'a [u8]) -> Self {
71 Self::Slice(slice)
72 }
73
74 pub fn from_bytes(bytes: Bytes) -> Self {
76 Self::Bytes(bytes)
77 }
78
79 pub fn from_cow(cow: Cow<'a, [u8]>) -> Self {
81 match cow {
82 Cow::Borrowed(slice) => Self::Slice(slice),
83 Cow::Owned(bytes) => Self::Vec(bytes),
84 }
85 }
86
87 pub fn from_vec(bytes: Vec<u8>) -> Self {
89 Self::Vec(bytes)
90 }
91
92 pub fn into_bytes(self) -> Bytes {
94 match self {
95 Self::Slice(slice) => Bytes::copy_from_slice(slice),
96 Self::StaticSlice(slice) => Bytes::from_static(slice),
97 Self::Vec(bytes) => Bytes::from(bytes),
98 Self::Bytes(bytes) => bytes,
99 }
100 }
101
102 pub fn as_bytes(&self) -> &[u8] {
104 match self {
105 Self::Slice(slice) => slice,
106 Self::StaticSlice(slice) => slice,
107 Self::Vec(bytes) => bytes.as_slice(),
108 Self::Bytes(bytes) => bytes.as_ref(),
109 }
110 }
111
112 pub fn len(&self) -> usize {
114 match self {
115 Self::Slice(slice) => slice.len(),
116 Self::StaticSlice(slice) => slice.len(),
117 Self::Vec(bytes) => bytes.len(),
118 Self::Bytes(bytes) => bytes.len(),
119 }
120 }
121
122 pub fn is_empty(&self) -> bool {
124 match self {
125 Self::Slice(slice) => slice.is_empty(),
126 Self::StaticSlice(slice) => slice.is_empty(),
127 Self::Vec(bytes) => bytes.is_empty(),
128 Self::Bytes(bytes) => bytes.is_empty(),
129 }
130 }
131
132 pub fn pad_to_u64_be(&self) -> u64 {
141 assert!(self.len() <= 8);
142
143 let mut buf = [0u8; 8];
145 buf[8 - self.len()..].copy_from_slice(self.as_bytes());
146 u64::from_be_bytes(buf)
147 }
148
149 pub fn pad_to_u32_be(&self) -> u32 {
158 assert!(self.len() <= 4);
159
160 let mut buf = [0u8; 4];
162 buf[4 - self.len()..].copy_from_slice(self.as_bytes());
163 u32::from_be_bytes(buf)
164 }
165}
166
167impl<T> PartialEq<T> for BytesCow<'_>
168where
169 T: AsRef<[u8]>,
170{
171 fn eq(&self, other: &T) -> bool {
172 self.as_bytes() == other.as_ref()
173 }
174}
175
176impl Hash for BytesCow<'_> {
177 fn hash<H: std::hash::Hasher>(&self, state: &mut H) {
178 self.as_bytes().hash(state);
179 }
180}
181
182impl AsRef<[u8]> for BytesCow<'_> {
183 fn as_ref(&self) -> &[u8] {
184 self.as_bytes()
185 }
186}
187
188impl<'a> From<Cow<'a, [u8]>> for BytesCow<'a> {
189 fn from(cow: Cow<'a, [u8]>) -> Self {
190 BytesCow::from_cow(cow)
191 }
192}
193
194impl From<Bytes> for BytesCow<'_> {
195 fn from(bytes: Bytes) -> Self {
196 BytesCow::from_bytes(bytes)
197 }
198}
199
200impl<'a> From<&'a [u8]> for BytesCow<'a> {
201 fn from(bytes: &'a [u8]) -> Self {
202 BytesCow::from_slice(bytes)
203 }
204}
205
206impl From<Vec<u8>> for BytesCow<'_> {
207 fn from(bytes: Vec<u8>) -> Self {
208 BytesCow::from_vec(bytes)
209 }
210}
211
212#[cfg(test)]
213#[cfg_attr(all(test, coverage_nightly), coverage(off))]
214mod tests {
215 use super::BytesCow;
216
217 #[test]
218 fn constructors() {
219 let cow = BytesCow::default();
220 assert_eq!(cow.as_bytes(), b"");
221
222 let cow = BytesCow::from_static(b"hello");
223 assert_eq!(cow.as_bytes(), b"hello");
224
225 let cow = BytesCow::from_slice(b"world");
226 assert_eq!(cow.as_bytes(), b"world");
227
228 let cow = BytesCow::from_vec(vec![1, 2, 3]);
229 assert_eq!(cow.as_bytes(), &[1, 2, 3]);
230 let cow = BytesCow::from(vec![1, 2, 3]);
231 assert_eq!(cow.as_bytes(), &[1, 2, 3]);
232
233 let cow = BytesCow::from_bytes(bytes::Bytes::from_static(b"foo"));
234 assert_eq!(cow.as_bytes(), b"foo");
235 let cow = BytesCow::from(bytes::Bytes::from(vec![7, 8, 9]));
236 assert_eq!(cow.as_bytes(), &[7, 8, 9]);
237
238 let cow = BytesCow::from_cow(std::borrow::Cow::Borrowed(b"bar"));
239 assert_eq!(cow.as_bytes(), b"bar");
240 let cow = BytesCow::from_cow(std::borrow::Cow::Owned(vec![10, 11, 12]));
241 assert_eq!(cow.as_bytes(), &[10, 11, 12]);
242 let cow = BytesCow::from(std::borrow::Cow::Owned(vec![4, 5, 6]));
243 assert_eq!(cow.as_bytes(), &[4, 5, 6]);
244
245 let cow = BytesCow::from(&b"hello world"[..]);
246 assert_eq!(cow.as_bytes(), b"hello world");
247 }
248
249 #[test]
250 fn into_bytes() {
251 let cow = BytesCow::from_static(b"hello");
252 assert_eq!(cow.into_bytes(), bytes::Bytes::from_static(b"hello"));
253
254 let cow = BytesCow::from_slice(b"world");
255 assert_eq!(cow.into_bytes(), bytes::Bytes::from_static(b"world"));
256
257 let cow = BytesCow::from_vec(vec![1, 2, 3]);
258 assert_eq!(cow.into_bytes(), bytes::Bytes::from(vec![1, 2, 3]));
259
260 let cow = BytesCow::from_bytes(bytes::Bytes::from_static(b"foo"));
261 assert_eq!(cow.into_bytes(), bytes::Bytes::from_static(b"foo"));
262
263 let cow = BytesCow::from_cow(std::borrow::Cow::Borrowed(b"bar"));
264 assert_eq!(cow.into_bytes(), bytes::Bytes::from_static(b"bar"));
265
266 let cow = BytesCow::from_cow(std::borrow::Cow::Owned(vec![10, 11, 12]));
267 assert_eq!(cow.into_bytes(), bytes::Bytes::from(vec![10, 11, 12]));
268 }
269
270 #[test]
271 fn as_ref() {
272 let cow = BytesCow::from_static(b"hello");
273 assert_eq!(cow.as_ref(), b"hello");
274
275 let cow = BytesCow::from_slice(b"world");
276 assert_eq!(cow.as_ref(), b"world");
277
278 let cow = BytesCow::from_vec(vec![1, 2, 3]);
279 assert_eq!(cow.as_ref(), &[1, 2, 3]);
280
281 let cow = BytesCow::from_bytes(bytes::Bytes::from_static(b"foo"));
282 assert_eq!(cow.as_ref(), b"foo");
283 }
284
285 #[test]
286 fn partial_eq() {
287 let cow = BytesCow::from_static(b"hello");
288 assert!(cow == b"hello");
289 assert!(cow != b"world");
290
291 let cow = BytesCow::from_slice(b"world");
292 assert!(cow == b"world");
293 assert!(cow != b"hello");
294
295 let cow = BytesCow::from_vec(vec![1, 2, 3]);
296 assert!(cow == [1, 2, 3]);
297 assert!(cow != [4, 5, 6]);
298 }
299
300 #[test]
301 fn hash() {
302 use std::collections::hash_map::DefaultHasher;
303 use std::hash::{Hash, Hasher};
304
305 let mut hasher = DefaultHasher::new();
306 b"hello".hash(&mut hasher);
307 let expected_hash = hasher.finish();
308
309 let cow = BytesCow::from_static(b"hello");
310 let mut hasher = DefaultHasher::new();
311 cow.hash(&mut hasher);
312 assert_eq!(hasher.finish(), expected_hash);
313 }
314}