1mod traits;
4
5#[unstable(feature = "bstr_internals", issue = "none")]
6pub use traits::{impl_partial_eq, impl_partial_eq_n, impl_partial_eq_ord};
7
8use crate::borrow::{Borrow, BorrowMut};
9use crate::fmt;
10use crate::ops::{Deref, DerefMut, DerefPure};
11
12#[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 #[doc(hidden)]
96 #[unstable(feature = "bstr_internals", issue = "none")]
97 #[inline]
98 pub fn as_bytes_mut(&mut self) -> &mut [u8] {
99 &mut self.0
100 }
101}
102
103#[unstable(feature = "bstr", issue = "134915")]
104impl Deref for ByteStr {
105 type Target = [u8];
106
107 #[inline]
108 fn deref(&self) -> &[u8] {
109 &self.0
110 }
111}
112
113#[unstable(feature = "bstr", issue = "134915")]
114impl DerefMut for ByteStr {
115 #[inline]
116 fn deref_mut(&mut self) -> &mut [u8] {
117 &mut self.0
118 }
119}
120
121#[unstable(feature = "deref_pure_trait", issue = "87121")]
122unsafe impl DerefPure for ByteStr {}
123
124#[unstable(feature = "bstr", issue = "134915")]
125impl fmt::Debug for ByteStr {
126 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
127 write!(f, "\"")?;
128 for chunk in self.utf8_chunks() {
129 for c in chunk.valid().chars() {
130 match c {
131 '\0' => write!(f, "\\0")?,
132 '\x01'..='\x7f' => write!(f, "{}", (c as u8).escape_ascii())?,
133 _ => write!(f, "{}", c.escape_debug())?,
134 }
135 }
136 write!(f, "{}", chunk.invalid().escape_ascii())?;
137 }
138 write!(f, "\"")?;
139 Ok(())
140 }
141}
142
143#[unstable(feature = "bstr", issue = "134915")]
144impl fmt::Display for ByteStr {
145 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
146 fn fmt_nopad(this: &ByteStr, f: &mut fmt::Formatter<'_>) -> fmt::Result {
147 for chunk in this.utf8_chunks() {
148 f.write_str(chunk.valid())?;
149 if !chunk.invalid().is_empty() {
150 f.write_str("\u{FFFD}")?;
151 }
152 }
153 Ok(())
154 }
155
156 let Some(align) = f.align() else {
157 return fmt_nopad(self, f);
158 };
159 let nchars: usize = self
160 .utf8_chunks()
161 .map(|chunk| {
162 chunk.valid().chars().count() + if chunk.invalid().is_empty() { 0 } else { 1 }
163 })
164 .sum();
165 let padding = f.width().unwrap_or(0).saturating_sub(nchars);
166 let fill = f.fill();
167 let (lpad, rpad) = match align {
168 fmt::Alignment::Left => (0, padding),
169 fmt::Alignment::Right => (padding, 0),
170 fmt::Alignment::Center => {
171 let half = padding / 2;
172 (half, half + padding % 2)
173 }
174 };
175 for _ in 0..lpad {
176 write!(f, "{fill}")?;
177 }
178 fmt_nopad(self, f)?;
179 for _ in 0..rpad {
180 write!(f, "{fill}")?;
181 }
182
183 Ok(())
184 }
185}
186
187#[unstable(feature = "bstr", issue = "134915")]
188impl AsRef<[u8]> for ByteStr {
189 #[inline]
190 fn as_ref(&self) -> &[u8] {
191 &self.0
192 }
193}
194
195#[unstable(feature = "bstr", issue = "134915")]
196impl AsRef<ByteStr> for ByteStr {
197 #[inline]
198 fn as_ref(&self) -> &ByteStr {
199 self
200 }
201}
202
203#[unstable(feature = "bstr", issue = "134915")]
206impl AsRef<ByteStr> for str {
207 #[inline]
208 fn as_ref(&self) -> &ByteStr {
209 ByteStr::new(self)
210 }
211}
212
213#[unstable(feature = "bstr", issue = "134915")]
214impl AsMut<[u8]> for ByteStr {
215 #[inline]
216 fn as_mut(&mut self) -> &mut [u8] {
217 &mut self.0
218 }
219}
220
221#[unstable(feature = "bstr", issue = "134915")]
228impl Borrow<[u8]> for ByteStr {
229 #[inline]
230 fn borrow(&self) -> &[u8] {
231 &self.0
232 }
233}
234
235#[unstable(feature = "bstr", issue = "134915")]
238impl BorrowMut<[u8]> for ByteStr {
239 #[inline]
240 fn borrow_mut(&mut self) -> &mut [u8] {
241 &mut self.0
242 }
243}
244
245#[unstable(feature = "bstr", issue = "134915")]
246impl<'a> Default for &'a ByteStr {
247 fn default() -> Self {
248 ByteStr::from_bytes(b"")
249 }
250}
251
252#[unstable(feature = "bstr", issue = "134915")]
253impl<'a> Default for &'a mut ByteStr {
254 fn default() -> Self {
255 ByteStr::from_bytes_mut(&mut [])
256 }
257}
258
259#[unstable(feature = "bstr", issue = "134915")]
306impl<'a> TryFrom<&'a ByteStr> for &'a str {
307 type Error = crate::str::Utf8Error;
308
309 #[inline]
310 fn try_from(s: &'a ByteStr) -> Result<Self, Self::Error> {
311 crate::str::from_utf8(&s.0)
312 }
313}
314
315#[unstable(feature = "bstr", issue = "134915")]
316impl<'a> TryFrom<&'a mut ByteStr> for &'a mut str {
317 type Error = crate::str::Utf8Error;
318
319 #[inline]
320 fn try_from(s: &'a mut ByteStr) -> Result<Self, Self::Error> {
321 crate::str::from_utf8_mut(&mut s.0)
322 }
323}