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| {
155 chunk.valid().chars().count() + if chunk.invalid().is_empty() { 0 } else { 1 }
156 })
157 .sum();
158 let padding = f.width().unwrap_or(0).saturating_sub(nchars);
159 let fill = f.fill();
160 let (lpad, rpad) = match align {
161 fmt::Alignment::Left => (0, padding),
162 fmt::Alignment::Right => (padding, 0),
163 fmt::Alignment::Center => {
164 let half = padding / 2;
165 (half, half + padding % 2)
166 }
167 };
168 for _ in 0..lpad {
169 write!(f, "{fill}")?;
170 }
171 fmt_nopad(self, f)?;
172 for _ in 0..rpad {
173 write!(f, "{fill}")?;
174 }
175
176 Ok(())
177 }
178}
179
180#[unstable(feature = "bstr", issue = "134915")]
181impl AsRef<[u8]> for ByteStr {
182 #[inline]
183 fn as_ref(&self) -> &[u8] {
184 &self.0
185 }
186}
187
188#[unstable(feature = "bstr", issue = "134915")]
189impl AsRef<ByteStr> for ByteStr {
190 #[inline]
191 fn as_ref(&self) -> &ByteStr {
192 self
193 }
194}
195
196#[unstable(feature = "bstr", issue = "134915")]
199impl AsRef<ByteStr> for str {
200 #[inline]
201 fn as_ref(&self) -> &ByteStr {
202 ByteStr::new(self)
203 }
204}
205
206#[unstable(feature = "bstr", issue = "134915")]
207impl AsMut<[u8]> for ByteStr {
208 #[inline]
209 fn as_mut(&mut self) -> &mut [u8] {
210 &mut self.0
211 }
212}
213
214#[unstable(feature = "bstr", issue = "134915")]
221impl Borrow<[u8]> for ByteStr {
222 #[inline]
223 fn borrow(&self) -> &[u8] {
224 &self.0
225 }
226}
227
228#[unstable(feature = "bstr", issue = "134915")]
231impl BorrowMut<[u8]> for ByteStr {
232 #[inline]
233 fn borrow_mut(&mut self) -> &mut [u8] {
234 &mut self.0
235 }
236}
237
238#[unstable(feature = "bstr", issue = "134915")]
239impl<'a> Default for &'a ByteStr {
240 fn default() -> Self {
241 ByteStr::from_bytes(b"")
242 }
243}
244
245#[unstable(feature = "bstr", issue = "134915")]
246impl<'a> Default for &'a mut ByteStr {
247 fn default() -> Self {
248 ByteStr::from_bytes_mut(&mut [])
249 }
250}
251
252#[unstable(feature = "bstr", issue = "134915")]
299impl hash::Hash for ByteStr {
300 #[inline]
301 fn hash<H: hash::Hasher>(&self, state: &mut H) {
302 self.0.hash(state);
303 }
304}
305
306#[unstable(feature = "bstr", issue = "134915")]
307impl Index<usize> for ByteStr {
308 type Output = u8;
309
310 #[inline]
311 fn index(&self, idx: usize) -> &u8 {
312 &self.0[idx]
313 }
314}
315
316#[unstable(feature = "bstr", issue = "134915")]
317impl Index<RangeFull> for ByteStr {
318 type Output = ByteStr;
319
320 #[inline]
321 fn index(&self, _: RangeFull) -> &ByteStr {
322 self
323 }
324}
325
326#[unstable(feature = "bstr", issue = "134915")]
327impl Index<Range<usize>> for ByteStr {
328 type Output = ByteStr;
329
330 #[inline]
331 fn index(&self, r: Range<usize>) -> &ByteStr {
332 ByteStr::from_bytes(&self.0[r])
333 }
334}
335
336#[unstable(feature = "bstr", issue = "134915")]
337impl Index<RangeInclusive<usize>> for ByteStr {
338 type Output = ByteStr;
339
340 #[inline]
341 fn index(&self, r: RangeInclusive<usize>) -> &ByteStr {
342 ByteStr::from_bytes(&self.0[r])
343 }
344}
345
346#[unstable(feature = "bstr", issue = "134915")]
347impl Index<RangeFrom<usize>> for ByteStr {
348 type Output = ByteStr;
349
350 #[inline]
351 fn index(&self, r: RangeFrom<usize>) -> &ByteStr {
352 ByteStr::from_bytes(&self.0[r])
353 }
354}
355
356#[unstable(feature = "bstr", issue = "134915")]
357impl Index<RangeTo<usize>> for ByteStr {
358 type Output = ByteStr;
359
360 #[inline]
361 fn index(&self, r: RangeTo<usize>) -> &ByteStr {
362 ByteStr::from_bytes(&self.0[r])
363 }
364}
365
366#[unstable(feature = "bstr", issue = "134915")]
367impl Index<RangeToInclusive<usize>> for ByteStr {
368 type Output = ByteStr;
369
370 #[inline]
371 fn index(&self, r: RangeToInclusive<usize>) -> &ByteStr {
372 ByteStr::from_bytes(&self.0[r])
373 }
374}
375
376#[unstable(feature = "bstr", issue = "134915")]
377impl IndexMut<usize> for ByteStr {
378 #[inline]
379 fn index_mut(&mut self, idx: usize) -> &mut u8 {
380 &mut self.0[idx]
381 }
382}
383
384#[unstable(feature = "bstr", issue = "134915")]
385impl IndexMut<RangeFull> for ByteStr {
386 #[inline]
387 fn index_mut(&mut self, _: RangeFull) -> &mut ByteStr {
388 self
389 }
390}
391
392#[unstable(feature = "bstr", issue = "134915")]
393impl IndexMut<Range<usize>> for ByteStr {
394 #[inline]
395 fn index_mut(&mut self, r: Range<usize>) -> &mut ByteStr {
396 ByteStr::from_bytes_mut(&mut self.0[r])
397 }
398}
399
400#[unstable(feature = "bstr", issue = "134915")]
401impl IndexMut<RangeInclusive<usize>> for ByteStr {
402 #[inline]
403 fn index_mut(&mut self, r: RangeInclusive<usize>) -> &mut ByteStr {
404 ByteStr::from_bytes_mut(&mut self.0[r])
405 }
406}
407
408#[unstable(feature = "bstr", issue = "134915")]
409impl IndexMut<RangeFrom<usize>> for ByteStr {
410 #[inline]
411 fn index_mut(&mut self, r: RangeFrom<usize>) -> &mut ByteStr {
412 ByteStr::from_bytes_mut(&mut self.0[r])
413 }
414}
415
416#[unstable(feature = "bstr", issue = "134915")]
417impl IndexMut<RangeTo<usize>> for ByteStr {
418 #[inline]
419 fn index_mut(&mut self, r: RangeTo<usize>) -> &mut ByteStr {
420 ByteStr::from_bytes_mut(&mut self.0[r])
421 }
422}
423
424#[unstable(feature = "bstr", issue = "134915")]
425impl IndexMut<RangeToInclusive<usize>> for ByteStr {
426 #[inline]
427 fn index_mut(&mut self, r: RangeToInclusive<usize>) -> &mut ByteStr {
428 ByteStr::from_bytes_mut(&mut self.0[r])
429 }
430}
431
432#[unstable(feature = "bstr", issue = "134915")]
433impl Eq for ByteStr {}
434
435#[unstable(feature = "bstr", issue = "134915")]
436impl PartialEq<ByteStr> for ByteStr {
437 #[inline]
438 fn eq(&self, other: &ByteStr) -> bool {
439 &self.0 == &other.0
440 }
441}
442
443#[doc(hidden)]
444#[macro_export]
445#[unstable(feature = "bstr_internals", issue = "none")]
446macro_rules! impl_partial_eq {
447 ($lhs:ty, $rhs:ty) => {
448 #[allow(unused_lifetimes)]
449 impl<'a> PartialEq<$rhs> for $lhs {
450 #[inline]
451 fn eq(&self, other: &$rhs) -> bool {
452 let other: &[u8] = other.as_ref();
453 PartialEq::eq(self.as_bytes(), other)
454 }
455 }
456
457 #[allow(unused_lifetimes)]
458 impl<'a> PartialEq<$lhs> for $rhs {
459 #[inline]
460 fn eq(&self, other: &$lhs) -> bool {
461 let this: &[u8] = self.as_ref();
462 PartialEq::eq(this, other.as_bytes())
463 }
464 }
465 };
466}
467
468#[doc(hidden)]
469#[unstable(feature = "bstr_internals", issue = "none")]
470pub use impl_partial_eq;
471
472#[doc(hidden)]
473#[macro_export]
474#[unstable(feature = "bstr_internals", issue = "none")]
475macro_rules! impl_partial_eq_ord {
476 ($lhs:ty, $rhs:ty) => {
477 $crate::bstr::impl_partial_eq!($lhs, $rhs);
478
479 #[allow(unused_lifetimes)]
480 #[unstable(feature = "bstr", issue = "134915")]
481 impl<'a> PartialOrd<$rhs> for $lhs {
482 #[inline]
483 fn partial_cmp(&self, other: &$rhs) -> Option<Ordering> {
484 let other: &[u8] = other.as_ref();
485 PartialOrd::partial_cmp(self.as_bytes(), other)
486 }
487 }
488
489 #[allow(unused_lifetimes)]
490 #[unstable(feature = "bstr", issue = "134915")]
491 impl<'a> PartialOrd<$lhs> for $rhs {
492 #[inline]
493 fn partial_cmp(&self, other: &$lhs) -> Option<Ordering> {
494 let this: &[u8] = self.as_ref();
495 PartialOrd::partial_cmp(this, other.as_bytes())
496 }
497 }
498 };
499}
500
501#[doc(hidden)]
502#[unstable(feature = "bstr_internals", issue = "none")]
503pub use impl_partial_eq_ord;
504
505#[doc(hidden)]
506#[macro_export]
507#[unstable(feature = "bstr_internals", issue = "none")]
508macro_rules! impl_partial_eq_n {
509 ($lhs:ty, $rhs:ty) => {
510 #[allow(unused_lifetimes)]
511 #[unstable(feature = "bstr", issue = "134915")]
512 impl<const N: usize> PartialEq<$rhs> for $lhs {
513 #[inline]
514 fn eq(&self, other: &$rhs) -> bool {
515 let other: &[u8] = other.as_ref();
516 PartialEq::eq(self.as_bytes(), other)
517 }
518 }
519
520 #[allow(unused_lifetimes)]
521 #[unstable(feature = "bstr", issue = "134915")]
522 impl<const N: usize> PartialEq<$lhs> for $rhs {
523 #[inline]
524 fn eq(&self, other: &$lhs) -> bool {
525 let this: &[u8] = self.as_ref();
526 PartialEq::eq(this, other.as_bytes())
527 }
528 }
529 };
530}
531
532#[doc(hidden)]
533#[unstable(feature = "bstr_internals", issue = "none")]
534pub use impl_partial_eq_n;
535
536impl_partial_eq!(ByteStr, [u8]);
538impl_partial_eq!(ByteStr, &[u8]);
540impl_partial_eq!(ByteStr, str);
542impl_partial_eq!(ByteStr, &str);
544impl_partial_eq_n!(ByteStr, [u8; N]);
546impl_partial_eq_n!(ByteStr, &[u8; N]);
548
549#[unstable(feature = "bstr", issue = "134915")]
550impl Ord for ByteStr {
551 #[inline]
552 fn cmp(&self, other: &ByteStr) -> Ordering {
553 Ord::cmp(&self.0, &other.0)
554 }
555}
556
557#[unstable(feature = "bstr", issue = "134915")]
558impl PartialOrd for ByteStr {
559 #[inline]
560 fn partial_cmp(&self, other: &ByteStr) -> Option<Ordering> {
561 PartialOrd::partial_cmp(&self.0, &other.0)
562 }
563}
564
565#[unstable(feature = "bstr", issue = "134915")]
566impl<'a> TryFrom<&'a ByteStr> for &'a str {
567 type Error = crate::str::Utf8Error;
568
569 #[inline]
570 fn try_from(s: &'a ByteStr) -> Result<Self, Self::Error> {
571 crate::str::from_utf8(&s.0)
572 }
573}
574
575#[unstable(feature = "bstr", issue = "134915")]
576impl<'a> TryFrom<&'a mut ByteStr> for &'a mut str {
577 type Error = crate::str::Utf8Error;
578
579 #[inline]
580 fn try_from(s: &'a mut ByteStr) -> Result<Self, Self::Error> {
581 crate::str::from_utf8_mut(&mut s.0)
582 }
583}