1use crate::borrow::{Borrow, BorrowMut};
4use crate::cmp::Ordering;
5use crate::ops::{
6    Deref, DerefMut, DerefPure, Index, IndexMut, Range, RangeFrom, RangeFull, RangeInclusive,
7    RangeTo, RangeToInclusive,
8};
9use crate::{fmt, hash};
10
11#[unstable(feature = "bstr", issue = "134915")]
41#[repr(transparent)]
42#[doc(alias = "BStr")]
43pub struct ByteStr(pub [u8]);
44
45impl ByteStr {
46    #[inline]
65    #[unstable(feature = "bstr", issue = "134915")]
66    pub fn new<B: ?Sized + AsRef<[u8]>>(bytes: &B) -> &Self {
67        ByteStr::from_bytes(bytes.as_ref())
68    }
69
70    #[doc(hidden)]
71    #[unstable(feature = "bstr_internals", issue = "none")]
72    #[inline]
73    pub fn from_bytes(slice: &[u8]) -> &Self {
74        unsafe { &*(slice as *const [u8] as *const Self) }
77    }
78
79    #[doc(hidden)]
80    #[unstable(feature = "bstr_internals", issue = "none")]
81    #[inline]
82    pub fn from_bytes_mut(slice: &mut [u8]) -> &mut Self {
83        unsafe { &mut *(slice as *mut [u8] as *mut Self) }
86    }
87
88    #[doc(hidden)]
89    #[unstable(feature = "bstr_internals", issue = "none")]
90    #[inline]
91    pub fn as_bytes(&self) -> &[u8] {
92        &self.0
93    }
94}
95
96#[unstable(feature = "bstr", issue = "134915")]
97impl Deref for ByteStr {
98    type Target = [u8];
99
100    #[inline]
101    fn deref(&self) -> &[u8] {
102        &self.0
103    }
104}
105
106#[unstable(feature = "bstr", issue = "134915")]
107impl DerefMut for ByteStr {
108    #[inline]
109    fn deref_mut(&mut self) -> &mut [u8] {
110        &mut self.0
111    }
112}
113
114#[unstable(feature = "deref_pure_trait", issue = "87121")]
115unsafe impl DerefPure for ByteStr {}
116
117#[unstable(feature = "bstr", issue = "134915")]
118impl fmt::Debug for ByteStr {
119    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
120        write!(f, "\"")?;
121        for chunk in self.utf8_chunks() {
122            for c in chunk.valid().chars() {
123                match c {
124                    '\0' => write!(f, "\\0")?,
125                    '\x01'..='\x7f' => write!(f, "{}", (c as u8).escape_ascii())?,
126                    _ => write!(f, "{}", c.escape_debug())?,
127                }
128            }
129            write!(f, "{}", chunk.invalid().escape_ascii())?;
130        }
131        write!(f, "\"")?;
132        Ok(())
133    }
134}
135
136#[unstable(feature = "bstr", issue = "134915")]
137impl fmt::Display for ByteStr {
138    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
139        fn fmt_nopad(this: &ByteStr, f: &mut fmt::Formatter<'_>) -> fmt::Result {
140            for chunk in this.utf8_chunks() {
141                f.write_str(chunk.valid())?;
142                if !chunk.invalid().is_empty() {
143                    f.write_str("\u{FFFD}")?;
144                }
145            }
146            Ok(())
147        }
148
149        let Some(align) = f.align() else {
150            return fmt_nopad(self, f);
151        };
152        let nchars: usize = self
153            .utf8_chunks()
154            .map(|chunk| chunk.valid().len() + if chunk.invalid().is_empty() { 0 } else { 1 })
155            .sum();
156        let padding = f.width().unwrap_or(0).saturating_sub(nchars);
157        let fill = f.fill();
158        let (lpad, rpad) = match align {
159            fmt::Alignment::Left => (0, padding),
160            fmt::Alignment::Right => (padding, 0),
161            fmt::Alignment::Center => {
162                let half = padding / 2;
163                (half, half + padding % 2)
164            }
165        };
166        for _ in 0..lpad {
167            write!(f, "{fill}")?;
168        }
169        fmt_nopad(self, f)?;
170        for _ in 0..rpad {
171            write!(f, "{fill}")?;
172        }
173
174        Ok(())
175    }
176}
177
178#[unstable(feature = "bstr", issue = "134915")]
179impl AsRef<[u8]> for ByteStr {
180    #[inline]
181    fn as_ref(&self) -> &[u8] {
182        &self.0
183    }
184}
185
186#[unstable(feature = "bstr", issue = "134915")]
187impl AsRef<ByteStr> for ByteStr {
188    #[inline]
189    fn as_ref(&self) -> &ByteStr {
190        self
191    }
192}
193
194#[unstable(feature = "bstr", issue = "134915")]
197impl AsRef<ByteStr> for str {
198    #[inline]
199    fn as_ref(&self) -> &ByteStr {
200        ByteStr::new(self)
201    }
202}
203
204#[unstable(feature = "bstr", issue = "134915")]
205impl AsMut<[u8]> for ByteStr {
206    #[inline]
207    fn as_mut(&mut self) -> &mut [u8] {
208        &mut self.0
209    }
210}
211
212#[unstable(feature = "bstr", issue = "134915")]
219impl Borrow<[u8]> for ByteStr {
220    #[inline]
221    fn borrow(&self) -> &[u8] {
222        &self.0
223    }
224}
225
226#[unstable(feature = "bstr", issue = "134915")]
229impl BorrowMut<[u8]> for ByteStr {
230    #[inline]
231    fn borrow_mut(&mut self) -> &mut [u8] {
232        &mut self.0
233    }
234}
235
236#[unstable(feature = "bstr", issue = "134915")]
237impl<'a> Default for &'a ByteStr {
238    fn default() -> Self {
239        ByteStr::from_bytes(b"")
240    }
241}
242
243#[unstable(feature = "bstr", issue = "134915")]
244impl<'a> Default for &'a mut ByteStr {
245    fn default() -> Self {
246        ByteStr::from_bytes_mut(&mut [])
247    }
248}
249
250#[unstable(feature = "bstr", issue = "134915")]
297impl hash::Hash for ByteStr {
298    #[inline]
299    fn hash<H: hash::Hasher>(&self, state: &mut H) {
300        self.0.hash(state);
301    }
302}
303
304#[unstable(feature = "bstr", issue = "134915")]
305impl Index<usize> for ByteStr {
306    type Output = u8;
307
308    #[inline]
309    fn index(&self, idx: usize) -> &u8 {
310        &self.0[idx]
311    }
312}
313
314#[unstable(feature = "bstr", issue = "134915")]
315impl Index<RangeFull> for ByteStr {
316    type Output = ByteStr;
317
318    #[inline]
319    fn index(&self, _: RangeFull) -> &ByteStr {
320        self
321    }
322}
323
324#[unstable(feature = "bstr", issue = "134915")]
325impl Index<Range<usize>> for ByteStr {
326    type Output = ByteStr;
327
328    #[inline]
329    fn index(&self, r: Range<usize>) -> &ByteStr {
330        ByteStr::from_bytes(&self.0[r])
331    }
332}
333
334#[unstable(feature = "bstr", issue = "134915")]
335impl Index<RangeInclusive<usize>> for ByteStr {
336    type Output = ByteStr;
337
338    #[inline]
339    fn index(&self, r: RangeInclusive<usize>) -> &ByteStr {
340        ByteStr::from_bytes(&self.0[r])
341    }
342}
343
344#[unstable(feature = "bstr", issue = "134915")]
345impl Index<RangeFrom<usize>> for ByteStr {
346    type Output = ByteStr;
347
348    #[inline]
349    fn index(&self, r: RangeFrom<usize>) -> &ByteStr {
350        ByteStr::from_bytes(&self.0[r])
351    }
352}
353
354#[unstable(feature = "bstr", issue = "134915")]
355impl Index<RangeTo<usize>> for ByteStr {
356    type Output = ByteStr;
357
358    #[inline]
359    fn index(&self, r: RangeTo<usize>) -> &ByteStr {
360        ByteStr::from_bytes(&self.0[r])
361    }
362}
363
364#[unstable(feature = "bstr", issue = "134915")]
365impl Index<RangeToInclusive<usize>> for ByteStr {
366    type Output = ByteStr;
367
368    #[inline]
369    fn index(&self, r: RangeToInclusive<usize>) -> &ByteStr {
370        ByteStr::from_bytes(&self.0[r])
371    }
372}
373
374#[unstable(feature = "bstr", issue = "134915")]
375impl IndexMut<usize> for ByteStr {
376    #[inline]
377    fn index_mut(&mut self, idx: usize) -> &mut u8 {
378        &mut self.0[idx]
379    }
380}
381
382#[unstable(feature = "bstr", issue = "134915")]
383impl IndexMut<RangeFull> for ByteStr {
384    #[inline]
385    fn index_mut(&mut self, _: RangeFull) -> &mut ByteStr {
386        self
387    }
388}
389
390#[unstable(feature = "bstr", issue = "134915")]
391impl IndexMut<Range<usize>> for ByteStr {
392    #[inline]
393    fn index_mut(&mut self, r: Range<usize>) -> &mut ByteStr {
394        ByteStr::from_bytes_mut(&mut self.0[r])
395    }
396}
397
398#[unstable(feature = "bstr", issue = "134915")]
399impl IndexMut<RangeInclusive<usize>> for ByteStr {
400    #[inline]
401    fn index_mut(&mut self, r: RangeInclusive<usize>) -> &mut ByteStr {
402        ByteStr::from_bytes_mut(&mut self.0[r])
403    }
404}
405
406#[unstable(feature = "bstr", issue = "134915")]
407impl IndexMut<RangeFrom<usize>> for ByteStr {
408    #[inline]
409    fn index_mut(&mut self, r: RangeFrom<usize>) -> &mut ByteStr {
410        ByteStr::from_bytes_mut(&mut self.0[r])
411    }
412}
413
414#[unstable(feature = "bstr", issue = "134915")]
415impl IndexMut<RangeTo<usize>> for ByteStr {
416    #[inline]
417    fn index_mut(&mut self, r: RangeTo<usize>) -> &mut ByteStr {
418        ByteStr::from_bytes_mut(&mut self.0[r])
419    }
420}
421
422#[unstable(feature = "bstr", issue = "134915")]
423impl IndexMut<RangeToInclusive<usize>> for ByteStr {
424    #[inline]
425    fn index_mut(&mut self, r: RangeToInclusive<usize>) -> &mut ByteStr {
426        ByteStr::from_bytes_mut(&mut self.0[r])
427    }
428}
429
430#[unstable(feature = "bstr", issue = "134915")]
431impl Eq for ByteStr {}
432
433#[unstable(feature = "bstr", issue = "134915")]
434impl PartialEq<ByteStr> for ByteStr {
435    #[inline]
436    fn eq(&self, other: &ByteStr) -> bool {
437        &self.0 == &other.0
438    }
439}
440
441#[doc(hidden)]
442#[macro_export]
443#[unstable(feature = "bstr_internals", issue = "none")]
444macro_rules! impl_partial_eq {
445    ($lhs:ty, $rhs:ty) => {
446        #[allow(unused_lifetimes)]
447        impl<'a> PartialEq<$rhs> for $lhs {
448            #[inline]
449            fn eq(&self, other: &$rhs) -> bool {
450                let other: &[u8] = other.as_ref();
451                PartialEq::eq(self.as_bytes(), other)
452            }
453        }
454
455        #[allow(unused_lifetimes)]
456        impl<'a> PartialEq<$lhs> for $rhs {
457            #[inline]
458            fn eq(&self, other: &$lhs) -> bool {
459                let this: &[u8] = self.as_ref();
460                PartialEq::eq(this, other.as_bytes())
461            }
462        }
463    };
464}
465
466#[doc(hidden)]
467#[unstable(feature = "bstr_internals", issue = "none")]
468pub use impl_partial_eq;
469
470#[doc(hidden)]
471#[macro_export]
472#[unstable(feature = "bstr_internals", issue = "none")]
473macro_rules! impl_partial_eq_ord {
474    ($lhs:ty, $rhs:ty) => {
475        $crate::bstr::impl_partial_eq!($lhs, $rhs);
476
477        #[allow(unused_lifetimes)]
478        #[unstable(feature = "bstr", issue = "134915")]
479        impl<'a> PartialOrd<$rhs> for $lhs {
480            #[inline]
481            fn partial_cmp(&self, other: &$rhs) -> Option<Ordering> {
482                let other: &[u8] = other.as_ref();
483                PartialOrd::partial_cmp(self.as_bytes(), other)
484            }
485        }
486
487        #[allow(unused_lifetimes)]
488        #[unstable(feature = "bstr", issue = "134915")]
489        impl<'a> PartialOrd<$lhs> for $rhs {
490            #[inline]
491            fn partial_cmp(&self, other: &$lhs) -> Option<Ordering> {
492                let this: &[u8] = self.as_ref();
493                PartialOrd::partial_cmp(this, other.as_bytes())
494            }
495        }
496    };
497}
498
499#[doc(hidden)]
500#[unstable(feature = "bstr_internals", issue = "none")]
501pub use impl_partial_eq_ord;
502
503#[doc(hidden)]
504#[macro_export]
505#[unstable(feature = "bstr_internals", issue = "none")]
506macro_rules! impl_partial_eq_n {
507    ($lhs:ty, $rhs:ty) => {
508        #[allow(unused_lifetimes)]
509        #[unstable(feature = "bstr", issue = "134915")]
510        impl<const N: usize> PartialEq<$rhs> for $lhs {
511            #[inline]
512            fn eq(&self, other: &$rhs) -> bool {
513                let other: &[u8] = other.as_ref();
514                PartialEq::eq(self.as_bytes(), other)
515            }
516        }
517
518        #[allow(unused_lifetimes)]
519        #[unstable(feature = "bstr", issue = "134915")]
520        impl<const N: usize> PartialEq<$lhs> for $rhs {
521            #[inline]
522            fn eq(&self, other: &$lhs) -> bool {
523                let this: &[u8] = self.as_ref();
524                PartialEq::eq(this, other.as_bytes())
525            }
526        }
527    };
528}
529
530#[doc(hidden)]
531#[unstable(feature = "bstr_internals", issue = "none")]
532pub use impl_partial_eq_n;
533
534impl_partial_eq!(ByteStr, [u8]);
536impl_partial_eq!(ByteStr, &[u8]);
538impl_partial_eq!(ByteStr, str);
540impl_partial_eq!(ByteStr, &str);
542impl_partial_eq_n!(ByteStr, [u8; N]);
544impl_partial_eq_n!(ByteStr, &[u8; N]);
546
547#[unstable(feature = "bstr", issue = "134915")]
548impl Ord for ByteStr {
549    #[inline]
550    fn cmp(&self, other: &ByteStr) -> Ordering {
551        Ord::cmp(&self.0, &other.0)
552    }
553}
554
555#[unstable(feature = "bstr", issue = "134915")]
556impl PartialOrd for ByteStr {
557    #[inline]
558    fn partial_cmp(&self, other: &ByteStr) -> Option<Ordering> {
559        PartialOrd::partial_cmp(&self.0, &other.0)
560    }
561}
562
563#[unstable(feature = "bstr", issue = "134915")]
564impl<'a> TryFrom<&'a ByteStr> for &'a str {
565    type Error = crate::str::Utf8Error;
566
567    #[inline]
568    fn try_from(s: &'a ByteStr) -> Result<Self, Self::Error> {
569        crate::str::from_utf8(&s.0)
570    }
571}
572
573#[unstable(feature = "bstr", issue = "134915")]
574impl<'a> TryFrom<&'a mut ByteStr> for &'a mut str {
575    type Error = crate::str::Utf8Error;
576
577    #[inline]
578    fn try_from(s: &'a mut ByteStr) -> Result<Self, Self::Error> {
579        crate::str::from_utf8_mut(&mut s.0)
580    }
581}