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::{self, Alignment};
10use crate::ops::{Deref, DerefMut, DerefPure};
11
12#[unstable(feature = "bstr", issue = "134915")]
41#[rustc_has_incoherent_inherent_impls]
42#[repr(transparent)]
43#[doc(alias = "BStr")]
44pub struct ByteStr(pub [u8]);
45
46impl ByteStr {
47 #[inline]
66 #[unstable(feature = "bstr", issue = "134915")]
67 #[rustc_const_unstable(feature = "const_convert", issue = "143773")]
68 pub const fn new<B: ?Sized + [const] AsRef<[u8]>>(bytes: &B) -> &Self {
69 ByteStr::from_bytes(bytes.as_ref())
70 }
71
72 #[inline]
78 #[unstable(feature = "bstr", issue = "134915")]
80 pub const fn as_byte_str(&self) -> &ByteStr {
81 self
82 }
83
84 #[inline]
90 #[unstable(feature = "bstr", issue = "134915")]
92 pub const fn as_mut_byte_str(&mut self) -> &mut ByteStr {
93 self
94 }
95
96 #[doc(hidden)]
97 #[unstable(feature = "bstr_internals", issue = "none")]
98 #[inline]
99 #[rustc_const_unstable(feature = "bstr_internals", issue = "none")]
100 pub const fn from_bytes(slice: &[u8]) -> &Self {
101 unsafe { &*(slice as *const [u8] as *const Self) }
104 }
105
106 #[doc(hidden)]
107 #[unstable(feature = "bstr_internals", issue = "none")]
108 #[inline]
109 #[rustc_const_unstable(feature = "bstr_internals", issue = "none")]
110 pub const fn from_bytes_mut(slice: &mut [u8]) -> &mut Self {
111 unsafe { &mut *(slice as *mut [u8] as *mut Self) }
114 }
115
116 #[doc(hidden)]
117 #[unstable(feature = "bstr_internals", issue = "none")]
118 #[inline]
119 #[rustc_const_unstable(feature = "bstr_internals", issue = "none")]
120 pub const fn as_bytes(&self) -> &[u8] {
121 &self.0
122 }
123
124 #[doc(hidden)]
125 #[unstable(feature = "bstr_internals", issue = "none")]
126 #[inline]
127 #[rustc_const_unstable(feature = "bstr_internals", issue = "none")]
128 pub const fn as_bytes_mut(&mut self) -> &mut [u8] {
129 &mut self.0
130 }
131}
132
133#[unstable(feature = "bstr", issue = "134915")]
134#[rustc_const_unstable(feature = "const_convert", issue = "143773")]
135const impl Deref for ByteStr {
136 type Target = [u8];
137
138 #[inline]
139 fn deref(&self) -> &[u8] {
140 &self.0
141 }
142}
143
144#[unstable(feature = "bstr", issue = "134915")]
145#[rustc_const_unstable(feature = "const_convert", issue = "143773")]
146const impl DerefMut for ByteStr {
147 #[inline]
148 fn deref_mut(&mut self) -> &mut [u8] {
149 &mut self.0
150 }
151}
152
153#[unstable(feature = "deref_pure_trait", issue = "87121")]
154unsafe impl DerefPure for ByteStr {}
155
156#[unstable(feature = "bstr", issue = "134915")]
157impl fmt::Debug for ByteStr {
158 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
159 write!(f, "\"")?;
160 for chunk in self.utf8_chunks() {
161 for c in chunk.valid().chars() {
162 match c {
163 '\0' => write!(f, "\\0")?,
164 '\x01'..='\x7f' => write!(f, "{}", (c as u8).escape_ascii())?,
165 _ => write!(f, "{}", c.escape_debug())?,
166 }
167 }
168 write!(f, "{}", chunk.invalid().escape_ascii())?;
169 }
170 write!(f, "\"")?;
171 Ok(())
172 }
173}
174
175#[unstable(feature = "bstr_to_string", issue = "134915")]
176impl fmt::Display for ByteStr {
177 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
178 fn emit(byte_str: &ByteStr, f: &mut fmt::Formatter<'_>) -> fmt::Result {
179 for chunk in byte_str.utf8_chunks() {
180 f.write_str(chunk.valid())?;
181 if !chunk.invalid().is_empty() {
182 f.write_str("\u{FFFD}")?;
183 }
184 }
185
186 Ok(())
187 }
188
189 let requested_width = f.width().unwrap_or(0);
190 if requested_width == 0 && f.precision().is_none() {
191 return emit(self, f);
194 }
195
196 let (truncated, actual_width) = match f.precision() {
197 Some(0) => (ByteStr::new(&[]), 0),
199 Some(precision) => {
201 let mut remaining_width = precision;
202 let mut chunks = self.utf8_chunks();
203 let mut current_width = 0;
204 let mut offset = 0;
205 loop {
206 let Some(chunk) = chunks.next() else {
207 break (self, current_width);
210 };
211
212 let mut chars = chunk.valid().char_indices();
213 let Err(remaining) = chars.advance_by(remaining_width) else {
214 break (&self[..offset + chars.offset()], precision);
217 };
218
219 offset += chunk.valid().len();
220 current_width += remaining_width - remaining.get();
221 remaining_width = remaining.get();
222
223 if !chunk.invalid().is_empty() {
227 offset += chunk.invalid().len();
228 current_width += 1;
229 remaining_width -= 1;
230
231 if remaining_width == 0 {
232 break (&self[..offset], precision);
233 }
234 }
235 }
236 }
237 None => {
240 let actual_width = self
241 .utf8_chunks()
242 .map(|chunk| {
243 chunk.valid().chars().count()
244 + if chunk.invalid().is_empty() { 0 } else { 1 }
245 })
246 .sum();
247 (self, actual_width)
248 }
249 };
250
251 let padding = u16::try_from(requested_width.saturating_sub(actual_width)).unwrap();
253
254 let post_padding = f.padding(padding, Alignment::Left)?;
255 emit(truncated, f)?;
256 post_padding.write(f)
257 }
258}
259
260#[unstable(feature = "bstr", issue = "134915")]
261#[rustc_const_unstable(feature = "const_convert", issue = "143773")]
262const impl AsRef<[u8]> for ByteStr {
263 #[inline]
264 fn as_ref(&self) -> &[u8] {
265 &self.0
266 }
267}
268
269#[unstable(feature = "bstr", issue = "134915")]
270#[rustc_const_unstable(feature = "const_convert", issue = "143773")]
271const impl AsRef<ByteStr> for ByteStr {
272 #[inline]
273 fn as_ref(&self) -> &ByteStr {
274 self
275 }
276}
277
278#[unstable(feature = "bstr", issue = "134915")]
281#[rustc_const_unstable(feature = "const_convert", issue = "143773")]
282const impl AsRef<ByteStr> for str {
283 #[inline]
284 fn as_ref(&self) -> &ByteStr {
285 ByteStr::new(self)
286 }
287}
288
289#[unstable(feature = "bstr", issue = "134915")]
290#[rustc_const_unstable(feature = "const_convert", issue = "143773")]
291const impl AsMut<[u8]> for ByteStr {
292 #[inline]
293 fn as_mut(&mut self) -> &mut [u8] {
294 &mut self.0
295 }
296}
297
298#[unstable(feature = "bstr", issue = "134915")]
305#[rustc_const_unstable(feature = "const_convert", issue = "143773")]
306const impl Borrow<[u8]> for ByteStr {
307 #[inline]
308 fn borrow(&self) -> &[u8] {
309 &self.0
310 }
311}
312
313#[unstable(feature = "bstr", issue = "134915")]
316#[rustc_const_unstable(feature = "const_convert", issue = "143773")]
317const impl BorrowMut<[u8]> for ByteStr {
318 #[inline]
319 fn borrow_mut(&mut self) -> &mut [u8] {
320 &mut self.0
321 }
322}
323
324#[unstable(feature = "bstr", issue = "134915")]
325impl<'a> Default for &'a ByteStr {
326 fn default() -> Self {
327 ByteStr::from_bytes(b"")
328 }
329}
330
331#[unstable(feature = "bstr", issue = "134915")]
332impl<'a> Default for &'a mut ByteStr {
333 fn default() -> Self {
334 ByteStr::from_bytes_mut(&mut [])
335 }
336}
337
338#[unstable(feature = "bstr", issue = "134915")]
385#[rustc_const_unstable(feature = "const_convert", issue = "143773")]
386const impl<'a> TryFrom<&'a ByteStr> for &'a str {
387 type Error = crate::str::Utf8Error;
388
389 #[inline]
390 fn try_from(s: &'a ByteStr) -> Result<Self, Self::Error> {
391 crate::str::from_utf8(&s.0)
392 }
393}
394
395#[unstable(feature = "bstr", issue = "134915")]
396#[rustc_const_unstable(feature = "const_convert", issue = "143773")]
397const impl<'a> TryFrom<&'a mut ByteStr> for &'a mut str {
398 type Error = crate::str::Utf8Error;
399
400 #[inline]
401 fn try_from(s: &'a mut ByteStr) -> Result<Self, Self::Error> {
402 crate::str::from_utf8_mut(&mut s.0)
403 }
404}