1#[cfg(not(feature = "ferrocene_subset"))]
4mod traits;
5
6#[unstable(feature = "bstr_internals", issue = "none")]
7#[cfg(not(feature = "ferrocene_subset"))]
8pub use traits::{impl_partial_eq, impl_partial_eq_n, impl_partial_eq_ord};
9
10#[cfg(not(feature = "ferrocene_subset"))]
11use crate::borrow::{Borrow, BorrowMut};
12use crate::fmt;
13use crate::ops::{Deref, DerefMut, DerefPure};
14
15#[unstable(feature = "bstr", issue = "134915")]
44#[repr(transparent)]
45#[doc(alias = "BStr")]
46pub struct ByteStr(pub [u8]);
47
48impl ByteStr {
49 #[cfg(not(feature = "ferrocene_subset"))]
68 #[inline]
69 #[unstable(feature = "bstr", issue = "134915")]
70 #[rustc_const_unstable(feature = "const_convert", issue = "143773")]
71 pub const fn new<B: ?Sized + [const] AsRef<[u8]>>(bytes: &B) -> &Self {
72 ByteStr::from_bytes(bytes.as_ref())
73 }
74
75 #[cfg(not(feature = "ferrocene_subset"))]
81 #[inline]
82 #[unstable(feature = "bstr", issue = "134915")]
84 pub const fn as_byte_str(&self) -> &ByteStr {
85 self
86 }
87
88 #[cfg(not(feature = "ferrocene_subset"))]
94 #[inline]
95 #[unstable(feature = "bstr", issue = "134915")]
97 pub const fn as_mut_byte_str(&mut self) -> &mut ByteStr {
98 self
99 }
100
101 #[doc(hidden)]
102 #[unstable(feature = "bstr_internals", issue = "none")]
103 #[inline]
104 #[rustc_const_unstable(feature = "bstr_internals", issue = "none")]
105 pub const fn from_bytes(slice: &[u8]) -> &Self {
106 unsafe { &*(slice as *const [u8] as *const Self) }
109 }
110
111 #[cfg(not(feature = "ferrocene_subset"))]
112 #[doc(hidden)]
113 #[unstable(feature = "bstr_internals", issue = "none")]
114 #[inline]
115 #[rustc_const_unstable(feature = "bstr_internals", issue = "none")]
116 pub const fn from_bytes_mut(slice: &mut [u8]) -> &mut Self {
117 unsafe { &mut *(slice as *mut [u8] as *mut Self) }
120 }
121
122 #[cfg(not(feature = "ferrocene_subset"))]
123 #[doc(hidden)]
124 #[unstable(feature = "bstr_internals", issue = "none")]
125 #[inline]
126 #[rustc_const_unstable(feature = "bstr_internals", issue = "none")]
127 pub const fn as_bytes(&self) -> &[u8] {
128 &self.0
129 }
130
131 #[cfg(not(feature = "ferrocene_subset"))]
132 #[doc(hidden)]
133 #[unstable(feature = "bstr_internals", issue = "none")]
134 #[inline]
135 #[rustc_const_unstable(feature = "bstr_internals", issue = "none")]
136 pub const fn as_bytes_mut(&mut self) -> &mut [u8] {
137 &mut self.0
138 }
139}
140
141#[unstable(feature = "bstr", issue = "134915")]
142#[rustc_const_unstable(feature = "const_convert", issue = "143773")]
143impl const Deref for ByteStr {
144 type Target = [u8];
145
146 #[inline]
147 fn deref(&self) -> &[u8] {
148 &self.0
149 }
150}
151
152#[unstable(feature = "bstr", issue = "134915")]
153#[rustc_const_unstable(feature = "const_convert", issue = "143773")]
154impl const DerefMut for ByteStr {
155 #[inline]
156 fn deref_mut(&mut self) -> &mut [u8] {
157 &mut self.0
158 }
159}
160
161#[unstable(feature = "deref_pure_trait", issue = "87121")]
162unsafe impl DerefPure for ByteStr {}
163
164#[unstable(feature = "bstr", issue = "134915")]
165impl fmt::Debug for ByteStr {
166 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
167 write!(f, "\"")?;
168 for chunk in self.utf8_chunks() {
169 for c in chunk.valid().chars() {
170 match c {
171 '\0' => write!(f, "\\0")?,
172 '\x01'..='\x7f' => write!(f, "{}", (c as u8).escape_ascii())?,
173 _ => write!(f, "{}", c.escape_debug())?,
174 }
175 }
176 write!(f, "{}", chunk.invalid().escape_ascii())?;
177 }
178 write!(f, "\"")?;
179 Ok(())
180 }
181}
182
183#[cfg(not(feature = "ferrocene_subset"))]
184#[unstable(feature = "bstr", issue = "134915")]
185impl fmt::Display for ByteStr {
186 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
187 let nchars: usize = self
188 .utf8_chunks()
189 .map(|chunk| {
190 chunk.valid().chars().count() + if chunk.invalid().is_empty() { 0 } else { 1 }
191 })
192 .sum();
193
194 let padding = f.width().unwrap_or(0).saturating_sub(nchars);
195 let fill = f.fill();
196
197 let (lpad, rpad) = match f.align() {
198 Some(fmt::Alignment::Right) => (padding, 0),
199 Some(fmt::Alignment::Center) => {
200 let half = padding / 2;
201 (half, half + padding % 2)
202 }
203 _ => (0, padding),
206 };
207
208 for _ in 0..lpad {
209 write!(f, "{fill}")?;
210 }
211
212 for chunk in self.utf8_chunks() {
213 f.write_str(chunk.valid())?;
214 if !chunk.invalid().is_empty() {
215 f.write_str("\u{FFFD}")?;
216 }
217 }
218
219 for _ in 0..rpad {
220 write!(f, "{fill}")?;
221 }
222
223 Ok(())
224 }
225}
226
227#[cfg(not(feature = "ferrocene_subset"))]
228#[unstable(feature = "bstr", issue = "134915")]
229#[rustc_const_unstable(feature = "const_convert", issue = "143773")]
230impl const AsRef<[u8]> for ByteStr {
231 #[inline]
232 fn as_ref(&self) -> &[u8] {
233 &self.0
234 }
235}
236
237#[cfg(not(feature = "ferrocene_subset"))]
238#[unstable(feature = "bstr", issue = "134915")]
239#[rustc_const_unstable(feature = "const_convert", issue = "143773")]
240impl const AsRef<ByteStr> for ByteStr {
241 #[inline]
242 fn as_ref(&self) -> &ByteStr {
243 self
244 }
245}
246
247#[cfg(not(feature = "ferrocene_subset"))]
250#[unstable(feature = "bstr", issue = "134915")]
251#[rustc_const_unstable(feature = "const_convert", issue = "143773")]
252impl const AsRef<ByteStr> for str {
253 #[inline]
254 fn as_ref(&self) -> &ByteStr {
255 ByteStr::new(self)
256 }
257}
258
259#[cfg(not(feature = "ferrocene_subset"))]
260#[unstable(feature = "bstr", issue = "134915")]
261#[rustc_const_unstable(feature = "const_convert", issue = "143773")]
262impl const AsMut<[u8]> for ByteStr {
263 #[inline]
264 fn as_mut(&mut self) -> &mut [u8] {
265 &mut self.0
266 }
267}
268
269#[cfg(not(feature = "ferrocene_subset"))]
276#[unstable(feature = "bstr", issue = "134915")]
277#[rustc_const_unstable(feature = "const_convert", issue = "143773")]
278impl const Borrow<[u8]> for ByteStr {
279 #[inline]
280 fn borrow(&self) -> &[u8] {
281 &self.0
282 }
283}
284
285#[cfg(not(feature = "ferrocene_subset"))]
288#[unstable(feature = "bstr", issue = "134915")]
289#[rustc_const_unstable(feature = "const_convert", issue = "143773")]
290impl const BorrowMut<[u8]> for ByteStr {
291 #[inline]
292 fn borrow_mut(&mut self) -> &mut [u8] {
293 &mut self.0
294 }
295}
296
297#[cfg(not(feature = "ferrocene_subset"))]
298#[unstable(feature = "bstr", issue = "134915")]
299impl<'a> Default for &'a ByteStr {
300 fn default() -> Self {
301 ByteStr::from_bytes(b"")
302 }
303}
304
305#[cfg(not(feature = "ferrocene_subset"))]
306#[unstable(feature = "bstr", issue = "134915")]
307impl<'a> Default for &'a mut ByteStr {
308 fn default() -> Self {
309 ByteStr::from_bytes_mut(&mut [])
310 }
311}
312
313#[cfg(not(feature = "ferrocene_subset"))]
360#[unstable(feature = "bstr", issue = "134915")]
361#[rustc_const_unstable(feature = "const_convert", issue = "143773")]
362impl<'a> const TryFrom<&'a ByteStr> for &'a str {
363 type Error = crate::str::Utf8Error;
364
365 #[inline]
366 fn try_from(s: &'a ByteStr) -> Result<Self, Self::Error> {
367 crate::str::from_utf8(&s.0)
368 }
369}
370
371#[cfg(not(feature = "ferrocene_subset"))]
372#[unstable(feature = "bstr", issue = "134915")]
373#[rustc_const_unstable(feature = "const_convert", issue = "143773")]
374impl<'a> const TryFrom<&'a mut ByteStr> for &'a mut str {
375 type Error = crate::str::Utf8Error;
376
377 #[inline]
378 fn try_from(s: &'a mut ByteStr) -> Result<Self, Self::Error> {
379 crate::str::from_utf8_mut(&mut s.0)
380 }
381}