bstr/ext_vec.rs
1use core::{fmt, iter, ops, ptr};
2
3use alloc::{borrow::Cow, string::String, vec, vec::Vec};
4
5#[cfg(feature = "std")]
6use std::{
7 error,
8 ffi::{OsStr, OsString},
9 path::{Path, PathBuf},
10};
11
12use crate::{
13 ext_slice::ByteSlice,
14 utf8::{self, Utf8Error},
15 BString,
16};
17
18/// Concatenate the elements given by the iterator together into a single
19/// `Vec<u8>`.
20///
21/// The elements may be any type that can be cheaply converted into an `&[u8]`.
22/// This includes, but is not limited to, `&str`, `&BStr` and `&[u8]` itself.
23///
24/// # Examples
25///
26/// Basic usage:
27///
28/// ```
29/// use bstr;
30///
31/// let s = bstr::concat(&["foo", "bar", "baz"]);
32/// assert_eq!(s, "foobarbaz".as_bytes());
33/// ```
34#[inline]
35pub fn concat<T, I>(elements: I) -> Vec<u8>
36where
37 T: AsRef<[u8]>,
38 I: IntoIterator<Item = T>,
39{
40 let mut dest = vec![];
41 for element in elements {
42 dest.push_str(element);
43 }
44 dest
45}
46
47/// Join the elements given by the iterator with the given separator into a
48/// single `Vec<u8>`.
49///
50/// Both the separator and the elements may be any type that can be cheaply
51/// converted into an `&[u8]`. This includes, but is not limited to,
52/// `&str`, `&BStr` and `&[u8]` itself.
53///
54/// # Examples
55///
56/// Basic usage:
57///
58/// ```
59/// use bstr;
60///
61/// let s = bstr::join(",", &["foo", "bar", "baz"]);
62/// assert_eq!(s, "foo,bar,baz".as_bytes());
63/// ```
64#[inline]
65pub fn join<B, T, I>(separator: B, elements: I) -> Vec<u8>
66where
67 B: AsRef<[u8]>,
68 T: AsRef<[u8]>,
69 I: IntoIterator<Item = T>,
70{
71 let mut it = elements.into_iter();
72 let mut dest = vec![];
73 match it.next() {
74 None => return dest,
75 Some(first) => {
76 dest.push_str(first);
77 }
78 }
79 for element in it {
80 dest.push_str(&separator);
81 dest.push_str(element);
82 }
83 dest
84}
85
86impl ByteVec for Vec<u8> {
87 #[inline]
88 fn as_vec(&self) -> &Vec<u8> {
89 self
90 }
91
92 #[inline]
93 fn as_vec_mut(&mut self) -> &mut Vec<u8> {
94 self
95 }
96
97 #[inline]
98 fn into_vec(self) -> Vec<u8> {
99 self
100 }
101}
102
103/// Ensure that callers cannot implement `ByteSlice` by making an
104/// umplementable trait its super trait.
105mod private {
106 pub trait Sealed {}
107}
108impl private::Sealed for Vec<u8> {}
109
110/// A trait that extends `Vec<u8>` with string oriented methods.
111///
112/// Note that when using the constructor methods, such as
113/// `ByteVec::from_slice`, one should actually call them using the concrete
114/// type. For example:
115///
116/// ```
117/// use bstr::{B, ByteVec};
118///
119/// let s = Vec::from_slice(b"abc"); // NOT ByteVec::from_slice("...")
120/// assert_eq!(s, B("abc"));
121/// ```
122///
123/// This trait is sealed and cannot be implemented outside of `bstr`.
124pub trait ByteVec: private::Sealed {
125 /// A method for accessing the raw vector bytes of this type. This is
126 /// always a no-op and callers shouldn't care about it. This only exists
127 /// for making the extension trait work.
128 #[doc(hidden)]
129 fn as_vec(&self) -> &Vec<u8>;
130
131 /// A method for accessing the raw vector bytes of this type, mutably. This
132 /// is always a no-op and callers shouldn't care about it. This only exists
133 /// for making the extension trait work.
134 #[doc(hidden)]
135 fn as_vec_mut(&mut self) -> &mut Vec<u8>;
136
137 /// A method for consuming ownership of this vector. This is always a no-op
138 /// and callers shouldn't care about it. This only exists for making the
139 /// extension trait work.
140 #[doc(hidden)]
141 fn into_vec(self) -> Vec<u8>
142 where
143 Self: Sized;
144
145 /// Convert this type to a `BString`.
146 ///
147 /// `BString` is useful if you want its trait implementations such as `Debug`, `PartialEq`, and
148 /// `PartialOrd`, or if you want to declare at an interface boundary (field or parameter) that
149 /// something uses "conventionally UTF-8" owned strings.
150 ///
151 /// This is a zero-cost conversion.
152 ///
153 /// # Examples
154 ///
155 /// Basic usage:
156 ///
157 /// ```
158 /// use bstr::ByteVec;
159 ///
160 /// let v = vec![b'a', b'b', b'c'];
161 /// let b = v.to_bstring();
162 /// println!("{b}");
163 /// assert_eq!(b, "abc");
164 /// assert_ne!(b, "hello");
165 /// ```
166 #[inline]
167 fn to_bstring(self) -> BString
168 where
169 Self: Sized,
170 {
171 BString::new(self.into_vec())
172 }
173
174 /// Convert a `&Vec<u8>` to a `&BString`, without copying.
175 ///
176 /// `BString` is useful if you want its trait implementations such as `Debug`, `PartialEq`, and
177 /// `PartialOrd`, or if you want to declare at an interface boundary (field or parameter) that
178 /// something uses "conventionally UTF-8" owned strings.
179 ///
180 /// # Examples
181 ///
182 /// Basic usage:
183 ///
184 /// ```
185 /// use bstr::ByteVec;
186 ///
187 /// let mut v = vec![b'a', b'b', b'c'];
188 /// let b = v.as_bstring();
189 /// println!("{b}");
190 /// assert_eq!(b, "abc");
191 /// assert_ne!(b, "hello");
192 /// // no references to `b` after this point
193 /// v.push(b'd');
194 /// assert_eq!(v, [b'a', b'b', b'c', b'd']);
195 /// ```
196 #[inline]
197 fn as_bstring(&self) -> &BString {
198 BString::from_vec_ref(self.as_vec())
199 }
200
201 /// Convert a `&mut Vec<u8>` to a `&mut BString`, without copying.
202 ///
203 /// `BString` is useful if you want its trait implementations such as `Debug`, `PartialEq`, and
204 /// `PartialOrd`, or if you want to declare at an interface boundary (field or parameter) that
205 /// something uses "conventionally UTF-8" owned strings.
206 ///
207 /// # Examples
208 ///
209 /// Basic usage:
210 ///
211 /// ```
212 /// use bstr::ByteVec;
213 ///
214 /// let mut v = vec![b'a', b'b', b'c'];
215 /// let b = v.as_bstring_mut();
216 /// println!("{b}");
217 /// assert_eq!(b, "abc");
218 /// assert_ne!(b, "hello");
219 /// b.push_str("de");
220 /// assert_eq!(v, [b'a', b'b', b'c', b'd', b'e']);
221 /// ```
222 #[inline]
223 fn as_bstring_mut(&mut self) -> &mut BString {
224 BString::from_vec_mut(self.as_vec_mut())
225 }
226
227 /// Create a new owned byte string from the given byte slice.
228 ///
229 /// # Examples
230 ///
231 /// Basic usage:
232 ///
233 /// ```
234 /// use bstr::{B, ByteVec};
235 ///
236 /// let s = Vec::from_slice(b"abc");
237 /// assert_eq!(s, B("abc"));
238 /// ```
239 #[inline]
240 fn from_slice<B: AsRef<[u8]>>(bytes: B) -> Vec<u8> {
241 bytes.as_ref().to_vec()
242 }
243
244 /// Create a new byte string from an owned OS string.
245 ///
246 /// When the underlying bytes of OS strings are accessible, then this
247 /// always succeeds and is zero cost. Otherwise, this returns the given
248 /// `OsString` if it is not valid UTF-8.
249 ///
250 /// # Examples
251 ///
252 /// Basic usage:
253 ///
254 /// ```
255 /// use std::ffi::OsString;
256 ///
257 /// use bstr::{B, ByteVec};
258 ///
259 /// let os_str = OsString::from("foo");
260 /// let bs = Vec::from_os_string(os_str).expect("valid UTF-8");
261 /// assert_eq!(bs, B("foo"));
262 /// ```
263 #[inline]
264 #[cfg(feature = "std")]
265 fn from_os_string(os_str: OsString) -> Result<Vec<u8>, OsString> {
266 #[cfg(unix)]
267 #[inline]
268 fn imp(os_str: OsString) -> Result<Vec<u8>, OsString> {
269 use std::os::unix::ffi::OsStringExt;
270
271 Ok(os_str.into_vec())
272 }
273
274 #[cfg(not(unix))]
275 #[inline]
276 fn imp(os_str: OsString) -> Result<Vec<u8>, OsString> {
277 os_str.into_string().map(Vec::from)
278 }
279
280 imp(os_str)
281 }
282
283 /// Lossily create a new byte string from an OS string slice.
284 ///
285 /// When the underlying bytes of OS strings are accessible, then this is
286 /// zero cost and always returns a slice. Otherwise, a UTF-8 check is
287 /// performed and if the given OS string is not valid UTF-8, then it is
288 /// lossily decoded into valid UTF-8 (with invalid bytes replaced by the
289 /// Unicode replacement codepoint).
290 ///
291 /// # Examples
292 ///
293 /// Basic usage:
294 ///
295 /// ```
296 /// use std::ffi::OsStr;
297 ///
298 /// use bstr::{B, ByteVec};
299 ///
300 /// let os_str = OsStr::new("foo");
301 /// let bs = Vec::from_os_str_lossy(os_str);
302 /// assert_eq!(bs, B("foo"));
303 /// ```
304 #[inline]
305 #[cfg(feature = "std")]
306 fn from_os_str_lossy(os_str: &OsStr) -> Cow<'_, [u8]> {
307 #[cfg(unix)]
308 #[inline]
309 fn imp(os_str: &OsStr) -> Cow<'_, [u8]> {
310 use std::os::unix::ffi::OsStrExt;
311
312 Cow::Borrowed(os_str.as_bytes())
313 }
314
315 #[cfg(not(unix))]
316 #[inline]
317 fn imp(os_str: &OsStr) -> Cow<'_, [u8]> {
318 match os_str.to_string_lossy() {
319 Cow::Borrowed(x) => Cow::Borrowed(x.as_bytes()),
320 Cow::Owned(x) => Cow::Owned(Vec::from(x)),
321 }
322 }
323
324 imp(os_str)
325 }
326
327 /// Create a new byte string from an owned file path.
328 ///
329 /// When the underlying bytes of paths are accessible, then this always
330 /// succeeds and is zero cost. Otherwise, this returns the given `PathBuf`
331 /// if it is not valid UTF-8.
332 ///
333 /// # Examples
334 ///
335 /// Basic usage:
336 ///
337 /// ```
338 /// use std::path::PathBuf;
339 ///
340 /// use bstr::{B, ByteVec};
341 ///
342 /// let path = PathBuf::from("foo");
343 /// let bs = Vec::from_path_buf(path).expect("must be valid UTF-8");
344 /// assert_eq!(bs, B("foo"));
345 /// ```
346 #[inline]
347 #[cfg(feature = "std")]
348 fn from_path_buf(path: PathBuf) -> Result<Vec<u8>, PathBuf> {
349 Vec::from_os_string(path.into_os_string()).map_err(PathBuf::from)
350 }
351
352 /// Lossily create a new byte string from a file path.
353 ///
354 /// When the underlying bytes of paths are accessible, then this is
355 /// zero cost and always returns a slice. Otherwise, a UTF-8 check is
356 /// performed and if the given path is not valid UTF-8, then it is lossily
357 /// decoded into valid UTF-8 (with invalid bytes replaced by the Unicode
358 /// replacement codepoint).
359 ///
360 /// # Examples
361 ///
362 /// Basic usage:
363 ///
364 /// ```
365 /// use std::path::Path;
366 ///
367 /// use bstr::{B, ByteVec};
368 ///
369 /// let path = Path::new("foo");
370 /// let bs = Vec::from_path_lossy(path);
371 /// assert_eq!(bs, B("foo"));
372 /// ```
373 #[inline]
374 #[cfg(feature = "std")]
375 fn from_path_lossy(path: &Path) -> Cow<'_, [u8]> {
376 Vec::from_os_str_lossy(path.as_os_str())
377 }
378
379 /// Unescapes the given string into its raw bytes.
380 ///
381 /// This looks for the escape sequences `\xNN`, `\0`, `\r`, `\n`, `\t`
382 /// and `\` and translates them into their corresponding unescaped form.
383 ///
384 /// Incomplete escape sequences or things that look like escape sequences
385 /// but are not (for example, `\i` or `\xYZ`) are passed through literally.
386 ///
387 /// This is the dual of [`ByteSlice::escape_bytes`].
388 ///
389 /// Note that the zero or NUL byte may be represented as either `\0` or
390 /// `\x00`. Both will be unescaped into the zero byte.
391 ///
392 /// # Examples
393 ///
394 /// This shows basic usage:
395 ///
396 /// ```
397 /// # #[cfg(feature = "alloc")] {
398 /// use bstr::{B, BString, ByteVec};
399 ///
400 /// assert_eq!(
401 /// BString::from(b"foo\xFFbar"),
402 /// Vec::unescape_bytes(r"foo\xFFbar"),
403 /// );
404 /// assert_eq!(
405 /// BString::from(b"foo\nbar"),
406 /// Vec::unescape_bytes(r"foo\nbar"),
407 /// );
408 /// assert_eq!(
409 /// BString::from(b"foo\tbar"),
410 /// Vec::unescape_bytes(r"foo\tbar"),
411 /// );
412 /// assert_eq!(
413 /// BString::from(b"foo\\bar"),
414 /// Vec::unescape_bytes(r"foo\\bar"),
415 /// );
416 /// assert_eq!(
417 /// BString::from("foo☃bar"),
418 /// Vec::unescape_bytes(r"foo☃bar"),
419 /// );
420 ///
421 /// # }
422 /// ```
423 ///
424 /// This shows some examples of how incomplete or "incorrect" escape
425 /// sequences get passed through literally.
426 ///
427 /// ```
428 /// # #[cfg(feature = "alloc")] {
429 /// use bstr::{B, BString, ByteVec};
430 ///
431 /// // Show some incomplete escape sequences.
432 /// assert_eq!(
433 /// BString::from(br"\"),
434 /// Vec::unescape_bytes(r"\"),
435 /// );
436 /// assert_eq!(
437 /// BString::from(br"\"),
438 /// Vec::unescape_bytes(r"\\"),
439 /// );
440 /// assert_eq!(
441 /// BString::from(br"\x"),
442 /// Vec::unescape_bytes(r"\x"),
443 /// );
444 /// assert_eq!(
445 /// BString::from(br"\xA"),
446 /// Vec::unescape_bytes(r"\xA"),
447 /// );
448 /// // And now some that kind of look like escape
449 /// // sequences, but aren't.
450 /// assert_eq!(
451 /// BString::from(br"\xZ"),
452 /// Vec::unescape_bytes(r"\xZ"),
453 /// );
454 /// assert_eq!(
455 /// BString::from(br"\xZZ"),
456 /// Vec::unescape_bytes(r"\xZZ"),
457 /// );
458 /// assert_eq!(
459 /// BString::from(br"\i"),
460 /// Vec::unescape_bytes(r"\i"),
461 /// );
462 /// assert_eq!(
463 /// BString::from(br"\u"),
464 /// Vec::unescape_bytes(r"\u"),
465 /// );
466 /// assert_eq!(
467 /// BString::from(br"\u{2603}"),
468 /// Vec::unescape_bytes(r"\u{2603}"),
469 /// );
470 ///
471 /// # }
472 /// ```
473 #[inline]
474 #[cfg(feature = "alloc")]
475 fn unescape_bytes<S: AsRef<str>>(escaped: S) -> Vec<u8> {
476 let s = escaped.as_ref();
477 crate::escape_bytes::UnescapeBytes::new(s.chars()).collect()
478 }
479
480 /// Appends the given byte to the end of this byte string.
481 ///
482 /// Note that this is equivalent to the generic `Vec::push` method. This
483 /// method is provided to permit callers to explicitly differentiate
484 /// between pushing bytes, codepoints and strings.
485 ///
486 /// # Examples
487 ///
488 /// Basic usage:
489 ///
490 /// ```
491 /// use bstr::ByteVec;
492 ///
493 /// let mut s = <Vec<u8>>::from("abc");
494 /// s.push_byte(b'\xE2');
495 /// s.push_byte(b'\x98');
496 /// s.push_byte(b'\x83');
497 /// assert_eq!(s, "abc☃".as_bytes());
498 /// ```
499 #[inline]
500 fn push_byte(&mut self, byte: u8) {
501 self.as_vec_mut().push(byte);
502 }
503
504 /// Appends the given `char` to the end of this byte string.
505 ///
506 /// # Examples
507 ///
508 /// Basic usage:
509 ///
510 /// ```
511 /// use bstr::ByteVec;
512 ///
513 /// let mut s = <Vec<u8>>::from("abc");
514 /// s.push_char('1');
515 /// s.push_char('2');
516 /// s.push_char('3');
517 /// assert_eq!(s, "abc123".as_bytes());
518 /// ```
519 #[inline]
520 fn push_char(&mut self, ch: char) {
521 if ch.len_utf8() == 1 {
522 self.push_byte(ch as u8);
523 return;
524 }
525 self.as_vec_mut()
526 .extend_from_slice(ch.encode_utf8(&mut [0; 4]).as_bytes());
527 }
528
529 /// Appends the given slice to the end of this byte string. This accepts
530 /// any type that be converted to a `&[u8]`. This includes, but is not
531 /// limited to, `&str`, `&BStr`, and of course, `&[u8]` itself.
532 ///
533 /// # Examples
534 ///
535 /// Basic usage:
536 ///
537 /// ```
538 /// use bstr::ByteVec;
539 ///
540 /// let mut s = <Vec<u8>>::from("abc");
541 /// s.push_str(b"123");
542 /// assert_eq!(s, "abc123".as_bytes());
543 /// ```
544 #[inline]
545 fn push_str<B: AsRef<[u8]>>(&mut self, bytes: B) {
546 self.as_vec_mut().extend_from_slice(bytes.as_ref());
547 }
548
549 /// Converts a `Vec<u8>` into a `String` if and only if this byte string is
550 /// valid UTF-8.
551 ///
552 /// If it is not valid UTF-8, then a
553 /// [`FromUtf8Error`](struct.FromUtf8Error.html)
554 /// is returned. (This error can be used to examine why UTF-8 validation
555 /// failed, or to regain the original byte string.)
556 ///
557 /// # Examples
558 ///
559 /// Basic usage:
560 ///
561 /// ```
562 /// use bstr::ByteVec;
563 ///
564 /// let bytes = Vec::from("hello");
565 /// let string = bytes.into_string().unwrap();
566 ///
567 /// assert_eq!("hello", string);
568 /// ```
569 ///
570 /// If this byte string is not valid UTF-8, then an error will be returned.
571 /// That error can then be used to inspect the location at which invalid
572 /// UTF-8 was found, or to regain the original byte string:
573 ///
574 /// ```
575 /// use bstr::{B, ByteVec};
576 ///
577 /// let bytes = Vec::from_slice(b"foo\xFFbar");
578 /// let err = bytes.into_string().unwrap_err();
579 ///
580 /// assert_eq!(err.utf8_error().valid_up_to(), 3);
581 /// assert_eq!(err.utf8_error().error_len(), Some(1));
582 ///
583 /// // At no point in this example is an allocation performed.
584 /// let bytes = Vec::from(err.into_vec());
585 /// assert_eq!(bytes, B(b"foo\xFFbar"));
586 /// ```
587 #[inline]
588 fn into_string(self) -> Result<String, FromUtf8Error>
589 where
590 Self: Sized,
591 {
592 match utf8::validate(self.as_vec()) {
593 Err(err) => Err(FromUtf8Error { original: self.into_vec(), err }),
594 Ok(()) => {
595 // SAFETY: This is safe because of the guarantees provided by
596 // utf8::validate.
597 unsafe { Ok(self.into_string_unchecked()) }
598 }
599 }
600 }
601
602 /// Lossily converts a `Vec<u8>` into a `String`. If this byte string
603 /// contains invalid UTF-8, then the invalid bytes are replaced with the
604 /// Unicode replacement codepoint.
605 ///
606 /// # Examples
607 ///
608 /// Basic usage:
609 ///
610 /// ```
611 /// use bstr::ByteVec;
612 ///
613 /// let bytes = Vec::from_slice(b"foo\xFFbar");
614 /// let string = bytes.into_string_lossy();
615 /// assert_eq!(string, "foo\u{FFFD}bar");
616 /// ```
617 #[inline]
618 fn into_string_lossy(self) -> String
619 where
620 Self: Sized,
621 {
622 match self.as_vec().to_str_lossy() {
623 Cow::Borrowed(_) => {
624 // SAFETY: to_str_lossy() returning a Cow::Borrowed guarantees
625 // the entire string is valid utf8.
626 unsafe { self.into_string_unchecked() }
627 }
628 Cow::Owned(s) => s,
629 }
630 }
631
632 /// Unsafely convert this byte string into a `String`, without checking for
633 /// valid UTF-8.
634 ///
635 /// # Safety
636 ///
637 /// Callers *must* ensure that this byte string is valid UTF-8 before
638 /// calling this method. Converting a byte string into a `String` that is
639 /// not valid UTF-8 is considered undefined behavior.
640 ///
641 /// This routine is useful in performance sensitive contexts where the
642 /// UTF-8 validity of the byte string is already known and it is
643 /// undesirable to pay the cost of an additional UTF-8 validation check
644 /// that [`into_string`](#method.into_string) performs.
645 ///
646 /// # Examples
647 ///
648 /// Basic usage:
649 ///
650 /// ```
651 /// use bstr::ByteVec;
652 ///
653 /// // SAFETY: This is safe because string literals are guaranteed to be
654 /// // valid UTF-8 by the Rust compiler.
655 /// let s = unsafe { Vec::from("☃βツ").into_string_unchecked() };
656 /// assert_eq!("☃βツ", s);
657 /// ```
658 #[inline]
659 unsafe fn into_string_unchecked(self) -> String
660 where
661 Self: Sized,
662 {
663 String::from_utf8_unchecked(self.into_vec())
664 }
665
666 /// Converts this byte string into an OS string, in place.
667 ///
668 /// When OS strings can be constructed from arbitrary byte sequences, this
669 /// always succeeds and is zero cost. Otherwise, if this byte string is not
670 /// valid UTF-8, then an error (with the original byte string) is returned.
671 ///
672 /// # Examples
673 ///
674 /// Basic usage:
675 ///
676 /// ```
677 /// use std::ffi::OsStr;
678 ///
679 /// use bstr::ByteVec;
680 ///
681 /// let bs = Vec::from("foo");
682 /// let os_str = bs.into_os_string().expect("should be valid UTF-8");
683 /// assert_eq!(os_str, OsStr::new("foo"));
684 /// ```
685 #[cfg(feature = "std")]
686 #[inline]
687 fn into_os_string(self) -> Result<OsString, FromUtf8Error>
688 where
689 Self: Sized,
690 {
691 #[cfg(unix)]
692 #[inline]
693 fn imp(v: Vec<u8>) -> Result<OsString, FromUtf8Error> {
694 use std::os::unix::ffi::OsStringExt;
695
696 Ok(OsString::from_vec(v))
697 }
698
699 #[cfg(not(unix))]
700 #[inline]
701 fn imp(v: Vec<u8>) -> Result<OsString, FromUtf8Error> {
702 v.into_string().map(OsString::from)
703 }
704
705 imp(self.into_vec())
706 }
707
708 /// Lossily converts this byte string into an OS string, in place.
709 ///
710 /// When OS strings can be constructed from arbitrary byte sequences, this
711 /// is zero cost and always returns a slice. Otherwise, this will perform a
712 /// UTF-8 check and lossily convert this byte string into valid UTF-8 using
713 /// the Unicode replacement codepoint.
714 ///
715 /// Note that this can prevent the correct roundtripping of file paths when
716 /// the representation of `OsString` is opaque.
717 ///
718 /// # Examples
719 ///
720 /// Basic usage:
721 ///
722 /// ```
723 /// use bstr::ByteVec;
724 ///
725 /// let bs = Vec::from_slice(b"foo\xFFbar");
726 /// let os_str = bs.into_os_string_lossy();
727 /// assert_eq!(os_str.to_string_lossy(), "foo\u{FFFD}bar");
728 /// ```
729 #[inline]
730 #[cfg(feature = "std")]
731 fn into_os_string_lossy(self) -> OsString
732 where
733 Self: Sized,
734 {
735 #[cfg(unix)]
736 #[inline]
737 fn imp(v: Vec<u8>) -> OsString {
738 use std::os::unix::ffi::OsStringExt;
739
740 OsString::from_vec(v)
741 }
742
743 #[cfg(not(unix))]
744 #[inline]
745 fn imp(v: Vec<u8>) -> OsString {
746 OsString::from(v.into_string_lossy())
747 }
748
749 imp(self.into_vec())
750 }
751
752 /// Converts this byte string into an owned file path, in place.
753 ///
754 /// When paths can be constructed from arbitrary byte sequences, this
755 /// always succeeds and is zero cost. Otherwise, if this byte string is not
756 /// valid UTF-8, then an error (with the original byte string) is returned.
757 ///
758 /// # Examples
759 ///
760 /// Basic usage:
761 ///
762 /// ```
763 /// use bstr::ByteVec;
764 ///
765 /// let bs = Vec::from("foo");
766 /// let path = bs.into_path_buf().expect("should be valid UTF-8");
767 /// assert_eq!(path.as_os_str(), "foo");
768 /// ```
769 #[cfg(feature = "std")]
770 #[inline]
771 fn into_path_buf(self) -> Result<PathBuf, FromUtf8Error>
772 where
773 Self: Sized,
774 {
775 self.into_os_string().map(PathBuf::from)
776 }
777
778 /// Lossily converts this byte string into an owned file path, in place.
779 ///
780 /// When paths can be constructed from arbitrary byte sequences, this is
781 /// zero cost and always returns a slice. Otherwise, this will perform a
782 /// UTF-8 check and lossily convert this byte string into valid UTF-8 using
783 /// the Unicode replacement codepoint.
784 ///
785 /// Note that this can prevent the correct roundtripping of file paths when
786 /// the representation of `PathBuf` is opaque.
787 ///
788 /// # Examples
789 ///
790 /// Basic usage:
791 ///
792 /// ```
793 /// use bstr::ByteVec;
794 ///
795 /// let bs = Vec::from_slice(b"foo\xFFbar");
796 /// let path = bs.into_path_buf_lossy();
797 /// assert_eq!(path.to_string_lossy(), "foo\u{FFFD}bar");
798 /// ```
799 #[inline]
800 #[cfg(feature = "std")]
801 fn into_path_buf_lossy(self) -> PathBuf
802 where
803 Self: Sized,
804 {
805 PathBuf::from(self.into_os_string_lossy())
806 }
807
808 /// Removes the last byte from this `Vec<u8>` and returns it.
809 ///
810 /// If this byte string is empty, then `None` is returned.
811 ///
812 /// If the last codepoint in this byte string is not ASCII, then removing
813 /// the last byte could make this byte string contain invalid UTF-8.
814 ///
815 /// Note that this is equivalent to the generic `Vec::pop` method. This
816 /// method is provided to permit callers to explicitly differentiate
817 /// between popping bytes and codepoints.
818 ///
819 /// # Examples
820 ///
821 /// Basic usage:
822 ///
823 /// ```
824 /// use bstr::ByteVec;
825 ///
826 /// let mut s = Vec::from("foo");
827 /// assert_eq!(s.pop_byte(), Some(b'o'));
828 /// assert_eq!(s.pop_byte(), Some(b'o'));
829 /// assert_eq!(s.pop_byte(), Some(b'f'));
830 /// assert_eq!(s.pop_byte(), None);
831 /// ```
832 #[inline]
833 fn pop_byte(&mut self) -> Option<u8> {
834 self.as_vec_mut().pop()
835 }
836
837 /// Removes the last codepoint from this `Vec<u8>` and returns it.
838 ///
839 /// If this byte string is empty, then `None` is returned. If the last
840 /// bytes of this byte string do not correspond to a valid UTF-8 code unit
841 /// sequence, then the Unicode replacement codepoint is yielded instead in
842 /// accordance with the
843 /// [replacement codepoint substitution policy](index.html#handling-of-invalid-utf8-8).
844 ///
845 /// # Examples
846 ///
847 /// Basic usage:
848 ///
849 /// ```
850 /// use bstr::ByteVec;
851 ///
852 /// let mut s = Vec::from("foo");
853 /// assert_eq!(s.pop_char(), Some('o'));
854 /// assert_eq!(s.pop_char(), Some('o'));
855 /// assert_eq!(s.pop_char(), Some('f'));
856 /// assert_eq!(s.pop_char(), None);
857 /// ```
858 ///
859 /// This shows the replacement codepoint substitution policy. Note that
860 /// the first pop yields a replacement codepoint but actually removes two
861 /// bytes. This is in contrast with subsequent pops when encountering
862 /// `\xFF` since `\xFF` is never a valid prefix for any valid UTF-8
863 /// code unit sequence.
864 ///
865 /// ```
866 /// use bstr::ByteVec;
867 ///
868 /// let mut s = Vec::from_slice(b"f\xFF\xFF\xFFoo\xE2\x98");
869 /// assert_eq!(s.pop_char(), Some('\u{FFFD}'));
870 /// assert_eq!(s.pop_char(), Some('o'));
871 /// assert_eq!(s.pop_char(), Some('o'));
872 /// assert_eq!(s.pop_char(), Some('\u{FFFD}'));
873 /// assert_eq!(s.pop_char(), Some('\u{FFFD}'));
874 /// assert_eq!(s.pop_char(), Some('\u{FFFD}'));
875 /// assert_eq!(s.pop_char(), Some('f'));
876 /// assert_eq!(s.pop_char(), None);
877 /// ```
878 #[inline]
879 fn pop_char(&mut self) -> Option<char> {
880 let (ch, size) = utf8::decode_last_lossy(self.as_vec());
881 if size == 0 {
882 return None;
883 }
884 let new_len = self.as_vec().len() - size;
885 self.as_vec_mut().truncate(new_len);
886 Some(ch)
887 }
888
889 /// Removes a `char` from this `Vec<u8>` at the given byte position and
890 /// returns it.
891 ///
892 /// If the bytes at the given position do not lead to a valid UTF-8 code
893 /// unit sequence, then a
894 /// [replacement codepoint is returned instead](index.html#handling-of-invalid-utf8-8).
895 ///
896 /// # Panics
897 ///
898 /// Panics if `at` is larger than or equal to this byte string's length.
899 ///
900 /// # Examples
901 ///
902 /// Basic usage:
903 ///
904 /// ```
905 /// use bstr::ByteVec;
906 ///
907 /// let mut s = Vec::from("foo☃bar");
908 /// assert_eq!(s.remove_char(3), '☃');
909 /// assert_eq!(s, b"foobar");
910 /// ```
911 ///
912 /// This example shows how the Unicode replacement codepoint policy is
913 /// used:
914 ///
915 /// ```
916 /// use bstr::ByteVec;
917 ///
918 /// let mut s = Vec::from_slice(b"foo\xFFbar");
919 /// assert_eq!(s.remove_char(3), '\u{FFFD}');
920 /// assert_eq!(s, b"foobar");
921 /// ```
922 #[inline]
923 fn remove_char(&mut self, at: usize) -> char {
924 let (ch, size) = utf8::decode_lossy(&self.as_vec()[at..]);
925 assert!(
926 size > 0,
927 "expected {} to be less than {}",
928 at,
929 self.as_vec().len(),
930 );
931 self.as_vec_mut().drain(at..at + size);
932 ch
933 }
934
935 /// Inserts the given codepoint into this `Vec<u8>` at a particular byte
936 /// position.
937 ///
938 /// This is an `O(n)` operation as it may copy a number of elements in this
939 /// byte string proportional to its length.
940 ///
941 /// # Panics
942 ///
943 /// Panics if `at` is larger than the byte string's length.
944 ///
945 /// # Examples
946 ///
947 /// Basic usage:
948 ///
949 /// ```
950 /// use bstr::ByteVec;
951 ///
952 /// let mut s = Vec::from("foobar");
953 /// s.insert_char(3, '☃');
954 /// assert_eq!(s, "foo☃bar".as_bytes());
955 /// ```
956 #[inline]
957 fn insert_char(&mut self, at: usize, ch: char) {
958 self.insert_str(at, ch.encode_utf8(&mut [0; 4]).as_bytes());
959 }
960
961 /// Inserts the given byte string into this byte string at a particular
962 /// byte position.
963 ///
964 /// This is an `O(n)` operation as it may copy a number of elements in this
965 /// byte string proportional to its length.
966 ///
967 /// The given byte string may be any type that can be cheaply converted
968 /// into a `&[u8]`. This includes, but is not limited to, `&str` and
969 /// `&[u8]`.
970 ///
971 /// # Panics
972 ///
973 /// Panics if `at` is larger than the byte string's length.
974 ///
975 /// # Examples
976 ///
977 /// Basic usage:
978 ///
979 /// ```
980 /// use bstr::ByteVec;
981 ///
982 /// let mut s = Vec::from("foobar");
983 /// s.insert_str(3, "☃☃☃");
984 /// assert_eq!(s, "foo☃☃☃bar".as_bytes());
985 /// ```
986 #[inline]
987 fn insert_str<B: AsRef<[u8]>>(&mut self, at: usize, bytes: B) {
988 let bytes = bytes.as_ref();
989 let len = self.as_vec().len();
990 assert!(at <= len, "expected {} to be <= {}", at, len);
991
992 // SAFETY: We'd like to efficiently splice in the given bytes into
993 // this byte string. Since we are only working with `u8` elements here,
994 // we only need to consider whether our bounds are correct and whether
995 // our byte string has enough space.
996 self.as_vec_mut().reserve(bytes.len());
997 unsafe {
998 // Shift bytes after `at` over by the length of `bytes` to make
999 // room for it. This requires referencing two regions of memory
1000 // that may overlap, so we use ptr::copy.
1001 ptr::copy(
1002 self.as_vec().as_ptr().add(at),
1003 self.as_vec_mut().as_mut_ptr().add(at + bytes.len()),
1004 len - at,
1005 );
1006 // Now copy the bytes given into the room we made above. In this
1007 // case, we know that the given bytes cannot possibly overlap
1008 // with this byte string since we have a mutable borrow of the
1009 // latter. Thus, we can use a nonoverlapping copy.
1010 ptr::copy_nonoverlapping(
1011 bytes.as_ptr(),
1012 self.as_vec_mut().as_mut_ptr().add(at),
1013 bytes.len(),
1014 );
1015 self.as_vec_mut().set_len(len + bytes.len());
1016 }
1017 }
1018
1019 /// Removes the specified range in this byte string and replaces it with
1020 /// the given bytes. The given bytes do not need to have the same length
1021 /// as the range provided.
1022 ///
1023 /// # Panics
1024 ///
1025 /// Panics if the given range is invalid.
1026 ///
1027 /// # Examples
1028 ///
1029 /// Basic usage:
1030 ///
1031 /// ```
1032 /// use bstr::ByteVec;
1033 ///
1034 /// let mut s = Vec::from("foobar");
1035 /// s.replace_range(2..4, "xxxxx");
1036 /// assert_eq!(s, "foxxxxxar".as_bytes());
1037 /// ```
1038 #[inline]
1039 fn replace_range<R, B>(&mut self, range: R, replace_with: B)
1040 where
1041 R: ops::RangeBounds<usize>,
1042 B: AsRef<[u8]>,
1043 {
1044 self.as_vec_mut().splice(range, replace_with.as_ref().iter().copied());
1045 }
1046
1047 /// Creates a draining iterator that removes the specified range in this
1048 /// `Vec<u8>` and yields each of the removed bytes.
1049 ///
1050 /// Note that the elements specified by the given range are removed
1051 /// regardless of whether the returned iterator is fully exhausted.
1052 ///
1053 /// Also note that is is unspecified how many bytes are removed from the
1054 /// `Vec<u8>` if the `DrainBytes` iterator is leaked.
1055 ///
1056 /// # Panics
1057 ///
1058 /// Panics if the given range is not valid.
1059 ///
1060 /// # Examples
1061 ///
1062 /// Basic usage:
1063 ///
1064 /// ```
1065 /// use bstr::ByteVec;
1066 ///
1067 /// let mut s = Vec::from("foobar");
1068 /// {
1069 /// let mut drainer = s.drain_bytes(2..4);
1070 /// assert_eq!(drainer.next(), Some(b'o'));
1071 /// assert_eq!(drainer.next(), Some(b'b'));
1072 /// assert_eq!(drainer.next(), None);
1073 /// }
1074 /// assert_eq!(s, "foar".as_bytes());
1075 /// ```
1076 #[inline]
1077 fn drain_bytes<R>(&mut self, range: R) -> DrainBytes<'_>
1078 where
1079 R: ops::RangeBounds<usize>,
1080 {
1081 DrainBytes { it: self.as_vec_mut().drain(range) }
1082 }
1083}
1084
1085/// A draining byte oriented iterator for `Vec<u8>`.
1086///
1087/// This iterator is created by
1088/// [`ByteVec::drain_bytes`](trait.ByteVec.html#method.drain_bytes).
1089///
1090/// # Examples
1091///
1092/// Basic usage:
1093///
1094/// ```
1095/// use bstr::ByteVec;
1096///
1097/// let mut s = Vec::from("foobar");
1098/// {
1099/// let mut drainer = s.drain_bytes(2..4);
1100/// assert_eq!(drainer.next(), Some(b'o'));
1101/// assert_eq!(drainer.next(), Some(b'b'));
1102/// assert_eq!(drainer.next(), None);
1103/// }
1104/// assert_eq!(s, "foar".as_bytes());
1105/// ```
1106#[derive(Debug)]
1107pub struct DrainBytes<'a> {
1108 it: vec::Drain<'a, u8>,
1109}
1110
1111impl<'a> iter::FusedIterator for DrainBytes<'a> {}
1112
1113impl<'a> Iterator for DrainBytes<'a> {
1114 type Item = u8;
1115
1116 #[inline]
1117 fn next(&mut self) -> Option<u8> {
1118 self.it.next()
1119 }
1120}
1121
1122impl<'a> DoubleEndedIterator for DrainBytes<'a> {
1123 #[inline]
1124 fn next_back(&mut self) -> Option<u8> {
1125 self.it.next_back()
1126 }
1127}
1128
1129impl<'a> ExactSizeIterator for DrainBytes<'a> {
1130 #[inline]
1131 fn len(&self) -> usize {
1132 self.it.len()
1133 }
1134}
1135
1136/// An error that may occur when converting a `Vec<u8>` to a `String`.
1137///
1138/// This error includes the original `Vec<u8>` that failed to convert to a
1139/// `String`. This permits callers to recover the allocation used even if it
1140/// it not valid UTF-8.
1141///
1142/// # Examples
1143///
1144/// Basic usage:
1145///
1146/// ```
1147/// use bstr::{B, ByteVec};
1148///
1149/// let bytes = Vec::from_slice(b"foo\xFFbar");
1150/// let err = bytes.into_string().unwrap_err();
1151///
1152/// assert_eq!(err.utf8_error().valid_up_to(), 3);
1153/// assert_eq!(err.utf8_error().error_len(), Some(1));
1154///
1155/// // At no point in this example is an allocation performed.
1156/// let bytes = Vec::from(err.into_vec());
1157/// assert_eq!(bytes, B(b"foo\xFFbar"));
1158/// ```
1159#[derive(Debug, Eq, PartialEq)]
1160pub struct FromUtf8Error {
1161 original: Vec<u8>,
1162 err: Utf8Error,
1163}
1164
1165impl FromUtf8Error {
1166 /// Return the original bytes as a slice that failed to convert to a
1167 /// `String`.
1168 ///
1169 /// # Examples
1170 ///
1171 /// Basic usage:
1172 ///
1173 /// ```
1174 /// use bstr::{B, ByteVec};
1175 ///
1176 /// let bytes = Vec::from_slice(b"foo\xFFbar");
1177 /// let err = bytes.into_string().unwrap_err();
1178 ///
1179 /// // At no point in this example is an allocation performed.
1180 /// assert_eq!(err.as_bytes(), B(b"foo\xFFbar"));
1181 /// ```
1182 #[inline]
1183 pub fn as_bytes(&self) -> &[u8] {
1184 &self.original
1185 }
1186
1187 /// Consume this error and return the original byte string that failed to
1188 /// convert to a `String`.
1189 ///
1190 /// # Examples
1191 ///
1192 /// Basic usage:
1193 ///
1194 /// ```
1195 /// use bstr::{B, ByteVec};
1196 ///
1197 /// let bytes = Vec::from_slice(b"foo\xFFbar");
1198 /// let err = bytes.into_string().unwrap_err();
1199 /// let original = err.into_vec();
1200 ///
1201 /// // At no point in this example is an allocation performed.
1202 /// assert_eq!(original, B(b"foo\xFFbar"));
1203 /// ```
1204 #[inline]
1205 pub fn into_vec(self) -> Vec<u8> {
1206 self.original
1207 }
1208
1209 /// Return the underlying UTF-8 error that occurred. This error provides
1210 /// information on the nature and location of the invalid UTF-8 detected.
1211 ///
1212 /// # Examples
1213 ///
1214 /// Basic usage:
1215 ///
1216 /// ```
1217 /// use bstr::{B, ByteVec};
1218 ///
1219 /// let bytes = Vec::from_slice(b"foo\xFFbar");
1220 /// let err = bytes.into_string().unwrap_err();
1221 ///
1222 /// assert_eq!(err.utf8_error().valid_up_to(), 3);
1223 /// assert_eq!(err.utf8_error().error_len(), Some(1));
1224 /// ```
1225 #[inline]
1226 pub fn utf8_error(&self) -> &Utf8Error {
1227 &self.err
1228 }
1229}
1230
1231#[cfg(feature = "std")]
1232impl error::Error for FromUtf8Error {
1233 #[inline]
1234 fn description(&self) -> &str {
1235 "invalid UTF-8 vector"
1236 }
1237}
1238
1239impl fmt::Display for FromUtf8Error {
1240 #[inline]
1241 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
1242 write!(f, "{}", self.err)
1243 }
1244}
1245
1246#[cfg(all(test, feature = "std"))]
1247mod tests {
1248 use alloc::{vec, vec::Vec};
1249
1250 use crate::ext_vec::ByteVec;
1251
1252 #[test]
1253 fn insert() {
1254 let mut s = vec![];
1255 s.insert_str(0, "foo");
1256 assert_eq!(s, "foo".as_bytes());
1257
1258 let mut s = Vec::from("a");
1259 s.insert_str(0, "foo");
1260 assert_eq!(s, "fooa".as_bytes());
1261
1262 let mut s = Vec::from("a");
1263 s.insert_str(1, "foo");
1264 assert_eq!(s, "afoo".as_bytes());
1265
1266 let mut s = Vec::from("foobar");
1267 s.insert_str(3, "quux");
1268 assert_eq!(s, "fooquuxbar".as_bytes());
1269
1270 let mut s = Vec::from("foobar");
1271 s.insert_str(3, "x");
1272 assert_eq!(s, "fooxbar".as_bytes());
1273
1274 let mut s = Vec::from("foobar");
1275 s.insert_str(0, "x");
1276 assert_eq!(s, "xfoobar".as_bytes());
1277
1278 let mut s = Vec::from("foobar");
1279 s.insert_str(6, "x");
1280 assert_eq!(s, "foobarx".as_bytes());
1281
1282 let mut s = Vec::from("foobar");
1283 s.insert_str(3, "quuxbazquux");
1284 assert_eq!(s, "fooquuxbazquuxbar".as_bytes());
1285 }
1286
1287 #[test]
1288 #[should_panic]
1289 fn insert_fail1() {
1290 let mut s = vec![];
1291 s.insert_str(1, "foo");
1292 }
1293
1294 #[test]
1295 #[should_panic]
1296 fn insert_fail2() {
1297 let mut s = Vec::from("a");
1298 s.insert_str(2, "foo");
1299 }
1300
1301 #[test]
1302 #[should_panic]
1303 fn insert_fail3() {
1304 let mut s = Vec::from("foobar");
1305 s.insert_str(7, "foo");
1306 }
1307}