1use core::hash;
16use core::ops;
17use std::fmt;
18use std::string::FromUtf8Error;
19
20pub struct ByteStr {
23 bytes: [u8],
24}
25
26impl ByteStr {
27 #[inline]
28 fn from_bytes(slice: &[u8]) -> &ByteStr {
29 unsafe { &*(slice as *const [u8] as *const ByteStr) }
30 }
31
32 #[inline]
33 fn from_bytes_mut(slice: &mut [u8]) -> &mut ByteStr {
34 unsafe { &mut *(slice as *mut [u8] as *mut ByteStr) }
35 }
36
37 #[inline]
38 pub fn as_bytes(&self) -> &[u8] {
39 &self.bytes
40 }
41}
42
43impl ops::Deref for ByteStr {
44 type Target = [u8];
45
46 #[inline]
47 fn deref(&self) -> &[u8] {
48 &self.bytes
49 }
50}
51
52impl ops::DerefMut for ByteStr {
53 #[inline]
54 fn deref_mut(&mut self) -> &mut [u8] {
55 &mut self.bytes
56 }
57}
58
59impl AsRef<[u8]> for ByteStr {
60 #[inline]
61 fn as_ref(&self) -> &[u8] {
62 &self.bytes
63 }
64}
65
66impl AsMut<[u8]> for ByteStr {
67 #[inline]
68 fn as_mut(&mut self) -> &mut [u8] {
69 &mut self.bytes
70 }
71}
72
73impl fmt::Debug for ByteStr {
75 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
76 write!(f, "b\"")?;
77 for &b in &self.bytes {
78 if b == b'\n' {
80 write!(f, "\\n")?;
81 } else if b == b'\r' {
82 write!(f, "\\r")?;
83 } else if b == b'\t' {
84 write!(f, "\\t")?;
85 } else if b == b'\\' || b == b'"' {
86 write!(f, "\\{}", b as char)?;
87 } else if b == b'\0' {
88 write!(f, "\\0")?;
89 } else if (0x20..0x7f).contains(&b) {
91 write!(f, "{}", b as char)?;
92 } else {
93 write!(f, "\\x{:02x}", b)?;
94 }
95 }
96 write!(f, "\"")?;
97 Ok(())
98 }
99}
100
101impl fmt::Display for ByteStr {
102 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
103 fmt::Display::fmt(&String::from_utf8_lossy(&self.bytes), f)
104 }
105}
106
107impl ops::Index<usize> for ByteStr {
108 type Output = u8;
109
110 #[inline]
111 fn index(&self, idx: usize) -> &u8 {
112 &self.as_bytes()[idx]
113 }
114}
115
116impl ops::Index<ops::RangeFull> for ByteStr {
117 type Output = ByteStr;
118
119 #[inline]
120 fn index(&self, _: ops::RangeFull) -> &ByteStr {
121 self
122 }
123}
124
125impl ops::Index<ops::Range<usize>> for ByteStr {
126 type Output = ByteStr;
127
128 #[inline]
129 fn index(&self, r: ops::Range<usize>) -> &ByteStr {
130 ByteStr::from_bytes(&self.as_bytes()[r.start..r.end])
131 }
132}
133
134impl ops::Index<ops::RangeInclusive<usize>> for ByteStr {
135 type Output = ByteStr;
136
137 #[inline]
138 fn index(&self, r: ops::RangeInclusive<usize>) -> &ByteStr {
139 ByteStr::from_bytes(&self.as_bytes()[*r.start()..=*r.end()])
140 }
141}
142
143impl ops::Index<ops::RangeFrom<usize>> for ByteStr {
144 type Output = ByteStr;
145
146 #[inline]
147 fn index(&self, r: ops::RangeFrom<usize>) -> &ByteStr {
148 ByteStr::from_bytes(&self.as_bytes()[r.start..])
149 }
150}
151
152impl ops::Index<ops::RangeTo<usize>> for ByteStr {
153 type Output = ByteStr;
154
155 #[inline]
156 fn index(&self, r: ops::RangeTo<usize>) -> &ByteStr {
157 ByteStr::from_bytes(&self.as_bytes()[..r.end])
158 }
159}
160
161impl ops::Index<ops::RangeToInclusive<usize>> for ByteStr {
162 type Output = ByteStr;
163
164 #[inline]
165 fn index(&self, r: ops::RangeToInclusive<usize>) -> &ByteStr {
166 ByteStr::from_bytes(&self.as_bytes()[..=r.end])
167 }
168}
169
170impl ops::IndexMut<usize> for ByteStr {
171 #[inline]
172 fn index_mut(&mut self, idx: usize) -> &mut u8 {
173 &mut self.bytes[idx]
174 }
175}
176
177impl ops::IndexMut<ops::RangeFull> for ByteStr {
178 #[inline]
179 fn index_mut(&mut self, _: ops::RangeFull) -> &mut ByteStr {
180 self
181 }
182}
183
184impl ops::IndexMut<ops::Range<usize>> for ByteStr {
185 #[inline]
186 fn index_mut(&mut self, r: ops::Range<usize>) -> &mut ByteStr {
187 ByteStr::from_bytes_mut(&mut self.bytes[r.start..r.end])
188 }
189}
190
191impl ops::IndexMut<ops::RangeInclusive<usize>> for ByteStr {
192 #[inline]
193 fn index_mut(&mut self, r: ops::RangeInclusive<usize>) -> &mut ByteStr {
194 ByteStr::from_bytes_mut(&mut self.bytes[*r.start()..=*r.end()])
195 }
196}
197
198impl ops::IndexMut<ops::RangeFrom<usize>> for ByteStr {
199 #[inline]
200 fn index_mut(&mut self, r: ops::RangeFrom<usize>) -> &mut ByteStr {
201 ByteStr::from_bytes_mut(&mut self.bytes[r.start..])
202 }
203}
204
205impl ops::IndexMut<ops::RangeTo<usize>> for ByteStr {
206 #[inline]
207 fn index_mut(&mut self, r: ops::RangeTo<usize>) -> &mut ByteStr {
208 ByteStr::from_bytes_mut(&mut self.bytes[..r.end])
209 }
210}
211
212impl ops::IndexMut<ops::RangeToInclusive<usize>> for ByteStr {
213 #[inline]
214 fn index_mut(&mut self, r: ops::RangeToInclusive<usize>) -> &mut ByteStr {
215 ByteStr::from_bytes_mut(&mut self.bytes[..=r.end])
216 }
217}
218
219impl Eq for ByteStr {}
220
221impl PartialEq<ByteStr> for ByteStr {
222 #[inline]
223 fn eq(&self, other: &ByteStr) -> bool {
224 self.as_bytes() == other.as_bytes()
225 }
226}
227
228impl PartialEq<String> for ByteStr {
229 #[inline]
230 fn eq(&self, other: &String) -> bool {
231 self.as_bytes() == other.as_bytes()
232 }
233}
234
235impl PartialEq<Vec<u8>> for ByteStr {
236 #[inline]
237 fn eq(&self, other: &Vec<u8>) -> bool {
238 self.as_bytes() == other.as_slice()
239 }
240}
241
242impl PartialEq<str> for ByteStr {
243 #[inline]
244 fn eq(&self, other: &str) -> bool {
245 self.as_bytes() == other.as_bytes()
246 }
247}
248
249impl PartialEq<&str> for ByteStr {
250 #[inline]
251 fn eq(&self, other: &&str) -> bool {
252 self.as_bytes() == other.as_bytes()
253 }
254}
255
256impl PartialEq<[u8]> for ByteStr {
257 #[inline]
258 fn eq(&self, other: &[u8]) -> bool {
259 self.as_bytes() == other
260 }
261}
262
263impl PartialEq<&[u8]> for ByteStr {
264 #[inline]
265 fn eq(&self, other: &&[u8]) -> bool {
266 self.as_bytes() == *other
267 }
268}
269
270impl PartialEq<ByteStr> for String {
271 #[inline]
272 fn eq(&self, other: &ByteStr) -> bool {
273 *other == *self
274 }
275}
276
277impl PartialEq<ByteStr> for Vec<u8> {
278 #[inline]
279 fn eq(&self, other: &ByteStr) -> bool {
280 *other == *self
281 }
282}
283
284impl PartialEq<ByteStr> for str {
285 #[inline]
286 fn eq(&self, other: &ByteStr) -> bool {
287 *other == *self
288 }
289}
290
291impl PartialEq<ByteStr> for &str {
292 #[inline]
293 fn eq(&self, other: &ByteStr) -> bool {
294 *other == *self
295 }
296}
297
298impl PartialEq<ByteStr> for &[u8] {
299 #[inline]
300 fn eq(&self, other: &ByteStr) -> bool {
301 *other == *self
302 }
303}
304
305impl PartialEq<ByteStr> for [u8] {
306 #[inline]
307 fn eq(&self, other: &ByteStr) -> bool {
308 *other == *self
309 }
310}
311
312impl hash::Hash for ByteStr {
313 fn hash<H>(&self, state: &mut H)
314 where
315 H: hash::Hasher,
316 {
317 self.as_bytes().hash(state);
318 }
319}
320
321#[derive(Default, Eq, Clone)]
324pub struct ByteString {
325 bytes: Vec<u8>,
326}
327
328impl ByteString {
329 pub fn new() -> Self {
330 Self::default()
331 }
332
333 pub fn is_empty(&self) -> bool {
334 self.as_ref().is_empty()
335 }
336
337 pub fn len(&self) -> usize {
338 self.as_ref().len()
339 }
340
341 pub fn as_bytes(&self) -> &[u8] {
342 self.as_ref()
343 }
344
345 pub fn into_bytes(self) -> Vec<u8> {
346 self.bytes
347 }
348
349 pub fn into_string(self) -> Result<String, FromUtf8Error> {
350 String::from_utf8(self.bytes)
351 }
352}
353
354impl ops::Deref for ByteString {
355 type Target = ByteStr;
356
357 #[inline]
358 fn deref(&self) -> &ByteStr {
359 ByteStr::from_bytes(&self.bytes)
360 }
361}
362
363impl ops::DerefMut for ByteString {
364 #[inline]
365 fn deref_mut(&mut self) -> &mut ByteStr {
366 ByteStr::from_bytes_mut(&mut self.bytes)
367 }
368}
369
370impl AsRef<[u8]> for ByteString {
371 #[inline]
372 fn as_ref(&self) -> &[u8] {
373 &self.bytes
374 }
375}
376
377impl AsMut<[u8]> for ByteString {
378 #[inline]
379 fn as_mut(&mut self) -> &mut [u8] {
380 &mut self.bytes
381 }
382}
383
384impl fmt::Display for ByteString {
385 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
386 fmt::Display::fmt(&**self, f)
387 }
388}
389
390impl fmt::Debug for ByteString {
391 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
392 fmt::Debug::fmt(&**self, f)
393 }
394}
395
396impl From<Vec<u8>> for ByteString {
397 #[inline]
398 fn from(bytes: Vec<u8>) -> Self {
399 ByteString { bytes }
400 }
401}
402
403impl From<&[u8]> for ByteString {
404 #[inline]
405 fn from(bytes: &[u8]) -> Self {
406 bytes.to_owned().into()
407 }
408}
409
410impl From<String> for ByteString {
411 #[inline]
412 fn from(text: String) -> Self {
413 text.into_bytes().into()
414 }
415}
416
417impl From<&str> for ByteString {
418 #[inline]
419 fn from(text: &str) -> Self {
420 text.to_owned().into()
421 }
422}
423
424impl From<&ByteString> for ByteString {
425 #[inline]
426 fn from(data: &ByteString) -> Self {
427 data.clone()
428 }
429}
430
431impl PartialEq for ByteString {
432 #[inline]
433 fn eq(&self, other: &ByteString) -> bool {
434 self.bytes == other.bytes
435 }
436}
437
438impl PartialEq<String> for ByteString {
439 #[inline]
440 fn eq(&self, other: &String) -> bool {
441 self.as_ref() == other.as_bytes()
442 }
443}
444
445impl PartialEq<Vec<u8>> for ByteString {
446 #[inline]
447 fn eq(&self, other: &Vec<u8>) -> bool {
448 self.as_ref() == other.as_slice()
449 }
450}
451
452impl PartialEq<str> for ByteString {
453 #[inline]
454 fn eq(&self, other: &str) -> bool {
455 self.as_ref() == other.as_bytes()
456 }
457}
458
459impl PartialEq<&str> for ByteString {
460 #[inline]
461 fn eq(&self, other: &&str) -> bool {
462 self.as_ref() == other.as_bytes()
463 }
464}
465
466impl PartialEq<[u8]> for ByteString {
467 #[inline]
468 fn eq(&self, other: &[u8]) -> bool {
469 self.as_ref() == other
470 }
471}
472
473impl PartialEq<&[u8]> for ByteString {
474 #[inline]
475 fn eq(&self, other: &&[u8]) -> bool {
476 self.as_ref() == *other
477 }
478}
479
480impl PartialEq<ByteString> for String {
481 #[inline]
482 fn eq(&self, other: &ByteString) -> bool {
483 *other == *self
484 }
485}
486
487impl PartialEq<ByteString> for Vec<u8> {
488 #[inline]
489 fn eq(&self, other: &ByteString) -> bool {
490 *other == *self
491 }
492}
493
494impl PartialEq<ByteString> for str {
495 #[inline]
496 fn eq(&self, other: &ByteString) -> bool {
497 *other == *self
498 }
499}
500
501impl PartialEq<ByteString> for &str {
502 #[inline]
503 fn eq(&self, other: &ByteString) -> bool {
504 *other == *self
505 }
506}
507
508impl PartialEq<ByteString> for [u8] {
509 #[inline]
510 fn eq(&self, other: &ByteString) -> bool {
511 *other == *self
512 }
513}
514
515impl PartialEq<ByteString> for &[u8] {
516 #[inline]
517 fn eq(&self, other: &ByteString) -> bool {
518 *other == *self
519 }
520}
521
522impl hash::Hash for ByteString {
523 fn hash<H>(&self, state: &mut H)
524 where
525 H: hash::Hasher,
526 {
527 (&**self).hash(state);
528 }
529}
530
531#[cfg(test)]
532mod tests {
533 use super::*;
534 use std::collections::hash_map::DefaultHasher;
535 use std::hash::{Hash, Hasher};
536
537 #[test]
538 fn test_bytestring_bstr_utf8() {
539 use bstr::ByteSlice;
540
541 let string: ByteString = "hello".into();
542 assert_eq!(string.is_utf8(), true);
543 assert_eq!(string.starts_with_str("hel"), true);
544 assert_eq!(string.ends_with_str("lo"), true);
545 }
546
547 #[test]
548 fn test_bytestring_bstr_bytes() {
549 use bstr::ByteSlice;
550
551 let bytes: ByteString = vec![144u8, 145u8, 146u8].into();
552 assert_eq!(bytes.is_utf8(), false);
553 assert_eq!(bytes.starts_with_str(b"\x90"), true);
554 assert_eq!(bytes.ends_with_str(b"\x92"), true);
555 }
556
557 #[test]
558 fn test_bytestring_display_utf8() {
559 let string: ByteString = "utf-8 encoded string".into();
560
561 assert_eq!(format!("{}", string), "utf-8 encoded string");
562 }
563
564 #[test]
565 fn test_bytestring_debug_utf8() {
566 let string: ByteString = "utf-8 encoded string".into();
567
568 assert_eq!(format!("{:?}", string), "b\"utf-8 encoded string\"");
569 }
570
571 #[test]
572 fn test_bytestring_display_bytes() {
573 let bytes: ByteString = vec![144u8, 145u8, 146u8].into();
574
575 assert_eq!(format!("{}", bytes), "���");
576 }
577
578 #[test]
579 fn test_bytestring_debug_bytes() {
580 let bytes: ByteString = vec![144u8, 145u8, 146u8].into();
581
582 assert_eq!(format!("{:?}", bytes), "b\"\\x90\\x91\\x92\"");
583 }
584
585 #[test]
586 fn test_bytestring_as_ref() {
587 fn receive<T>(value: T)
588 where
589 T: AsRef<[u8]>,
590 {
591 value.as_ref();
592 }
593
594 let string: ByteString = "utf-8 encoded string".into();
595 receive(string);
596
597 let bytes: ByteString = vec![144u8, 145u8, 146u8].into();
598 receive(bytes);
599 }
600
601 #[test]
602 fn test_bytestring_substr_eq_utf8() {
603 let string: ByteString = "hello".into();
604
605 assert_eq!(string[1..=3], "ell");
606 assert_eq!(string[1..=3], "ell".to_owned());
607
608 assert_eq!("ell", string[1..=3]);
609 assert_eq!("ell".to_owned(), string[1..=3]);
610 }
611
612 #[test]
613 fn test_bytestring_substr_eq_bytes() {
614 let bytes: ByteString = vec![144u8, 145u8, 146u8].into();
615
616 assert_eq!(bytes[1..2], b"\x91" as &[u8]);
617 assert_eq!(bytes[1..2], b"\x91".to_vec());
618
619 assert_eq!(b"\x91" as &[u8], bytes[1..2]);
620 assert_eq!(b"\x91".to_vec(), bytes[1..2]);
621 }
622
623 #[test]
624 #[allow(clippy::eq_op)]
625 fn test_bytestring_eq_string() {
626 let string: ByteString = "utf-8 encoded string".into();
627
628 assert_eq!(string, "utf-8 encoded string");
629 assert_eq!(string, b"utf-8 encoded string" as &[u8]);
630
631 assert_eq!("utf-8 encoded string", string);
632 assert_eq!(b"utf-8 encoded string" as &[u8], string);
633
634 assert_eq!(string, string);
635 }
636
637 #[test]
638 #[allow(clippy::eq_op)]
639 fn test_bytestring_eq_bytes() {
640 let bytes: ByteString = vec![144u8, 145u8, 146u8].into();
641
642 assert_eq!(bytes, vec![144u8, 145u8, 146u8]);
643 assert_eq!(bytes, b"\x90\x91\x92" as &[u8]);
644
645 assert_eq!(vec![144u8, 145u8, 146u8], bytes);
646 assert_eq!(b"\x90\x91\x92" as &[u8], bytes);
647
648 assert_eq!(bytes, bytes);
649 }
650
651 fn hash<T: Hash>(t: &T) -> u64 {
652 let mut h = DefaultHasher::new();
653 t.hash(&mut h);
654 h.finish()
655 }
656
657 #[test]
658 fn test_bytestring_hash_string() {
659 let string: ByteString = "utf-8 encoded string".into();
660
661 assert_ne!(hash(&string), hash(&"utf-8 encoded string"));
662 assert_eq!(hash(&string), hash(&b"utf-8 encoded string"));
663
664 assert_ne!(hash(&"utf-8 encoded string"), hash(&string));
665 assert_eq!(hash(&b"utf-8 encoded string"), hash(&string));
666 }
667
668 #[test]
669 fn test_bytestring_hash_bytes() {
670 let bytes: ByteString = vec![144u8, 145u8, 146u8].into();
671
672 assert_eq!(hash(&bytes), hash(&vec![144u8, 145u8, 146u8]));
673 assert_eq!(hash(&bytes), hash(&[144u8, 145u8, 146u8]));
674
675 assert_eq!(hash(&vec![144u8, 145u8, 146u8]), hash(&bytes));
676 assert_eq!(hash(&[144u8, 145u8, 146u8]), hash(&bytes));
677 }
678}