bstr/ext_slice.rs
1use core::{iter, slice, str};
2
3#[cfg(all(feature = "alloc", feature = "unicode"))]
4use alloc::vec;
5#[cfg(feature = "alloc")]
6use alloc::{borrow::Cow, string::String, vec::Vec};
7
8#[cfg(feature = "std")]
9use std::{ffi::OsStr, path::Path};
10
11use memchr::{memchr, memmem, memrchr};
12
13use crate::escape_bytes::EscapeBytes;
14#[cfg(feature = "alloc")]
15use crate::ext_vec::ByteVec;
16#[cfg(feature = "unicode")]
17use crate::unicode::{
18 whitespace_len_fwd, whitespace_len_rev, GraphemeIndices, Graphemes,
19 SentenceIndices, Sentences, WordIndices, Words, WordsWithBreakIndices,
20 WordsWithBreaks,
21};
22use crate::{
23 ascii,
24 bstr::BStr,
25 byteset,
26 utf8::{self, CharIndices, Chars, Utf8Chunks, Utf8Error},
27};
28
29/// A short-hand constructor for building a `&[u8]`.
30///
31/// This idiosyncratic constructor is useful for concisely building byte string
32/// slices. Its primary utility is in conveniently writing byte string literals
33/// in a uniform way. For example, consider this code that does not compile:
34///
35/// ```ignore
36/// let strs = vec![b"a", b"xy"];
37/// ```
38///
39/// The above code doesn't compile because the type of the byte string literal
40/// `b"a"` is `&'static [u8; 1]`, and the type of `b"xy"` is
41/// `&'static [u8; 2]`. Since their types aren't the same, they can't be stored
42/// in the same `Vec`. (This is dissimilar from normal Unicode string slices,
43/// where both `"a"` and `"xy"` have the same type of `&'static str`.)
44///
45/// One way of getting the above code to compile is to convert byte strings to
46/// slices. You might try this:
47///
48/// ```ignore
49/// let strs = vec![&b"a", &b"xy"];
50/// ```
51///
52/// But this just creates values with type `& &'static [u8; 1]` and
53/// `& &'static [u8; 2]`. Instead, you need to force the issue like so:
54///
55/// ```
56/// let strs = vec![&b"a"[..], &b"xy"[..]];
57/// // or
58/// let strs = vec![b"a".as_ref(), b"xy".as_ref()];
59/// ```
60///
61/// But neither of these are particularly convenient to type, especially when
62/// it's something as common as a string literal. Thus, this constructor
63/// permits writing the following instead:
64///
65/// ```
66/// use bstr::B;
67///
68/// let strs = vec![B("a"), B(b"xy")];
69/// ```
70///
71/// Notice that this also lets you mix and match both string literals and byte
72/// string literals. This can be quite convenient!
73#[allow(non_snake_case)]
74#[inline]
75pub fn B<B: ?Sized + AsRef<[u8]>>(bytes: &B) -> &[u8] {
76 bytes.as_ref()
77}
78
79impl ByteSlice for [u8] {
80 #[inline]
81 fn as_bytes(&self) -> &[u8] {
82 self
83 }
84
85 #[inline]
86 fn as_bytes_mut(&mut self) -> &mut [u8] {
87 self
88 }
89}
90
91impl<const N: usize> ByteSlice for [u8; N] {
92 #[inline]
93 fn as_bytes(&self) -> &[u8] {
94 self
95 }
96
97 #[inline]
98 fn as_bytes_mut(&mut self) -> &mut [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 [u8] {}
109impl<const N: usize> private::Sealed for [u8; N] {}
110
111/// A trait that extends `&[u8]` with string oriented methods.
112///
113/// This trait is sealed and cannot be implemented outside of `bstr`.
114pub trait ByteSlice: private::Sealed {
115 /// A method for accessing the raw bytes of this type. This is always a
116 /// no-op and callers shouldn't care about it. This only exists for making
117 /// the extension trait work.
118 #[doc(hidden)]
119 fn as_bytes(&self) -> &[u8];
120
121 /// A method for accessing the raw bytes of this type, mutably. This is
122 /// always a no-op and callers shouldn't care about it. This only exists
123 /// for making the extension trait work.
124 #[doc(hidden)]
125 fn as_bytes_mut(&mut self) -> &mut [u8];
126
127 /// Return this byte slice as a `&BStr`.
128 ///
129 /// `&BStr` is useful because of its `fmt::Debug` representation
130 /// and various other trait implementations (such as `PartialEq` and
131 /// `PartialOrd`). In particular, the `Debug` implementation for `BStr`
132 /// shows its bytes as a normal string. For invalid UTF-8, hex escape
133 /// sequences are used.
134 ///
135 /// # Examples
136 ///
137 /// Basic usage:
138 ///
139 /// ```
140 /// use bstr::ByteSlice;
141 ///
142 /// println!("{:?}", b"foo\xFFbar".as_bstr());
143 /// ```
144 #[inline]
145 fn as_bstr(&self) -> &BStr {
146 BStr::new(self.as_bytes())
147 }
148
149 /// Return this byte slice as a `&mut BStr`.
150 ///
151 /// `&mut BStr` is useful because of its `fmt::Debug` representation
152 /// and various other trait implementations (such as `PartialEq` and
153 /// `PartialOrd`). In particular, the `Debug` implementation for `BStr`
154 /// shows its bytes as a normal string. For invalid UTF-8, hex escape
155 /// sequences are used.
156 ///
157 /// # Examples
158 ///
159 /// Basic usage:
160 ///
161 /// ```
162 /// use bstr::ByteSlice;
163 ///
164 /// let mut bytes = *b"foo\xFFbar";
165 /// println!("{:?}", &mut bytes.as_bstr_mut());
166 /// ```
167 #[inline]
168 fn as_bstr_mut(&mut self) -> &mut BStr {
169 BStr::new_mut(self.as_bytes_mut())
170 }
171
172 /// Create an immutable byte string from an OS string slice.
173 ///
174 /// When the underlying bytes of OS strings are accessible, then this
175 /// always succeeds and is zero cost. Otherwise, this returns `None` if the
176 /// given OS string is not valid UTF-8. (For example, when the underlying
177 /// bytes are inaccessible on Windows, file paths are allowed to be a
178 /// sequence of arbitrary 16-bit integers. Not all such sequences can be
179 /// transcoded to valid UTF-8.)
180 ///
181 /// # Examples
182 ///
183 /// Basic usage:
184 ///
185 /// ```
186 /// use std::ffi::OsStr;
187 ///
188 /// use bstr::{B, ByteSlice};
189 ///
190 /// let os_str = OsStr::new("foo");
191 /// let bs = <[u8]>::from_os_str(os_str).expect("should be valid UTF-8");
192 /// assert_eq!(bs, B("foo"));
193 /// ```
194 #[cfg(feature = "std")]
195 #[inline]
196 fn from_os_str(os_str: &OsStr) -> Option<&[u8]> {
197 #[cfg(unix)]
198 #[inline]
199 fn imp(os_str: &OsStr) -> Option<&[u8]> {
200 use std::os::unix::ffi::OsStrExt;
201
202 Some(os_str.as_bytes())
203 }
204
205 #[cfg(not(unix))]
206 #[inline]
207 fn imp(os_str: &OsStr) -> Option<&[u8]> {
208 os_str.to_str().map(|s| s.as_bytes())
209 }
210
211 imp(os_str)
212 }
213
214 /// Create an immutable byte string from a file path.
215 ///
216 /// When the underlying bytes of paths are accessible, then this always
217 /// succeeds and is zero cost. Otherwise, this returns `None` if the given
218 /// path is not valid UTF-8. (For example, when the underlying bytes are
219 /// inaccessible on Windows, file paths are allowed to be a sequence of
220 /// arbitrary 16-bit integers. Not all such sequences can be transcoded to
221 /// valid UTF-8.)
222 ///
223 /// # Examples
224 ///
225 /// Basic usage:
226 ///
227 /// ```
228 /// use std::path::Path;
229 ///
230 /// use bstr::{B, ByteSlice};
231 ///
232 /// let path = Path::new("foo");
233 /// let bs = <[u8]>::from_path(path).expect("should be valid UTF-8");
234 /// assert_eq!(bs, B("foo"));
235 /// ```
236 #[cfg(feature = "std")]
237 #[inline]
238 fn from_path(path: &Path) -> Option<&[u8]> {
239 Self::from_os_str(path.as_os_str())
240 }
241
242 /// Safely convert this byte string into a `&str` if it's valid UTF-8.
243 ///
244 /// If this byte string is not valid UTF-8, then an error is returned. The
245 /// error returned indicates the first invalid byte found and the length
246 /// of the error.
247 ///
248 /// In cases where a lossy conversion to `&str` is acceptable, then use one
249 /// of the [`to_str_lossy`](trait.ByteSlice.html#method.to_str_lossy) or
250 /// [`to_str_lossy_into`](trait.ByteSlice.html#method.to_str_lossy_into)
251 /// methods.
252 ///
253 /// # Examples
254 ///
255 /// Basic usage:
256 ///
257 /// ```
258 /// # #[cfg(feature = "alloc")] {
259 /// use bstr::{B, ByteSlice, ByteVec};
260 ///
261 /// # fn example() -> Result<(), bstr::Utf8Error> {
262 /// let s = B("☃βツ").to_str()?;
263 /// assert_eq!("☃βツ", s);
264 ///
265 /// let mut bstring = <Vec<u8>>::from("☃βツ");
266 /// bstring.push(b'\xFF');
267 /// let err = bstring.to_str().unwrap_err();
268 /// assert_eq!(8, err.valid_up_to());
269 /// # Ok(()) }; example().unwrap()
270 /// # }
271 /// ```
272 #[inline]
273 fn to_str(&self) -> Result<&str, Utf8Error> {
274 utf8::validate(self.as_bytes()).map(|_| {
275 // SAFETY: This is safe because of the guarantees provided by
276 // utf8::validate.
277 unsafe { str::from_utf8_unchecked(self.as_bytes()) }
278 })
279 }
280
281 /// Unsafely convert this byte string into a `&str`, without checking for
282 /// valid UTF-8.
283 ///
284 /// # Safety
285 ///
286 /// Callers *must* ensure that this byte string is valid UTF-8 before
287 /// calling this method. Converting a byte string into a `&str` that is
288 /// not valid UTF-8 is considered undefined behavior.
289 ///
290 /// This routine is useful in performance sensitive contexts where the
291 /// UTF-8 validity of the byte string is already known and it is
292 /// undesirable to pay the cost of an additional UTF-8 validation check
293 /// that [`to_str`](trait.ByteSlice.html#method.to_str) performs.
294 ///
295 /// # Examples
296 ///
297 /// Basic usage:
298 ///
299 /// ```
300 /// use bstr::{B, ByteSlice};
301 ///
302 /// // SAFETY: This is safe because string literals are guaranteed to be
303 /// // valid UTF-8 by the Rust compiler.
304 /// let s = unsafe { B("☃βツ").to_str_unchecked() };
305 /// assert_eq!("☃βツ", s);
306 /// ```
307 #[inline]
308 unsafe fn to_str_unchecked(&self) -> &str {
309 str::from_utf8_unchecked(self.as_bytes())
310 }
311
312 /// Convert this byte string to a valid UTF-8 string by replacing invalid
313 /// UTF-8 bytes with the Unicode replacement codepoint (`U+FFFD`).
314 ///
315 /// If the byte string is already valid UTF-8, then no copying or
316 /// allocation is performed and a borrrowed string slice is returned. If
317 /// the byte string is not valid UTF-8, then an owned string buffer is
318 /// returned with invalid bytes replaced by the replacement codepoint.
319 ///
320 /// This method uses the "substitution of maximal subparts" (Unicode
321 /// Standard, Chapter 3, Section 9) strategy for inserting the replacement
322 /// codepoint. Specifically, a replacement codepoint is inserted whenever a
323 /// byte is found that cannot possibly lead to a valid code unit sequence.
324 /// If there were previous bytes that represented a prefix of a well-formed
325 /// code unit sequence, then all of those bytes are substituted with a
326 /// single replacement codepoint. The "substitution of maximal subparts"
327 /// strategy is the same strategy used by
328 /// [W3C's Encoding standard](https://www.w3.org/TR/encoding/).
329 /// For a more precise description of the maximal subpart strategy, see
330 /// the Unicode Standard, Chapter 3, Section 9. See also
331 /// [Public Review Issue #121](https://www.unicode.org/review/pr-121.html).
332 ///
333 /// N.B. Rust's standard library also appears to use the same strategy,
334 /// but it does not appear to be an API guarantee.
335 ///
336 /// # Examples
337 ///
338 /// Basic usage:
339 ///
340 /// ```
341 /// use std::borrow::Cow;
342 ///
343 /// use bstr::ByteSlice;
344 ///
345 /// let mut bstring = <Vec<u8>>::from("☃βツ");
346 /// assert_eq!(Cow::Borrowed("☃βツ"), bstring.to_str_lossy());
347 ///
348 /// // Add a byte that makes the sequence invalid.
349 /// bstring.push(b'\xFF');
350 /// assert_eq!(Cow::Borrowed("☃βツ\u{FFFD}"), bstring.to_str_lossy());
351 /// ```
352 ///
353 /// This demonstrates the "maximal subpart" substitution logic.
354 ///
355 /// ```
356 /// use bstr::{B, ByteSlice};
357 ///
358 /// // \x61 is the ASCII codepoint for 'a'.
359 /// // \xF1\x80\x80 is a valid 3-byte code unit prefix.
360 /// // \xE1\x80 is a valid 2-byte code unit prefix.
361 /// // \xC2 is a valid 1-byte code unit prefix.
362 /// // \x62 is the ASCII codepoint for 'b'.
363 /// //
364 /// // In sum, each of the prefixes is replaced by a single replacement
365 /// // codepoint since none of the prefixes are properly completed. This
366 /// // is in contrast to other strategies that might insert a replacement
367 /// // codepoint for every single byte.
368 /// let bs = B(b"\x61\xF1\x80\x80\xE1\x80\xC2\x62");
369 /// assert_eq!("a\u{FFFD}\u{FFFD}\u{FFFD}b", bs.to_str_lossy());
370 /// ```
371 #[cfg(feature = "alloc")]
372 #[inline]
373 fn to_str_lossy(&self) -> Cow<'_, str> {
374 match utf8::validate(self.as_bytes()) {
375 Ok(()) => {
376 // SAFETY: This is safe because of the guarantees provided by
377 // utf8::validate.
378 unsafe {
379 Cow::Borrowed(str::from_utf8_unchecked(self.as_bytes()))
380 }
381 }
382 Err(err) => {
383 let mut lossy = String::with_capacity(self.as_bytes().len());
384 let (valid, after) =
385 self.as_bytes().split_at(err.valid_up_to());
386 // SAFETY: This is safe because utf8::validate guarantees
387 // that all of `valid` is valid UTF-8.
388 lossy.push_str(unsafe { str::from_utf8_unchecked(valid) });
389 lossy.push_str("\u{FFFD}");
390 if let Some(len) = err.error_len() {
391 after[len..].to_str_lossy_into(&mut lossy);
392 }
393 Cow::Owned(lossy)
394 }
395 }
396 }
397
398 /// Copy the contents of this byte string into the given owned string
399 /// buffer, while replacing invalid UTF-8 code unit sequences with the
400 /// Unicode replacement codepoint (`U+FFFD`).
401 ///
402 /// This method uses the same "substitution of maximal subparts" strategy
403 /// for inserting the replacement codepoint as the
404 /// [`to_str_lossy`](trait.ByteSlice.html#method.to_str_lossy) method.
405 ///
406 /// This routine is useful for amortizing allocation. However, unlike
407 /// `to_str_lossy`, this routine will _always_ copy the contents of this
408 /// byte string into the destination buffer, even if this byte string is
409 /// valid UTF-8.
410 ///
411 /// # Examples
412 ///
413 /// Basic usage:
414 ///
415 /// ```
416 /// use std::borrow::Cow;
417 ///
418 /// use bstr::ByteSlice;
419 ///
420 /// let mut bstring = <Vec<u8>>::from("☃βツ");
421 /// // Add a byte that makes the sequence invalid.
422 /// bstring.push(b'\xFF');
423 ///
424 /// let mut dest = String::new();
425 /// bstring.to_str_lossy_into(&mut dest);
426 /// assert_eq!("☃βツ\u{FFFD}", dest);
427 /// ```
428 #[cfg(feature = "alloc")]
429 #[inline]
430 fn to_str_lossy_into(&self, dest: &mut String) {
431 let mut bytes = self.as_bytes();
432 dest.reserve(bytes.len());
433 loop {
434 match utf8::validate(bytes) {
435 Ok(()) => {
436 // SAFETY: This is safe because utf8::validate guarantees
437 // that all of `bytes` is valid UTF-8.
438 dest.push_str(unsafe { str::from_utf8_unchecked(bytes) });
439 break;
440 }
441 Err(err) => {
442 let (valid, after) = bytes.split_at(err.valid_up_to());
443 // SAFETY: This is safe because utf8::validate guarantees
444 // that all of `valid` is valid UTF-8.
445 dest.push_str(unsafe { str::from_utf8_unchecked(valid) });
446 dest.push_str("\u{FFFD}");
447 match err.error_len() {
448 None => break,
449 Some(len) => bytes = &after[len..],
450 }
451 }
452 }
453 }
454 }
455
456 /// Create an OS string slice from this byte string.
457 ///
458 /// When OS strings can be constructed from arbitrary byte sequences, this
459 /// always succeeds and is zero cost. Otherwise, this returns a UTF-8
460 /// decoding error if this byte string is not valid UTF-8. (For example,
461 /// assuming the representation of `OsStr` is opaque on Windows, file paths
462 /// are allowed to be a sequence of arbitrary 16-bit integers. There is
463 /// no obvious mapping from an arbitrary sequence of 8-bit integers to an
464 /// arbitrary sequence of 16-bit integers. If the representation of `OsStr`
465 /// is even opened up, then this will convert any sequence of bytes to an
466 /// `OsStr` without cost.)
467 ///
468 /// # Examples
469 ///
470 /// Basic usage:
471 ///
472 /// ```
473 /// use bstr::{B, ByteSlice};
474 ///
475 /// let os_str = b"foo".to_os_str().expect("should be valid UTF-8");
476 /// assert_eq!(os_str, "foo");
477 /// ```
478 #[cfg(feature = "std")]
479 #[inline]
480 fn to_os_str(&self) -> Result<&OsStr, Utf8Error> {
481 #[cfg(unix)]
482 #[inline]
483 fn imp(bytes: &[u8]) -> Result<&OsStr, Utf8Error> {
484 use std::os::unix::ffi::OsStrExt;
485
486 Ok(OsStr::from_bytes(bytes))
487 }
488
489 #[cfg(not(unix))]
490 #[inline]
491 fn imp(bytes: &[u8]) -> Result<&OsStr, Utf8Error> {
492 bytes.to_str().map(OsStr::new)
493 }
494
495 imp(self.as_bytes())
496 }
497
498 /// Lossily create an OS string slice from this byte string.
499 ///
500 /// When OS strings can be constructed from arbitrary byte sequences, this
501 /// is zero cost and always returns a slice. Otherwise, this will perform a
502 /// UTF-8 check and lossily convert this byte string into valid UTF-8 using
503 /// the Unicode replacement codepoint.
504 ///
505 /// Note that this can prevent the correct roundtripping of file paths when
506 /// the representation of `OsStr` is opaque.
507 ///
508 /// # Examples
509 ///
510 /// Basic usage:
511 ///
512 /// ```
513 /// use bstr::ByteSlice;
514 ///
515 /// let os_str = b"foo\xFFbar".to_os_str_lossy();
516 /// assert_eq!(os_str.to_string_lossy(), "foo\u{FFFD}bar");
517 /// ```
518 #[cfg(feature = "std")]
519 #[inline]
520 fn to_os_str_lossy(&self) -> Cow<'_, OsStr> {
521 #[cfg(unix)]
522 #[inline]
523 fn imp(bytes: &[u8]) -> Cow<'_, OsStr> {
524 use std::os::unix::ffi::OsStrExt;
525
526 Cow::Borrowed(OsStr::from_bytes(bytes))
527 }
528
529 #[cfg(not(unix))]
530 #[inline]
531 fn imp(bytes: &[u8]) -> Cow<'_, OsStr> {
532 use std::ffi::OsString;
533
534 match bytes.to_str_lossy() {
535 Cow::Borrowed(x) => Cow::Borrowed(OsStr::new(x)),
536 Cow::Owned(x) => Cow::Owned(OsString::from(x)),
537 }
538 }
539
540 imp(self.as_bytes())
541 }
542
543 /// Create a path slice from this byte string.
544 ///
545 /// When paths can be constructed from arbitrary byte sequences, this
546 /// always succeeds and is zero cost. Otherwise, this returns a UTF-8
547 /// decoding error if this byte string is not valid UTF-8. (For example,
548 /// assuming the representation of `Path` is opaque on Windows, file paths
549 /// are allowed to be a sequence of arbitrary 16-bit integers. There is
550 /// no obvious mapping from an arbitrary sequence of 8-bit integers to an
551 /// arbitrary sequence of 16-bit integers. If the representation of `Path`
552 /// is even opened up, then this will convert any sequence of bytes to an
553 /// `Path` without cost.)
554 ///
555 /// # Examples
556 ///
557 /// Basic usage:
558 ///
559 /// ```
560 /// use bstr::ByteSlice;
561 ///
562 /// let path = b"foo".to_path().expect("should be valid UTF-8");
563 /// assert_eq!(path.as_os_str(), "foo");
564 /// ```
565 #[cfg(feature = "std")]
566 #[inline]
567 fn to_path(&self) -> Result<&Path, Utf8Error> {
568 self.to_os_str().map(Path::new)
569 }
570
571 /// Lossily create a path slice from this byte string.
572 ///
573 /// When paths can be constructed from arbitrary byte sequences, this is
574 /// zero cost and always returns a slice. Otherwise, this will perform a
575 /// UTF-8 check and lossily convert this byte string into valid UTF-8 using
576 /// the Unicode replacement codepoint.
577 ///
578 /// Note that this can prevent the correct roundtripping of file paths when
579 /// the representation of `Path` is opaque.
580 ///
581 /// # Examples
582 ///
583 /// Basic usage:
584 ///
585 /// ```
586 /// use bstr::ByteSlice;
587 ///
588 /// let bs = b"foo\xFFbar";
589 /// let path = bs.to_path_lossy();
590 /// assert_eq!(path.to_string_lossy(), "foo\u{FFFD}bar");
591 /// ```
592 #[cfg(feature = "std")]
593 #[inline]
594 fn to_path_lossy(&self) -> Cow<'_, Path> {
595 use std::path::PathBuf;
596
597 match self.to_os_str_lossy() {
598 Cow::Borrowed(x) => Cow::Borrowed(Path::new(x)),
599 Cow::Owned(x) => Cow::Owned(PathBuf::from(x)),
600 }
601 }
602
603 /// Create a new byte string by repeating this byte string `n` times.
604 ///
605 /// # Panics
606 ///
607 /// This function panics if the capacity of the new byte string would
608 /// overflow.
609 ///
610 /// # Examples
611 ///
612 /// Basic usage:
613 ///
614 /// ```
615 /// use bstr::{B, ByteSlice};
616 ///
617 /// assert_eq!(b"foo".repeatn(4), B("foofoofoofoo"));
618 /// assert_eq!(b"foo".repeatn(0), B(""));
619 /// ```
620 #[cfg(feature = "alloc")]
621 #[inline]
622 fn repeatn(&self, n: usize) -> Vec<u8> {
623 self.as_bytes().repeat(n)
624 }
625
626 /// Returns true if and only if this byte string contains the given needle.
627 ///
628 /// # Examples
629 ///
630 /// Basic usage:
631 ///
632 /// ```
633 /// use bstr::ByteSlice;
634 ///
635 /// assert!(b"foo bar".contains_str("foo"));
636 /// assert!(b"foo bar".contains_str("bar"));
637 /// assert!(!b"foo".contains_str("foobar"));
638 /// ```
639 #[inline]
640 fn contains_str<B: AsRef<[u8]>>(&self, needle: B) -> bool {
641 self.find(needle).is_some()
642 }
643
644 /// Returns true if and only if this byte string has the given prefix.
645 ///
646 /// # Examples
647 ///
648 /// Basic usage:
649 ///
650 /// ```
651 /// use bstr::ByteSlice;
652 ///
653 /// assert!(b"foo bar".starts_with_str("foo"));
654 /// assert!(!b"foo bar".starts_with_str("bar"));
655 /// assert!(!b"foo".starts_with_str("foobar"));
656 /// ```
657 #[inline]
658 fn starts_with_str<B: AsRef<[u8]>>(&self, prefix: B) -> bool {
659 self.as_bytes().starts_with(prefix.as_ref())
660 }
661
662 /// Returns true if and only if this byte string has the given suffix.
663 ///
664 /// # Examples
665 ///
666 /// Basic usage:
667 ///
668 /// ```
669 /// use bstr::ByteSlice;
670 ///
671 /// assert!(b"foo bar".ends_with_str("bar"));
672 /// assert!(!b"foo bar".ends_with_str("foo"));
673 /// assert!(!b"bar".ends_with_str("foobar"));
674 /// ```
675 #[inline]
676 fn ends_with_str<B: AsRef<[u8]>>(&self, suffix: B) -> bool {
677 self.as_bytes().ends_with(suffix.as_ref())
678 }
679
680 /// Returns the index of the first occurrence of the given needle.
681 ///
682 /// The needle may be any type that can be cheaply converted into a
683 /// `&[u8]`. This includes, but is not limited to, `&str` and `&[u8]`.
684 ///
685 /// Note that if you're are searching for the same needle in many
686 /// different small haystacks, it may be faster to initialize a
687 /// [`Finder`](struct.Finder.html) once, and reuse it for each search.
688 ///
689 /// # Complexity
690 ///
691 /// This routine is guaranteed to have worst case linear time complexity
692 /// with respect to both the needle and the haystack. That is, this runs
693 /// in `O(needle.len() + haystack.len())` time.
694 ///
695 /// This routine is also guaranteed to have worst case constant space
696 /// complexity.
697 ///
698 /// # Examples
699 ///
700 /// Basic usage:
701 ///
702 /// ```
703 /// use bstr::ByteSlice;
704 ///
705 /// let s = b"foo bar baz";
706 /// assert_eq!(Some(0), s.find("foo"));
707 /// assert_eq!(Some(4), s.find("bar"));
708 /// assert_eq!(None, s.find("quux"));
709 /// ```
710 #[inline]
711 fn find<B: AsRef<[u8]>>(&self, needle: B) -> Option<usize> {
712 Finder::new(needle.as_ref()).find(self.as_bytes())
713 }
714
715 /// Returns the index of the last occurrence of the given needle.
716 ///
717 /// The needle may be any type that can be cheaply converted into a
718 /// `&[u8]`. This includes, but is not limited to, `&str` and `&[u8]`.
719 ///
720 /// Note that if you're are searching for the same needle in many
721 /// different small haystacks, it may be faster to initialize a
722 /// [`FinderReverse`](struct.FinderReverse.html) once, and reuse it for
723 /// each search.
724 ///
725 /// # Complexity
726 ///
727 /// This routine is guaranteed to have worst case linear time complexity
728 /// with respect to both the needle and the haystack. That is, this runs
729 /// in `O(needle.len() + haystack.len())` time.
730 ///
731 /// This routine is also guaranteed to have worst case constant space
732 /// complexity.
733 ///
734 /// # Examples
735 ///
736 /// Basic usage:
737 ///
738 /// ```
739 /// use bstr::ByteSlice;
740 ///
741 /// let s = b"foo bar baz";
742 /// assert_eq!(Some(0), s.rfind("foo"));
743 /// assert_eq!(Some(4), s.rfind("bar"));
744 /// assert_eq!(Some(8), s.rfind("ba"));
745 /// assert_eq!(None, s.rfind("quux"));
746 /// ```
747 #[inline]
748 fn rfind<B: AsRef<[u8]>>(&self, needle: B) -> Option<usize> {
749 FinderReverse::new(needle.as_ref()).rfind(self.as_bytes())
750 }
751
752 /// Returns an iterator of the non-overlapping occurrences of the given
753 /// needle. The iterator yields byte offset positions indicating the start
754 /// of each match.
755 ///
756 /// # Complexity
757 ///
758 /// This routine is guaranteed to have worst case linear time complexity
759 /// with respect to both the needle and the haystack. That is, this runs
760 /// in `O(needle.len() + haystack.len())` time.
761 ///
762 /// This routine is also guaranteed to have worst case constant space
763 /// complexity.
764 ///
765 /// # Examples
766 ///
767 /// Basic usage:
768 ///
769 /// ```
770 /// use bstr::ByteSlice;
771 ///
772 /// let s = b"foo bar foo foo quux foo";
773 /// let matches: Vec<usize> = s.find_iter("foo").collect();
774 /// assert_eq!(matches, vec![0, 8, 12, 21]);
775 /// ```
776 ///
777 /// An empty string matches at every position, including the position
778 /// immediately following the last byte:
779 ///
780 /// ```
781 /// use bstr::ByteSlice;
782 ///
783 /// let matches: Vec<usize> = b"foo".find_iter("").collect();
784 /// assert_eq!(matches, vec![0, 1, 2, 3]);
785 ///
786 /// let matches: Vec<usize> = b"".find_iter("").collect();
787 /// assert_eq!(matches, vec![0]);
788 /// ```
789 #[inline]
790 fn find_iter<'h, 'n, B: ?Sized + AsRef<[u8]>>(
791 &'h self,
792 needle: &'n B,
793 ) -> Find<'h, 'n> {
794 Find::new(self.as_bytes(), needle.as_ref())
795 }
796
797 /// Returns an iterator of the non-overlapping occurrences of the given
798 /// needle in reverse. The iterator yields byte offset positions indicating
799 /// the start of each match.
800 ///
801 /// # Complexity
802 ///
803 /// This routine is guaranteed to have worst case linear time complexity
804 /// with respect to both the needle and the haystack. That is, this runs
805 /// in `O(needle.len() + haystack.len())` time.
806 ///
807 /// This routine is also guaranteed to have worst case constant space
808 /// complexity.
809 ///
810 /// # Examples
811 ///
812 /// Basic usage:
813 ///
814 /// ```
815 /// use bstr::ByteSlice;
816 ///
817 /// let s = b"foo bar foo foo quux foo";
818 /// let matches: Vec<usize> = s.rfind_iter("foo").collect();
819 /// assert_eq!(matches, vec![21, 12, 8, 0]);
820 /// ```
821 ///
822 /// An empty string matches at every position, including the position
823 /// immediately following the last byte:
824 ///
825 /// ```
826 /// use bstr::ByteSlice;
827 ///
828 /// let matches: Vec<usize> = b"foo".rfind_iter("").collect();
829 /// assert_eq!(matches, vec![3, 2, 1, 0]);
830 ///
831 /// let matches: Vec<usize> = b"".rfind_iter("").collect();
832 /// assert_eq!(matches, vec![0]);
833 /// ```
834 #[inline]
835 fn rfind_iter<'h, 'n, B: ?Sized + AsRef<[u8]>>(
836 &'h self,
837 needle: &'n B,
838 ) -> FindReverse<'h, 'n> {
839 FindReverse::new(self.as_bytes(), needle.as_ref())
840 }
841
842 /// Returns the index of the first occurrence of the given byte. If the
843 /// byte does not occur in this byte string, then `None` is returned.
844 ///
845 /// # Examples
846 ///
847 /// Basic usage:
848 ///
849 /// ```
850 /// use bstr::ByteSlice;
851 ///
852 /// assert_eq!(Some(10), b"foo bar baz".find_byte(b'z'));
853 /// assert_eq!(None, b"foo bar baz".find_byte(b'y'));
854 /// ```
855 #[inline]
856 fn find_byte(&self, byte: u8) -> Option<usize> {
857 memchr(byte, self.as_bytes())
858 }
859
860 /// Returns the index of the last occurrence of the given byte. If the
861 /// byte does not occur in this byte string, then `None` is returned.
862 ///
863 /// # Examples
864 ///
865 /// Basic usage:
866 ///
867 /// ```
868 /// use bstr::ByteSlice;
869 ///
870 /// assert_eq!(Some(10), b"foo bar baz".rfind_byte(b'z'));
871 /// assert_eq!(None, b"foo bar baz".rfind_byte(b'y'));
872 /// ```
873 #[inline]
874 fn rfind_byte(&self, byte: u8) -> Option<usize> {
875 memrchr(byte, self.as_bytes())
876 }
877
878 /// Returns the index of the first occurrence of the given codepoint.
879 /// If the codepoint does not occur in this byte string, then `None` is
880 /// returned.
881 ///
882 /// Note that if one searches for the replacement codepoint, `\u{FFFD}`,
883 /// then only explicit occurrences of that encoding will be found. Invalid
884 /// UTF-8 sequences will not be matched.
885 ///
886 /// # Examples
887 ///
888 /// Basic usage:
889 ///
890 /// ```
891 /// use bstr::{B, ByteSlice};
892 ///
893 /// assert_eq!(Some(10), b"foo bar baz".find_char('z'));
894 /// assert_eq!(Some(4), B("αβγγδ").find_char('γ'));
895 /// assert_eq!(None, b"foo bar baz".find_char('y'));
896 /// ```
897 #[inline]
898 fn find_char(&self, ch: char) -> Option<usize> {
899 self.find(ch.encode_utf8(&mut [0; 4]))
900 }
901
902 /// Returns the index of the last occurrence of the given codepoint.
903 /// If the codepoint does not occur in this byte string, then `None` is
904 /// returned.
905 ///
906 /// Note that if one searches for the replacement codepoint, `\u{FFFD}`,
907 /// then only explicit occurrences of that encoding will be found. Invalid
908 /// UTF-8 sequences will not be matched.
909 ///
910 /// # Examples
911 ///
912 /// Basic usage:
913 ///
914 /// ```
915 /// use bstr::{B, ByteSlice};
916 ///
917 /// assert_eq!(Some(10), b"foo bar baz".rfind_char('z'));
918 /// assert_eq!(Some(6), B("αβγγδ").rfind_char('γ'));
919 /// assert_eq!(None, b"foo bar baz".rfind_char('y'));
920 /// ```
921 #[inline]
922 fn rfind_char(&self, ch: char) -> Option<usize> {
923 self.rfind(ch.encode_utf8(&mut [0; 4]))
924 }
925
926 /// Returns the index of the first occurrence of any of the bytes in the
927 /// provided set.
928 ///
929 /// The `byteset` may be any type that can be cheaply converted into a
930 /// `&[u8]`. This includes, but is not limited to, `&str` and `&[u8]`, but
931 /// note that passing a `&str` which contains multibyte characters may not
932 /// behave as you expect: each byte in the `&str` is treated as an
933 /// individual member of the byte set.
934 ///
935 /// Note that order is irrelevant for the `byteset` parameter, and
936 /// duplicate bytes present in its body are ignored.
937 ///
938 /// # Complexity
939 ///
940 /// This routine is guaranteed to have worst case linear time complexity
941 /// with respect to both the set of bytes and the haystack. That is, this
942 /// runs in `O(byteset.len() + haystack.len())` time.
943 ///
944 /// This routine is also guaranteed to have worst case constant space
945 /// complexity.
946 ///
947 /// # Examples
948 ///
949 /// Basic usage:
950 ///
951 /// ```
952 /// use bstr::ByteSlice;
953 ///
954 /// assert_eq!(b"foo bar baz".find_byteset(b"zr"), Some(6));
955 /// assert_eq!(b"foo baz bar".find_byteset(b"bzr"), Some(4));
956 /// assert_eq!(None, b"foo baz bar".find_byteset(b"\t\n"));
957 /// // The empty byteset never matches.
958 /// assert_eq!(None, b"abc".find_byteset(b""));
959 /// assert_eq!(None, b"".find_byteset(b""));
960 /// ```
961 #[inline]
962 fn find_byteset<B: AsRef<[u8]>>(&self, byteset: B) -> Option<usize> {
963 byteset::find(self.as_bytes(), byteset.as_ref())
964 }
965
966 /// Returns the index of the first occurrence of a byte that is not a
967 /// member of the provided set.
968 ///
969 /// The `byteset` may be any type that can be cheaply converted into a
970 /// `&[u8]`. This includes, but is not limited to, `&str` and `&[u8]`, but
971 /// note that passing a `&str` which contains multibyte characters may not
972 /// behave as you expect: each byte in the `&str` is treated as an
973 /// individual member of the byte set.
974 ///
975 /// Note that order is irrelevant for the `byteset` parameter, and
976 /// duplicate bytes present in its body are ignored.
977 ///
978 /// # Complexity
979 ///
980 /// This routine is guaranteed to have worst case linear time complexity
981 /// with respect to both the set of bytes and the haystack. That is, this
982 /// runs in `O(byteset.len() + haystack.len())` time.
983 ///
984 /// This routine is also guaranteed to have worst case constant space
985 /// complexity.
986 ///
987 /// # Examples
988 ///
989 /// Basic usage:
990 ///
991 /// ```
992 /// use bstr::ByteSlice;
993 ///
994 /// assert_eq!(b"foo bar baz".find_not_byteset(b"fo "), Some(4));
995 /// assert_eq!(b"\t\tbaz bar".find_not_byteset(b" \t\r\n"), Some(2));
996 /// assert_eq!(b"foo\nbaz\tbar".find_not_byteset(b"\t\n"), Some(0));
997 /// // The negation of the empty byteset matches everything.
998 /// assert_eq!(Some(0), b"abc".find_not_byteset(b""));
999 /// // But an empty string never contains anything.
1000 /// assert_eq!(None, b"".find_not_byteset(b""));
1001 /// ```
1002 #[inline]
1003 fn find_not_byteset<B: AsRef<[u8]>>(&self, byteset: B) -> Option<usize> {
1004 byteset::find_not(self.as_bytes(), byteset.as_ref())
1005 }
1006
1007 /// Returns the index of the last occurrence of any of the bytes in the
1008 /// provided set.
1009 ///
1010 /// The `byteset` may be any type that can be cheaply converted into a
1011 /// `&[u8]`. This includes, but is not limited to, `&str` and `&[u8]`, but
1012 /// note that passing a `&str` which contains multibyte characters may not
1013 /// behave as you expect: each byte in the `&str` is treated as an
1014 /// individual member of the byte set.
1015 ///
1016 /// Note that order is irrelevant for the `byteset` parameter, and duplicate
1017 /// bytes present in its body are ignored.
1018 ///
1019 /// # Complexity
1020 ///
1021 /// This routine is guaranteed to have worst case linear time complexity
1022 /// with respect to both the set of bytes and the haystack. That is, this
1023 /// runs in `O(byteset.len() + haystack.len())` time.
1024 ///
1025 /// This routine is also guaranteed to have worst case constant space
1026 /// complexity.
1027 ///
1028 /// # Examples
1029 ///
1030 /// Basic usage:
1031 ///
1032 /// ```
1033 /// use bstr::ByteSlice;
1034 ///
1035 /// assert_eq!(b"foo bar baz".rfind_byteset(b"agb"), Some(9));
1036 /// assert_eq!(b"foo baz bar".rfind_byteset(b"rabz "), Some(10));
1037 /// assert_eq!(b"foo baz bar".rfind_byteset(b"\n123"), None);
1038 /// ```
1039 #[inline]
1040 fn rfind_byteset<B: AsRef<[u8]>>(&self, byteset: B) -> Option<usize> {
1041 byteset::rfind(self.as_bytes(), byteset.as_ref())
1042 }
1043
1044 /// Returns the index of the last occurrence of a byte that is not a member
1045 /// of the provided set.
1046 ///
1047 /// The `byteset` may be any type that can be cheaply converted into a
1048 /// `&[u8]`. This includes, but is not limited to, `&str` and `&[u8]`, but
1049 /// note that passing a `&str` which contains multibyte characters may not
1050 /// behave as you expect: each byte in the `&str` is treated as an
1051 /// individual member of the byte set.
1052 ///
1053 /// Note that order is irrelevant for the `byteset` parameter, and
1054 /// duplicate bytes present in its body are ignored.
1055 ///
1056 /// # Complexity
1057 ///
1058 /// This routine is guaranteed to have worst case linear time complexity
1059 /// with respect to both the set of bytes and the haystack. That is, this
1060 /// runs in `O(byteset.len() + haystack.len())` time.
1061 ///
1062 /// This routine is also guaranteed to have worst case constant space
1063 /// complexity.
1064 ///
1065 /// # Examples
1066 ///
1067 /// Basic usage:
1068 ///
1069 /// ```
1070 /// use bstr::ByteSlice;
1071 ///
1072 /// assert_eq!(b"foo bar baz,\t".rfind_not_byteset(b",\t"), Some(10));
1073 /// assert_eq!(b"foo baz bar".rfind_not_byteset(b"rabz "), Some(2));
1074 /// assert_eq!(None, b"foo baz bar".rfind_not_byteset(b"barfoz "));
1075 /// ```
1076 #[inline]
1077 fn rfind_not_byteset<B: AsRef<[u8]>>(&self, byteset: B) -> Option<usize> {
1078 byteset::rfind_not(self.as_bytes(), byteset.as_ref())
1079 }
1080
1081 /// Returns an iterator over the fields in a byte string, separated
1082 /// by contiguous whitespace (according to the Unicode property
1083 /// `White_Space`).
1084 ///
1085 /// # Example
1086 ///
1087 /// Basic usage:
1088 ///
1089 /// ```
1090 /// use bstr::{B, ByteSlice};
1091 ///
1092 /// let s = B(" foo\tbar\t\u{2003}\nquux \n");
1093 /// let fields: Vec<&[u8]> = s.fields().collect();
1094 /// assert_eq!(fields, vec![B("foo"), B("bar"), B("quux")]);
1095 /// ```
1096 ///
1097 /// A byte string consisting of just whitespace yields no elements:
1098 ///
1099 /// ```
1100 /// use bstr::{B, ByteSlice};
1101 ///
1102 /// assert_eq!(0, B(" \n\t\u{2003}\n \t").fields().count());
1103 /// ```
1104 #[cfg(feature = "unicode")]
1105 #[doc(alias = "split_whitespace")]
1106 #[inline]
1107 fn fields(&self) -> Fields<'_> {
1108 Fields::new(self.as_bytes())
1109 }
1110
1111 /// Returns an iterator over the fields in a byte string, separated by
1112 /// contiguous codepoints satisfying the given predicate.
1113 ///
1114 /// If this byte string is not valid UTF-8, then the given closure will
1115 /// be called with a Unicode replacement codepoint when invalid UTF-8
1116 /// bytes are seen.
1117 ///
1118 /// # Example
1119 ///
1120 /// Basic usage:
1121 ///
1122 /// ```
1123 /// use bstr::{B, ByteSlice};
1124 ///
1125 /// let s = b"123foo999999bar1quux123456";
1126 /// let fields: Vec<&[u8]> = s.fields_with(|c| c.is_numeric()).collect();
1127 /// assert_eq!(fields, vec![B("foo"), B("bar"), B("quux")]);
1128 /// ```
1129 ///
1130 /// A byte string consisting of all codepoints satisfying the predicate
1131 /// yields no elements:
1132 ///
1133 /// ```
1134 /// use bstr::ByteSlice;
1135 ///
1136 /// assert_eq!(0, b"1911354563".fields_with(|c| c.is_numeric()).count());
1137 /// ```
1138 #[inline]
1139 fn fields_with<F: FnMut(char) -> bool>(&self, f: F) -> FieldsWith<'_, F> {
1140 FieldsWith::new(self.as_bytes(), f)
1141 }
1142
1143 /// Returns an iterator over substrings of this byte string, separated
1144 /// by the given byte string. Each element yielded is guaranteed not to
1145 /// include the splitter substring.
1146 ///
1147 /// The splitter may be any type that can be cheaply converted into a
1148 /// `&[u8]`. This includes, but is not limited to, `&str` and `&[u8]`.
1149 ///
1150 /// # Examples
1151 ///
1152 /// Basic usage:
1153 ///
1154 /// ```
1155 /// use bstr::{B, ByteSlice};
1156 ///
1157 /// let x: Vec<&[u8]> = b"Mary had a little lamb".split_str(" ").collect();
1158 /// assert_eq!(x, vec![
1159 /// B("Mary"), B("had"), B("a"), B("little"), B("lamb"),
1160 /// ]);
1161 ///
1162 /// let x: Vec<&[u8]> = b"".split_str("X").collect();
1163 /// assert_eq!(x, vec![b""]);
1164 ///
1165 /// let x: Vec<&[u8]> = b"lionXXtigerXleopard".split_str("X").collect();
1166 /// assert_eq!(x, vec![B("lion"), B(""), B("tiger"), B("leopard")]);
1167 ///
1168 /// let x: Vec<&[u8]> = b"lion::tiger::leopard".split_str("::").collect();
1169 /// assert_eq!(x, vec![B("lion"), B("tiger"), B("leopard")]);
1170 /// ```
1171 ///
1172 /// If a string contains multiple contiguous separators, you will end up
1173 /// with empty strings yielded by the iterator:
1174 ///
1175 /// ```
1176 /// use bstr::{B, ByteSlice};
1177 ///
1178 /// let x: Vec<&[u8]> = b"||||a||b|c".split_str("|").collect();
1179 /// assert_eq!(x, vec![
1180 /// B(""), B(""), B(""), B(""), B("a"), B(""), B("b"), B("c"),
1181 /// ]);
1182 ///
1183 /// let x: Vec<&[u8]> = b"(///)".split_str("/").collect();
1184 /// assert_eq!(x, vec![B("("), B(""), B(""), B(")")]);
1185 /// ```
1186 ///
1187 /// Separators at the start or end of a string are neighbored by empty
1188 /// strings.
1189 ///
1190 /// ```
1191 /// use bstr::{B, ByteSlice};
1192 ///
1193 /// let x: Vec<&[u8]> = b"010".split_str("0").collect();
1194 /// assert_eq!(x, vec![B(""), B("1"), B("")]);
1195 /// ```
1196 ///
1197 /// When the empty string is used as a separator, it splits every **byte**
1198 /// in the byte string, along with the beginning and end of the byte
1199 /// string.
1200 ///
1201 /// ```
1202 /// use bstr::{B, ByteSlice};
1203 ///
1204 /// let x: Vec<&[u8]> = b"rust".split_str("").collect();
1205 /// assert_eq!(x, vec![
1206 /// B(""), B("r"), B("u"), B("s"), B("t"), B(""),
1207 /// ]);
1208 ///
1209 /// // Splitting by an empty string is not UTF-8 aware. Elements yielded
1210 /// // may not be valid UTF-8!
1211 /// let x: Vec<&[u8]> = B("☃").split_str("").collect();
1212 /// assert_eq!(x, vec![
1213 /// B(""), B(b"\xE2"), B(b"\x98"), B(b"\x83"), B(""),
1214 /// ]);
1215 /// ```
1216 ///
1217 /// Contiguous separators, especially whitespace, can lead to possibly
1218 /// surprising behavior. For example, this code is correct:
1219 ///
1220 /// ```
1221 /// use bstr::{B, ByteSlice};
1222 ///
1223 /// let x: Vec<&[u8]> = b" a b c".split_str(" ").collect();
1224 /// assert_eq!(x, vec![
1225 /// B(""), B(""), B(""), B(""), B("a"), B(""), B("b"), B("c"),
1226 /// ]);
1227 /// ```
1228 ///
1229 /// It does *not* give you `["a", "b", "c"]`. For that behavior, use
1230 /// [`fields`](#method.fields) instead.
1231 #[inline]
1232 fn split_str<'h, 's, B: ?Sized + AsRef<[u8]>>(
1233 &'h self,
1234 splitter: &'s B,
1235 ) -> Split<'h, 's> {
1236 Split::new(self.as_bytes(), splitter.as_ref())
1237 }
1238
1239 /// Returns an iterator over substrings of this byte string, separated by
1240 /// the given byte string, in reverse. Each element yielded is guaranteed
1241 /// not to include the splitter substring.
1242 ///
1243 /// The splitter may be any type that can be cheaply converted into a
1244 /// `&[u8]`. This includes, but is not limited to, `&str` and `&[u8]`.
1245 ///
1246 /// # Examples
1247 ///
1248 /// Basic usage:
1249 ///
1250 /// ```
1251 /// use bstr::{B, ByteSlice};
1252 ///
1253 /// let x: Vec<&[u8]> =
1254 /// b"Mary had a little lamb".rsplit_str(" ").collect();
1255 /// assert_eq!(x, vec![
1256 /// B("lamb"), B("little"), B("a"), B("had"), B("Mary"),
1257 /// ]);
1258 ///
1259 /// let x: Vec<&[u8]> = b"".rsplit_str("X").collect();
1260 /// assert_eq!(x, vec![b""]);
1261 ///
1262 /// let x: Vec<&[u8]> = b"lionXXtigerXleopard".rsplit_str("X").collect();
1263 /// assert_eq!(x, vec![B("leopard"), B("tiger"), B(""), B("lion")]);
1264 ///
1265 /// let x: Vec<&[u8]> = b"lion::tiger::leopard".rsplit_str("::").collect();
1266 /// assert_eq!(x, vec![B("leopard"), B("tiger"), B("lion")]);
1267 /// ```
1268 ///
1269 /// If a string contains multiple contiguous separators, you will end up
1270 /// with empty strings yielded by the iterator:
1271 ///
1272 /// ```
1273 /// use bstr::{B, ByteSlice};
1274 ///
1275 /// let x: Vec<&[u8]> = b"||||a||b|c".rsplit_str("|").collect();
1276 /// assert_eq!(x, vec![
1277 /// B("c"), B("b"), B(""), B("a"), B(""), B(""), B(""), B(""),
1278 /// ]);
1279 ///
1280 /// let x: Vec<&[u8]> = b"(///)".rsplit_str("/").collect();
1281 /// assert_eq!(x, vec![B(")"), B(""), B(""), B("(")]);
1282 /// ```
1283 ///
1284 /// Separators at the start or end of a string are neighbored by empty
1285 /// strings.
1286 ///
1287 /// ```
1288 /// use bstr::{B, ByteSlice};
1289 ///
1290 /// let x: Vec<&[u8]> = b"010".rsplit_str("0").collect();
1291 /// assert_eq!(x, vec![B(""), B("1"), B("")]);
1292 /// ```
1293 ///
1294 /// When the empty string is used as a separator, it splits every **byte**
1295 /// in the byte string, along with the beginning and end of the byte
1296 /// string.
1297 ///
1298 /// ```
1299 /// use bstr::{B, ByteSlice};
1300 ///
1301 /// let x: Vec<&[u8]> = b"rust".rsplit_str("").collect();
1302 /// assert_eq!(x, vec![
1303 /// B(""), B("t"), B("s"), B("u"), B("r"), B(""),
1304 /// ]);
1305 ///
1306 /// // Splitting by an empty string is not UTF-8 aware. Elements yielded
1307 /// // may not be valid UTF-8!
1308 /// let x: Vec<&[u8]> = B("☃").rsplit_str("").collect();
1309 /// assert_eq!(x, vec![B(""), B(b"\x83"), B(b"\x98"), B(b"\xE2"), B("")]);
1310 /// ```
1311 ///
1312 /// Contiguous separators, especially whitespace, can lead to possibly
1313 /// surprising behavior. For example, this code is correct:
1314 ///
1315 /// ```
1316 /// use bstr::{B, ByteSlice};
1317 ///
1318 /// let x: Vec<&[u8]> = b" a b c".rsplit_str(" ").collect();
1319 /// assert_eq!(x, vec![
1320 /// B("c"), B("b"), B(""), B("a"), B(""), B(""), B(""), B(""),
1321 /// ]);
1322 /// ```
1323 ///
1324 /// It does *not* give you `["a", "b", "c"]`.
1325 #[inline]
1326 fn rsplit_str<'h, 's, B: ?Sized + AsRef<[u8]>>(
1327 &'h self,
1328 splitter: &'s B,
1329 ) -> SplitReverse<'h, 's> {
1330 SplitReverse::new(self.as_bytes(), splitter.as_ref())
1331 }
1332
1333 /// Split this byte string at the first occurrence of `splitter`.
1334 ///
1335 /// If the `splitter` is found in the byte string, returns a tuple
1336 /// containing the parts of the string before and after the first occurrence
1337 /// of `splitter` respectively. Otherwise, if there are no occurrences of
1338 /// `splitter` in the byte string, returns `None`.
1339 ///
1340 /// The splitter may be any type that can be cheaply converted into a
1341 /// `&[u8]`. This includes, but is not limited to, `&str` and `&[u8]`.
1342 ///
1343 /// If you need to split on the *last* instance of a delimiter instead, see
1344 /// the [`ByteSlice::rsplit_once_str`](#method.rsplit_once_str) method .
1345 ///
1346 /// # Examples
1347 ///
1348 /// Basic usage:
1349 ///
1350 /// ```
1351 /// use bstr::{B, ByteSlice};
1352 ///
1353 /// assert_eq!(
1354 /// B("foo,bar").split_once_str(","),
1355 /// Some((B("foo"), B("bar"))),
1356 /// );
1357 /// assert_eq!(
1358 /// B("foo,bar,baz").split_once_str(","),
1359 /// Some((B("foo"), B("bar,baz"))),
1360 /// );
1361 /// assert_eq!(B("foo").split_once_str(","), None);
1362 /// assert_eq!(B("foo,").split_once_str(b","), Some((B("foo"), B(""))));
1363 /// assert_eq!(B(",foo").split_once_str(b","), Some((B(""), B("foo"))));
1364 /// ```
1365 #[inline]
1366 fn split_once_str<'a, B: ?Sized + AsRef<[u8]>>(
1367 &'a self,
1368 splitter: &B,
1369 ) -> Option<(&'a [u8], &'a [u8])> {
1370 let bytes = self.as_bytes();
1371 let splitter = splitter.as_ref();
1372 let start = Finder::new(splitter).find(bytes)?;
1373 let end = start + splitter.len();
1374 Some((&bytes[..start], &bytes[end..]))
1375 }
1376
1377 /// Split this byte string at the last occurrence of `splitter`.
1378 ///
1379 /// If the `splitter` is found in the byte string, returns a tuple
1380 /// containing the parts of the string before and after the last occurrence
1381 /// of `splitter`, respectively. Otherwise, if there are no occurrences of
1382 /// `splitter` in the byte string, returns `None`.
1383 ///
1384 /// The splitter may be any type that can be cheaply converted into a
1385 /// `&[u8]`. This includes, but is not limited to, `&str` and `&[u8]`.
1386 ///
1387 /// If you need to split on the *first* instance of a delimiter instead, see
1388 /// the [`ByteSlice::split_once_str`](#method.split_once_str) method.
1389 ///
1390 /// # Examples
1391 ///
1392 /// Basic usage:
1393 ///
1394 /// ```
1395 /// use bstr::{B, ByteSlice};
1396 ///
1397 /// assert_eq!(
1398 /// B("foo,bar").rsplit_once_str(","),
1399 /// Some((B("foo"), B("bar"))),
1400 /// );
1401 /// assert_eq!(
1402 /// B("foo,bar,baz").rsplit_once_str(","),
1403 /// Some((B("foo,bar"), B("baz"))),
1404 /// );
1405 /// assert_eq!(B("foo").rsplit_once_str(","), None);
1406 /// assert_eq!(B("foo,").rsplit_once_str(b","), Some((B("foo"), B(""))));
1407 /// assert_eq!(B(",foo").rsplit_once_str(b","), Some((B(""), B("foo"))));
1408 /// ```
1409 #[inline]
1410 fn rsplit_once_str<'a, B: ?Sized + AsRef<[u8]>>(
1411 &'a self,
1412 splitter: &B,
1413 ) -> Option<(&'a [u8], &'a [u8])> {
1414 let bytes = self.as_bytes();
1415 let splitter = splitter.as_ref();
1416 let start = FinderReverse::new(splitter).rfind(bytes)?;
1417 let end = start + splitter.len();
1418 Some((&bytes[..start], &bytes[end..]))
1419 }
1420
1421 /// Returns an iterator of at most `limit` substrings of this byte string,
1422 /// separated by the given byte string. If `limit` substrings are yielded,
1423 /// then the last substring will contain the remainder of this byte string.
1424 ///
1425 /// The needle may be any type that can be cheaply converted into a
1426 /// `&[u8]`. This includes, but is not limited to, `&str` and `&[u8]`.
1427 ///
1428 /// # Examples
1429 ///
1430 /// Basic usage:
1431 ///
1432 /// ```
1433 /// use bstr::{B, ByteSlice};
1434 ///
1435 /// let x: Vec<_> = b"Mary had a little lamb".splitn_str(3, " ").collect();
1436 /// assert_eq!(x, vec![B("Mary"), B("had"), B("a little lamb")]);
1437 ///
1438 /// let x: Vec<_> = b"".splitn_str(3, "X").collect();
1439 /// assert_eq!(x, vec![b""]);
1440 ///
1441 /// let x: Vec<_> = b"lionXXtigerXleopard".splitn_str(3, "X").collect();
1442 /// assert_eq!(x, vec![B("lion"), B(""), B("tigerXleopard")]);
1443 ///
1444 /// let x: Vec<_> = b"lion::tiger::leopard".splitn_str(2, "::").collect();
1445 /// assert_eq!(x, vec![B("lion"), B("tiger::leopard")]);
1446 ///
1447 /// let x: Vec<_> = b"abcXdef".splitn_str(1, "X").collect();
1448 /// assert_eq!(x, vec![B("abcXdef")]);
1449 ///
1450 /// let x: Vec<_> = b"abcdef".splitn_str(2, "X").collect();
1451 /// assert_eq!(x, vec![B("abcdef")]);
1452 ///
1453 /// let x: Vec<_> = b"abcXdef".splitn_str(0, "X").collect();
1454 /// assert!(x.is_empty());
1455 /// ```
1456 #[inline]
1457 fn splitn_str<'h, 's, B: ?Sized + AsRef<[u8]>>(
1458 &'h self,
1459 limit: usize,
1460 splitter: &'s B,
1461 ) -> SplitN<'h, 's> {
1462 SplitN::new(self.as_bytes(), splitter.as_ref(), limit)
1463 }
1464
1465 /// Returns an iterator of at most `limit` substrings of this byte string,
1466 /// separated by the given byte string, in reverse. If `limit` substrings
1467 /// are yielded, then the last substring will contain the remainder of this
1468 /// byte string.
1469 ///
1470 /// The needle may be any type that can be cheaply converted into a
1471 /// `&[u8]`. This includes, but is not limited to, `&str` and `&[u8]`.
1472 ///
1473 /// # Examples
1474 ///
1475 /// Basic usage:
1476 ///
1477 /// ```
1478 /// use bstr::{B, ByteSlice};
1479 ///
1480 /// let x: Vec<_> =
1481 /// b"Mary had a little lamb".rsplitn_str(3, " ").collect();
1482 /// assert_eq!(x, vec![B("lamb"), B("little"), B("Mary had a")]);
1483 ///
1484 /// let x: Vec<_> = b"".rsplitn_str(3, "X").collect();
1485 /// assert_eq!(x, vec![b""]);
1486 ///
1487 /// let x: Vec<_> = b"lionXXtigerXleopard".rsplitn_str(3, "X").collect();
1488 /// assert_eq!(x, vec![B("leopard"), B("tiger"), B("lionX")]);
1489 ///
1490 /// let x: Vec<_> = b"lion::tiger::leopard".rsplitn_str(2, "::").collect();
1491 /// assert_eq!(x, vec![B("leopard"), B("lion::tiger")]);
1492 ///
1493 /// let x: Vec<_> = b"abcXdef".rsplitn_str(1, "X").collect();
1494 /// assert_eq!(x, vec![B("abcXdef")]);
1495 ///
1496 /// let x: Vec<_> = b"abcdef".rsplitn_str(2, "X").collect();
1497 /// assert_eq!(x, vec![B("abcdef")]);
1498 ///
1499 /// let x: Vec<_> = b"abcXdef".rsplitn_str(0, "X").collect();
1500 /// assert!(x.is_empty());
1501 /// ```
1502 #[inline]
1503 fn rsplitn_str<'h, 's, B: ?Sized + AsRef<[u8]>>(
1504 &'h self,
1505 limit: usize,
1506 splitter: &'s B,
1507 ) -> SplitNReverse<'h, 's> {
1508 SplitNReverse::new(self.as_bytes(), splitter.as_ref(), limit)
1509 }
1510
1511 /// Replace all matches of the given needle with the given replacement, and
1512 /// the result as a new `Vec<u8>`.
1513 ///
1514 /// This routine is useful as a convenience. If you need to reuse an
1515 /// allocation, use [`replace_into`](#method.replace_into) instead.
1516 ///
1517 /// # Examples
1518 ///
1519 /// Basic usage:
1520 ///
1521 /// ```
1522 /// use bstr::ByteSlice;
1523 ///
1524 /// let s = b"this is old".replace("old", "new");
1525 /// assert_eq!(s, "this is new".as_bytes());
1526 /// ```
1527 ///
1528 /// When the pattern doesn't match:
1529 ///
1530 /// ```
1531 /// use bstr::ByteSlice;
1532 ///
1533 /// let s = b"this is old".replace("nada nada", "limonada");
1534 /// assert_eq!(s, "this is old".as_bytes());
1535 /// ```
1536 ///
1537 /// When the needle is an empty string:
1538 ///
1539 /// ```
1540 /// use bstr::ByteSlice;
1541 ///
1542 /// let s = b"foo".replace("", "Z");
1543 /// assert_eq!(s, "ZfZoZoZ".as_bytes());
1544 /// ```
1545 #[cfg(feature = "alloc")]
1546 #[must_use]
1547 #[inline]
1548 fn replace<N: AsRef<[u8]>, R: AsRef<[u8]>>(
1549 &self,
1550 needle: N,
1551 replacement: R,
1552 ) -> Vec<u8> {
1553 let mut dest = Vec::with_capacity(self.as_bytes().len());
1554 self.replace_into(needle, replacement, &mut dest);
1555 dest
1556 }
1557
1558 /// Replace up to `limit` matches of the given needle with the given
1559 /// replacement, and the result as a new `Vec<u8>`.
1560 ///
1561 /// This routine is useful as a convenience. If you need to reuse an
1562 /// allocation, use [`replacen_into`](#method.replacen_into) instead.
1563 ///
1564 /// # Examples
1565 ///
1566 /// Basic usage:
1567 ///
1568 /// ```
1569 /// use bstr::ByteSlice;
1570 ///
1571 /// let s = b"foofoo".replacen("o", "z", 2);
1572 /// assert_eq!(s, "fzzfoo".as_bytes());
1573 /// ```
1574 ///
1575 /// When the pattern doesn't match:
1576 ///
1577 /// ```
1578 /// use bstr::ByteSlice;
1579 ///
1580 /// let s = b"foofoo".replacen("a", "z", 2);
1581 /// assert_eq!(s, "foofoo".as_bytes());
1582 /// ```
1583 ///
1584 /// When the needle is an empty string:
1585 ///
1586 /// ```
1587 /// use bstr::ByteSlice;
1588 ///
1589 /// let s = b"foo".replacen("", "Z", 2);
1590 /// assert_eq!(s, "ZfZoo".as_bytes());
1591 /// ```
1592 #[cfg(feature = "alloc")]
1593 #[must_use]
1594 #[inline]
1595 fn replacen<N: AsRef<[u8]>, R: AsRef<[u8]>>(
1596 &self,
1597 needle: N,
1598 replacement: R,
1599 limit: usize,
1600 ) -> Vec<u8> {
1601 let mut dest = Vec::with_capacity(self.as_bytes().len());
1602 self.replacen_into(needle, replacement, limit, &mut dest);
1603 dest
1604 }
1605
1606 /// Replace all matches of the given needle with the given replacement,
1607 /// and write the result into the provided `Vec<u8>`.
1608 ///
1609 /// This does **not** clear `dest` before writing to it.
1610 ///
1611 /// This routine is useful for reusing allocation. For a more convenient
1612 /// API, use [`replace`](#method.replace) instead.
1613 ///
1614 /// # Examples
1615 ///
1616 /// Basic usage:
1617 ///
1618 /// ```
1619 /// use bstr::ByteSlice;
1620 ///
1621 /// let s = b"this is old";
1622 ///
1623 /// let mut dest = vec![];
1624 /// s.replace_into("old", "new", &mut dest);
1625 /// assert_eq!(dest, "this is new".as_bytes());
1626 /// ```
1627 ///
1628 /// When the pattern doesn't match:
1629 ///
1630 /// ```
1631 /// use bstr::ByteSlice;
1632 ///
1633 /// let s = b"this is old";
1634 ///
1635 /// let mut dest = vec![];
1636 /// s.replace_into("nada nada", "limonada", &mut dest);
1637 /// assert_eq!(dest, "this is old".as_bytes());
1638 /// ```
1639 ///
1640 /// When the needle is an empty string:
1641 ///
1642 /// ```
1643 /// use bstr::ByteSlice;
1644 ///
1645 /// let s = b"foo";
1646 ///
1647 /// let mut dest = vec![];
1648 /// s.replace_into("", "Z", &mut dest);
1649 /// assert_eq!(dest, "ZfZoZoZ".as_bytes());
1650 /// ```
1651 #[cfg(feature = "alloc")]
1652 #[inline]
1653 fn replace_into<N: AsRef<[u8]>, R: AsRef<[u8]>>(
1654 &self,
1655 needle: N,
1656 replacement: R,
1657 dest: &mut Vec<u8>,
1658 ) {
1659 let (needle, replacement) = (needle.as_ref(), replacement.as_ref());
1660
1661 let mut last = 0;
1662 for start in self.find_iter(needle) {
1663 dest.push_str(&self.as_bytes()[last..start]);
1664 dest.push_str(replacement);
1665 last = start + needle.len();
1666 }
1667 dest.push_str(&self.as_bytes()[last..]);
1668 }
1669
1670 /// Replace up to `limit` matches of the given needle with the given
1671 /// replacement, and write the result into the provided `Vec<u8>`.
1672 ///
1673 /// This does **not** clear `dest` before writing to it.
1674 ///
1675 /// This routine is useful for reusing allocation. For a more convenient
1676 /// API, use [`replacen`](#method.replacen) instead.
1677 ///
1678 /// # Examples
1679 ///
1680 /// Basic usage:
1681 ///
1682 /// ```
1683 /// use bstr::ByteSlice;
1684 ///
1685 /// let s = b"foofoo";
1686 ///
1687 /// let mut dest = vec![];
1688 /// s.replacen_into("o", "z", 2, &mut dest);
1689 /// assert_eq!(dest, "fzzfoo".as_bytes());
1690 /// ```
1691 ///
1692 /// When the pattern doesn't match:
1693 ///
1694 /// ```
1695 /// use bstr::ByteSlice;
1696 ///
1697 /// let s = b"foofoo";
1698 ///
1699 /// let mut dest = vec![];
1700 /// s.replacen_into("a", "z", 2, &mut dest);
1701 /// assert_eq!(dest, "foofoo".as_bytes());
1702 /// ```
1703 ///
1704 /// When the needle is an empty string:
1705 ///
1706 /// ```
1707 /// use bstr::ByteSlice;
1708 ///
1709 /// let s = b"foo";
1710 ///
1711 /// let mut dest = vec![];
1712 /// s.replacen_into("", "Z", 2, &mut dest);
1713 /// assert_eq!(dest, "ZfZoo".as_bytes());
1714 /// ```
1715 #[cfg(feature = "alloc")]
1716 #[inline]
1717 fn replacen_into<N: AsRef<[u8]>, R: AsRef<[u8]>>(
1718 &self,
1719 needle: N,
1720 replacement: R,
1721 limit: usize,
1722 dest: &mut Vec<u8>,
1723 ) {
1724 let (needle, replacement) = (needle.as_ref(), replacement.as_ref());
1725
1726 let mut last = 0;
1727 for start in self.find_iter(needle).take(limit) {
1728 dest.push_str(&self.as_bytes()[last..start]);
1729 dest.push_str(replacement);
1730 last = start + needle.len();
1731 }
1732 dest.push_str(&self.as_bytes()[last..]);
1733 }
1734
1735 /// Returns an iterator over the bytes in this byte string.
1736 ///
1737 /// # Examples
1738 ///
1739 /// Basic usage:
1740 ///
1741 /// ```
1742 /// use bstr::ByteSlice;
1743 ///
1744 /// let bs = b"foobar";
1745 /// let bytes: Vec<u8> = bs.bytes().collect();
1746 /// assert_eq!(bytes, bs);
1747 /// ```
1748 #[inline]
1749 fn bytes(&self) -> Bytes<'_> {
1750 Bytes { it: self.as_bytes().iter() }
1751 }
1752
1753 /// Returns an iterator over the Unicode scalar values in this byte string.
1754 /// If invalid UTF-8 is encountered, then the Unicode replacement codepoint
1755 /// is yielded instead.
1756 ///
1757 /// # Examples
1758 ///
1759 /// Basic usage:
1760 ///
1761 /// ```
1762 /// use bstr::ByteSlice;
1763 ///
1764 /// let bs = b"\xE2\x98\x83\xFF\xF0\x9D\x9E\x83\xE2\x98\x61";
1765 /// let chars: Vec<char> = bs.chars().collect();
1766 /// assert_eq!(vec!['☃', '\u{FFFD}', '𝞃', '\u{FFFD}', 'a'], chars);
1767 /// ```
1768 ///
1769 /// Codepoints can also be iterated over in reverse:
1770 ///
1771 /// ```
1772 /// use bstr::ByteSlice;
1773 ///
1774 /// let bs = b"\xE2\x98\x83\xFF\xF0\x9D\x9E\x83\xE2\x98\x61";
1775 /// let chars: Vec<char> = bs.chars().rev().collect();
1776 /// assert_eq!(vec!['a', '\u{FFFD}', '𝞃', '\u{FFFD}', '☃'], chars);
1777 /// ```
1778 #[inline]
1779 fn chars(&self) -> Chars<'_> {
1780 Chars::new(self.as_bytes())
1781 }
1782
1783 /// Returns an iterator over the Unicode scalar values in this byte string
1784 /// along with their starting and ending byte index positions. If invalid
1785 /// UTF-8 is encountered, then the Unicode replacement codepoint is yielded
1786 /// instead.
1787 ///
1788 /// Note that this is slightly different from the `CharIndices` iterator
1789 /// provided by the standard library. Aside from working on possibly
1790 /// invalid UTF-8, this iterator provides both the corresponding starting
1791 /// and ending byte indices of each codepoint yielded. The ending position
1792 /// is necessary to slice the original byte string when invalid UTF-8 bytes
1793 /// are converted into a Unicode replacement codepoint, since a single
1794 /// replacement codepoint can substitute anywhere from 1 to 3 invalid bytes
1795 /// (inclusive).
1796 ///
1797 /// # Examples
1798 ///
1799 /// Basic usage:
1800 ///
1801 /// ```
1802 /// use bstr::ByteSlice;
1803 ///
1804 /// let bs = b"\xE2\x98\x83\xFF\xF0\x9D\x9E\x83\xE2\x98\x61";
1805 /// let chars: Vec<(usize, usize, char)> = bs.char_indices().collect();
1806 /// assert_eq!(chars, vec![
1807 /// (0, 3, '☃'),
1808 /// (3, 4, '\u{FFFD}'),
1809 /// (4, 8, '𝞃'),
1810 /// (8, 10, '\u{FFFD}'),
1811 /// (10, 11, 'a'),
1812 /// ]);
1813 /// ```
1814 ///
1815 /// Codepoints can also be iterated over in reverse:
1816 ///
1817 /// ```
1818 /// use bstr::ByteSlice;
1819 ///
1820 /// let bs = b"\xE2\x98\x83\xFF\xF0\x9D\x9E\x83\xE2\x98\x61";
1821 /// let chars: Vec<(usize, usize, char)> = bs
1822 /// .char_indices()
1823 /// .rev()
1824 /// .collect();
1825 /// assert_eq!(chars, vec![
1826 /// (10, 11, 'a'),
1827 /// (8, 10, '\u{FFFD}'),
1828 /// (4, 8, '𝞃'),
1829 /// (3, 4, '\u{FFFD}'),
1830 /// (0, 3, '☃'),
1831 /// ]);
1832 /// ```
1833 #[inline]
1834 fn char_indices(&self) -> CharIndices<'_> {
1835 CharIndices::new(self.as_bytes())
1836 }
1837
1838 /// Iterate over chunks of valid UTF-8.
1839 ///
1840 /// The iterator returned yields chunks of valid UTF-8 separated by invalid
1841 /// UTF-8 bytes, if they exist. Invalid UTF-8 bytes are always 1-3 bytes,
1842 /// which are determined via the "substitution of maximal subparts"
1843 /// strategy described in the docs for the
1844 /// [`ByteSlice::to_str_lossy`](trait.ByteSlice.html#method.to_str_lossy)
1845 /// method.
1846 ///
1847 /// # Examples
1848 ///
1849 /// This example shows how to gather all valid and invalid chunks from a
1850 /// byte slice:
1851 ///
1852 /// ```
1853 /// use bstr::{ByteSlice, Utf8Chunk};
1854 ///
1855 /// let bytes = b"foo\xFD\xFEbar\xFF";
1856 ///
1857 /// let (mut valid_chunks, mut invalid_chunks) = (vec![], vec![]);
1858 /// for chunk in bytes.utf8_chunks() {
1859 /// if !chunk.valid().is_empty() {
1860 /// valid_chunks.push(chunk.valid());
1861 /// }
1862 /// if !chunk.invalid().is_empty() {
1863 /// invalid_chunks.push(chunk.invalid());
1864 /// }
1865 /// }
1866 ///
1867 /// assert_eq!(valid_chunks, vec!["foo", "bar"]);
1868 /// assert_eq!(invalid_chunks, vec![b"\xFD", b"\xFE", b"\xFF"]);
1869 /// ```
1870 #[inline]
1871 fn utf8_chunks(&self) -> Utf8Chunks<'_> {
1872 Utf8Chunks { bytes: self.as_bytes() }
1873 }
1874
1875 /// Returns an iterator over the grapheme clusters in this byte string.
1876 /// If invalid UTF-8 is encountered, then the Unicode replacement codepoint
1877 /// is yielded instead.
1878 ///
1879 /// # Examples
1880 ///
1881 /// This example shows how multiple codepoints can combine to form a
1882 /// single grapheme cluster:
1883 ///
1884 /// ```
1885 /// use bstr::ByteSlice;
1886 ///
1887 /// let bs = "a\u{0300}\u{0316}\u{1F1FA}\u{1F1F8}".as_bytes();
1888 /// let graphemes: Vec<&str> = bs.graphemes().collect();
1889 /// assert_eq!(vec!["à̖", "🇺🇸"], graphemes);
1890 /// ```
1891 ///
1892 /// This shows that graphemes can be iterated over in reverse:
1893 ///
1894 /// ```
1895 /// use bstr::ByteSlice;
1896 ///
1897 /// let bs = "a\u{0300}\u{0316}\u{1F1FA}\u{1F1F8}".as_bytes();
1898 /// let graphemes: Vec<&str> = bs.graphemes().rev().collect();
1899 /// assert_eq!(vec!["🇺🇸", "à̖"], graphemes);
1900 /// ```
1901 #[cfg(feature = "unicode")]
1902 #[inline]
1903 fn graphemes(&self) -> Graphemes<'_> {
1904 Graphemes::new(self.as_bytes())
1905 }
1906
1907 /// Returns an iterator over the grapheme clusters in this byte string
1908 /// along with their starting and ending byte index positions. If invalid
1909 /// UTF-8 is encountered, then the Unicode replacement codepoint is yielded
1910 /// instead.
1911 ///
1912 /// # Examples
1913 ///
1914 /// This example shows how to get the byte offsets of each individual
1915 /// grapheme cluster:
1916 ///
1917 /// ```
1918 /// use bstr::ByteSlice;
1919 ///
1920 /// let bs = "a\u{0300}\u{0316}\u{1F1FA}\u{1F1F8}".as_bytes();
1921 /// let graphemes: Vec<(usize, usize, &str)> =
1922 /// bs.grapheme_indices().collect();
1923 /// assert_eq!(vec![(0, 5, "à̖"), (5, 13, "🇺🇸")], graphemes);
1924 /// ```
1925 ///
1926 /// This example shows what happens when invalid UTF-8 is encountered. Note
1927 /// that the offsets are valid indices into the original string, and do
1928 /// not necessarily correspond to the length of the `&str` returned!
1929 ///
1930 /// ```
1931 /// # #[cfg(all(feature = "alloc"))] {
1932 /// use bstr::{ByteSlice, ByteVec};
1933 ///
1934 /// let mut bytes = vec![];
1935 /// bytes.push_str("a\u{0300}\u{0316}");
1936 /// bytes.push(b'\xFF');
1937 /// bytes.push_str("\u{1F1FA}\u{1F1F8}");
1938 ///
1939 /// let graphemes: Vec<(usize, usize, &str)> =
1940 /// bytes.grapheme_indices().collect();
1941 /// assert_eq!(
1942 /// graphemes,
1943 /// vec![(0, 5, "à̖"), (5, 6, "\u{FFFD}"), (6, 14, "🇺🇸")]
1944 /// );
1945 /// # }
1946 /// ```
1947 #[cfg(feature = "unicode")]
1948 #[inline]
1949 fn grapheme_indices(&self) -> GraphemeIndices<'_> {
1950 GraphemeIndices::new(self.as_bytes())
1951 }
1952
1953 /// Returns an iterator over the words in this byte string. If invalid
1954 /// UTF-8 is encountered, then the Unicode replacement codepoint is yielded
1955 /// instead.
1956 ///
1957 /// This is similar to
1958 /// [`words_with_breaks`](trait.ByteSlice.html#method.words_with_breaks),
1959 /// except it only returns elements that contain a "word" character. A word
1960 /// character is defined by UTS #18 (Annex C) to be the combination of the
1961 /// `Alphabetic` and `Join_Control` properties, along with the
1962 /// `Decimal_Number`, `Mark` and `Connector_Punctuation` general
1963 /// categories.
1964 ///
1965 /// Since words are made up of one or more codepoints, this iterator
1966 /// yields `&str` elements. When invalid UTF-8 is encountered, replacement
1967 /// codepoints are [substituted](index.html#handling-of-invalid-utf-8).
1968 ///
1969 /// # Examples
1970 ///
1971 /// Basic usage:
1972 ///
1973 /// ```
1974 /// use bstr::ByteSlice;
1975 ///
1976 /// let bs = br#"The quick ("brown") fox can't jump 32.3 feet, right?"#;
1977 /// let words: Vec<&str> = bs.words().collect();
1978 /// assert_eq!(words, vec![
1979 /// "The", "quick", "brown", "fox", "can't",
1980 /// "jump", "32.3", "feet", "right",
1981 /// ]);
1982 /// ```
1983 #[cfg(feature = "unicode")]
1984 #[inline]
1985 fn words(&self) -> Words<'_> {
1986 Words::new(self.as_bytes())
1987 }
1988
1989 /// Returns an iterator over the words in this byte string along with
1990 /// their starting and ending byte index positions.
1991 ///
1992 /// This is similar to
1993 /// [`words_with_break_indices`](trait.ByteSlice.html#method.words_with_break_indices),
1994 /// except it only returns elements that contain a "word" character. A word
1995 /// character is defined by UTS #18 (Annex C) to be the combination of the
1996 /// `Alphabetic` and `Join_Control` properties, along with the
1997 /// `Decimal_Number`, `Mark` and `Connector_Punctuation` general
1998 /// categories.
1999 ///
2000 /// Since words are made up of one or more codepoints, this iterator
2001 /// yields `&str` elements. When invalid UTF-8 is encountered, replacement
2002 /// codepoints are [substituted](index.html#handling-of-invalid-utf-8).
2003 ///
2004 /// # Examples
2005 ///
2006 /// This example shows how to get the byte offsets of each individual
2007 /// word:
2008 ///
2009 /// ```
2010 /// use bstr::ByteSlice;
2011 ///
2012 /// let bs = b"can't jump 32.3 feet";
2013 /// let words: Vec<(usize, usize, &str)> = bs.word_indices().collect();
2014 /// assert_eq!(words, vec![
2015 /// (0, 5, "can't"),
2016 /// (6, 10, "jump"),
2017 /// (11, 15, "32.3"),
2018 /// (16, 20, "feet"),
2019 /// ]);
2020 /// ```
2021 #[cfg(feature = "unicode")]
2022 #[inline]
2023 fn word_indices(&self) -> WordIndices<'_> {
2024 WordIndices::new(self.as_bytes())
2025 }
2026
2027 /// Returns an iterator over the words in this byte string, along with
2028 /// all breaks between the words. Concatenating all elements yielded by
2029 /// the iterator results in the original string (modulo Unicode replacement
2030 /// codepoint substitutions if invalid UTF-8 is encountered).
2031 ///
2032 /// Since words are made up of one or more codepoints, this iterator
2033 /// yields `&str` elements. When invalid UTF-8 is encountered, replacement
2034 /// codepoints are [substituted](index.html#handling-of-invalid-utf-8).
2035 ///
2036 /// # Examples
2037 ///
2038 /// Basic usage:
2039 ///
2040 /// ```
2041 /// use bstr::ByteSlice;
2042 ///
2043 /// let bs = br#"The quick ("brown") fox can't jump 32.3 feet, right?"#;
2044 /// let words: Vec<&str> = bs.words_with_breaks().collect();
2045 /// assert_eq!(words, vec![
2046 /// "The", " ", "quick", " ", "(", "\"", "brown", "\"", ")",
2047 /// " ", "fox", " ", "can't", " ", "jump", " ", "32.3", " ", "feet",
2048 /// ",", " ", "right", "?",
2049 /// ]);
2050 /// ```
2051 #[cfg(feature = "unicode")]
2052 #[inline]
2053 fn words_with_breaks(&self) -> WordsWithBreaks<'_> {
2054 WordsWithBreaks::new(self.as_bytes())
2055 }
2056
2057 /// Returns an iterator over the words and their byte offsets in this
2058 /// byte string, along with all breaks between the words. Concatenating
2059 /// all elements yielded by the iterator results in the original string
2060 /// (modulo Unicode replacement codepoint substitutions if invalid UTF-8 is
2061 /// encountered).
2062 ///
2063 /// Since words are made up of one or more codepoints, this iterator
2064 /// yields `&str` elements. When invalid UTF-8 is encountered, replacement
2065 /// codepoints are [substituted](index.html#handling-of-invalid-utf-8).
2066 ///
2067 /// # Examples
2068 ///
2069 /// This example shows how to get the byte offsets of each individual
2070 /// word:
2071 ///
2072 /// ```
2073 /// use bstr::ByteSlice;
2074 ///
2075 /// let bs = b"can't jump 32.3 feet";
2076 /// let words: Vec<(usize, usize, &str)> =
2077 /// bs.words_with_break_indices().collect();
2078 /// assert_eq!(words, vec![
2079 /// (0, 5, "can't"),
2080 /// (5, 6, " "),
2081 /// (6, 10, "jump"),
2082 /// (10, 11, " "),
2083 /// (11, 15, "32.3"),
2084 /// (15, 16, " "),
2085 /// (16, 20, "feet"),
2086 /// ]);
2087 /// ```
2088 #[cfg(feature = "unicode")]
2089 #[inline]
2090 fn words_with_break_indices(&self) -> WordsWithBreakIndices<'_> {
2091 WordsWithBreakIndices::new(self.as_bytes())
2092 }
2093
2094 /// Returns an iterator over the sentences in this byte string.
2095 ///
2096 /// Typically, a sentence will include its trailing punctuation and
2097 /// whitespace. Concatenating all elements yielded by the iterator
2098 /// results in the original string (modulo Unicode replacement codepoint
2099 /// substitutions if invalid UTF-8 is encountered).
2100 ///
2101 /// Since sentences are made up of one or more codepoints, this iterator
2102 /// yields `&str` elements. When invalid UTF-8 is encountered, replacement
2103 /// codepoints are [substituted](index.html#handling-of-invalid-utf-8).
2104 ///
2105 /// # Examples
2106 ///
2107 /// Basic usage:
2108 ///
2109 /// ```
2110 /// use bstr::ByteSlice;
2111 ///
2112 /// let bs = b"I want this. Not that. Right now.";
2113 /// let sentences: Vec<&str> = bs.sentences().collect();
2114 /// assert_eq!(sentences, vec![
2115 /// "I want this. ",
2116 /// "Not that. ",
2117 /// "Right now.",
2118 /// ]);
2119 /// ```
2120 #[cfg(feature = "unicode")]
2121 #[inline]
2122 fn sentences(&self) -> Sentences<'_> {
2123 Sentences::new(self.as_bytes())
2124 }
2125
2126 /// Returns an iterator over the sentences in this byte string along with
2127 /// their starting and ending byte index positions.
2128 ///
2129 /// Typically, a sentence will include its trailing punctuation and
2130 /// whitespace. Concatenating all elements yielded by the iterator
2131 /// results in the original string (modulo Unicode replacement codepoint
2132 /// substitutions if invalid UTF-8 is encountered).
2133 ///
2134 /// Since sentences are made up of one or more codepoints, this iterator
2135 /// yields `&str` elements. When invalid UTF-8 is encountered, replacement
2136 /// codepoints are [substituted](index.html#handling-of-invalid-utf-8).
2137 ///
2138 /// # Examples
2139 ///
2140 /// Basic usage:
2141 ///
2142 /// ```
2143 /// use bstr::ByteSlice;
2144 ///
2145 /// let bs = b"I want this. Not that. Right now.";
2146 /// let sentences: Vec<(usize, usize, &str)> =
2147 /// bs.sentence_indices().collect();
2148 /// assert_eq!(sentences, vec![
2149 /// (0, 13, "I want this. "),
2150 /// (13, 23, "Not that. "),
2151 /// (23, 33, "Right now."),
2152 /// ]);
2153 /// ```
2154 #[cfg(feature = "unicode")]
2155 #[inline]
2156 fn sentence_indices(&self) -> SentenceIndices<'_> {
2157 SentenceIndices::new(self.as_bytes())
2158 }
2159
2160 /// An iterator over all lines in a byte string, without their
2161 /// terminators.
2162 ///
2163 /// For this iterator, the only line terminators recognized are `\r\n` and
2164 /// `\n`.
2165 ///
2166 /// # Examples
2167 ///
2168 /// Basic usage:
2169 ///
2170 /// ```
2171 /// use bstr::{B, ByteSlice};
2172 ///
2173 /// let s = b"\
2174 /// foo
2175 ///
2176 /// bar\r
2177 /// baz
2178 ///
2179 ///
2180 /// quux";
2181 /// let lines: Vec<&[u8]> = s.lines().collect();
2182 /// assert_eq!(lines, vec![
2183 /// B("foo"), B(""), B("bar"), B("baz"), B(""), B(""), B("quux"),
2184 /// ]);
2185 /// ```
2186 #[inline]
2187 fn lines(&self) -> Lines<'_> {
2188 Lines::new(self.as_bytes())
2189 }
2190
2191 /// An iterator over all lines in a byte string, including their
2192 /// terminators.
2193 ///
2194 /// For this iterator, the only line terminator recognized is `\n`. (Since
2195 /// line terminators are included, this also handles `\r\n` line endings.)
2196 ///
2197 /// Line terminators are only included if they are present in the original
2198 /// byte string. For example, the last line in a byte string may not end
2199 /// with a line terminator.
2200 ///
2201 /// Concatenating all elements yielded by this iterator is guaranteed to
2202 /// yield the original byte string.
2203 ///
2204 /// # Examples
2205 ///
2206 /// Basic usage:
2207 ///
2208 /// ```
2209 /// use bstr::{B, ByteSlice};
2210 ///
2211 /// let s = b"\
2212 /// foo
2213 ///
2214 /// bar\r
2215 /// baz
2216 ///
2217 ///
2218 /// quux";
2219 /// let lines: Vec<&[u8]> = s.lines_with_terminator().collect();
2220 /// assert_eq!(lines, vec![
2221 /// B("foo\n"),
2222 /// B("\n"),
2223 /// B("bar\r\n"),
2224 /// B("baz\n"),
2225 /// B("\n"),
2226 /// B("\n"),
2227 /// B("quux"),
2228 /// ]);
2229 /// ```
2230 #[inline]
2231 fn lines_with_terminator(&self) -> LinesWithTerminator<'_> {
2232 LinesWithTerminator::new(self.as_bytes())
2233 }
2234
2235 /// Return a byte string slice with leading and trailing whitespace
2236 /// removed.
2237 ///
2238 /// Whitespace is defined according to the terms of the `White_Space`
2239 /// Unicode property.
2240 ///
2241 /// # Examples
2242 ///
2243 /// Basic usage:
2244 ///
2245 /// ```
2246 /// use bstr::{B, ByteSlice};
2247 ///
2248 /// let s = B(" foo\tbar\t\u{2003}\n");
2249 /// assert_eq!(s.trim(), B("foo\tbar"));
2250 /// ```
2251 #[cfg(feature = "unicode")]
2252 #[inline]
2253 fn trim(&self) -> &[u8] {
2254 self.trim_start().trim_end()
2255 }
2256
2257 /// Return a byte string slice with leading whitespace removed.
2258 ///
2259 /// Whitespace is defined according to the terms of the `White_Space`
2260 /// Unicode property.
2261 ///
2262 /// # Examples
2263 ///
2264 /// Basic usage:
2265 ///
2266 /// ```
2267 /// use bstr::{B, ByteSlice};
2268 ///
2269 /// let s = B(" foo\tbar\t\u{2003}\n");
2270 /// assert_eq!(s.trim_start(), B("foo\tbar\t\u{2003}\n"));
2271 /// ```
2272 #[cfg(feature = "unicode")]
2273 #[inline]
2274 fn trim_start(&self) -> &[u8] {
2275 let start = whitespace_len_fwd(self.as_bytes());
2276 &self.as_bytes()[start..]
2277 }
2278
2279 /// Return a byte string slice with trailing whitespace removed.
2280 ///
2281 /// Whitespace is defined according to the terms of the `White_Space`
2282 /// Unicode property.
2283 ///
2284 /// # Examples
2285 ///
2286 /// Basic usage:
2287 ///
2288 /// ```
2289 /// use bstr::{B, ByteSlice};
2290 ///
2291 /// let s = B(" foo\tbar\t\u{2003}\n");
2292 /// assert_eq!(s.trim_end(), B(" foo\tbar"));
2293 /// ```
2294 #[cfg(feature = "unicode")]
2295 #[inline]
2296 fn trim_end(&self) -> &[u8] {
2297 let end = whitespace_len_rev(self.as_bytes());
2298 &self.as_bytes()[..end]
2299 }
2300
2301 /// Return a byte string slice with leading and trailing characters
2302 /// satisfying the given predicate removed.
2303 ///
2304 /// # Examples
2305 ///
2306 /// Basic usage:
2307 ///
2308 /// ```
2309 /// use bstr::{B, ByteSlice};
2310 ///
2311 /// let s = b"123foo5bar789";
2312 /// assert_eq!(s.trim_with(|c| c.is_numeric()), B("foo5bar"));
2313 /// ```
2314 #[inline]
2315 fn trim_with<F: FnMut(char) -> bool>(&self, mut trim: F) -> &[u8] {
2316 self.trim_start_with(&mut trim).trim_end_with(&mut trim)
2317 }
2318
2319 /// Return a byte string slice with leading characters satisfying the given
2320 /// predicate removed.
2321 ///
2322 /// # Examples
2323 ///
2324 /// Basic usage:
2325 ///
2326 /// ```
2327 /// use bstr::{B, ByteSlice};
2328 ///
2329 /// let s = b"123foo5bar789";
2330 /// assert_eq!(s.trim_start_with(|c| c.is_numeric()), B("foo5bar789"));
2331 /// ```
2332 #[inline]
2333 fn trim_start_with<F: FnMut(char) -> bool>(&self, mut trim: F) -> &[u8] {
2334 for (s, _, ch) in self.char_indices() {
2335 if !trim(ch) {
2336 return &self.as_bytes()[s..];
2337 }
2338 }
2339 b""
2340 }
2341
2342 /// Return a byte string slice with trailing characters satisfying the
2343 /// given predicate removed.
2344 ///
2345 /// # Examples
2346 ///
2347 /// Basic usage:
2348 ///
2349 /// ```
2350 /// use bstr::{B, ByteSlice};
2351 ///
2352 /// let s = b"123foo5bar789";
2353 /// assert_eq!(s.trim_end_with(|c| c.is_numeric()), B("123foo5bar"));
2354 /// ```
2355 #[inline]
2356 fn trim_end_with<F: FnMut(char) -> bool>(&self, mut trim: F) -> &[u8] {
2357 for (_, e, ch) in self.char_indices().rev() {
2358 if !trim(ch) {
2359 return &self.as_bytes()[..e];
2360 }
2361 }
2362 b""
2363 }
2364
2365 /// Returns a new `Vec<u8>` containing the lowercase equivalent of this
2366 /// byte string.
2367 ///
2368 /// In this case, lowercase is defined according to the `Lowercase` Unicode
2369 /// property.
2370 ///
2371 /// If invalid UTF-8 is seen, or if a character has no lowercase variant,
2372 /// then it is written to the given buffer unchanged.
2373 ///
2374 /// Note that some characters in this byte string may expand into multiple
2375 /// characters when changing the case, so the number of bytes written to
2376 /// the given byte string may not be equivalent to the number of bytes in
2377 /// this byte string.
2378 ///
2379 /// If you'd like to reuse an allocation for performance reasons, then use
2380 /// [`to_lowercase_into`](#method.to_lowercase_into) instead.
2381 ///
2382 /// # Examples
2383 ///
2384 /// Basic usage:
2385 ///
2386 /// ```
2387 /// use bstr::{B, ByteSlice};
2388 ///
2389 /// let s = B("HELLO Β");
2390 /// assert_eq!("hello β".as_bytes(), s.to_lowercase().as_bytes());
2391 /// ```
2392 ///
2393 /// Scripts without case are not changed:
2394 ///
2395 /// ```
2396 /// use bstr::{B, ByteSlice};
2397 ///
2398 /// let s = B("农历新年");
2399 /// assert_eq!("农历新年".as_bytes(), s.to_lowercase().as_bytes());
2400 /// ```
2401 ///
2402 /// Invalid UTF-8 remains as is:
2403 ///
2404 /// ```
2405 /// use bstr::{B, ByteSlice};
2406 ///
2407 /// let s = B(b"FOO\xFFBAR\xE2\x98BAZ");
2408 /// assert_eq!(B(b"foo\xFFbar\xE2\x98baz"), s.to_lowercase().as_bytes());
2409 /// ```
2410 #[cfg(all(feature = "alloc", feature = "unicode"))]
2411 #[inline]
2412 fn to_lowercase(&self) -> Vec<u8> {
2413 let mut buf = vec![];
2414 self.to_lowercase_into(&mut buf);
2415 buf
2416 }
2417
2418 /// Writes the lowercase equivalent of this byte string into the given
2419 /// buffer. The buffer is not cleared before written to.
2420 ///
2421 /// In this case, lowercase is defined according to the `Lowercase`
2422 /// Unicode property.
2423 ///
2424 /// If invalid UTF-8 is seen, or if a character has no lowercase variant,
2425 /// then it is written to the given buffer unchanged.
2426 ///
2427 /// Note that some characters in this byte string may expand into multiple
2428 /// characters when changing the case, so the number of bytes written to
2429 /// the given byte string may not be equivalent to the number of bytes in
2430 /// this byte string.
2431 ///
2432 /// If you don't need to amortize allocation and instead prefer
2433 /// convenience, then use [`to_lowercase`](#method.to_lowercase) instead.
2434 ///
2435 /// # Examples
2436 ///
2437 /// Basic usage:
2438 ///
2439 /// ```
2440 /// use bstr::{B, ByteSlice};
2441 ///
2442 /// let s = B("HELLO Β");
2443 ///
2444 /// let mut buf = vec![];
2445 /// s.to_lowercase_into(&mut buf);
2446 /// assert_eq!("hello β".as_bytes(), buf.as_bytes());
2447 /// ```
2448 ///
2449 /// Scripts without case are not changed:
2450 ///
2451 /// ```
2452 /// use bstr::{B, ByteSlice};
2453 ///
2454 /// let s = B("农历新年");
2455 ///
2456 /// let mut buf = vec![];
2457 /// s.to_lowercase_into(&mut buf);
2458 /// assert_eq!("农历新年".as_bytes(), buf.as_bytes());
2459 /// ```
2460 ///
2461 /// Invalid UTF-8 remains as is:
2462 ///
2463 /// ```
2464 /// use bstr::{B, ByteSlice};
2465 ///
2466 /// let s = B(b"FOO\xFFBAR\xE2\x98BAZ");
2467 ///
2468 /// let mut buf = vec![];
2469 /// s.to_lowercase_into(&mut buf);
2470 /// assert_eq!(B(b"foo\xFFbar\xE2\x98baz"), buf.as_bytes());
2471 /// ```
2472 #[cfg(all(feature = "alloc", feature = "unicode"))]
2473 #[inline]
2474 fn to_lowercase_into(&self, buf: &mut Vec<u8>) {
2475 // TODO: This is the best we can do given what std exposes I think.
2476 // If we roll our own case handling, then we might be able to do this
2477 // a bit faster. We shouldn't roll our own case handling unless we
2478 // need to, e.g., for doing caseless matching or case folding.
2479
2480 // TODO(BUG): This doesn't handle any special casing rules.
2481
2482 buf.reserve(self.as_bytes().len());
2483 for (s, e, ch) in self.char_indices() {
2484 if ch == '\u{FFFD}' {
2485 buf.push_str(&self.as_bytes()[s..e]);
2486 } else if ch.is_ascii() {
2487 buf.push_char(ch.to_ascii_lowercase());
2488 } else {
2489 for upper in ch.to_lowercase() {
2490 buf.push_char(upper);
2491 }
2492 }
2493 }
2494 }
2495
2496 /// Returns a new `Vec<u8>` containing the ASCII lowercase equivalent of
2497 /// this byte string.
2498 ///
2499 /// In this case, lowercase is only defined in ASCII letters. Namely, the
2500 /// letters `A-Z` are converted to `a-z`. All other bytes remain unchanged.
2501 /// In particular, the length of the byte string returned is always
2502 /// equivalent to the length of this byte string.
2503 ///
2504 /// If you'd like to reuse an allocation for performance reasons, then use
2505 /// [`make_ascii_lowercase`](#method.make_ascii_lowercase) to perform
2506 /// the conversion in place.
2507 ///
2508 /// # Examples
2509 ///
2510 /// Basic usage:
2511 ///
2512 /// ```
2513 /// use bstr::{B, ByteSlice};
2514 ///
2515 /// let s = B("HELLO Β");
2516 /// assert_eq!("hello Β".as_bytes(), s.to_ascii_lowercase().as_bytes());
2517 /// ```
2518 ///
2519 /// Invalid UTF-8 remains as is:
2520 ///
2521 /// ```
2522 /// use bstr::{B, ByteSlice};
2523 ///
2524 /// let s = B(b"FOO\xFFBAR\xE2\x98BAZ");
2525 /// assert_eq!(s.to_ascii_lowercase(), B(b"foo\xFFbar\xE2\x98baz"));
2526 /// ```
2527 #[cfg(feature = "alloc")]
2528 #[inline]
2529 fn to_ascii_lowercase(&self) -> Vec<u8> {
2530 self.as_bytes().to_ascii_lowercase()
2531 }
2532
2533 /// Convert this byte string to its lowercase ASCII equivalent in place.
2534 ///
2535 /// In this case, lowercase is only defined in ASCII letters. Namely, the
2536 /// letters `A-Z` are converted to `a-z`. All other bytes remain unchanged.
2537 ///
2538 /// If you don't need to do the conversion in
2539 /// place and instead prefer convenience, then use
2540 /// [`to_ascii_lowercase`](#method.to_ascii_lowercase) instead.
2541 ///
2542 /// # Examples
2543 ///
2544 /// Basic usage:
2545 ///
2546 /// ```
2547 /// use bstr::ByteSlice;
2548 ///
2549 /// let mut s = <Vec<u8>>::from("HELLO Β");
2550 /// s.make_ascii_lowercase();
2551 /// assert_eq!(s, "hello Β".as_bytes());
2552 /// ```
2553 ///
2554 /// Invalid UTF-8 remains as is:
2555 ///
2556 /// ```
2557 /// # #[cfg(feature = "alloc")] {
2558 /// use bstr::{B, ByteSlice, ByteVec};
2559 ///
2560 /// let mut s = <Vec<u8>>::from_slice(b"FOO\xFFBAR\xE2\x98BAZ");
2561 /// s.make_ascii_lowercase();
2562 /// assert_eq!(s, B(b"foo\xFFbar\xE2\x98baz"));
2563 /// # }
2564 /// ```
2565 #[inline]
2566 fn make_ascii_lowercase(&mut self) {
2567 self.as_bytes_mut().make_ascii_lowercase();
2568 }
2569
2570 /// Returns a new `Vec<u8>` containing the uppercase equivalent of this
2571 /// byte string.
2572 ///
2573 /// In this case, uppercase is defined according to the `Uppercase`
2574 /// Unicode property.
2575 ///
2576 /// If invalid UTF-8 is seen, or if a character has no uppercase variant,
2577 /// then it is written to the given buffer unchanged.
2578 ///
2579 /// Note that some characters in this byte string may expand into multiple
2580 /// characters when changing the case, so the number of bytes written to
2581 /// the given byte string may not be equivalent to the number of bytes in
2582 /// this byte string.
2583 ///
2584 /// If you'd like to reuse an allocation for performance reasons, then use
2585 /// [`to_uppercase_into`](#method.to_uppercase_into) instead.
2586 ///
2587 /// # Examples
2588 ///
2589 /// Basic usage:
2590 ///
2591 /// ```
2592 /// use bstr::{B, ByteSlice};
2593 ///
2594 /// let s = B("hello β");
2595 /// assert_eq!(s.to_uppercase(), B("HELLO Β"));
2596 /// ```
2597 ///
2598 /// Scripts without case are not changed:
2599 ///
2600 /// ```
2601 /// use bstr::{B, ByteSlice};
2602 ///
2603 /// let s = B("农历新年");
2604 /// assert_eq!(s.to_uppercase(), B("农历新年"));
2605 /// ```
2606 ///
2607 /// Invalid UTF-8 remains as is:
2608 ///
2609 /// ```
2610 /// use bstr::{B, ByteSlice};
2611 ///
2612 /// let s = B(b"foo\xFFbar\xE2\x98baz");
2613 /// assert_eq!(s.to_uppercase(), B(b"FOO\xFFBAR\xE2\x98BAZ"));
2614 /// ```
2615 #[cfg(all(feature = "alloc", feature = "unicode"))]
2616 #[inline]
2617 fn to_uppercase(&self) -> Vec<u8> {
2618 let mut buf = vec![];
2619 self.to_uppercase_into(&mut buf);
2620 buf
2621 }
2622
2623 /// Writes the uppercase equivalent of this byte string into the given
2624 /// buffer. The buffer is not cleared before written to.
2625 ///
2626 /// In this case, uppercase is defined according to the `Uppercase`
2627 /// Unicode property.
2628 ///
2629 /// If invalid UTF-8 is seen, or if a character has no uppercase variant,
2630 /// then it is written to the given buffer unchanged.
2631 ///
2632 /// Note that some characters in this byte string may expand into multiple
2633 /// characters when changing the case, so the number of bytes written to
2634 /// the given byte string may not be equivalent to the number of bytes in
2635 /// this byte string.
2636 ///
2637 /// If you don't need to amortize allocation and instead prefer
2638 /// convenience, then use [`to_uppercase`](#method.to_uppercase) instead.
2639 ///
2640 /// # Examples
2641 ///
2642 /// Basic usage:
2643 ///
2644 /// ```
2645 /// use bstr::{B, ByteSlice};
2646 ///
2647 /// let s = B("hello β");
2648 ///
2649 /// let mut buf = vec![];
2650 /// s.to_uppercase_into(&mut buf);
2651 /// assert_eq!(buf, B("HELLO Β"));
2652 /// ```
2653 ///
2654 /// Scripts without case are not changed:
2655 ///
2656 /// ```
2657 /// use bstr::{B, ByteSlice};
2658 ///
2659 /// let s = B("农历新年");
2660 ///
2661 /// let mut buf = vec![];
2662 /// s.to_uppercase_into(&mut buf);
2663 /// assert_eq!(buf, B("农历新年"));
2664 /// ```
2665 ///
2666 /// Invalid UTF-8 remains as is:
2667 ///
2668 /// ```
2669 /// use bstr::{B, ByteSlice};
2670 ///
2671 /// let s = B(b"foo\xFFbar\xE2\x98baz");
2672 ///
2673 /// let mut buf = vec![];
2674 /// s.to_uppercase_into(&mut buf);
2675 /// assert_eq!(buf, B(b"FOO\xFFBAR\xE2\x98BAZ"));
2676 /// ```
2677 #[cfg(all(feature = "alloc", feature = "unicode"))]
2678 #[inline]
2679 fn to_uppercase_into(&self, buf: &mut Vec<u8>) {
2680 // TODO: This is the best we can do given what std exposes I think.
2681 // If we roll our own case handling, then we might be able to do this
2682 // a bit faster. We shouldn't roll our own case handling unless we
2683 // need to, e.g., for doing caseless matching or case folding.
2684 buf.reserve(self.as_bytes().len());
2685 for (s, e, ch) in self.char_indices() {
2686 if ch == '\u{FFFD}' {
2687 buf.push_str(&self.as_bytes()[s..e]);
2688 } else if ch.is_ascii() {
2689 buf.push_char(ch.to_ascii_uppercase());
2690 } else {
2691 for upper in ch.to_uppercase() {
2692 buf.push_char(upper);
2693 }
2694 }
2695 }
2696 }
2697
2698 /// Returns a new `Vec<u8>` containing the ASCII uppercase equivalent of
2699 /// this byte string.
2700 ///
2701 /// In this case, uppercase is only defined in ASCII letters. Namely, the
2702 /// letters `a-z` are converted to `A-Z`. All other bytes remain unchanged.
2703 /// In particular, the length of the byte string returned is always
2704 /// equivalent to the length of this byte string.
2705 ///
2706 /// If you'd like to reuse an allocation for performance reasons, then use
2707 /// [`make_ascii_uppercase`](#method.make_ascii_uppercase) to perform
2708 /// the conversion in place.
2709 ///
2710 /// # Examples
2711 ///
2712 /// Basic usage:
2713 ///
2714 /// ```
2715 /// use bstr::{B, ByteSlice};
2716 ///
2717 /// let s = B("hello β");
2718 /// assert_eq!(s.to_ascii_uppercase(), B("HELLO β"));
2719 /// ```
2720 ///
2721 /// Invalid UTF-8 remains as is:
2722 ///
2723 /// ```
2724 /// use bstr::{B, ByteSlice};
2725 ///
2726 /// let s = B(b"foo\xFFbar\xE2\x98baz");
2727 /// assert_eq!(s.to_ascii_uppercase(), B(b"FOO\xFFBAR\xE2\x98BAZ"));
2728 /// ```
2729 #[cfg(feature = "alloc")]
2730 #[inline]
2731 fn to_ascii_uppercase(&self) -> Vec<u8> {
2732 self.as_bytes().to_ascii_uppercase()
2733 }
2734
2735 /// Convert this byte string to its uppercase ASCII equivalent in place.
2736 ///
2737 /// In this case, uppercase is only defined in ASCII letters. Namely, the
2738 /// letters `a-z` are converted to `A-Z`. All other bytes remain unchanged.
2739 ///
2740 /// If you don't need to do the conversion in
2741 /// place and instead prefer convenience, then use
2742 /// [`to_ascii_uppercase`](#method.to_ascii_uppercase) instead.
2743 ///
2744 /// # Examples
2745 ///
2746 /// Basic usage:
2747 ///
2748 /// ```
2749 /// use bstr::{B, ByteSlice};
2750 ///
2751 /// let mut s = <Vec<u8>>::from("hello β");
2752 /// s.make_ascii_uppercase();
2753 /// assert_eq!(s, B("HELLO β"));
2754 /// ```
2755 ///
2756 /// Invalid UTF-8 remains as is:
2757 ///
2758 /// ```
2759 /// # #[cfg(feature = "alloc")] {
2760 /// use bstr::{B, ByteSlice, ByteVec};
2761 ///
2762 /// let mut s = <Vec<u8>>::from_slice(b"foo\xFFbar\xE2\x98baz");
2763 /// s.make_ascii_uppercase();
2764 /// assert_eq!(s, B(b"FOO\xFFBAR\xE2\x98BAZ"));
2765 /// # }
2766 /// ```
2767 #[inline]
2768 fn make_ascii_uppercase(&mut self) {
2769 self.as_bytes_mut().make_ascii_uppercase();
2770 }
2771
2772 /// Escapes this byte string into a sequence of `char` values.
2773 ///
2774 /// When the sequence of `char` values is concatenated into a string, the
2775 /// result is always valid UTF-8. Any unprintable or invalid UTF-8 in this
2776 /// byte string are escaped using using `\xNN` notation. Moreover, the
2777 /// characters `\0`, `\r`, `\n`, `\t` and `\` are escaped as well.
2778 ///
2779 /// This is useful when one wants to get a human readable view of the raw
2780 /// bytes that is also valid UTF-8.
2781 ///
2782 /// The iterator returned implements the `Display` trait. So one can do
2783 /// `b"foo\xFFbar".escape_bytes().to_string()` to get a `String` with its
2784 /// bytes escaped.
2785 ///
2786 /// The dual of this function is [`ByteVec::unescape_bytes`].
2787 ///
2788 /// Note that this is similar to, but not equivalent to the `Debug`
2789 /// implementation on [`BStr`] and [`BString`](crate::BString). The `Debug`
2790 /// implementations also use the debug representation for all Unicode
2791 /// codepoints. However, this escaping routine only escapes individual
2792 /// bytes. All Unicode codepoints above `U+007F` are passed through
2793 /// unchanged without any escaping.
2794 ///
2795 /// # Examples
2796 ///
2797 /// ```
2798 /// # #[cfg(feature = "alloc")] {
2799 /// use bstr::{B, ByteSlice};
2800 ///
2801 /// assert_eq!(r"foo\xFFbar", b"foo\xFFbar".escape_bytes().to_string());
2802 /// assert_eq!(r"foo\nbar", b"foo\nbar".escape_bytes().to_string());
2803 /// assert_eq!(r"foo\tbar", b"foo\tbar".escape_bytes().to_string());
2804 /// assert_eq!(r"foo\\bar", b"foo\\bar".escape_bytes().to_string());
2805 /// assert_eq!(r"foo☃bar", B("foo☃bar").escape_bytes().to_string());
2806 /// # }
2807 /// ```
2808 #[inline]
2809 fn escape_bytes(&self) -> EscapeBytes<'_> {
2810 EscapeBytes::new(self.as_bytes())
2811 }
2812
2813 /// Reverse the bytes in this string, in place.
2814 ///
2815 /// This is not necessarily a well formed operation! For example, if this
2816 /// byte string contains valid UTF-8 that isn't ASCII, then reversing the
2817 /// string will likely result in invalid UTF-8 and otherwise non-sensical
2818 /// content.
2819 ///
2820 /// Note that this is equivalent to the generic `[u8]::reverse` method.
2821 /// This method is provided to permit callers to explicitly differentiate
2822 /// between reversing bytes, codepoints and graphemes.
2823 ///
2824 /// # Examples
2825 ///
2826 /// Basic usage:
2827 ///
2828 /// ```
2829 /// use bstr::ByteSlice;
2830 ///
2831 /// let mut s = <Vec<u8>>::from("hello");
2832 /// s.reverse_bytes();
2833 /// assert_eq!(s, "olleh".as_bytes());
2834 /// ```
2835 #[inline]
2836 fn reverse_bytes(&mut self) {
2837 self.as_bytes_mut().reverse();
2838 }
2839
2840 /// Reverse the codepoints in this string, in place.
2841 ///
2842 /// If this byte string is valid UTF-8, then its reversal by codepoint
2843 /// is also guaranteed to be valid UTF-8.
2844 ///
2845 /// This operation is equivalent to the following, but without allocating:
2846 ///
2847 /// ```
2848 /// use bstr::ByteSlice;
2849 ///
2850 /// let mut s = <Vec<u8>>::from("foo☃bar");
2851 ///
2852 /// let mut chars: Vec<char> = s.chars().collect();
2853 /// chars.reverse();
2854 ///
2855 /// let reversed: String = chars.into_iter().collect();
2856 /// assert_eq!(reversed, "rab☃oof");
2857 /// ```
2858 ///
2859 /// Note that this is not necessarily a well formed operation. For example,
2860 /// if this byte string contains grapheme clusters with more than one
2861 /// codepoint, then those grapheme clusters will not necessarily be
2862 /// preserved. If you'd like to preserve grapheme clusters, then use
2863 /// [`reverse_graphemes`](#method.reverse_graphemes) instead.
2864 ///
2865 /// # Examples
2866 ///
2867 /// Basic usage:
2868 ///
2869 /// ```
2870 /// use bstr::ByteSlice;
2871 ///
2872 /// let mut s = <Vec<u8>>::from("foo☃bar");
2873 /// s.reverse_chars();
2874 /// assert_eq!(s, "rab☃oof".as_bytes());
2875 /// ```
2876 ///
2877 /// This example shows that not all reversals lead to a well formed string.
2878 /// For example, in this case, combining marks are used to put accents over
2879 /// some letters, and those accent marks must appear after the codepoints
2880 /// they modify.
2881 ///
2882 /// ```
2883 /// use bstr::{B, ByteSlice};
2884 ///
2885 /// let mut s = <Vec<u8>>::from("résumé");
2886 /// s.reverse_chars();
2887 /// assert_eq!(s, B(b"\xCC\x81emus\xCC\x81er"));
2888 /// ```
2889 ///
2890 /// A word of warning: the above example relies on the fact that
2891 /// `résumé` is in decomposed normal form, which means there are separate
2892 /// codepoints for the accents above `e`. If it is instead in composed
2893 /// normal form, then the example works:
2894 ///
2895 /// ```
2896 /// use bstr::{B, ByteSlice};
2897 ///
2898 /// let mut s = <Vec<u8>>::from("résumé");
2899 /// s.reverse_chars();
2900 /// assert_eq!(s, B("émusér"));
2901 /// ```
2902 ///
2903 /// The point here is to be cautious and not assume that just because
2904 /// `reverse_chars` works in one case, that it therefore works in all
2905 /// cases.
2906 #[inline]
2907 fn reverse_chars(&mut self) {
2908 let mut i = 0;
2909 loop {
2910 let (_, size) = utf8::decode(&self.as_bytes()[i..]);
2911 if size == 0 {
2912 break;
2913 }
2914 if size > 1 {
2915 self.as_bytes_mut()[i..i + size].reverse_bytes();
2916 }
2917 i += size;
2918 }
2919 self.reverse_bytes();
2920 }
2921
2922 /// Reverse the graphemes in this string, in place.
2923 ///
2924 /// If this byte string is valid UTF-8, then its reversal by grapheme
2925 /// is also guaranteed to be valid UTF-8.
2926 ///
2927 /// This operation is equivalent to the following, but without allocating:
2928 ///
2929 /// ```
2930 /// use bstr::ByteSlice;
2931 ///
2932 /// let mut s = <Vec<u8>>::from("foo☃bar");
2933 ///
2934 /// let mut graphemes: Vec<&str> = s.graphemes().collect();
2935 /// graphemes.reverse();
2936 ///
2937 /// let reversed = graphemes.concat();
2938 /// assert_eq!(reversed, "rab☃oof");
2939 /// ```
2940 ///
2941 /// # Examples
2942 ///
2943 /// Basic usage:
2944 ///
2945 /// ```
2946 /// use bstr::ByteSlice;
2947 ///
2948 /// let mut s = <Vec<u8>>::from("foo☃bar");
2949 /// s.reverse_graphemes();
2950 /// assert_eq!(s, "rab☃oof".as_bytes());
2951 /// ```
2952 ///
2953 /// This example shows how this correctly handles grapheme clusters,
2954 /// unlike `reverse_chars`.
2955 ///
2956 /// ```
2957 /// use bstr::ByteSlice;
2958 ///
2959 /// let mut s = <Vec<u8>>::from("résumé");
2960 /// s.reverse_graphemes();
2961 /// assert_eq!(s, "émusér".as_bytes());
2962 /// ```
2963 #[cfg(feature = "unicode")]
2964 #[inline]
2965 fn reverse_graphemes(&mut self) {
2966 use crate::unicode::decode_grapheme;
2967
2968 let mut i = 0;
2969 loop {
2970 let (_, size) = decode_grapheme(&self.as_bytes()[i..]);
2971 if size == 0 {
2972 break;
2973 }
2974 if size > 1 {
2975 self.as_bytes_mut()[i..i + size].reverse_bytes();
2976 }
2977 i += size;
2978 }
2979 self.reverse_bytes();
2980 }
2981
2982 /// Returns true if and only if every byte in this byte string is ASCII.
2983 ///
2984 /// ASCII is an encoding that defines 128 codepoints. A byte corresponds to
2985 /// an ASCII codepoint if and only if it is in the inclusive range
2986 /// `[0, 127]`.
2987 ///
2988 /// # Examples
2989 ///
2990 /// Basic usage:
2991 ///
2992 /// ```
2993 /// use bstr::{B, ByteSlice};
2994 ///
2995 /// assert!(B("abc").is_ascii());
2996 /// assert!(!B("☃βツ").is_ascii());
2997 /// assert!(!B(b"\xFF").is_ascii());
2998 /// ```
2999 #[inline]
3000 fn is_ascii(&self) -> bool {
3001 ascii::first_non_ascii_byte(self.as_bytes()) == self.as_bytes().len()
3002 }
3003
3004 /// Returns true if and only if the entire byte string is valid UTF-8.
3005 ///
3006 /// If you need location information about where a byte string's first
3007 /// invalid UTF-8 byte is, then use the [`to_str`](#method.to_str) method.
3008 ///
3009 /// # Examples
3010 ///
3011 /// Basic usage:
3012 ///
3013 /// ```
3014 /// use bstr::{B, ByteSlice};
3015 ///
3016 /// assert!(B("abc").is_utf8());
3017 /// assert!(B("☃βツ").is_utf8());
3018 /// // invalid bytes
3019 /// assert!(!B(b"abc\xFF").is_utf8());
3020 /// // surrogate encoding
3021 /// assert!(!B(b"\xED\xA0\x80").is_utf8());
3022 /// // incomplete sequence
3023 /// assert!(!B(b"\xF0\x9D\x9Ca").is_utf8());
3024 /// // overlong sequence
3025 /// assert!(!B(b"\xF0\x82\x82\xAC").is_utf8());
3026 /// ```
3027 #[inline]
3028 fn is_utf8(&self) -> bool {
3029 utf8::validate(self.as_bytes()).is_ok()
3030 }
3031
3032 /// Returns the last byte in this byte string, if it's non-empty. If this
3033 /// byte string is empty, this returns `None`.
3034 ///
3035 /// Note that this is like the generic `[u8]::last`, except this returns
3036 /// the byte by value instead of a reference to the byte.
3037 ///
3038 /// # Examples
3039 ///
3040 /// Basic usage:
3041 ///
3042 /// ```
3043 /// use bstr::ByteSlice;
3044 ///
3045 /// assert_eq!(Some(b'z'), b"baz".last_byte());
3046 /// assert_eq!(None, b"".last_byte());
3047 /// ```
3048 #[inline]
3049 fn last_byte(&self) -> Option<u8> {
3050 let bytes = self.as_bytes();
3051 bytes.last().copied()
3052 }
3053
3054 /// Returns the index of the first non-ASCII byte in this byte string (if
3055 /// any such indices exist). Specifically, it returns the index of the
3056 /// first byte with a value greater than or equal to `0x80`.
3057 ///
3058 /// # Examples
3059 ///
3060 /// Basic usage:
3061 ///
3062 /// ```
3063 /// use bstr::{ByteSlice, B};
3064 ///
3065 /// assert_eq!(Some(3), b"abc\xff".find_non_ascii_byte());
3066 /// assert_eq!(None, b"abcde".find_non_ascii_byte());
3067 /// assert_eq!(Some(0), B("😀").find_non_ascii_byte());
3068 /// ```
3069 #[inline]
3070 fn find_non_ascii_byte(&self) -> Option<usize> {
3071 let index = ascii::first_non_ascii_byte(self.as_bytes());
3072 if index == self.as_bytes().len() {
3073 None
3074 } else {
3075 Some(index)
3076 }
3077 }
3078}
3079
3080/// A single substring searcher fixed to a particular needle.
3081///
3082/// The purpose of this type is to permit callers to construct a substring
3083/// searcher that can be used to search haystacks without the overhead of
3084/// constructing the searcher in the first place. This is a somewhat niche
3085/// concern when it's necessary to reuse the same needle to search multiple
3086/// different haystacks with as little overhead as possible. In general, using
3087/// [`ByteSlice::find`](trait.ByteSlice.html#method.find)
3088/// or
3089/// [`ByteSlice::find_iter`](trait.ByteSlice.html#method.find_iter)
3090/// is good enough, but `Finder` is useful when you can meaningfully observe
3091/// searcher construction time in a profile.
3092///
3093/// When the `std` feature is enabled, then this type has an `into_owned`
3094/// version which permits building a `Finder` that is not connected to the
3095/// lifetime of its needle.
3096#[derive(Clone, Debug)]
3097pub struct Finder<'a>(memmem::Finder<'a>);
3098
3099impl<'a> Finder<'a> {
3100 /// Create a new finder for the given needle.
3101 #[inline]
3102 pub fn new<B: ?Sized + AsRef<[u8]>>(needle: &'a B) -> Finder<'a> {
3103 Finder(memmem::Finder::new(needle.as_ref()))
3104 }
3105
3106 /// Convert this finder into its owned variant, such that it no longer
3107 /// borrows the needle.
3108 ///
3109 /// If this is already an owned finder, then this is a no-op. Otherwise,
3110 /// this copies the needle.
3111 ///
3112 /// This is only available when the `alloc` feature is enabled.
3113 #[cfg(feature = "alloc")]
3114 #[inline]
3115 pub fn into_owned(self) -> Finder<'static> {
3116 Finder(self.0.into_owned())
3117 }
3118
3119 /// Returns the needle that this finder searches for.
3120 ///
3121 /// Note that the lifetime of the needle returned is tied to the lifetime
3122 /// of the finder, and may be shorter than the `'a` lifetime. Namely, a
3123 /// finder's needle can be either borrowed or owned, so the lifetime of the
3124 /// needle returned must necessarily be the shorter of the two.
3125 #[inline]
3126 pub fn needle(&self) -> &[u8] {
3127 self.0.needle()
3128 }
3129
3130 /// Returns the index of the first occurrence of this needle in the given
3131 /// haystack.
3132 ///
3133 /// The haystack may be any type that can be cheaply converted into a
3134 /// `&[u8]`. This includes, but is not limited to, `&str` and `&[u8]`.
3135 ///
3136 /// # Complexity
3137 ///
3138 /// This routine is guaranteed to have worst case linear time complexity
3139 /// with respect to both the needle and the haystack. That is, this runs
3140 /// in `O(needle.len() + haystack.len())` time.
3141 ///
3142 /// This routine is also guaranteed to have worst case constant space
3143 /// complexity.
3144 ///
3145 /// # Examples
3146 ///
3147 /// Basic usage:
3148 ///
3149 /// ```
3150 /// use bstr::Finder;
3151 ///
3152 /// let haystack = "foo bar baz";
3153 /// assert_eq!(Some(0), Finder::new("foo").find(haystack));
3154 /// assert_eq!(Some(4), Finder::new("bar").find(haystack));
3155 /// assert_eq!(None, Finder::new("quux").find(haystack));
3156 /// ```
3157 #[inline]
3158 pub fn find<B: AsRef<[u8]>>(&self, haystack: B) -> Option<usize> {
3159 self.0.find(haystack.as_ref())
3160 }
3161}
3162
3163/// A single substring reverse searcher fixed to a particular needle.
3164///
3165/// The purpose of this type is to permit callers to construct a substring
3166/// searcher that can be used to search haystacks without the overhead of
3167/// constructing the searcher in the first place. This is a somewhat niche
3168/// concern when it's necessary to re-use the same needle to search multiple
3169/// different haystacks with as little overhead as possible. In general, using
3170/// [`ByteSlice::rfind`](trait.ByteSlice.html#method.rfind)
3171/// or
3172/// [`ByteSlice::rfind_iter`](trait.ByteSlice.html#method.rfind_iter)
3173/// is good enough, but `FinderReverse` is useful when you can meaningfully
3174/// observe searcher construction time in a profile.
3175///
3176/// When the `std` feature is enabled, then this type has an `into_owned`
3177/// version which permits building a `FinderReverse` that is not connected to
3178/// the lifetime of its needle.
3179#[derive(Clone, Debug)]
3180pub struct FinderReverse<'a>(memmem::FinderRev<'a>);
3181
3182impl<'a> FinderReverse<'a> {
3183 /// Create a new reverse finder for the given needle.
3184 #[inline]
3185 pub fn new<B: ?Sized + AsRef<[u8]>>(needle: &'a B) -> FinderReverse<'a> {
3186 FinderReverse(memmem::FinderRev::new(needle.as_ref()))
3187 }
3188
3189 /// Convert this finder into its owned variant, such that it no longer
3190 /// borrows the needle.
3191 ///
3192 /// If this is already an owned finder, then this is a no-op. Otherwise,
3193 /// this copies the needle.
3194 ///
3195 /// This is only available when the `alloc` feature is enabled.
3196 #[cfg(feature = "alloc")]
3197 #[inline]
3198 pub fn into_owned(self) -> FinderReverse<'static> {
3199 FinderReverse(self.0.into_owned())
3200 }
3201
3202 /// Returns the needle that this finder searches for.
3203 ///
3204 /// Note that the lifetime of the needle returned is tied to the lifetime
3205 /// of this finder, and may be shorter than the `'a` lifetime. Namely,
3206 /// a finder's needle can be either borrowed or owned, so the lifetime of
3207 /// the needle returned must necessarily be the shorter of the two.
3208 #[inline]
3209 pub fn needle(&self) -> &[u8] {
3210 self.0.needle()
3211 }
3212
3213 /// Returns the index of the last occurrence of this needle in the given
3214 /// haystack.
3215 ///
3216 /// The haystack may be any type that can be cheaply converted into a
3217 /// `&[u8]`. This includes, but is not limited to, `&str` and `&[u8]`.
3218 ///
3219 /// # Complexity
3220 ///
3221 /// This routine is guaranteed to have worst case linear time complexity
3222 /// with respect to both the needle and the haystack. That is, this runs
3223 /// in `O(needle.len() + haystack.len())` time.
3224 ///
3225 /// This routine is also guaranteed to have worst case constant space
3226 /// complexity.
3227 ///
3228 /// # Examples
3229 ///
3230 /// Basic usage:
3231 ///
3232 /// ```
3233 /// use bstr::FinderReverse;
3234 ///
3235 /// let haystack = "foo bar baz";
3236 /// assert_eq!(Some(0), FinderReverse::new("foo").rfind(haystack));
3237 /// assert_eq!(Some(4), FinderReverse::new("bar").rfind(haystack));
3238 /// assert_eq!(None, FinderReverse::new("quux").rfind(haystack));
3239 /// ```
3240 #[inline]
3241 pub fn rfind<B: AsRef<[u8]>>(&self, haystack: B) -> Option<usize> {
3242 self.0.rfind(haystack.as_ref())
3243 }
3244}
3245
3246/// An iterator over non-overlapping substring matches.
3247///
3248/// Matches are reported by the byte offset at which they begin.
3249///
3250/// `'h` is the lifetime of the haystack while `'n` is the lifetime of the
3251/// needle.
3252#[derive(Clone, Debug)]
3253pub struct Find<'h, 'n> {
3254 it: memmem::FindIter<'h, 'n>,
3255 haystack: &'h [u8],
3256 needle: &'n [u8],
3257}
3258
3259impl<'h, 'n> Find<'h, 'n> {
3260 fn new(haystack: &'h [u8], needle: &'n [u8]) -> Find<'h, 'n> {
3261 Find { it: memmem::find_iter(haystack, needle), haystack, needle }
3262 }
3263}
3264
3265impl<'h, 'n> Iterator for Find<'h, 'n> {
3266 type Item = usize;
3267
3268 #[inline]
3269 fn next(&mut self) -> Option<usize> {
3270 self.it.next()
3271 }
3272}
3273
3274/// An iterator over non-overlapping substring matches in reverse.
3275///
3276/// Matches are reported by the byte offset at which they begin.
3277///
3278/// `'h` is the lifetime of the haystack while `'n` is the lifetime of the
3279/// needle.
3280#[derive(Clone, Debug)]
3281pub struct FindReverse<'h, 'n> {
3282 it: memmem::FindRevIter<'h, 'n>,
3283 haystack: &'h [u8],
3284 needle: &'n [u8],
3285}
3286
3287impl<'h, 'n> FindReverse<'h, 'n> {
3288 fn new(haystack: &'h [u8], needle: &'n [u8]) -> FindReverse<'h, 'n> {
3289 FindReverse {
3290 it: memmem::rfind_iter(haystack, needle),
3291 haystack,
3292 needle,
3293 }
3294 }
3295
3296 fn haystack(&self) -> &'h [u8] {
3297 self.haystack
3298 }
3299
3300 fn needle(&self) -> &'n [u8] {
3301 self.needle
3302 }
3303}
3304
3305impl<'h, 'n> Iterator for FindReverse<'h, 'n> {
3306 type Item = usize;
3307
3308 #[inline]
3309 fn next(&mut self) -> Option<usize> {
3310 self.it.next()
3311 }
3312}
3313
3314/// An iterator over the bytes in a byte string.
3315///
3316/// `'a` is the lifetime of the byte string being traversed.
3317#[derive(Clone, Debug)]
3318pub struct Bytes<'a> {
3319 it: slice::Iter<'a, u8>,
3320}
3321
3322impl<'a> Bytes<'a> {
3323 /// Views the remaining underlying data as a subslice of the original data.
3324 /// This has the same lifetime as the original slice,
3325 /// and so the iterator can continue to be used while this exists.
3326 #[inline]
3327 pub fn as_bytes(&self) -> &'a [u8] {
3328 self.it.as_slice()
3329 }
3330}
3331
3332impl<'a> Iterator for Bytes<'a> {
3333 type Item = u8;
3334
3335 #[inline]
3336 fn next(&mut self) -> Option<u8> {
3337 self.it.next().copied()
3338 }
3339
3340 #[inline]
3341 fn size_hint(&self) -> (usize, Option<usize>) {
3342 self.it.size_hint()
3343 }
3344}
3345
3346impl<'a> DoubleEndedIterator for Bytes<'a> {
3347 #[inline]
3348 fn next_back(&mut self) -> Option<u8> {
3349 self.it.next_back().copied()
3350 }
3351}
3352
3353impl<'a> ExactSizeIterator for Bytes<'a> {
3354 #[inline]
3355 fn len(&self) -> usize {
3356 self.it.len()
3357 }
3358}
3359
3360impl<'a> iter::FusedIterator for Bytes<'a> {}
3361
3362/// An iterator over the fields in a byte string, separated by whitespace.
3363///
3364/// Whitespace for this iterator is defined by the Unicode property
3365/// `White_Space`.
3366///
3367/// This iterator splits on contiguous runs of whitespace, such that the fields
3368/// in `foo\t\t\n \nbar` are `foo` and `bar`.
3369///
3370/// `'a` is the lifetime of the byte string being split.
3371#[cfg(feature = "unicode")]
3372#[doc(alias = "SplitWhitespace")]
3373#[derive(Clone, Debug)]
3374pub struct Fields<'a> {
3375 it: FieldsWith<'a, fn(char) -> bool>,
3376}
3377
3378#[cfg(feature = "unicode")]
3379impl<'a> Fields<'a> {
3380 fn new(bytes: &'a [u8]) -> Fields<'a> {
3381 Fields { it: bytes.fields_with(char::is_whitespace) }
3382 }
3383}
3384
3385#[cfg(feature = "unicode")]
3386impl<'a> Iterator for Fields<'a> {
3387 type Item = &'a [u8];
3388
3389 #[inline]
3390 fn next(&mut self) -> Option<&'a [u8]> {
3391 self.it.next()
3392 }
3393}
3394
3395/// An iterator over fields in the byte string, separated by a predicate over
3396/// codepoints.
3397///
3398/// This iterator splits a byte string based on its predicate function such
3399/// that the elements returned are separated by contiguous runs of codepoints
3400/// for which the predicate returns true.
3401///
3402/// `'a` is the lifetime of the byte string being split, while `F` is the type
3403/// of the predicate, i.e., `FnMut(char) -> bool`.
3404#[derive(Clone, Debug)]
3405pub struct FieldsWith<'a, F> {
3406 f: F,
3407 bytes: &'a [u8],
3408 chars: CharIndices<'a>,
3409}
3410
3411impl<'a, F: FnMut(char) -> bool> FieldsWith<'a, F> {
3412 fn new(bytes: &'a [u8], f: F) -> FieldsWith<'a, F> {
3413 FieldsWith { f, bytes, chars: bytes.char_indices() }
3414 }
3415}
3416
3417impl<'a, F: FnMut(char) -> bool> Iterator for FieldsWith<'a, F> {
3418 type Item = &'a [u8];
3419
3420 #[inline]
3421 fn next(&mut self) -> Option<&'a [u8]> {
3422 let (start, mut end);
3423 loop {
3424 match self.chars.next() {
3425 None => return None,
3426 Some((s, e, ch)) => {
3427 if !(self.f)(ch) {
3428 start = s;
3429 end = e;
3430 break;
3431 }
3432 }
3433 }
3434 }
3435 for (_, e, ch) in self.chars.by_ref() {
3436 if (self.f)(ch) {
3437 break;
3438 }
3439 end = e;
3440 }
3441 Some(&self.bytes[start..end])
3442 }
3443}
3444
3445/// An iterator over substrings in a byte string, split by a separator.
3446///
3447/// `'h` is the lifetime of the byte string being split (the haystack), while
3448/// `'s` is the lifetime of the byte string doing the splitting.
3449#[derive(Clone, Debug)]
3450pub struct Split<'h, 's> {
3451 finder: Find<'h, 's>,
3452 /// The end position of the previous match of our splitter. The element
3453 /// we yield corresponds to the substring starting at `last` up to the
3454 /// beginning of the next match of the splitter.
3455 last: usize,
3456 /// Only set when iteration is complete. A corner case here is when a
3457 /// splitter is matched at the end of the haystack. At that point, we still
3458 /// need to yield an empty string following it.
3459 done: bool,
3460}
3461
3462impl<'h, 's> Split<'h, 's> {
3463 fn new(haystack: &'h [u8], splitter: &'s [u8]) -> Split<'h, 's> {
3464 let finder = haystack.find_iter(splitter);
3465 Split { finder, last: 0, done: false }
3466 }
3467}
3468
3469impl<'h, 's> Iterator for Split<'h, 's> {
3470 type Item = &'h [u8];
3471
3472 #[inline]
3473 fn next(&mut self) -> Option<&'h [u8]> {
3474 let haystack = self.finder.haystack;
3475 match self.finder.next() {
3476 Some(start) => {
3477 let next = &haystack[self.last..start];
3478 self.last = start + self.finder.needle.len();
3479 Some(next)
3480 }
3481 None => {
3482 if self.last >= haystack.len() {
3483 if !self.done {
3484 self.done = true;
3485 Some(b"")
3486 } else {
3487 None
3488 }
3489 } else {
3490 let s = &haystack[self.last..];
3491 self.last = haystack.len();
3492 self.done = true;
3493 Some(s)
3494 }
3495 }
3496 }
3497 }
3498}
3499
3500/// An iterator over substrings in a byte string, split by a separator, in
3501/// reverse.
3502///
3503/// `'h` is the lifetime of the byte string being split (the haystack), while
3504/// `'s` is the lifetime of the byte string doing the splitting.
3505#[derive(Clone, Debug)]
3506pub struct SplitReverse<'h, 's> {
3507 finder: FindReverse<'h, 's>,
3508 /// The end position of the previous match of our splitter. The element
3509 /// we yield corresponds to the substring starting at `last` up to the
3510 /// beginning of the next match of the splitter.
3511 last: usize,
3512 /// Only set when iteration is complete. A corner case here is when a
3513 /// splitter is matched at the end of the haystack. At that point, we still
3514 /// need to yield an empty string following it.
3515 done: bool,
3516}
3517
3518impl<'h, 's> SplitReverse<'h, 's> {
3519 fn new(haystack: &'h [u8], splitter: &'s [u8]) -> SplitReverse<'h, 's> {
3520 let finder = haystack.rfind_iter(splitter);
3521 SplitReverse { finder, last: haystack.len(), done: false }
3522 }
3523}
3524
3525impl<'h, 's> Iterator for SplitReverse<'h, 's> {
3526 type Item = &'h [u8];
3527
3528 #[inline]
3529 fn next(&mut self) -> Option<&'h [u8]> {
3530 let haystack = self.finder.haystack();
3531 match self.finder.next() {
3532 Some(start) => {
3533 let nlen = self.finder.needle().len();
3534 let next = &haystack[start + nlen..self.last];
3535 self.last = start;
3536 Some(next)
3537 }
3538 None => {
3539 if self.last == 0 {
3540 if !self.done {
3541 self.done = true;
3542 Some(b"")
3543 } else {
3544 None
3545 }
3546 } else {
3547 let s = &haystack[..self.last];
3548 self.last = 0;
3549 self.done = true;
3550 Some(s)
3551 }
3552 }
3553 }
3554 }
3555}
3556
3557/// An iterator over at most `n` substrings in a byte string, split by a
3558/// separator.
3559///
3560/// `'h` is the lifetime of the byte string being split (the haystack), while
3561/// `'s` is the lifetime of the byte string doing the splitting.
3562#[derive(Clone, Debug)]
3563pub struct SplitN<'h, 's> {
3564 split: Split<'h, 's>,
3565 limit: usize,
3566 count: usize,
3567}
3568
3569impl<'h, 's> SplitN<'h, 's> {
3570 fn new(
3571 haystack: &'h [u8],
3572 splitter: &'s [u8],
3573 limit: usize,
3574 ) -> SplitN<'h, 's> {
3575 let split = haystack.split_str(splitter);
3576 SplitN { split, limit, count: 0 }
3577 }
3578}
3579
3580impl<'h, 's> Iterator for SplitN<'h, 's> {
3581 type Item = &'h [u8];
3582
3583 #[inline]
3584 fn next(&mut self) -> Option<&'h [u8]> {
3585 self.count += 1;
3586 if self.count > self.limit || self.split.done {
3587 None
3588 } else if self.count == self.limit {
3589 Some(&self.split.finder.haystack[self.split.last..])
3590 } else {
3591 self.split.next()
3592 }
3593 }
3594}
3595
3596/// An iterator over at most `n` substrings in a byte string, split by a
3597/// separator, in reverse.
3598///
3599/// `'h` is the lifetime of the byte string being split (the haystack), while
3600/// `'s` is the lifetime of the byte string doing the splitting.
3601#[derive(Clone, Debug)]
3602pub struct SplitNReverse<'h, 's> {
3603 split: SplitReverse<'h, 's>,
3604 limit: usize,
3605 count: usize,
3606}
3607
3608impl<'h, 's> SplitNReverse<'h, 's> {
3609 fn new(
3610 haystack: &'h [u8],
3611 splitter: &'s [u8],
3612 limit: usize,
3613 ) -> SplitNReverse<'h, 's> {
3614 let split = haystack.rsplit_str(splitter);
3615 SplitNReverse { split, limit, count: 0 }
3616 }
3617}
3618
3619impl<'h, 's> Iterator for SplitNReverse<'h, 's> {
3620 type Item = &'h [u8];
3621
3622 #[inline]
3623 fn next(&mut self) -> Option<&'h [u8]> {
3624 self.count += 1;
3625 if self.count > self.limit || self.split.done {
3626 None
3627 } else if self.count == self.limit {
3628 Some(&self.split.finder.haystack()[..self.split.last])
3629 } else {
3630 self.split.next()
3631 }
3632 }
3633}
3634
3635/// An iterator over all lines in a byte string, without their terminators.
3636///
3637/// For this iterator, the only line terminators recognized are `\r\n` and
3638/// `\n`.
3639///
3640/// `'a` is the lifetime of the byte string being iterated over.
3641#[derive(Clone, Debug)]
3642pub struct Lines<'a> {
3643 it: LinesWithTerminator<'a>,
3644}
3645
3646impl<'a> Lines<'a> {
3647 fn new(bytes: &'a [u8]) -> Lines<'a> {
3648 Lines { it: LinesWithTerminator::new(bytes) }
3649 }
3650
3651 /// Return a copy of the rest of the underlying bytes without affecting the
3652 /// iterator itself.
3653 ///
3654 /// # Examples
3655 ///
3656 /// Basic usage:
3657 ///
3658 /// ```
3659 /// use bstr::{B, ByteSlice};
3660 ///
3661 /// let s = b"\
3662 /// foo
3663 /// bar\r
3664 /// baz";
3665 /// let mut lines = s.lines();
3666 /// assert_eq!(lines.next(), Some(B("foo")));
3667 /// assert_eq!(lines.as_bytes(), B("bar\r\nbaz"));
3668 /// ```
3669 pub fn as_bytes(&self) -> &'a [u8] {
3670 self.it.bytes
3671 }
3672}
3673
3674impl<'a> Iterator for Lines<'a> {
3675 type Item = &'a [u8];
3676
3677 #[inline]
3678 fn next(&mut self) -> Option<&'a [u8]> {
3679 Some(trim_last_terminator(self.it.next()?))
3680 }
3681}
3682
3683impl<'a> DoubleEndedIterator for Lines<'a> {
3684 #[inline]
3685 fn next_back(&mut self) -> Option<Self::Item> {
3686 Some(trim_last_terminator(self.it.next_back()?))
3687 }
3688}
3689
3690impl<'a> iter::FusedIterator for Lines<'a> {}
3691
3692/// An iterator over all lines in a byte string, including their terminators.
3693///
3694/// For this iterator, the only line terminator recognized is `\n`. (Since
3695/// line terminators are included, this also handles `\r\n` line endings.)
3696///
3697/// Line terminators are only included if they are present in the original
3698/// byte string. For example, the last line in a byte string may not end with
3699/// a line terminator.
3700///
3701/// Concatenating all elements yielded by this iterator is guaranteed to yield
3702/// the original byte string.
3703///
3704/// `'a` is the lifetime of the byte string being iterated over.
3705#[derive(Clone, Debug)]
3706pub struct LinesWithTerminator<'a> {
3707 bytes: &'a [u8],
3708}
3709
3710impl<'a> LinesWithTerminator<'a> {
3711 fn new(bytes: &'a [u8]) -> LinesWithTerminator<'a> {
3712 LinesWithTerminator { bytes }
3713 }
3714
3715 /// Return a copy of the rest of the underlying bytes without affecting the
3716 /// iterator itself.
3717 ///
3718 /// # Examples
3719 ///
3720 /// Basic usage:
3721 ///
3722 /// ```
3723 /// use bstr::{B, ByteSlice};
3724 ///
3725 /// let s = b"\
3726 /// foo
3727 /// bar\r
3728 /// baz";
3729 /// let mut lines = s.lines_with_terminator();
3730 /// assert_eq!(lines.next(), Some(B("foo\n")));
3731 /// assert_eq!(lines.as_bytes(), B("bar\r\nbaz"));
3732 /// ```
3733 pub fn as_bytes(&self) -> &'a [u8] {
3734 self.bytes
3735 }
3736}
3737
3738impl<'a> Iterator for LinesWithTerminator<'a> {
3739 type Item = &'a [u8];
3740
3741 #[inline]
3742 fn next(&mut self) -> Option<&'a [u8]> {
3743 match self.bytes.find_byte(b'\n') {
3744 None if self.bytes.is_empty() => None,
3745 None => {
3746 let line = self.bytes;
3747 self.bytes = b"";
3748 Some(line)
3749 }
3750 Some(end) => {
3751 let line = &self.bytes[..=end];
3752 self.bytes = &self.bytes[end + 1..];
3753 Some(line)
3754 }
3755 }
3756 }
3757}
3758
3759impl<'a> DoubleEndedIterator for LinesWithTerminator<'a> {
3760 #[inline]
3761 fn next_back(&mut self) -> Option<Self::Item> {
3762 let end = self.bytes.len().checked_sub(1)?;
3763 match self.bytes[..end].rfind_byte(b'\n') {
3764 None => {
3765 let line = self.bytes;
3766 self.bytes = b"";
3767 Some(line)
3768 }
3769 Some(end) => {
3770 let line = &self.bytes[end + 1..];
3771 self.bytes = &self.bytes[..=end];
3772 Some(line)
3773 }
3774 }
3775 }
3776}
3777
3778impl<'a> iter::FusedIterator for LinesWithTerminator<'a> {}
3779
3780fn trim_last_terminator(mut s: &[u8]) -> &[u8] {
3781 if s.last_byte() == Some(b'\n') {
3782 s = &s[..s.len() - 1];
3783 if s.last_byte() == Some(b'\r') {
3784 s = &s[..s.len() - 1];
3785 }
3786 }
3787 s
3788}
3789
3790#[cfg(all(test, feature = "std"))]
3791mod tests {
3792 use alloc::{string::String, vec::Vec};
3793
3794 use crate::{
3795 ext_slice::{ByteSlice, Lines, LinesWithTerminator, B},
3796 tests::LOSSY_TESTS,
3797 };
3798
3799 #[test]
3800 fn to_str_lossy() {
3801 for (i, &(expected, input)) in LOSSY_TESTS.iter().enumerate() {
3802 let got = B(input).to_str_lossy();
3803 assert_eq!(
3804 expected.as_bytes(),
3805 got.as_bytes(),
3806 "to_str_lossy(ith: {:?}, given: {:?})",
3807 i,
3808 input,
3809 );
3810
3811 let mut got = String::new();
3812 B(input).to_str_lossy_into(&mut got);
3813 assert_eq!(
3814 expected.as_bytes(),
3815 got.as_bytes(),
3816 "to_str_lossy_into",
3817 );
3818
3819 let got = String::from_utf8_lossy(input);
3820 assert_eq!(expected.as_bytes(), got.as_bytes(), "std");
3821 }
3822 }
3823
3824 #[test]
3825 fn lines_iteration() {
3826 macro_rules! t {
3827 ($it:expr, $forward:expr) => {
3828 let mut res: Vec<&[u8]> = Vec::from($forward);
3829 assert_eq!($it.collect::<Vec<_>>(), res);
3830 res.reverse();
3831 assert_eq!($it.rev().collect::<Vec<_>>(), res);
3832 };
3833 }
3834
3835 t!(Lines::new(b""), []);
3836 t!(LinesWithTerminator::new(b""), []);
3837
3838 t!(Lines::new(b"\n"), [B("")]);
3839 t!(Lines::new(b"\r\n"), [B("")]);
3840 t!(LinesWithTerminator::new(b"\n"), [B("\n")]);
3841
3842 t!(Lines::new(b"a"), [B("a")]);
3843 t!(LinesWithTerminator::new(b"a"), [B("a")]);
3844
3845 t!(Lines::new(b"abc"), [B("abc")]);
3846 t!(LinesWithTerminator::new(b"abc"), [B("abc")]);
3847
3848 t!(Lines::new(b"abc\n"), [B("abc")]);
3849 t!(Lines::new(b"abc\r\n"), [B("abc")]);
3850 t!(LinesWithTerminator::new(b"abc\n"), [B("abc\n")]);
3851
3852 t!(Lines::new(b"abc\n\n"), [B("abc"), B("")]);
3853 t!(LinesWithTerminator::new(b"abc\n\n"), [B("abc\n"), B("\n")]);
3854
3855 t!(Lines::new(b"abc\n\ndef"), [B("abc"), B(""), B("def")]);
3856 t!(
3857 LinesWithTerminator::new(b"abc\n\ndef"),
3858 [B("abc\n"), B("\n"), B("def")]
3859 );
3860
3861 t!(Lines::new(b"abc\n\ndef\n"), [B("abc"), B(""), B("def")]);
3862 t!(
3863 LinesWithTerminator::new(b"abc\n\ndef\n"),
3864 [B("abc\n"), B("\n"), B("def\n")]
3865 );
3866
3867 t!(Lines::new(b"\na\nb\n"), [B(""), B("a"), B("b")]);
3868 t!(
3869 LinesWithTerminator::new(b"\na\nb\n"),
3870 [B("\n"), B("a\n"), B("b\n")]
3871 );
3872
3873 t!(Lines::new(b"\n\n\n"), [B(""), B(""), B("")]);
3874 t!(LinesWithTerminator::new(b"\n\n\n"), [B("\n"), B("\n"), B("\n")]);
3875 }
3876}