/rust/registry/src/index.crates.io-1949cf8c6b5b557f/bstr-1.12.3/src/ext_slice.rs
Line | Count | Source |
1 | | use core::{iter, slice, str}; |
2 | | |
3 | | #[cfg(all(feature = "alloc", feature = "unicode"))] |
4 | | use alloc::vec; |
5 | | #[cfg(feature = "alloc")] |
6 | | use alloc::{borrow::Cow, string::String, vec::Vec}; |
7 | | |
8 | | #[cfg(feature = "std")] |
9 | | use std::{ffi::OsStr, path::Path}; |
10 | | |
11 | | use memchr::{memchr, memmem, memrchr}; |
12 | | |
13 | | use crate::escape_bytes::EscapeBytes; |
14 | | #[cfg(feature = "alloc")] |
15 | | use crate::ext_vec::ByteVec; |
16 | | #[cfg(feature = "unicode")] |
17 | | use crate::unicode::{ |
18 | | whitespace_len_fwd, whitespace_len_rev, GraphemeIndices, Graphemes, |
19 | | SentenceIndices, Sentences, WordIndices, Words, WordsWithBreakIndices, |
20 | | WordsWithBreaks, |
21 | | }; |
22 | | use 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] |
75 | 0 | pub fn B<B: ?Sized + AsRef<[u8]>>(bytes: &B) -> &[u8] { |
76 | 0 | bytes.as_ref() |
77 | 0 | } Unexecuted instantiation: bstr::ext_slice::B::<_> Unexecuted instantiation: bstr::ext_slice::B::<_> Unexecuted instantiation: bstr::ext_slice::B::<_> |
78 | | |
79 | | impl ByteSlice for [u8] { |
80 | | #[inline] |
81 | 1.03G | fn as_bytes(&self) -> &[u8] { |
82 | 1.03G | self |
83 | 1.03G | } <[u8] as bstr::ext_slice::ByteSlice>::as_bytes Line | Count | Source | 81 | 10.1M | fn as_bytes(&self) -> &[u8] { | 82 | 10.1M | self | 83 | 10.1M | } |
<[u8] as bstr::ext_slice::ByteSlice>::as_bytes Line | Count | Source | 81 | 90.7M | fn as_bytes(&self) -> &[u8] { | 82 | 90.7M | self | 83 | 90.7M | } |
<[u8] as bstr::ext_slice::ByteSlice>::as_bytes Line | Count | Source | 81 | 724M | fn as_bytes(&self) -> &[u8] { | 82 | 724M | self | 83 | 724M | } |
<[u8] as bstr::ext_slice::ByteSlice>::as_bytes Line | Count | Source | 81 | 211M | fn as_bytes(&self) -> &[u8] { | 82 | 211M | self | 83 | 211M | } |
|
84 | | |
85 | | #[inline] |
86 | 0 | fn as_bytes_mut(&mut self) -> &mut [u8] { |
87 | 0 | self |
88 | 0 | } Unexecuted instantiation: <[u8] as bstr::ext_slice::ByteSlice>::as_bytes_mut Unexecuted instantiation: <[u8] as bstr::ext_slice::ByteSlice>::as_bytes_mut Unexecuted instantiation: <[u8] as bstr::ext_slice::ByteSlice>::as_bytes_mut |
89 | | } |
90 | | |
91 | | impl<const N: usize> ByteSlice for [u8; N] { |
92 | | #[inline] |
93 | 104k | fn as_bytes(&self) -> &[u8] { |
94 | 104k | self |
95 | 104k | } Unexecuted instantiation: <[u8; _] as bstr::ext_slice::ByteSlice>::as_bytes <[u8; 1] as bstr::ext_slice::ByteSlice>::as_bytes Line | Count | Source | 93 | 26.0k | fn as_bytes(&self) -> &[u8] { | 94 | 26.0k | self | 95 | 26.0k | } |
Unexecuted instantiation: <[u8; 0] as bstr::ext_slice::ByteSlice>::as_bytes Unexecuted instantiation: <[u8; 19] as bstr::ext_slice::ByteSlice>::as_bytes <[u8; 10] as bstr::ext_slice::ByteSlice>::as_bytes Line | Count | Source | 93 | 21.9k | fn as_bytes(&self) -> &[u8] { | 94 | 21.9k | self | 95 | 21.9k | } |
<[u8; 11] as bstr::ext_slice::ByteSlice>::as_bytes Line | Count | Source | 93 | 6.67k | fn as_bytes(&self) -> &[u8] { | 94 | 6.67k | self | 95 | 6.67k | } |
<[u8; 12] as bstr::ext_slice::ByteSlice>::as_bytes Line | Count | Source | 93 | 3.28k | fn as_bytes(&self) -> &[u8] { | 94 | 3.28k | self | 95 | 3.28k | } |
<[u8; 13] as bstr::ext_slice::ByteSlice>::as_bytes Line | Count | Source | 93 | 3.31k | fn as_bytes(&self) -> &[u8] { | 94 | 3.31k | self | 95 | 3.31k | } |
<[u8; 14] as bstr::ext_slice::ByteSlice>::as_bytes Line | Count | Source | 93 | 22.1k | fn as_bytes(&self) -> &[u8] { | 94 | 22.1k | self | 95 | 22.1k | } |
<[u8; 15] as bstr::ext_slice::ByteSlice>::as_bytes Line | Count | Source | 93 | 3.21k | fn as_bytes(&self) -> &[u8] { | 94 | 3.21k | self | 95 | 3.21k | } |
Unexecuted instantiation: <[u8; 0] as bstr::ext_slice::ByteSlice>::as_bytes Unexecuted instantiation: <[u8; _] as bstr::ext_slice::ByteSlice>::as_bytes <[u8; 4] as bstr::ext_slice::ByteSlice>::as_bytes Line | Count | Source | 93 | 804 | fn as_bytes(&self) -> &[u8] { | 94 | 804 | self | 95 | 804 | } |
Unexecuted instantiation: <[u8; 4] as bstr::ext_slice::ByteSlice>::as_bytes Unexecuted instantiation: <[u8; 4] as bstr::ext_slice::ByteSlice>::as_bytes <[u8; 4] as bstr::ext_slice::ByteSlice>::as_bytes Line | Count | Source | 93 | 193 | fn as_bytes(&self) -> &[u8] { | 94 | 193 | self | 95 | 193 | } |
Unexecuted instantiation: <[u8; 0] as bstr::ext_slice::ByteSlice>::as_bytes Unexecuted instantiation: <[u8; _] as bstr::ext_slice::ByteSlice>::as_bytes Unexecuted instantiation: <[u8; 0] as bstr::ext_slice::ByteSlice>::as_bytes Unexecuted instantiation: <[u8; 4] as bstr::ext_slice::ByteSlice>::as_bytes Unexecuted instantiation: <[u8; 0] as bstr::ext_slice::ByteSlice>::as_bytes <[u8; 4] as bstr::ext_slice::ByteSlice>::as_bytes Line | Count | Source | 93 | 1.67k | fn as_bytes(&self) -> &[u8] { | 94 | 1.67k | self | 95 | 1.67k | } |
<[u8; 4] as bstr::ext_slice::ByteSlice>::as_bytes Line | Count | Source | 93 | 1.20k | fn as_bytes(&self) -> &[u8] { | 94 | 1.20k | self | 95 | 1.20k | } |
Unexecuted instantiation: <[u8; 4] as bstr::ext_slice::ByteSlice>::as_bytes Unexecuted instantiation: <[u8; 0] as bstr::ext_slice::ByteSlice>::as_bytes Unexecuted instantiation: <[u8; 0] as bstr::ext_slice::ByteSlice>::as_bytes <[u8; 0] as bstr::ext_slice::ByteSlice>::as_bytes Line | Count | Source | 93 | 14.5k | fn as_bytes(&self) -> &[u8] { | 94 | 14.5k | self | 95 | 14.5k | } |
Unexecuted instantiation: <[u8; 4] as bstr::ext_slice::ByteSlice>::as_bytes Unexecuted instantiation: <[u8; 4] as bstr::ext_slice::ByteSlice>::as_bytes Unexecuted instantiation: <[u8; 0] as bstr::ext_slice::ByteSlice>::as_bytes Unexecuted instantiation: <[u8; 0] as bstr::ext_slice::ByteSlice>::as_bytes |
96 | | |
97 | | #[inline] |
98 | 0 | fn as_bytes_mut(&mut self) -> &mut [u8] { |
99 | 0 | self |
100 | 0 | } Unexecuted instantiation: <[u8; _] as bstr::ext_slice::ByteSlice>::as_bytes_mut Unexecuted instantiation: <[u8; _] as bstr::ext_slice::ByteSlice>::as_bytes_mut Unexecuted instantiation: <[u8; _] as bstr::ext_slice::ByteSlice>::as_bytes_mut |
101 | | } |
102 | | |
103 | | /// Ensure that callers cannot implement `ByteSlice` by making an |
104 | | /// umplementable trait its super trait. |
105 | | mod private { |
106 | | pub trait Sealed {} |
107 | | } |
108 | | impl private::Sealed for [u8] {} |
109 | | impl<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`. |
114 | | pub 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 | | /// Use `&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 | 276M | fn as_bstr(&self) -> &BStr { |
146 | 276M | BStr::new(self.as_bytes()) |
147 | 276M | } <[u8] as bstr::ext_slice::ByteSlice>::as_bstr Line | Count | Source | 145 | 53.8k | fn as_bstr(&self) -> &BStr { | 146 | 53.8k | BStr::new(self.as_bytes()) | 147 | 53.8k | } |
<[u8] as bstr::ext_slice::ByteSlice>::as_bstr Line | Count | Source | 145 | 3.61M | fn as_bstr(&self) -> &BStr { | 146 | 3.61M | BStr::new(self.as_bytes()) | 147 | 3.61M | } |
<[u8] as bstr::ext_slice::ByteSlice>::as_bstr Line | Count | Source | 145 | 157k | fn as_bstr(&self) -> &BStr { | 146 | 157k | BStr::new(self.as_bytes()) | 147 | 157k | } |
Unexecuted instantiation: <_ as bstr::ext_slice::ByteSlice>::as_bstr <[u8] as bstr::ext_slice::ByteSlice>::as_bstr Line | Count | Source | 145 | 6.48k | fn as_bstr(&self) -> &BStr { | 146 | 6.48k | BStr::new(self.as_bytes()) | 147 | 6.48k | } |
<[u8; 1] as bstr::ext_slice::ByteSlice>::as_bstr Line | Count | Source | 145 | 26.0k | fn as_bstr(&self) -> &BStr { | 146 | 26.0k | BStr::new(self.as_bytes()) | 147 | 26.0k | } |
<[u8] as bstr::ext_slice::ByteSlice>::as_bstr Line | Count | Source | 145 | 228M | fn as_bstr(&self) -> &BStr { | 146 | 228M | BStr::new(self.as_bytes()) | 147 | 228M | } |
Unexecuted instantiation: <[u8] as bstr::ext_slice::ByteSlice>::as_bstr Unexecuted instantiation: <[u8; 0] as bstr::ext_slice::ByteSlice>::as_bstr Unexecuted instantiation: <[u8; 19] as bstr::ext_slice::ByteSlice>::as_bstr <[u8; 10] as bstr::ext_slice::ByteSlice>::as_bstr Line | Count | Source | 145 | 21.9k | fn as_bstr(&self) -> &BStr { | 146 | 21.9k | BStr::new(self.as_bytes()) | 147 | 21.9k | } |
<[u8; 11] as bstr::ext_slice::ByteSlice>::as_bstr Line | Count | Source | 145 | 6.67k | fn as_bstr(&self) -> &BStr { | 146 | 6.67k | BStr::new(self.as_bytes()) | 147 | 6.67k | } |
<[u8; 12] as bstr::ext_slice::ByteSlice>::as_bstr Line | Count | Source | 145 | 3.28k | fn as_bstr(&self) -> &BStr { | 146 | 3.28k | BStr::new(self.as_bytes()) | 147 | 3.28k | } |
<[u8; 13] as bstr::ext_slice::ByteSlice>::as_bstr Line | Count | Source | 145 | 3.31k | fn as_bstr(&self) -> &BStr { | 146 | 3.31k | BStr::new(self.as_bytes()) | 147 | 3.31k | } |
<[u8; 14] as bstr::ext_slice::ByteSlice>::as_bstr Line | Count | Source | 145 | 22.1k | fn as_bstr(&self) -> &BStr { | 146 | 22.1k | BStr::new(self.as_bytes()) | 147 | 22.1k | } |
<[u8; 15] as bstr::ext_slice::ByteSlice>::as_bstr Line | Count | Source | 145 | 3.21k | fn as_bstr(&self) -> &BStr { | 146 | 3.21k | BStr::new(self.as_bytes()) | 147 | 3.21k | } |
<[u8] as bstr::ext_slice::ByteSlice>::as_bstr Line | Count | Source | 145 | 6.07M | fn as_bstr(&self) -> &BStr { | 146 | 6.07M | BStr::new(self.as_bytes()) | 147 | 6.07M | } |
Unexecuted instantiation: <[u8] as bstr::ext_slice::ByteSlice>::as_bstr Unexecuted instantiation: <[u8; 0] as bstr::ext_slice::ByteSlice>::as_bstr Unexecuted instantiation: <[u8] as bstr::ext_slice::ByteSlice>::as_bstr <[u8] as bstr::ext_slice::ByteSlice>::as_bstr Line | Count | Source | 145 | 211k | fn as_bstr(&self) -> &BStr { | 146 | 211k | BStr::new(self.as_bytes()) | 147 | 211k | } |
Unexecuted instantiation: <[u8] as bstr::ext_slice::ByteSlice>::as_bstr Unexecuted instantiation: <[u8] as bstr::ext_slice::ByteSlice>::as_bstr Unexecuted instantiation: <_ as bstr::ext_slice::ByteSlice>::as_bstr <[u8; 4] as bstr::ext_slice::ByteSlice>::as_bstr Line | Count | Source | 145 | 804 | fn as_bstr(&self) -> &BStr { | 146 | 804 | BStr::new(self.as_bytes()) | 147 | 804 | } |
Unexecuted instantiation: <[u8; 4] as bstr::ext_slice::ByteSlice>::as_bstr Unexecuted instantiation: <[u8; 4] as bstr::ext_slice::ByteSlice>::as_bstr <[u8; 4] as bstr::ext_slice::ByteSlice>::as_bstr Line | Count | Source | 145 | 193 | fn as_bstr(&self) -> &BStr { | 146 | 193 | BStr::new(self.as_bytes()) | 147 | 193 | } |
Unexecuted instantiation: <[u8; 0] as bstr::ext_slice::ByteSlice>::as_bstr Unexecuted instantiation: <[u8] as bstr::ext_slice::ByteSlice>::as_bstr Unexecuted instantiation: <[u8] as bstr::ext_slice::ByteSlice>::as_bstr Unexecuted instantiation: <[u8] as bstr::ext_slice::ByteSlice>::as_bstr Unexecuted instantiation: <_ as bstr::ext_slice::ByteSlice>::as_bstr Unexecuted instantiation: <[u8; 0] as bstr::ext_slice::ByteSlice>::as_bstr <[u8] as bstr::ext_slice::ByteSlice>::as_bstr Line | Count | Source | 145 | 6.54M | fn as_bstr(&self) -> &BStr { | 146 | 6.54M | BStr::new(self.as_bytes()) | 147 | 6.54M | } |
Unexecuted instantiation: <[u8] as bstr::ext_slice::ByteSlice>::as_bstr Unexecuted instantiation: <[u8] as bstr::ext_slice::ByteSlice>::as_bstr Unexecuted instantiation: <[u8] as bstr::ext_slice::ByteSlice>::as_bstr Unexecuted instantiation: <[u8] as bstr::ext_slice::ByteSlice>::as_bstr <[u8] as bstr::ext_slice::ByteSlice>::as_bstr Line | Count | Source | 145 | 346 | fn as_bstr(&self) -> &BStr { | 146 | 346 | BStr::new(self.as_bytes()) | 147 | 346 | } |
<[u8] as bstr::ext_slice::ByteSlice>::as_bstr Line | Count | Source | 145 | 577k | fn as_bstr(&self) -> &BStr { | 146 | 577k | BStr::new(self.as_bytes()) | 147 | 577k | } |
Unexecuted instantiation: <[u8] as bstr::ext_slice::ByteSlice>::as_bstr Unexecuted instantiation: <[u8; 4] as bstr::ext_slice::ByteSlice>::as_bstr Unexecuted instantiation: <[u8; 0] as bstr::ext_slice::ByteSlice>::as_bstr Unexecuted instantiation: <[u8] as bstr::ext_slice::ByteSlice>::as_bstr Unexecuted instantiation: <[u8] as bstr::ext_slice::ByteSlice>::as_bstr Unexecuted instantiation: <[u8] as bstr::ext_slice::ByteSlice>::as_bstr Unexecuted instantiation: <[u8] as bstr::ext_slice::ByteSlice>::as_bstr <[u8] as bstr::ext_slice::ByteSlice>::as_bstr Line | Count | Source | 145 | 1.76k | fn as_bstr(&self) -> &BStr { | 146 | 1.76k | BStr::new(self.as_bytes()) | 147 | 1.76k | } |
<[u8] as bstr::ext_slice::ByteSlice>::as_bstr Line | Count | Source | 145 | 1.00k | fn as_bstr(&self) -> &BStr { | 146 | 1.00k | BStr::new(self.as_bytes()) | 147 | 1.00k | } |
<[u8] as bstr::ext_slice::ByteSlice>::as_bstr Line | Count | Source | 145 | 97.6k | fn as_bstr(&self) -> &BStr { | 146 | 97.6k | BStr::new(self.as_bytes()) | 147 | 97.6k | } |
Unexecuted instantiation: <[u8] as bstr::ext_slice::ByteSlice>::as_bstr <[u8] as bstr::ext_slice::ByteSlice>::as_bstr Line | Count | Source | 145 | 39.6k | fn as_bstr(&self) -> &BStr { | 146 | 39.6k | BStr::new(self.as_bytes()) | 147 | 39.6k | } |
<[u8] as bstr::ext_slice::ByteSlice>::as_bstr Line | Count | Source | 145 | 3.37M | fn as_bstr(&self) -> &BStr { | 146 | 3.37M | BStr::new(self.as_bytes()) | 147 | 3.37M | } |
<[u8] as bstr::ext_slice::ByteSlice>::as_bstr Line | Count | Source | 145 | 328k | fn as_bstr(&self) -> &BStr { | 146 | 328k | BStr::new(self.as_bytes()) | 147 | 328k | } |
Unexecuted instantiation: <[u8] as bstr::ext_slice::ByteSlice>::as_bstr <[u8] as bstr::ext_slice::ByteSlice>::as_bstr Line | Count | Source | 145 | 17.8k | fn as_bstr(&self) -> &BStr { | 146 | 17.8k | BStr::new(self.as_bytes()) | 147 | 17.8k | } |
Unexecuted instantiation: <[u8] as bstr::ext_slice::ByteSlice>::as_bstr <[u8] as bstr::ext_slice::ByteSlice>::as_bstr Line | Count | Source | 145 | 2.27k | fn as_bstr(&self) -> &BStr { | 146 | 2.27k | BStr::new(self.as_bytes()) | 147 | 2.27k | } |
<[u8] as bstr::ext_slice::ByteSlice>::as_bstr Line | Count | Source | 145 | 3.00k | fn as_bstr(&self) -> &BStr { | 146 | 3.00k | BStr::new(self.as_bytes()) | 147 | 3.00k | } |
<[u8] as bstr::ext_slice::ByteSlice>::as_bstr Line | Count | Source | 145 | 53.7k | fn as_bstr(&self) -> &BStr { | 146 | 53.7k | BStr::new(self.as_bytes()) | 147 | 53.7k | } |
<[u8; 4] as bstr::ext_slice::ByteSlice>::as_bstr Line | Count | Source | 145 | 1.67k | fn as_bstr(&self) -> &BStr { | 146 | 1.67k | BStr::new(self.as_bytes()) | 147 | 1.67k | } |
<[u8; 4] as bstr::ext_slice::ByteSlice>::as_bstr Line | Count | Source | 145 | 1.20k | fn as_bstr(&self) -> &BStr { | 146 | 1.20k | BStr::new(self.as_bytes()) | 147 | 1.20k | } |
<[u8] as bstr::ext_slice::ByteSlice>::as_bstr Line | Count | Source | 145 | 14.4M | fn as_bstr(&self) -> &BStr { | 146 | 14.4M | BStr::new(self.as_bytes()) | 147 | 14.4M | } |
Unexecuted instantiation: <[u8] as bstr::ext_slice::ByteSlice>::as_bstr Unexecuted instantiation: <[u8] as bstr::ext_slice::ByteSlice>::as_bstr Unexecuted instantiation: <[u8] as bstr::ext_slice::ByteSlice>::as_bstr Unexecuted instantiation: <[u8; 4] as bstr::ext_slice::ByteSlice>::as_bstr Unexecuted instantiation: <[u8] as bstr::ext_slice::ByteSlice>::as_bstr Unexecuted instantiation: <[u8] as bstr::ext_slice::ByteSlice>::as_bstr Unexecuted instantiation: <[u8] as bstr::ext_slice::ByteSlice>::as_bstr Unexecuted instantiation: <[u8; 0] as bstr::ext_slice::ByteSlice>::as_bstr Unexecuted instantiation: <[u8] as bstr::ext_slice::ByteSlice>::as_bstr Unexecuted instantiation: <[u8; 0] as bstr::ext_slice::ByteSlice>::as_bstr Unexecuted instantiation: <[u8] as bstr::ext_slice::ByteSlice>::as_bstr Unexecuted instantiation: <[u8] as bstr::ext_slice::ByteSlice>::as_bstr Unexecuted instantiation: <[u8] as bstr::ext_slice::ByteSlice>::as_bstr <[u8; 0] as bstr::ext_slice::ByteSlice>::as_bstr Line | Count | Source | 145 | 14.5k | fn as_bstr(&self) -> &BStr { | 146 | 14.5k | BStr::new(self.as_bytes()) | 147 | 14.5k | } |
<[u8] as bstr::ext_slice::ByteSlice>::as_bstr Line | Count | Source | 145 | 48.1k | fn as_bstr(&self) -> &BStr { | 146 | 48.1k | BStr::new(self.as_bytes()) | 147 | 48.1k | } |
<[u8] as bstr::ext_slice::ByteSlice>::as_bstr Line | Count | Source | 145 | 300k | fn as_bstr(&self) -> &BStr { | 146 | 300k | BStr::new(self.as_bytes()) | 147 | 300k | } |
Unexecuted instantiation: <[u8] as bstr::ext_slice::ByteSlice>::as_bstr <[u8] as bstr::ext_slice::ByteSlice>::as_bstr Line | Count | Source | 145 | 3.32M | fn as_bstr(&self) -> &BStr { | 146 | 3.32M | BStr::new(self.as_bytes()) | 147 | 3.32M | } |
Unexecuted instantiation: <[u8] as bstr::ext_slice::ByteSlice>::as_bstr Unexecuted instantiation: <[u8] as bstr::ext_slice::ByteSlice>::as_bstr <[u8] as bstr::ext_slice::ByteSlice>::as_bstr Line | Count | Source | 145 | 52.5k | fn as_bstr(&self) -> &BStr { | 146 | 52.5k | BStr::new(self.as_bytes()) | 147 | 52.5k | } |
<[u8] as bstr::ext_slice::ByteSlice>::as_bstr Line | Count | Source | 145 | 38.0k | fn as_bstr(&self) -> &BStr { | 146 | 38.0k | BStr::new(self.as_bytes()) | 147 | 38.0k | } |
Unexecuted instantiation: <[u8; 4] as bstr::ext_slice::ByteSlice>::as_bstr Unexecuted instantiation: <[u8; 4] as bstr::ext_slice::ByteSlice>::as_bstr Unexecuted instantiation: <[u8; 0] as bstr::ext_slice::ByteSlice>::as_bstr Unexecuted instantiation: <[u8] as bstr::ext_slice::ByteSlice>::as_bstr <[u8] as bstr::ext_slice::ByteSlice>::as_bstr Line | Count | Source | 145 | 3.60M | fn as_bstr(&self) -> &BStr { | 146 | 3.60M | BStr::new(self.as_bytes()) | 147 | 3.60M | } |
Unexecuted instantiation: <[u8; 0] as bstr::ext_slice::ByteSlice>::as_bstr <[u8] as bstr::ext_slice::ByteSlice>::as_bstr Line | Count | Source | 145 | 4.83M | fn as_bstr(&self) -> &BStr { | 146 | 4.83M | BStr::new(self.as_bytes()) | 147 | 4.83M | } |
Unexecuted instantiation: <[u8] as bstr::ext_slice::ByteSlice>::as_bstr |
148 | | |
149 | | /// Return this byte slice as a `&mut BStr`. |
150 | | /// |
151 | | /// Use `&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 | 0 | fn as_bstr_mut(&mut self) -> &mut BStr { |
169 | 0 | BStr::new_mut(self.as_bytes_mut()) |
170 | 0 | } Unexecuted instantiation: <_ as bstr::ext_slice::ByteSlice>::as_bstr_mut Unexecuted instantiation: <_ as bstr::ext_slice::ByteSlice>::as_bstr_mut Unexecuted instantiation: <_ as bstr::ext_slice::ByteSlice>::as_bstr_mut |
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 | 0 | fn from_os_str(os_str: &OsStr) -> Option<&[u8]> { |
197 | | #[cfg(unix)] |
198 | | #[inline] |
199 | 0 | fn imp(os_str: &OsStr) -> Option<&[u8]> { |
200 | | use std::os::unix::ffi::OsStrExt; |
201 | | |
202 | 0 | Some(os_str.as_bytes()) |
203 | 0 | } Unexecuted instantiation: bstr::ext_slice::ByteSlice::from_os_str::imp Unexecuted instantiation: bstr::ext_slice::ByteSlice::from_os_str::imp Unexecuted instantiation: bstr::ext_slice::ByteSlice::from_os_str::imp |
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 | 0 | imp(os_str) |
212 | 0 | } Unexecuted instantiation: <_ as bstr::ext_slice::ByteSlice>::from_os_str Unexecuted instantiation: <_ as bstr::ext_slice::ByteSlice>::from_os_str Unexecuted instantiation: <_ as bstr::ext_slice::ByteSlice>::from_os_str |
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 | 0 | fn from_path(path: &Path) -> Option<&[u8]> { |
239 | 0 | Self::from_os_str(path.as_os_str()) |
240 | 0 | } Unexecuted instantiation: <_ as bstr::ext_slice::ByteSlice>::from_path Unexecuted instantiation: <_ as bstr::ext_slice::ByteSlice>::from_path Unexecuted instantiation: <_ as bstr::ext_slice::ByteSlice>::from_path |
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 | 5.77M | fn to_str(&self) -> Result<&str, Utf8Error> { |
274 | 5.77M | utf8::validate(self.as_bytes()).map(|_| { |
275 | | // SAFETY: This is safe because of the guarantees provided by |
276 | | // utf8::validate. |
277 | 5.51M | unsafe { str::from_utf8_unchecked(self.as_bytes()) } |
278 | 5.51M | }) <[u8] as bstr::ext_slice::ByteSlice>::to_str::{closure#0}Line | Count | Source | 274 | 633k | utf8::validate(self.as_bytes()).map(|_| { | 275 | | // SAFETY: This is safe because of the guarantees provided by | 276 | | // utf8::validate. | 277 | 633k | unsafe { str::from_utf8_unchecked(self.as_bytes()) } | 278 | 633k | }) |
Unexecuted instantiation: <_ as bstr::ext_slice::ByteSlice>::to_str::{closure#0}Unexecuted instantiation: <[u8] as bstr::ext_slice::ByteSlice>::to_str::{closure#0}Unexecuted instantiation: <[u8] as bstr::ext_slice::ByteSlice>::to_str::{closure#0}Unexecuted instantiation: <[u8] as bstr::ext_slice::ByteSlice>::to_str::{closure#0}Unexecuted instantiation: <_ as bstr::ext_slice::ByteSlice>::to_str::{closure#0}Unexecuted instantiation: <_ as bstr::ext_slice::ByteSlice>::to_str::{closure#0}<[u8] as bstr::ext_slice::ByteSlice>::to_str::{closure#0}Line | Count | Source | 274 | 561 | utf8::validate(self.as_bytes()).map(|_| { | 275 | | // SAFETY: This is safe because of the guarantees provided by | 276 | | // utf8::validate. | 277 | 561 | unsafe { str::from_utf8_unchecked(self.as_bytes()) } | 278 | 561 | }) |
Unexecuted instantiation: <[u8] as bstr::ext_slice::ByteSlice>::to_str::{closure#0}<[u8] as bstr::ext_slice::ByteSlice>::to_str::{closure#0}Line | Count | Source | 274 | 12.8k | utf8::validate(self.as_bytes()).map(|_| { | 275 | | // SAFETY: This is safe because of the guarantees provided by | 276 | | // utf8::validate. | 277 | 12.8k | unsafe { str::from_utf8_unchecked(self.as_bytes()) } | 278 | 12.8k | }) |
<[u8] as bstr::ext_slice::ByteSlice>::to_str::{closure#0}Line | Count | Source | 274 | 6.07k | utf8::validate(self.as_bytes()).map(|_| { | 275 | | // SAFETY: This is safe because of the guarantees provided by | 276 | | // utf8::validate. | 277 | 6.07k | unsafe { str::from_utf8_unchecked(self.as_bytes()) } | 278 | 6.07k | }) |
Unexecuted instantiation: <[u8] as bstr::ext_slice::ByteSlice>::to_str::{closure#0}<[u8] as bstr::ext_slice::ByteSlice>::to_str::{closure#0}Line | Count | Source | 274 | 55.2k | utf8::validate(self.as_bytes()).map(|_| { | 275 | | // SAFETY: This is safe because of the guarantees provided by | 276 | | // utf8::validate. | 277 | 55.2k | unsafe { str::from_utf8_unchecked(self.as_bytes()) } | 278 | 55.2k | }) |
<[u8] as bstr::ext_slice::ByteSlice>::to_str::{closure#0}Line | Count | Source | 274 | 9.85k | utf8::validate(self.as_bytes()).map(|_| { | 275 | | // SAFETY: This is safe because of the guarantees provided by | 276 | | // utf8::validate. | 277 | 9.85k | unsafe { str::from_utf8_unchecked(self.as_bytes()) } | 278 | 9.85k | }) |
Unexecuted instantiation: <[u8] as bstr::ext_slice::ByteSlice>::to_str::{closure#0}Unexecuted instantiation: <[u8] as bstr::ext_slice::ByteSlice>::to_str::{closure#0}Unexecuted instantiation: <[u8] as bstr::ext_slice::ByteSlice>::to_str::{closure#0}Unexecuted instantiation: <[u8] as bstr::ext_slice::ByteSlice>::to_str::{closure#0}Unexecuted instantiation: <[u8] as bstr::ext_slice::ByteSlice>::to_str::{closure#0}<[u8] as bstr::ext_slice::ByteSlice>::to_str::{closure#0}Line | Count | Source | 274 | 29.4k | utf8::validate(self.as_bytes()).map(|_| { | 275 | | // SAFETY: This is safe because of the guarantees provided by | 276 | | // utf8::validate. | 277 | 29.4k | unsafe { str::from_utf8_unchecked(self.as_bytes()) } | 278 | 29.4k | }) |
<[u8] as bstr::ext_slice::ByteSlice>::to_str::{closure#0}Line | Count | Source | 274 | 19.3k | utf8::validate(self.as_bytes()).map(|_| { | 275 | | // SAFETY: This is safe because of the guarantees provided by | 276 | | // utf8::validate. | 277 | 19.3k | unsafe { str::from_utf8_unchecked(self.as_bytes()) } | 278 | 19.3k | }) |
<[u8] as bstr::ext_slice::ByteSlice>::to_str::{closure#0}Line | Count | Source | 274 | 6.96k | utf8::validate(self.as_bytes()).map(|_| { | 275 | | // SAFETY: This is safe because of the guarantees provided by | 276 | | // utf8::validate. | 277 | 6.96k | unsafe { str::from_utf8_unchecked(self.as_bytes()) } | 278 | 6.96k | }) |
Unexecuted instantiation: <[u8] as bstr::ext_slice::ByteSlice>::to_str::{closure#0}<[u8] as bstr::ext_slice::ByteSlice>::to_str::{closure#0}Line | Count | Source | 274 | 4.73M | utf8::validate(self.as_bytes()).map(|_| { | 275 | | // SAFETY: This is safe because of the guarantees provided by | 276 | | // utf8::validate. | 277 | 4.73M | unsafe { str::from_utf8_unchecked(self.as_bytes()) } | 278 | 4.73M | }) |
|
279 | 5.77M | } <[u8] as bstr::ext_slice::ByteSlice>::to_str Line | Count | Source | 273 | 885k | fn to_str(&self) -> Result<&str, Utf8Error> { | 274 | 885k | 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 | 885k | } |
Unexecuted instantiation: <_ as bstr::ext_slice::ByteSlice>::to_str Unexecuted instantiation: <[u8] as bstr::ext_slice::ByteSlice>::to_str Unexecuted instantiation: <[u8] as bstr::ext_slice::ByteSlice>::to_str Unexecuted instantiation: <[u8] as bstr::ext_slice::ByteSlice>::to_str Unexecuted instantiation: <_ as bstr::ext_slice::ByteSlice>::to_str Unexecuted instantiation: <_ as bstr::ext_slice::ByteSlice>::to_str <[u8] as bstr::ext_slice::ByteSlice>::to_str Line | Count | Source | 273 | 1.11k | fn to_str(&self) -> Result<&str, Utf8Error> { | 274 | 1.11k | 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 | 1.11k | } |
Unexecuted instantiation: <[u8] as bstr::ext_slice::ByteSlice>::to_str <[u8] as bstr::ext_slice::ByteSlice>::to_str Line | Count | Source | 273 | 13.6k | fn to_str(&self) -> Result<&str, Utf8Error> { | 274 | 13.6k | 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 | 13.6k | } |
<[u8] as bstr::ext_slice::ByteSlice>::to_str Line | Count | Source | 273 | 6.17k | fn to_str(&self) -> Result<&str, Utf8Error> { | 274 | 6.17k | 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 | 6.17k | } |
Unexecuted instantiation: <[u8] as bstr::ext_slice::ByteSlice>::to_str <[u8] as bstr::ext_slice::ByteSlice>::to_str Line | Count | Source | 273 | 55.9k | fn to_str(&self) -> Result<&str, Utf8Error> { | 274 | 55.9k | 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 | 55.9k | } |
<[u8] as bstr::ext_slice::ByteSlice>::to_str Line | Count | Source | 273 | 15.4k | fn to_str(&self) -> Result<&str, Utf8Error> { | 274 | 15.4k | 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 | 15.4k | } |
Unexecuted instantiation: <[u8] as bstr::ext_slice::ByteSlice>::to_str Unexecuted instantiation: <[u8] as bstr::ext_slice::ByteSlice>::to_str Unexecuted instantiation: <[u8] as bstr::ext_slice::ByteSlice>::to_str Unexecuted instantiation: <[u8] as bstr::ext_slice::ByteSlice>::to_str Unexecuted instantiation: <[u8] as bstr::ext_slice::ByteSlice>::to_str <[u8] as bstr::ext_slice::ByteSlice>::to_str Line | Count | Source | 273 | 29.4k | fn to_str(&self) -> Result<&str, Utf8Error> { | 274 | 29.4k | 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 | 29.4k | } |
<[u8] as bstr::ext_slice::ByteSlice>::to_str Line | Count | Source | 273 | 20.1k | fn to_str(&self) -> Result<&str, Utf8Error> { | 274 | 20.1k | 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 | 20.1k | } |
<[u8] as bstr::ext_slice::ByteSlice>::to_str Line | Count | Source | 273 | 7.10k | fn to_str(&self) -> Result<&str, Utf8Error> { | 274 | 7.10k | 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 | 7.10k | } |
Unexecuted instantiation: <[u8] as bstr::ext_slice::ByteSlice>::to_str <[u8] as bstr::ext_slice::ByteSlice>::to_str Line | Count | Source | 273 | 4.73M | fn to_str(&self) -> Result<&str, Utf8Error> { | 274 | 4.73M | 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 | 4.73M | } |
|
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 | 0 | unsafe fn to_str_unchecked(&self) -> &str { |
309 | 0 | str::from_utf8_unchecked(self.as_bytes()) |
310 | 0 | } Unexecuted instantiation: <[u8] as bstr::ext_slice::ByteSlice>::to_str_unchecked Unexecuted instantiation: <[u8] as bstr::ext_slice::ByteSlice>::to_str_unchecked Unexecuted instantiation: <_ as bstr::ext_slice::ByteSlice>::to_str_unchecked |
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 | 3.42M | fn to_str_lossy(&self) -> Cow<'_, str> { |
374 | 3.42M | 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 | 3.36M | Cow::Borrowed(str::from_utf8_unchecked(self.as_bytes())) |
380 | | } |
381 | | } |
382 | 61.0k | Err(err) => { |
383 | 61.0k | let mut lossy = String::with_capacity(self.as_bytes().len()); |
384 | 61.0k | let (valid, after) = |
385 | 61.0k | 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 | 61.0k | lossy.push_str(unsafe { str::from_utf8_unchecked(valid) }); |
389 | 61.0k | lossy.push_str("\u{FFFD}"); |
390 | 61.0k | if let Some(len) = err.error_len() { |
391 | 47.3k | after[len..].to_str_lossy_into(&mut lossy); |
392 | 47.3k | } |
393 | 61.0k | Cow::Owned(lossy) |
394 | | } |
395 | | } |
396 | 3.42M | } Unexecuted instantiation: <_ as bstr::ext_slice::ByteSlice>::to_str_lossy Unexecuted instantiation: <_ as bstr::ext_slice::ByteSlice>::to_str_lossy Unexecuted instantiation: <_ as bstr::ext_slice::ByteSlice>::to_str_lossy Unexecuted instantiation: <[u8] as bstr::ext_slice::ByteSlice>::to_str_lossy Unexecuted instantiation: <[u8] as bstr::ext_slice::ByteSlice>::to_str_lossy Unexecuted instantiation: <[u8] as bstr::ext_slice::ByteSlice>::to_str_lossy Unexecuted instantiation: <[u8] as bstr::ext_slice::ByteSlice>::to_str_lossy <[u8] as bstr::ext_slice::ByteSlice>::to_str_lossy Line | Count | Source | 373 | 3.32M | fn to_str_lossy(&self) -> Cow<'_, str> { | 374 | 3.32M | 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 | 3.26M | Cow::Borrowed(str::from_utf8_unchecked(self.as_bytes())) | 380 | | } | 381 | | } | 382 | 61.0k | Err(err) => { | 383 | 61.0k | let mut lossy = String::with_capacity(self.as_bytes().len()); | 384 | 61.0k | let (valid, after) = | 385 | 61.0k | 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 | 61.0k | lossy.push_str(unsafe { str::from_utf8_unchecked(valid) }); | 389 | 61.0k | lossy.push_str("\u{FFFD}"); | 390 | 61.0k | if let Some(len) = err.error_len() { | 391 | 47.3k | after[len..].to_str_lossy_into(&mut lossy); | 392 | 47.3k | } | 393 | 61.0k | Cow::Owned(lossy) | 394 | | } | 395 | | } | 396 | 3.32M | } |
<[u8] as bstr::ext_slice::ByteSlice>::to_str_lossy Line | Count | Source | 373 | 95.5k | fn to_str_lossy(&self) -> Cow<'_, str> { | 374 | 95.5k | 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 | 95.5k | Cow::Borrowed(str::from_utf8_unchecked(self.as_bytes())) | 380 | | } | 381 | | } | 382 | 0 | Err(err) => { | 383 | 0 | let mut lossy = String::with_capacity(self.as_bytes().len()); | 384 | 0 | let (valid, after) = | 385 | 0 | 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 | 0 | lossy.push_str(unsafe { str::from_utf8_unchecked(valid) }); | 389 | 0 | lossy.push_str("\u{FFFD}"); | 390 | 0 | if let Some(len) = err.error_len() { | 391 | 0 | after[len..].to_str_lossy_into(&mut lossy); | 392 | 0 | } | 393 | 0 | Cow::Owned(lossy) | 394 | | } | 395 | | } | 396 | 95.5k | } |
|
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 | 47.3k | fn to_str_lossy_into(&self, dest: &mut String) { |
431 | 47.3k | let mut bytes = self.as_bytes(); |
432 | 47.3k | dest.reserve(bytes.len()); |
433 | | loop { |
434 | 11.2M | 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 | 41.2k | dest.push_str(unsafe { str::from_utf8_unchecked(bytes) }); |
439 | 41.2k | break; |
440 | | } |
441 | 11.1M | Err(err) => { |
442 | 11.1M | 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 | 11.1M | dest.push_str(unsafe { str::from_utf8_unchecked(valid) }); |
446 | 11.1M | dest.push_str("\u{FFFD}"); |
447 | 11.1M | match err.error_len() { |
448 | 6.13k | None => break, |
449 | 11.1M | Some(len) => bytes = &after[len..], |
450 | | } |
451 | | } |
452 | | } |
453 | | } |
454 | 47.3k | } Unexecuted instantiation: <_ as bstr::ext_slice::ByteSlice>::to_str_lossy_into Unexecuted instantiation: <_ as bstr::ext_slice::ByteSlice>::to_str_lossy_into Unexecuted instantiation: <_ as bstr::ext_slice::ByteSlice>::to_str_lossy_into Unexecuted instantiation: <[u8] as bstr::ext_slice::ByteSlice>::to_str_lossy_into Unexecuted instantiation: <[u8] as bstr::ext_slice::ByteSlice>::to_str_lossy_into Unexecuted instantiation: <[u8] as bstr::ext_slice::ByteSlice>::to_str_lossy_into Unexecuted instantiation: <[u8] as bstr::ext_slice::ByteSlice>::to_str_lossy_into <[u8] as bstr::ext_slice::ByteSlice>::to_str_lossy_into Line | Count | Source | 430 | 47.3k | fn to_str_lossy_into(&self, dest: &mut String) { | 431 | 47.3k | let mut bytes = self.as_bytes(); | 432 | 47.3k | dest.reserve(bytes.len()); | 433 | | loop { | 434 | 11.2M | 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 | 41.2k | dest.push_str(unsafe { str::from_utf8_unchecked(bytes) }); | 439 | 41.2k | break; | 440 | | } | 441 | 11.1M | Err(err) => { | 442 | 11.1M | 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 | 11.1M | dest.push_str(unsafe { str::from_utf8_unchecked(valid) }); | 446 | 11.1M | dest.push_str("\u{FFFD}"); | 447 | 11.1M | match err.error_len() { | 448 | 6.13k | None => break, | 449 | 11.1M | Some(len) => bytes = &after[len..], | 450 | | } | 451 | | } | 452 | | } | 453 | | } | 454 | 47.3k | } |
Unexecuted instantiation: <[u8] as bstr::ext_slice::ByteSlice>::to_str_lossy_into |
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 | 0 | fn to_os_str(&self) -> Result<&OsStr, Utf8Error> { |
481 | | #[cfg(unix)] |
482 | | #[inline] |
483 | 0 | fn imp(bytes: &[u8]) -> Result<&OsStr, Utf8Error> { |
484 | | use std::os::unix::ffi::OsStrExt; |
485 | | |
486 | 0 | Ok(OsStr::from_bytes(bytes)) |
487 | 0 | } Unexecuted instantiation: bstr::ext_slice::ByteSlice::to_os_str::imp Unexecuted instantiation: bstr::ext_slice::ByteSlice::to_os_str::imp Unexecuted instantiation: bstr::ext_slice::ByteSlice::to_os_str::imp |
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 | 0 | imp(self.as_bytes()) |
496 | 0 | } Unexecuted instantiation: <_ as bstr::ext_slice::ByteSlice>::to_os_str Unexecuted instantiation: <[u8] as bstr::ext_slice::ByteSlice>::to_os_str Unexecuted instantiation: <_ as bstr::ext_slice::ByteSlice>::to_os_str Unexecuted instantiation: <_ as bstr::ext_slice::ByteSlice>::to_os_str Unexecuted instantiation: <[u8] as bstr::ext_slice::ByteSlice>::to_os_str Unexecuted instantiation: <[u8] as bstr::ext_slice::ByteSlice>::to_os_str Unexecuted instantiation: <[u8] as bstr::ext_slice::ByteSlice>::to_os_str |
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 | 0 | fn to_os_str_lossy(&self) -> Cow<'_, OsStr> { |
521 | | #[cfg(unix)] |
522 | | #[inline] |
523 | 0 | fn imp(bytes: &[u8]) -> Cow<'_, OsStr> { |
524 | | use std::os::unix::ffi::OsStrExt; |
525 | | |
526 | 0 | Cow::Borrowed(OsStr::from_bytes(bytes)) |
527 | 0 | } Unexecuted instantiation: bstr::ext_slice::ByteSlice::to_os_str_lossy::imp Unexecuted instantiation: bstr::ext_slice::ByteSlice::to_os_str_lossy::imp Unexecuted instantiation: bstr::ext_slice::ByteSlice::to_os_str_lossy::imp |
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 | 0 | imp(self.as_bytes()) |
541 | 0 | } Unexecuted instantiation: <_ as bstr::ext_slice::ByteSlice>::to_os_str_lossy Unexecuted instantiation: <_ as bstr::ext_slice::ByteSlice>::to_os_str_lossy Unexecuted instantiation: <_ as bstr::ext_slice::ByteSlice>::to_os_str_lossy Unexecuted instantiation: <[u8] as bstr::ext_slice::ByteSlice>::to_os_str_lossy |
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 | 0 | fn to_path(&self) -> Result<&Path, Utf8Error> { |
568 | 0 | self.to_os_str().map(Path::new) |
569 | 0 | } Unexecuted instantiation: <_ as bstr::ext_slice::ByteSlice>::to_path Unexecuted instantiation: <[u8] as bstr::ext_slice::ByteSlice>::to_path Unexecuted instantiation: <_ as bstr::ext_slice::ByteSlice>::to_path Unexecuted instantiation: <_ as bstr::ext_slice::ByteSlice>::to_path Unexecuted instantiation: <[u8] as bstr::ext_slice::ByteSlice>::to_path Unexecuted instantiation: <[u8] as bstr::ext_slice::ByteSlice>::to_path Unexecuted instantiation: <[u8] as bstr::ext_slice::ByteSlice>::to_path |
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 | 0 | fn to_path_lossy(&self) -> Cow<'_, Path> { |
595 | | use std::path::PathBuf; |
596 | | |
597 | 0 | match self.to_os_str_lossy() { |
598 | 0 | Cow::Borrowed(x) => Cow::Borrowed(Path::new(x)), |
599 | 0 | Cow::Owned(x) => Cow::Owned(PathBuf::from(x)), |
600 | | } |
601 | 0 | } Unexecuted instantiation: <_ as bstr::ext_slice::ByteSlice>::to_path_lossy Unexecuted instantiation: <_ as bstr::ext_slice::ByteSlice>::to_path_lossy Unexecuted instantiation: <_ as bstr::ext_slice::ByteSlice>::to_path_lossy |
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 | 0 | fn repeatn(&self, n: usize) -> Vec<u8> { |
623 | 0 | self.as_bytes().repeat(n) |
624 | 0 | } Unexecuted instantiation: <_ as bstr::ext_slice::ByteSlice>::repeatn Unexecuted instantiation: <_ as bstr::ext_slice::ByteSlice>::repeatn Unexecuted instantiation: <_ as bstr::ext_slice::ByteSlice>::repeatn |
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 | 2.07M | fn contains_str<B: AsRef<[u8]>>(&self, needle: B) -> bool { |
641 | 2.07M | self.find(needle).is_some() |
642 | 2.07M | } Unexecuted instantiation: <_ as bstr::ext_slice::ByteSlice>::contains_str::<_> <[u8] as bstr::ext_slice::ByteSlice>::contains_str::<&[u8]> Line | Count | Source | 640 | 1.64M | fn contains_str<B: AsRef<[u8]>>(&self, needle: B) -> bool { | 641 | 1.64M | self.find(needle).is_some() | 642 | 1.64M | } |
<[u8] as bstr::ext_slice::ByteSlice>::contains_str::<&bstr::bstr::BStr> Line | Count | Source | 640 | 426k | fn contains_str<B: AsRef<[u8]>>(&self, needle: B) -> bool { | 641 | 426k | self.find(needle).is_some() | 642 | 426k | } |
Unexecuted instantiation: <_ as bstr::ext_slice::ByteSlice>::contains_str::<_> Unexecuted instantiation: <_ as bstr::ext_slice::ByteSlice>::contains_str::<_> Unexecuted instantiation: <[u8] as bstr::ext_slice::ByteSlice>::contains_str::<&[u8; 16]> Unexecuted instantiation: <[u8] as bstr::ext_slice::ByteSlice>::contains_str::<&[u8; 17]> Unexecuted instantiation: <[u8] as bstr::ext_slice::ByteSlice>::contains_str::<&[u8; 9]> Unexecuted instantiation: <[u8] as bstr::ext_slice::ByteSlice>::contains_str::<&[u8; 15]> Unexecuted instantiation: <[u8] as bstr::ext_slice::ByteSlice>::contains_str::<&str> |
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 | 23.3k | fn starts_with_str<B: AsRef<[u8]>>(&self, prefix: B) -> bool { |
659 | 23.3k | self.as_bytes().starts_with(prefix.as_ref()) |
660 | 23.3k | } Unexecuted instantiation: <_ as bstr::ext_slice::ByteSlice>::starts_with_str::<_> <[u8] as bstr::ext_slice::ByteSlice>::starts_with_str::<&bstr::bstring::BString> Line | Count | Source | 658 | 2.01k | fn starts_with_str<B: AsRef<[u8]>>(&self, prefix: B) -> bool { | 659 | 2.01k | self.as_bytes().starts_with(prefix.as_ref()) | 660 | 2.01k | } |
<[u8] as bstr::ext_slice::ByteSlice>::starts_with_str::<&str> Line | Count | Source | 658 | 17.6k | fn starts_with_str<B: AsRef<[u8]>>(&self, prefix: B) -> bool { | 659 | 17.6k | self.as_bytes().starts_with(prefix.as_ref()) | 660 | 17.6k | } |
Unexecuted instantiation: <_ as bstr::ext_slice::ByteSlice>::starts_with_str::<_> Unexecuted instantiation: <_ as bstr::ext_slice::ByteSlice>::starts_with_str::<_> <[u8] as bstr::ext_slice::ByteSlice>::starts_with_str::<&str> Line | Count | Source | 658 | 2.08k | fn starts_with_str<B: AsRef<[u8]>>(&self, prefix: B) -> bool { | 659 | 2.08k | self.as_bytes().starts_with(prefix.as_ref()) | 660 | 2.08k | } |
<[u8] as bstr::ext_slice::ByteSlice>::starts_with_str::<&str> Line | Count | Source | 658 | 1.61k | fn starts_with_str<B: AsRef<[u8]>>(&self, prefix: B) -> bool { | 659 | 1.61k | self.as_bytes().starts_with(prefix.as_ref()) | 660 | 1.61k | } |
|
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 | 18.9M | fn ends_with_str<B: AsRef<[u8]>>(&self, suffix: B) -> bool { |
677 | 18.9M | self.as_bytes().ends_with(suffix.as_ref()) |
678 | 18.9M | } Unexecuted instantiation: <_ as bstr::ext_slice::ByteSlice>::ends_with_str::<_> Unexecuted instantiation: <[u8] as bstr::ext_slice::ByteSlice>::ends_with_str::<&[u8; 1]> <[u8] as bstr::ext_slice::ByteSlice>::ends_with_str::<&str> Line | Count | Source | 676 | 18.8M | fn ends_with_str<B: AsRef<[u8]>>(&self, suffix: B) -> bool { | 677 | 18.8M | self.as_bytes().ends_with(suffix.as_ref()) | 678 | 18.8M | } |
Unexecuted instantiation: <_ as bstr::ext_slice::ByteSlice>::ends_with_str::<_> Unexecuted instantiation: <[u8] as bstr::ext_slice::ByteSlice>::ends_with_str::<&[u8; 1]> Unexecuted instantiation: <_ as bstr::ext_slice::ByteSlice>::ends_with_str::<_> Unexecuted instantiation: <[u8] as bstr::ext_slice::ByteSlice>::ends_with_str::<&[u8; 1]> <[u8] as bstr::ext_slice::ByteSlice>::ends_with_str::<&str> Line | Count | Source | 676 | 3.19k | fn ends_with_str<B: AsRef<[u8]>>(&self, suffix: B) -> bool { | 677 | 3.19k | self.as_bytes().ends_with(suffix.as_ref()) | 678 | 3.19k | } |
Unexecuted instantiation: <[u8] as bstr::ext_slice::ByteSlice>::ends_with_str::<&[u8; 1]> <[u8] as bstr::ext_slice::ByteSlice>::ends_with_str::<&str> Line | Count | Source | 676 | 1.64k | fn ends_with_str<B: AsRef<[u8]>>(&self, suffix: B) -> bool { | 677 | 1.64k | self.as_bytes().ends_with(suffix.as_ref()) | 678 | 1.64k | } |
Unexecuted instantiation: <[u8] as bstr::ext_slice::ByteSlice>::ends_with_str::<&[u8; 1]> Unexecuted instantiation: <[u8] as bstr::ext_slice::ByteSlice>::ends_with_str::<&str> Unexecuted instantiation: <[u8] as bstr::ext_slice::ByteSlice>::ends_with_str::<&[u8; 1]> |
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 | 2.09M | fn find<B: AsRef<[u8]>>(&self, needle: B) -> Option<usize> { |
712 | 2.09M | Finder::new(needle.as_ref()).find(self.as_bytes()) |
713 | 2.09M | } Unexecuted instantiation: <_ as bstr::ext_slice::ByteSlice>::find::<_> <[u8] as bstr::ext_slice::ByteSlice>::find::<&[u8]> Line | Count | Source | 711 | 1.64M | fn find<B: AsRef<[u8]>>(&self, needle: B) -> Option<usize> { | 712 | 1.64M | Finder::new(needle.as_ref()).find(self.as_bytes()) | 713 | 1.64M | } |
<[u8] as bstr::ext_slice::ByteSlice>::find::<&bstr::bstr::BStr> Line | Count | Source | 711 | 426k | fn find<B: AsRef<[u8]>>(&self, needle: B) -> Option<usize> { | 712 | 426k | Finder::new(needle.as_ref()).find(self.as_bytes()) | 713 | 426k | } |
Unexecuted instantiation: <[u8] as bstr::ext_slice::ByteSlice>::find::<&[u8; 1]> Unexecuted instantiation: <_ as bstr::ext_slice::ByteSlice>::find::<_> Unexecuted instantiation: <[u8] as bstr::ext_slice::ByteSlice>::find::<&[u8; 1]> Unexecuted instantiation: <_ as bstr::ext_slice::ByteSlice>::find::<_> Unexecuted instantiation: <[u8] as bstr::ext_slice::ByteSlice>::find::<&[u8; 1]> Unexecuted instantiation: <[u8] as bstr::ext_slice::ByteSlice>::find::<&[u8; 1]> Unexecuted instantiation: <[u8] as bstr::ext_slice::ByteSlice>::find::<&[u8; 16]> Unexecuted instantiation: <[u8] as bstr::ext_slice::ByteSlice>::find::<&[u8; 17]> <[u8] as bstr::ext_slice::ByteSlice>::find::<&[u8; 1]> Line | Count | Source | 711 | 2.66k | fn find<B: AsRef<[u8]>>(&self, needle: B) -> Option<usize> { | 712 | 2.66k | Finder::new(needle.as_ref()).find(self.as_bytes()) | 713 | 2.66k | } |
Unexecuted instantiation: <[u8] as bstr::ext_slice::ByteSlice>::find::<&[u8; 9]> Unexecuted instantiation: <[u8] as bstr::ext_slice::ByteSlice>::find::<&[u8; 15]> Unexecuted instantiation: <[u8] as bstr::ext_slice::ByteSlice>::find::<&str> <[u8] as bstr::ext_slice::ByteSlice>::find::<&str> Line | Count | Source | 711 | 10.4k | fn find<B: AsRef<[u8]>>(&self, needle: B) -> Option<usize> { | 712 | 10.4k | Finder::new(needle.as_ref()).find(self.as_bytes()) | 713 | 10.4k | } |
Unexecuted instantiation: <[u8] as bstr::ext_slice::ByteSlice>::find::<&[u8; 2]> Unexecuted instantiation: <[u8] as bstr::ext_slice::ByteSlice>::find::<&[u8; 4]> Unexecuted instantiation: <[u8] as bstr::ext_slice::ByteSlice>::find::<&[u8; 1]> <[u8] as bstr::ext_slice::ByteSlice>::find::<&str> Line | Count | Source | 711 | 6.25k | fn find<B: AsRef<[u8]>>(&self, needle: B) -> Option<usize> { | 712 | 6.25k | Finder::new(needle.as_ref()).find(self.as_bytes()) | 713 | 6.25k | } |
Unexecuted instantiation: <[u8] as bstr::ext_slice::ByteSlice>::find::<&[u8; 1]> <[u8] as bstr::ext_slice::ByteSlice>::find::<&str> Line | Count | Source | 711 | 4.04k | fn find<B: AsRef<[u8]>>(&self, needle: B) -> Option<usize> { | 712 | 4.04k | Finder::new(needle.as_ref()).find(self.as_bytes()) | 713 | 4.04k | } |
|
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 | 78.6k | fn rfind<B: AsRef<[u8]>>(&self, needle: B) -> Option<usize> { |
749 | 78.6k | FinderReverse::new(needle.as_ref()).rfind(self.as_bytes()) |
750 | 78.6k | } Unexecuted instantiation: <_ as bstr::ext_slice::ByteSlice>::rfind::<_> <[u8] as bstr::ext_slice::ByteSlice>::rfind::<&[u8; 1]> Line | Count | Source | 748 | 71.7k | fn rfind<B: AsRef<[u8]>>(&self, needle: B) -> Option<usize> { | 749 | 71.7k | FinderReverse::new(needle.as_ref()).rfind(self.as_bytes()) | 750 | 71.7k | } |
Unexecuted instantiation: <_ as bstr::ext_slice::ByteSlice>::rfind::<_> Unexecuted instantiation: <_ as bstr::ext_slice::ByteSlice>::rfind::<_> Unexecuted instantiation: <[u8] as bstr::ext_slice::ByteSlice>::rfind::<&[u8; 1]> Unexecuted instantiation: <[u8] as bstr::ext_slice::ByteSlice>::rfind::<&[u8; 1]> <[u8] as bstr::ext_slice::ByteSlice>::rfind::<&[u8; 1]> Line | Count | Source | 748 | 6.92k | fn rfind<B: AsRef<[u8]>>(&self, needle: B) -> Option<usize> { | 749 | 6.92k | FinderReverse::new(needle.as_ref()).rfind(self.as_bytes()) | 750 | 6.92k | } |
Unexecuted instantiation: <[u8] as bstr::ext_slice::ByteSlice>::rfind::<&[u8; 1]> |
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 | 2.53k | fn find_iter<'h, 'n, B: ?Sized + AsRef<[u8]>>( |
791 | 2.53k | &'h self, |
792 | 2.53k | needle: &'n B, |
793 | 2.53k | ) -> Find<'h, 'n> { |
794 | 2.53k | Find::new(self.as_bytes(), needle.as_ref()) |
795 | 2.53k | } Unexecuted instantiation: <[u8] as bstr::ext_slice::ByteSlice>::find_iter::<[u8]> <[u8] as bstr::ext_slice::ByteSlice>::find_iter::<[u8]> Line | Count | Source | 790 | 2.53k | fn find_iter<'h, 'n, B: ?Sized + AsRef<[u8]>>( | 791 | 2.53k | &'h self, | 792 | 2.53k | needle: &'n B, | 793 | 2.53k | ) -> Find<'h, 'n> { | 794 | 2.53k | Find::new(self.as_bytes(), needle.as_ref()) | 795 | 2.53k | } |
Unexecuted instantiation: <[u8] as bstr::ext_slice::ByteSlice>::find_iter::<[u8]> Unexecuted instantiation: <[u8] as bstr::ext_slice::ByteSlice>::find_iter::<[u8; 1]> |
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 | 0 | fn rfind_iter<'h, 'n, B: ?Sized + AsRef<[u8]>>( |
836 | 0 | &'h self, |
837 | 0 | needle: &'n B, |
838 | 0 | ) -> FindReverse<'h, 'n> { |
839 | 0 | FindReverse::new(self.as_bytes(), needle.as_ref()) |
840 | 0 | } Unexecuted instantiation: <[u8] as bstr::ext_slice::ByteSlice>::rfind_iter::<[u8]> Unexecuted instantiation: <[u8] as bstr::ext_slice::ByteSlice>::rfind_iter::<[u8]> Unexecuted instantiation: <[u8] as bstr::ext_slice::ByteSlice>::rfind_iter::<[u8]> |
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 | 664M | fn find_byte(&self, byte: u8) -> Option<usize> { |
857 | 664M | memchr(byte, self.as_bytes()) |
858 | 664M | } <[u8] as bstr::ext_slice::ByteSlice>::find_byte Line | Count | Source | 856 | 7.37M | fn find_byte(&self, byte: u8) -> Option<usize> { | 857 | 7.37M | memchr(byte, self.as_bytes()) | 858 | 7.37M | } |
<[u8] as bstr::ext_slice::ByteSlice>::find_byte Line | Count | Source | 856 | 104k | fn find_byte(&self, byte: u8) -> Option<usize> { | 857 | 104k | memchr(byte, self.as_bytes()) | 858 | 104k | } |
Unexecuted instantiation: <_ as bstr::ext_slice::ByteSlice>::find_byte <[u8] as bstr::ext_slice::ByteSlice>::find_byte Line | Count | Source | 856 | 46.2M | fn find_byte(&self, byte: u8) -> Option<usize> { | 857 | 46.2M | memchr(byte, self.as_bytes()) | 858 | 46.2M | } |
Unexecuted instantiation: <[u8] as bstr::ext_slice::ByteSlice>::find_byte <[u8] as bstr::ext_slice::ByteSlice>::find_byte Line | Count | Source | 856 | 6.57M | fn find_byte(&self, byte: u8) -> Option<usize> { | 857 | 6.57M | memchr(byte, self.as_bytes()) | 858 | 6.57M | } |
Unexecuted instantiation: <[u8] as bstr::ext_slice::ByteSlice>::find_byte <[u8] as bstr::ext_slice::ByteSlice>::find_byte Line | Count | Source | 856 | 147k | fn find_byte(&self, byte: u8) -> Option<usize> { | 857 | 147k | memchr(byte, self.as_bytes()) | 858 | 147k | } |
Unexecuted instantiation: <[u8] as bstr::ext_slice::ByteSlice>::find_byte <[u8] as bstr::ext_slice::ByteSlice>::find_byte Line | Count | Source | 856 | 1.42M | fn find_byte(&self, byte: u8) -> Option<usize> { | 857 | 1.42M | memchr(byte, self.as_bytes()) | 858 | 1.42M | } |
Unexecuted instantiation: <_ as bstr::ext_slice::ByteSlice>::find_byte <[u8] as bstr::ext_slice::ByteSlice>::find_byte Line | Count | Source | 856 | 211M | fn find_byte(&self, byte: u8) -> Option<usize> { | 857 | 211M | memchr(byte, self.as_bytes()) | 858 | 211M | } |
<[u8] as bstr::ext_slice::ByteSlice>::find_byte Line | Count | Source | 856 | 3.34k | fn find_byte(&self, byte: u8) -> Option<usize> { | 857 | 3.34k | memchr(byte, self.as_bytes()) | 858 | 3.34k | } |
Unexecuted instantiation: <[u8] as bstr::ext_slice::ByteSlice>::find_byte Unexecuted instantiation: <_ as bstr::ext_slice::ByteSlice>::find_byte <[u8] as bstr::ext_slice::ByteSlice>::find_byte Line | Count | Source | 856 | 9.83M | fn find_byte(&self, byte: u8) -> Option<usize> { | 857 | 9.83M | memchr(byte, self.as_bytes()) | 858 | 9.83M | } |
Unexecuted instantiation: <[u8] as bstr::ext_slice::ByteSlice>::find_byte Unexecuted instantiation: <[u8] as bstr::ext_slice::ByteSlice>::find_byte Unexecuted instantiation: <[u8] as bstr::ext_slice::ByteSlice>::find_byte Unexecuted instantiation: <[u8] as bstr::ext_slice::ByteSlice>::find_byte Unexecuted instantiation: <[u8] as bstr::ext_slice::ByteSlice>::find_byte Unexecuted instantiation: <[u8] as bstr::ext_slice::ByteSlice>::find_byte <[u8] as bstr::ext_slice::ByteSlice>::find_byte Line | Count | Source | 856 | 19.7k | fn find_byte(&self, byte: u8) -> Option<usize> { | 857 | 19.7k | memchr(byte, self.as_bytes()) | 858 | 19.7k | } |
Unexecuted instantiation: <[u8] as bstr::ext_slice::ByteSlice>::find_byte <[u8] as bstr::ext_slice::ByteSlice>::find_byte Line | Count | Source | 856 | 4.86k | fn find_byte(&self, byte: u8) -> Option<usize> { | 857 | 4.86k | memchr(byte, self.as_bytes()) | 858 | 4.86k | } |
Unexecuted instantiation: <[u8] as bstr::ext_slice::ByteSlice>::find_byte <[u8] as bstr::ext_slice::ByteSlice>::find_byte Line | Count | Source | 856 | 5.51k | fn find_byte(&self, byte: u8) -> Option<usize> { | 857 | 5.51k | memchr(byte, self.as_bytes()) | 858 | 5.51k | } |
<[u8] as bstr::ext_slice::ByteSlice>::find_byte Line | Count | Source | 856 | 64.9k | fn find_byte(&self, byte: u8) -> Option<usize> { | 857 | 64.9k | memchr(byte, self.as_bytes()) | 858 | 64.9k | } |
Unexecuted instantiation: <[u8] as bstr::ext_slice::ByteSlice>::find_byte <[u8] as bstr::ext_slice::ByteSlice>::find_byte Line | Count | Source | 856 | 377M | fn find_byte(&self, byte: u8) -> Option<usize> { | 857 | 377M | memchr(byte, self.as_bytes()) | 858 | 377M | } |
Unexecuted instantiation: <[u8] as bstr::ext_slice::ByteSlice>::find_byte Unexecuted instantiation: <[u8] as bstr::ext_slice::ByteSlice>::find_byte Unexecuted instantiation: <[u8] as bstr::ext_slice::ByteSlice>::find_byte Unexecuted instantiation: <[u8] as bstr::ext_slice::ByteSlice>::find_byte Unexecuted instantiation: <[u8] as bstr::ext_slice::ByteSlice>::find_byte <[u8] as bstr::ext_slice::ByteSlice>::find_byte Line | Count | Source | 856 | 33.7k | fn find_byte(&self, byte: u8) -> Option<usize> { | 857 | 33.7k | memchr(byte, self.as_bytes()) | 858 | 33.7k | } |
<[u8] as bstr::ext_slice::ByteSlice>::find_byte Line | Count | Source | 856 | 2.42k | fn find_byte(&self, byte: u8) -> Option<usize> { | 857 | 2.42k | memchr(byte, self.as_bytes()) | 858 | 2.42k | } |
Unexecuted instantiation: <[u8] as bstr::ext_slice::ByteSlice>::find_byte <[u8] as bstr::ext_slice::ByteSlice>::find_byte Line | Count | Source | 856 | 4.89k | fn find_byte(&self, byte: u8) -> Option<usize> { | 857 | 4.89k | memchr(byte, self.as_bytes()) | 858 | 4.89k | } |
Unexecuted instantiation: <[u8] as bstr::ext_slice::ByteSlice>::find_byte Unexecuted instantiation: <[u8] as bstr::ext_slice::ByteSlice>::find_byte Unexecuted instantiation: <[u8] as bstr::ext_slice::ByteSlice>::find_byte <[u8] as bstr::ext_slice::ByteSlice>::find_byte Line | Count | Source | 856 | 3.70M | fn find_byte(&self, byte: u8) -> Option<usize> { | 857 | 3.70M | memchr(byte, self.as_bytes()) | 858 | 3.70M | } |
Unexecuted instantiation: <[u8] as bstr::ext_slice::ByteSlice>::find_byte Unexecuted instantiation: <[u8] as bstr::ext_slice::ByteSlice>::find_byte |
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 | 1.56M | fn rfind_byte(&self, byte: u8) -> Option<usize> { |
875 | 1.56M | memrchr(byte, self.as_bytes()) |
876 | 1.56M | } <[u8] as bstr::ext_slice::ByteSlice>::rfind_byte Line | Count | Source | 874 | 53.3k | fn rfind_byte(&self, byte: u8) -> Option<usize> { | 875 | 53.3k | memrchr(byte, self.as_bytes()) | 876 | 53.3k | } |
Unexecuted instantiation: <_ as bstr::ext_slice::ByteSlice>::rfind_byte Unexecuted instantiation: <[u8] as bstr::ext_slice::ByteSlice>::rfind_byte Unexecuted instantiation: <[u8] as bstr::ext_slice::ByteSlice>::rfind_byte <[u8] as bstr::ext_slice::ByteSlice>::rfind_byte Line | Count | Source | 874 | 76.3k | fn rfind_byte(&self, byte: u8) -> Option<usize> { | 875 | 76.3k | memrchr(byte, self.as_bytes()) | 876 | 76.3k | } |
Unexecuted instantiation: <_ as bstr::ext_slice::ByteSlice>::rfind_byte Unexecuted instantiation: <[u8] as bstr::ext_slice::ByteSlice>::rfind_byte Unexecuted instantiation: <[u8] as bstr::ext_slice::ByteSlice>::rfind_byte Unexecuted instantiation: <[u8] as bstr::ext_slice::ByteSlice>::rfind_byte Unexecuted instantiation: <_ as bstr::ext_slice::ByteSlice>::rfind_byte Unexecuted instantiation: <[u8] as bstr::ext_slice::ByteSlice>::rfind_byte Unexecuted instantiation: <[u8] as bstr::ext_slice::ByteSlice>::rfind_byte Unexecuted instantiation: <[u8] as bstr::ext_slice::ByteSlice>::rfind_byte Unexecuted instantiation: <[u8] as bstr::ext_slice::ByteSlice>::rfind_byte Unexecuted instantiation: <[u8] as bstr::ext_slice::ByteSlice>::rfind_byte Unexecuted instantiation: <[u8] as bstr::ext_slice::ByteSlice>::rfind_byte Unexecuted instantiation: <[u8] as bstr::ext_slice::ByteSlice>::rfind_byte <[u8] as bstr::ext_slice::ByteSlice>::rfind_byte Line | Count | Source | 874 | 1.42M | fn rfind_byte(&self, byte: u8) -> Option<usize> { | 875 | 1.42M | memrchr(byte, self.as_bytes()) | 876 | 1.42M | } |
Unexecuted instantiation: <[u8] as bstr::ext_slice::ByteSlice>::rfind_byte Unexecuted instantiation: <[u8] as bstr::ext_slice::ByteSlice>::rfind_byte Unexecuted instantiation: <[u8] as bstr::ext_slice::ByteSlice>::rfind_byte Unexecuted instantiation: <[u8] as bstr::ext_slice::ByteSlice>::rfind_byte Unexecuted instantiation: <[u8] as bstr::ext_slice::ByteSlice>::rfind_byte <[u8] as bstr::ext_slice::ByteSlice>::rfind_byte Line | Count | Source | 874 | 6.94k | fn rfind_byte(&self, byte: u8) -> Option<usize> { | 875 | 6.94k | memrchr(byte, self.as_bytes()) | 876 | 6.94k | } |
Unexecuted instantiation: <[u8] as bstr::ext_slice::ByteSlice>::rfind_byte Unexecuted instantiation: <[u8] as bstr::ext_slice::ByteSlice>::rfind_byte Unexecuted instantiation: <[u8] as bstr::ext_slice::ByteSlice>::rfind_byte |
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 | 0 | fn find_char(&self, ch: char) -> Option<usize> { |
899 | 0 | self.find(ch.encode_utf8(&mut [0; 4])) |
900 | 0 | } Unexecuted instantiation: <_ as bstr::ext_slice::ByteSlice>::find_char Unexecuted instantiation: <_ as bstr::ext_slice::ByteSlice>::find_char Unexecuted instantiation: <_ as bstr::ext_slice::ByteSlice>::find_char |
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 | 0 | fn rfind_char(&self, ch: char) -> Option<usize> { |
923 | 0 | self.rfind(ch.encode_utf8(&mut [0; 4])) |
924 | 0 | } Unexecuted instantiation: <_ as bstr::ext_slice::ByteSlice>::rfind_char Unexecuted instantiation: <_ as bstr::ext_slice::ByteSlice>::rfind_char Unexecuted instantiation: <_ as bstr::ext_slice::ByteSlice>::rfind_char |
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 | 23.3M | fn find_byteset<B: AsRef<[u8]>>(&self, byteset: B) -> Option<usize> { |
963 | 23.3M | byteset::find(self.as_bytes(), byteset.as_ref()) |
964 | 23.3M | } <[u8] as bstr::ext_slice::ByteSlice>::find_byteset::<&[u8; 3]> Line | Count | Source | 962 | 9.34k | fn find_byteset<B: AsRef<[u8]>>(&self, byteset: B) -> Option<usize> { | 963 | 9.34k | byteset::find(self.as_bytes(), byteset.as_ref()) | 964 | 9.34k | } |
Unexecuted instantiation: <_ as bstr::ext_slice::ByteSlice>::find_byteset::<_> <[u8] as bstr::ext_slice::ByteSlice>::find_byteset::<&[u8; 2]> Line | Count | Source | 962 | 17.0M | fn find_byteset<B: AsRef<[u8]>>(&self, byteset: B) -> Option<usize> { | 963 | 17.0M | byteset::find(self.as_bytes(), byteset.as_ref()) | 964 | 17.0M | } |
Unexecuted instantiation: <[u8] as bstr::ext_slice::ByteSlice>::find_byteset::<&[u8]> Unexecuted instantiation: <[u8] as bstr::ext_slice::ByteSlice>::find_byteset::<&[u8]> Unexecuted instantiation: <[u8] as bstr::ext_slice::ByteSlice>::find_byteset::<&[u8; 3]> Unexecuted instantiation: <[u8] as bstr::ext_slice::ByteSlice>::find_byteset::<&[u8; 2]> Unexecuted instantiation: <_ as bstr::ext_slice::ByteSlice>::find_byteset::<_> Unexecuted instantiation: <[u8] as bstr::ext_slice::ByteSlice>::find_byteset::<&[u8]> Unexecuted instantiation: <_ as bstr::ext_slice::ByteSlice>::find_byteset::<_> <[u8] as bstr::ext_slice::ByteSlice>::find_byteset::<&[u8]> Line | Count | Source | 962 | 6.25M | fn find_byteset<B: AsRef<[u8]>>(&self, byteset: B) -> Option<usize> { | 963 | 6.25M | byteset::find(self.as_bytes(), byteset.as_ref()) | 964 | 6.25M | } |
Unexecuted instantiation: <[u8] as bstr::ext_slice::ByteSlice>::find_byteset::<&[u8; 2]> <[u8] as bstr::ext_slice::ByteSlice>::find_byteset::<&[u8; 17]> Line | Count | Source | 962 | 1.01k | fn find_byteset<B: AsRef<[u8]>>(&self, byteset: B) -> Option<usize> { | 963 | 1.01k | byteset::find(self.as_bytes(), byteset.as_ref()) | 964 | 1.01k | } |
<[u8] as bstr::ext_slice::ByteSlice>::find_byteset::<&[u8; 22]> Line | Count | Source | 962 | 3.29k | fn find_byteset<B: AsRef<[u8]>>(&self, byteset: B) -> Option<usize> { | 963 | 3.29k | byteset::find(self.as_bytes(), byteset.as_ref()) | 964 | 3.29k | } |
Unexecuted instantiation: <[u8] as bstr::ext_slice::ByteSlice>::find_byteset::<&[u8; 2]> Unexecuted instantiation: <[u8] as bstr::ext_slice::ByteSlice>::find_byteset::<&[u8]> Unexecuted instantiation: <[u8] as bstr::ext_slice::ByteSlice>::find_byteset::<&[u8]> Unexecuted instantiation: <[u8] as bstr::ext_slice::ByteSlice>::find_byteset::<&[u8; 4]> Unexecuted instantiation: <[u8] as bstr::ext_slice::ByteSlice>::find_byteset::<&[u8]> Unexecuted instantiation: <[u8] as bstr::ext_slice::ByteSlice>::find_byteset::<&[u8; 17]> Unexecuted instantiation: <[u8] as bstr::ext_slice::ByteSlice>::find_byteset::<&[u8; 22]> <[u8] as bstr::ext_slice::ByteSlice>::find_byteset::<&[u8; 2]> Line | Count | Source | 962 | 9.51k | fn find_byteset<B: AsRef<[u8]>>(&self, byteset: B) -> Option<usize> { | 963 | 9.51k | byteset::find(self.as_bytes(), byteset.as_ref()) | 964 | 9.51k | } |
Unexecuted instantiation: <[u8] as bstr::ext_slice::ByteSlice>::find_byteset::<&[u8; 2]> Unexecuted instantiation: <[u8] as bstr::ext_slice::ByteSlice>::find_byteset::<&[u8; 17]> Unexecuted instantiation: <[u8] as bstr::ext_slice::ByteSlice>::find_byteset::<&[u8; 22]> Unexecuted instantiation: <[u8] as bstr::ext_slice::ByteSlice>::find_byteset::<&[u8]> Unexecuted instantiation: <[u8] as bstr::ext_slice::ByteSlice>::find_byteset::<&[u8]> Unexecuted instantiation: <[u8] as bstr::ext_slice::ByteSlice>::find_byteset::<&[u8; 2]> Unexecuted instantiation: <[u8] as bstr::ext_slice::ByteSlice>::find_byteset::<&[u8]> <[u8] as bstr::ext_slice::ByteSlice>::find_byteset::<&[u8]> Line | Count | Source | 962 | 14.5k | fn find_byteset<B: AsRef<[u8]>>(&self, byteset: B) -> Option<usize> { | 963 | 14.5k | byteset::find(self.as_bytes(), byteset.as_ref()) | 964 | 14.5k | } |
<[u8] as bstr::ext_slice::ByteSlice>::find_byteset::<&[u8]> Line | Count | Source | 962 | 19.6k | fn find_byteset<B: AsRef<[u8]>>(&self, byteset: B) -> Option<usize> { | 963 | 19.6k | byteset::find(self.as_bytes(), byteset.as_ref()) | 964 | 19.6k | } |
Unexecuted instantiation: <[u8] as bstr::ext_slice::ByteSlice>::find_byteset::<&[u8; 2]> Unexecuted instantiation: <[u8] as bstr::ext_slice::ByteSlice>::find_byteset::<&[u8]> Unexecuted instantiation: <[u8] as bstr::ext_slice::ByteSlice>::find_byteset::<&[u8]> Unexecuted instantiation: <[u8] as bstr::ext_slice::ByteSlice>::find_byteset::<&[u8]> |
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 | 26.8k | fn find_not_byteset<B: AsRef<[u8]>>(&self, byteset: B) -> Option<usize> { |
1004 | 26.8k | byteset::find_not(self.as_bytes(), byteset.as_ref()) |
1005 | 26.8k | } Unexecuted instantiation: <_ as bstr::ext_slice::ByteSlice>::find_not_byteset::<_> Unexecuted instantiation: <_ as bstr::ext_slice::ByteSlice>::find_not_byteset::<_> Unexecuted instantiation: <_ as bstr::ext_slice::ByteSlice>::find_not_byteset::<_> Unexecuted instantiation: <[u8] as bstr::ext_slice::ByteSlice>::find_not_byteset::<&[u8]> <[u8] as bstr::ext_slice::ByteSlice>::find_not_byteset::<&[u8]> Line | Count | Source | 1003 | 26.8k | fn find_not_byteset<B: AsRef<[u8]>>(&self, byteset: B) -> Option<usize> { | 1004 | 26.8k | byteset::find_not(self.as_bytes(), byteset.as_ref()) | 1005 | 26.8k | } |
Unexecuted instantiation: <[u8] as bstr::ext_slice::ByteSlice>::find_not_byteset::<&[u8]> |
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 | 0 | fn rfind_byteset<B: AsRef<[u8]>>(&self, byteset: B) -> Option<usize> { |
1041 | 0 | byteset::rfind(self.as_bytes(), byteset.as_ref()) |
1042 | 0 | } Unexecuted instantiation: <_ as bstr::ext_slice::ByteSlice>::rfind_byteset::<_> Unexecuted instantiation: <_ as bstr::ext_slice::ByteSlice>::rfind_byteset::<_> Unexecuted instantiation: <_ as bstr::ext_slice::ByteSlice>::rfind_byteset::<_> Unexecuted instantiation: <[u8] as bstr::ext_slice::ByteSlice>::rfind_byteset::<&[u8; 2]> Unexecuted instantiation: <[u8] as bstr::ext_slice::ByteSlice>::rfind_byteset::<&[u8; 2]> Unexecuted instantiation: <[u8] as bstr::ext_slice::ByteSlice>::rfind_byteset::<&[u8; 2]> |
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 | 0 | fn rfind_not_byteset<B: AsRef<[u8]>>(&self, byteset: B) -> Option<usize> { |
1078 | 0 | byteset::rfind_not(self.as_bytes(), byteset.as_ref()) |
1079 | 0 | } Unexecuted instantiation: <_ as bstr::ext_slice::ByteSlice>::rfind_not_byteset::<_> Unexecuted instantiation: <[u8] as bstr::ext_slice::ByteSlice>::rfind_not_byteset::<&[u8; 5]> Unexecuted instantiation: <_ as bstr::ext_slice::ByteSlice>::rfind_not_byteset::<_> Unexecuted instantiation: <[u8] as bstr::ext_slice::ByteSlice>::rfind_not_byteset::<&[u8; 5]> Unexecuted instantiation: <_ as bstr::ext_slice::ByteSlice>::rfind_not_byteset::<_> Unexecuted instantiation: <[u8] as bstr::ext_slice::ByteSlice>::rfind_not_byteset::<&[u8; 5]> Unexecuted instantiation: <[u8] as bstr::ext_slice::ByteSlice>::rfind_not_byteset::<&[u8; 5]> Unexecuted instantiation: <[u8] as bstr::ext_slice::ByteSlice>::rfind_not_byteset::<&[u8; 5]> Unexecuted instantiation: <[u8] as bstr::ext_slice::ByteSlice>::rfind_not_byteset::<&[u8; 5]> |
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 | 19.1k | fn fields(&self) -> Fields<'_> { |
1108 | 19.1k | Fields::new(self.as_bytes()) |
1109 | 19.1k | } Unexecuted instantiation: <_ as bstr::ext_slice::ByteSlice>::fields Unexecuted instantiation: <_ as bstr::ext_slice::ByteSlice>::fields Unexecuted instantiation: <[u8] as bstr::ext_slice::ByteSlice>::fields <[u8] as bstr::ext_slice::ByteSlice>::fields Line | Count | Source | 1107 | 15.4k | fn fields(&self) -> Fields<'_> { | 1108 | 15.4k | Fields::new(self.as_bytes()) | 1109 | 15.4k | } |
<[u8] as bstr::ext_slice::ByteSlice>::fields Line | Count | Source | 1107 | 3.75k | fn fields(&self) -> Fields<'_> { | 1108 | 3.75k | Fields::new(self.as_bytes()) | 1109 | 3.75k | } |
|
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 | 19.1k | fn fields_with<F: FnMut(char) -> bool>(&self, f: F) -> FieldsWith<'_, F> { |
1140 | 19.1k | FieldsWith::new(self.as_bytes(), f) |
1141 | 19.1k | } <[u8] as bstr::ext_slice::ByteSlice>::fields_with::<fn(char) -> bool> Line | Count | Source | 1139 | 19.1k | fn fields_with<F: FnMut(char) -> bool>(&self, f: F) -> FieldsWith<'_, F> { | 1140 | 19.1k | FieldsWith::new(self.as_bytes(), f) | 1141 | 19.1k | } |
Unexecuted instantiation: <[u8] as bstr::ext_slice::ByteSlice>::fields_with::<fn(char) -> bool> Unexecuted instantiation: <_ as bstr::ext_slice::ByteSlice>::fields_with::<_> |
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 | 2.53k | fn split_str<'h, 's, B: ?Sized + AsRef<[u8]>>( |
1233 | 2.53k | &'h self, |
1234 | 2.53k | splitter: &'s B, |
1235 | 2.53k | ) -> Split<'h, 's> { |
1236 | 2.53k | Split::new(self.as_bytes(), splitter.as_ref()) |
1237 | 2.53k | } Unexecuted instantiation: <[u8] as bstr::ext_slice::ByteSlice>::split_str::<[u8]> <[u8] as bstr::ext_slice::ByteSlice>::split_str::<[u8; 1]> Line | Count | Source | 1232 | 1.53k | fn split_str<'h, 's, B: ?Sized + AsRef<[u8]>>( | 1233 | 1.53k | &'h self, | 1234 | 1.53k | splitter: &'s B, | 1235 | 1.53k | ) -> Split<'h, 's> { | 1236 | 1.53k | Split::new(self.as_bytes(), splitter.as_ref()) | 1237 | 1.53k | } |
Unexecuted instantiation: <[u8] as bstr::ext_slice::ByteSlice>::split_str::<[u8]> Unexecuted instantiation: <[u8] as bstr::ext_slice::ByteSlice>::split_str::<[u8]> <[u8] as bstr::ext_slice::ByteSlice>::split_str::<[u8; 1]> Line | Count | Source | 1232 | 1.00k | fn split_str<'h, 's, B: ?Sized + AsRef<[u8]>>( | 1233 | 1.00k | &'h self, | 1234 | 1.00k | splitter: &'s B, | 1235 | 1.00k | ) -> Split<'h, 's> { | 1236 | 1.00k | Split::new(self.as_bytes(), splitter.as_ref()) | 1237 | 1.00k | } |
|
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 | 0 | fn rsplit_str<'h, 's, B: ?Sized + AsRef<[u8]>>( |
1327 | 0 | &'h self, |
1328 | 0 | splitter: &'s B, |
1329 | 0 | ) -> SplitReverse<'h, 's> { |
1330 | 0 | SplitReverse::new(self.as_bytes(), splitter.as_ref()) |
1331 | 0 | } Unexecuted instantiation: <[u8] as bstr::ext_slice::ByteSlice>::rsplit_str::<[u8]> Unexecuted instantiation: <[u8] as bstr::ext_slice::ByteSlice>::rsplit_str::<[u8]> Unexecuted instantiation: <[u8] as bstr::ext_slice::ByteSlice>::rsplit_str::<[u8]> |
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 | 0 | fn split_once_str<'a, B: ?Sized + AsRef<[u8]>>( |
1367 | 0 | &'a self, |
1368 | 0 | splitter: &B, |
1369 | 0 | ) -> Option<(&'a [u8], &'a [u8])> { |
1370 | 0 | let bytes = self.as_bytes(); |
1371 | 0 | let splitter = splitter.as_ref(); |
1372 | 0 | let start = Finder::new(splitter).find(bytes)?; |
1373 | 0 | let end = start + splitter.len(); |
1374 | 0 | Some((&bytes[..start], &bytes[end..])) |
1375 | 0 | } Unexecuted instantiation: <_ as bstr::ext_slice::ByteSlice>::split_once_str::<_> Unexecuted instantiation: <_ as bstr::ext_slice::ByteSlice>::split_once_str::<_> Unexecuted instantiation: <_ as bstr::ext_slice::ByteSlice>::split_once_str::<_> |
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 | 0 | fn rsplit_once_str<'a, B: ?Sized + AsRef<[u8]>>( |
1411 | 0 | &'a self, |
1412 | 0 | splitter: &B, |
1413 | 0 | ) -> Option<(&'a [u8], &'a [u8])> { |
1414 | 0 | let bytes = self.as_bytes(); |
1415 | 0 | let splitter = splitter.as_ref(); |
1416 | 0 | let start = FinderReverse::new(splitter).rfind(bytes)?; |
1417 | 0 | let end = start + splitter.len(); |
1418 | 0 | Some((&bytes[..start], &bytes[end..])) |
1419 | 0 | } Unexecuted instantiation: <_ as bstr::ext_slice::ByteSlice>::rsplit_once_str::<_> Unexecuted instantiation: <_ as bstr::ext_slice::ByteSlice>::rsplit_once_str::<_> Unexecuted instantiation: <_ as bstr::ext_slice::ByteSlice>::rsplit_once_str::<_> |
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 | 0 | fn splitn_str<'h, 's, B: ?Sized + AsRef<[u8]>>( |
1458 | 0 | &'h self, |
1459 | 0 | limit: usize, |
1460 | 0 | splitter: &'s B, |
1461 | 0 | ) -> SplitN<'h, 's> { |
1462 | 0 | SplitN::new(self.as_bytes(), splitter.as_ref(), limit) |
1463 | 0 | } Unexecuted instantiation: <_ as bstr::ext_slice::ByteSlice>::splitn_str::<_> Unexecuted instantiation: <_ as bstr::ext_slice::ByteSlice>::splitn_str::<_> Unexecuted instantiation: <_ as bstr::ext_slice::ByteSlice>::splitn_str::<_> |
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 | 0 | fn rsplitn_str<'h, 's, B: ?Sized + AsRef<[u8]>>( |
1504 | 0 | &'h self, |
1505 | 0 | limit: usize, |
1506 | 0 | splitter: &'s B, |
1507 | 0 | ) -> SplitNReverse<'h, 's> { |
1508 | 0 | SplitNReverse::new(self.as_bytes(), splitter.as_ref(), limit) |
1509 | 0 | } Unexecuted instantiation: <_ as bstr::ext_slice::ByteSlice>::rsplitn_str::<_> Unexecuted instantiation: <_ as bstr::ext_slice::ByteSlice>::rsplitn_str::<_> Unexecuted instantiation: <_ as bstr::ext_slice::ByteSlice>::rsplitn_str::<_> |
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 | 0 | fn replace<N: AsRef<[u8]>, R: AsRef<[u8]>>( |
1549 | 0 | &self, |
1550 | 0 | needle: N, |
1551 | 0 | replacement: R, |
1552 | 0 | ) -> Vec<u8> { |
1553 | 0 | let mut dest = Vec::with_capacity(self.as_bytes().len()); |
1554 | 0 | self.replace_into(needle, replacement, &mut dest); |
1555 | 0 | dest |
1556 | 0 | } Unexecuted instantiation: <_ as bstr::ext_slice::ByteSlice>::replace::<_, _> Unexecuted instantiation: <_ as bstr::ext_slice::ByteSlice>::replace::<_, _> Unexecuted instantiation: <_ as bstr::ext_slice::ByteSlice>::replace::<_, _> |
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 | 0 | fn replacen<N: AsRef<[u8]>, R: AsRef<[u8]>>( |
1596 | 0 | &self, |
1597 | 0 | needle: N, |
1598 | 0 | replacement: R, |
1599 | 0 | limit: usize, |
1600 | 0 | ) -> Vec<u8> { |
1601 | 0 | let mut dest = Vec::with_capacity(self.as_bytes().len()); |
1602 | 0 | self.replacen_into(needle, replacement, limit, &mut dest); |
1603 | 0 | dest |
1604 | 0 | } Unexecuted instantiation: <_ as bstr::ext_slice::ByteSlice>::replacen::<_, _> Unexecuted instantiation: <_ as bstr::ext_slice::ByteSlice>::replacen::<_, _> Unexecuted instantiation: <_ as bstr::ext_slice::ByteSlice>::replacen::<_, _> |
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 | 0 | fn replace_into<N: AsRef<[u8]>, R: AsRef<[u8]>>( |
1654 | 0 | &self, |
1655 | 0 | needle: N, |
1656 | 0 | replacement: R, |
1657 | 0 | dest: &mut Vec<u8>, |
1658 | 0 | ) { |
1659 | 0 | let (needle, replacement) = (needle.as_ref(), replacement.as_ref()); |
1660 | | |
1661 | 0 | let mut last = 0; |
1662 | 0 | for start in self.find_iter(needle) { |
1663 | 0 | dest.push_str(&self.as_bytes()[last..start]); |
1664 | 0 | dest.push_str(replacement); |
1665 | 0 | last = start + needle.len(); |
1666 | 0 | } |
1667 | 0 | dest.push_str(&self.as_bytes()[last..]); |
1668 | 0 | } Unexecuted instantiation: <_ as bstr::ext_slice::ByteSlice>::replace_into::<_, _> Unexecuted instantiation: <_ as bstr::ext_slice::ByteSlice>::replace_into::<_, _> Unexecuted instantiation: <_ as bstr::ext_slice::ByteSlice>::replace_into::<_, _> |
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 | 0 | fn replacen_into<N: AsRef<[u8]>, R: AsRef<[u8]>>( |
1718 | 0 | &self, |
1719 | 0 | needle: N, |
1720 | 0 | replacement: R, |
1721 | 0 | limit: usize, |
1722 | 0 | dest: &mut Vec<u8>, |
1723 | 0 | ) { |
1724 | 0 | let (needle, replacement) = (needle.as_ref(), replacement.as_ref()); |
1725 | | |
1726 | 0 | let mut last = 0; |
1727 | 0 | for start in self.find_iter(needle).take(limit) { |
1728 | 0 | dest.push_str(&self.as_bytes()[last..start]); |
1729 | 0 | dest.push_str(replacement); |
1730 | 0 | last = start + needle.len(); |
1731 | 0 | } |
1732 | 0 | dest.push_str(&self.as_bytes()[last..]); |
1733 | 0 | } Unexecuted instantiation: <_ as bstr::ext_slice::ByteSlice>::replacen_into::<_, _> Unexecuted instantiation: <_ as bstr::ext_slice::ByteSlice>::replacen_into::<_, _> Unexecuted instantiation: <_ as bstr::ext_slice::ByteSlice>::replacen_into::<_, _> |
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 | 4.77M | fn bytes(&self) -> Bytes<'_> { |
1750 | 4.77M | Bytes { it: self.as_bytes().iter() } |
1751 | 4.77M | } Unexecuted instantiation: <_ as bstr::ext_slice::ByteSlice>::bytes <[u8] as bstr::ext_slice::ByteSlice>::bytes Line | Count | Source | 1749 | 3.95k | fn bytes(&self) -> Bytes<'_> { | 1750 | 3.95k | Bytes { it: self.as_bytes().iter() } | 1751 | 3.95k | } |
Unexecuted instantiation: <[u8] as bstr::ext_slice::ByteSlice>::bytes Unexecuted instantiation: <_ as bstr::ext_slice::ByteSlice>::bytes Unexecuted instantiation: <_ as bstr::ext_slice::ByteSlice>::bytes Unexecuted instantiation: <[u8] as bstr::ext_slice::ByteSlice>::bytes Unexecuted instantiation: <[u8] as bstr::ext_slice::ByteSlice>::bytes <[u8] as bstr::ext_slice::ByteSlice>::bytes Line | Count | Source | 1749 | 29.7k | fn bytes(&self) -> Bytes<'_> { | 1750 | 29.7k | Bytes { it: self.as_bytes().iter() } | 1751 | 29.7k | } |
Unexecuted instantiation: <[u8] as bstr::ext_slice::ByteSlice>::bytes <[u8] as bstr::ext_slice::ByteSlice>::bytes Line | Count | Source | 1749 | 4.73M | fn bytes(&self) -> Bytes<'_> { | 1750 | 4.73M | Bytes { it: self.as_bytes().iter() } | 1751 | 4.73M | } |
|
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 | 0 | fn chars(&self) -> Chars<'_> { |
1780 | 0 | Chars::new(self.as_bytes()) |
1781 | 0 | } Unexecuted instantiation: <_ as bstr::ext_slice::ByteSlice>::chars Unexecuted instantiation: <[u8] as bstr::ext_slice::ByteSlice>::chars Unexecuted instantiation: <[u8] as bstr::ext_slice::ByteSlice>::chars Unexecuted instantiation: <[u8] as bstr::ext_slice::ByteSlice>::chars Unexecuted instantiation: <[u8] as bstr::ext_slice::ByteSlice>::chars Unexecuted instantiation: <[u8] as bstr::ext_slice::ByteSlice>::chars Unexecuted instantiation: <[u8] as bstr::ext_slice::ByteSlice>::chars Unexecuted instantiation: <[u8] as bstr::ext_slice::ByteSlice>::chars Unexecuted instantiation: <_ as bstr::ext_slice::ByteSlice>::chars Unexecuted instantiation: <[u8] as bstr::ext_slice::ByteSlice>::chars Unexecuted instantiation: <[u8] as bstr::ext_slice::ByteSlice>::chars Unexecuted instantiation: <[u8] as bstr::ext_slice::ByteSlice>::chars Unexecuted instantiation: <[u8] as bstr::ext_slice::ByteSlice>::chars Unexecuted instantiation: <[u8] as bstr::ext_slice::ByteSlice>::chars Unexecuted instantiation: <[u8] as bstr::ext_slice::ByteSlice>::chars Unexecuted instantiation: <_ as bstr::ext_slice::ByteSlice>::chars Unexecuted instantiation: <[u8] as bstr::ext_slice::ByteSlice>::chars Unexecuted instantiation: <[u8] as bstr::ext_slice::ByteSlice>::chars Unexecuted instantiation: <[u8] as bstr::ext_slice::ByteSlice>::chars Unexecuted instantiation: <[u8] as bstr::ext_slice::ByteSlice>::chars Unexecuted instantiation: <[u8] as bstr::ext_slice::ByteSlice>::chars Unexecuted instantiation: <[u8] as bstr::ext_slice::ByteSlice>::chars Unexecuted instantiation: <[u8] as bstr::ext_slice::ByteSlice>::chars Unexecuted instantiation: <[u8] as bstr::ext_slice::ByteSlice>::chars Unexecuted instantiation: <[u8] as bstr::ext_slice::ByteSlice>::chars Unexecuted instantiation: <[u8] as bstr::ext_slice::ByteSlice>::chars Unexecuted instantiation: <[u8] as bstr::ext_slice::ByteSlice>::chars Unexecuted instantiation: <[u8] as bstr::ext_slice::ByteSlice>::chars Unexecuted instantiation: <[u8] as bstr::ext_slice::ByteSlice>::chars Unexecuted instantiation: <[u8] as bstr::ext_slice::ByteSlice>::chars Unexecuted instantiation: <[u8] as bstr::ext_slice::ByteSlice>::chars Unexecuted instantiation: <[u8] as bstr::ext_slice::ByteSlice>::chars Unexecuted instantiation: <[u8] as bstr::ext_slice::ByteSlice>::chars Unexecuted instantiation: <[u8] as bstr::ext_slice::ByteSlice>::chars Unexecuted instantiation: <[u8] as bstr::ext_slice::ByteSlice>::chars Unexecuted instantiation: <[u8] as bstr::ext_slice::ByteSlice>::chars Unexecuted instantiation: <[u8] as bstr::ext_slice::ByteSlice>::chars Unexecuted instantiation: <[u8] as bstr::ext_slice::ByteSlice>::chars Unexecuted instantiation: <[u8] as bstr::ext_slice::ByteSlice>::chars Unexecuted instantiation: <[u8] as bstr::ext_slice::ByteSlice>::chars Unexecuted instantiation: <[u8] as bstr::ext_slice::ByteSlice>::chars Unexecuted instantiation: <[u8] as bstr::ext_slice::ByteSlice>::chars Unexecuted instantiation: <[u8] as bstr::ext_slice::ByteSlice>::chars Unexecuted instantiation: <[u8] as bstr::ext_slice::ByteSlice>::chars Unexecuted instantiation: <[u8] as bstr::ext_slice::ByteSlice>::chars Unexecuted instantiation: <[u8] as bstr::ext_slice::ByteSlice>::chars Unexecuted instantiation: <[u8] as bstr::ext_slice::ByteSlice>::chars Unexecuted instantiation: <[u8] as bstr::ext_slice::ByteSlice>::chars Unexecuted instantiation: <[u8] as bstr::ext_slice::ByteSlice>::chars Unexecuted instantiation: <[u8] as bstr::ext_slice::ByteSlice>::chars Unexecuted instantiation: <[u8] as bstr::ext_slice::ByteSlice>::chars Unexecuted instantiation: <[u8] as bstr::ext_slice::ByteSlice>::chars Unexecuted instantiation: <[u8] as bstr::ext_slice::ByteSlice>::chars Unexecuted instantiation: <[u8] as bstr::ext_slice::ByteSlice>::chars |
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 | 31.3k | fn char_indices(&self) -> CharIndices<'_> { |
1835 | 31.3k | CharIndices::new(self.as_bytes()) |
1836 | 31.3k | } Unexecuted instantiation: <[u8] as bstr::ext_slice::ByteSlice>::char_indices Unexecuted instantiation: <[u8] as bstr::ext_slice::ByteSlice>::char_indices Unexecuted instantiation: <[u8] as bstr::ext_slice::ByteSlice>::char_indices Unexecuted instantiation: <[u8] as bstr::ext_slice::ByteSlice>::char_indices Unexecuted instantiation: <[u8] as bstr::ext_slice::ByteSlice>::char_indices Unexecuted instantiation: <[u8] as bstr::ext_slice::ByteSlice>::char_indices <[u8] as bstr::ext_slice::ByteSlice>::char_indices Line | Count | Source | 1834 | 19.1k | fn char_indices(&self) -> CharIndices<'_> { | 1835 | 19.1k | CharIndices::new(self.as_bytes()) | 1836 | 19.1k | } |
Unexecuted instantiation: <[u8] as bstr::ext_slice::ByteSlice>::char_indices Unexecuted instantiation: <[u8] as bstr::ext_slice::ByteSlice>::char_indices Unexecuted instantiation: <[u8] as bstr::ext_slice::ByteSlice>::char_indices Unexecuted instantiation: <[u8] as bstr::ext_slice::ByteSlice>::char_indices Unexecuted instantiation: <[u8] as bstr::ext_slice::ByteSlice>::char_indices Unexecuted instantiation: <[u8] as bstr::ext_slice::ByteSlice>::char_indices Unexecuted instantiation: <[u8] as bstr::ext_slice::ByteSlice>::char_indices Unexecuted instantiation: <[u8] as bstr::ext_slice::ByteSlice>::char_indices Unexecuted instantiation: <[u8] as bstr::ext_slice::ByteSlice>::char_indices Unexecuted instantiation: <[u8] as bstr::ext_slice::ByteSlice>::char_indices Unexecuted instantiation: <[u8] as bstr::ext_slice::ByteSlice>::char_indices Unexecuted instantiation: <[u8] as bstr::ext_slice::ByteSlice>::char_indices Unexecuted instantiation: <[u8] as bstr::ext_slice::ByteSlice>::char_indices Unexecuted instantiation: <[u8] as bstr::ext_slice::ByteSlice>::char_indices Unexecuted instantiation: <_ as bstr::ext_slice::ByteSlice>::char_indices Unexecuted instantiation: <[u8] as bstr::ext_slice::ByteSlice>::char_indices Unexecuted instantiation: <[u8] as bstr::ext_slice::ByteSlice>::char_indices Unexecuted instantiation: <[u8] as bstr::ext_slice::ByteSlice>::char_indices Unexecuted instantiation: <[u8] as bstr::ext_slice::ByteSlice>::char_indices Unexecuted instantiation: <[u8] as bstr::ext_slice::ByteSlice>::char_indices Unexecuted instantiation: <[u8] as bstr::ext_slice::ByteSlice>::char_indices Unexecuted instantiation: <[u8] as bstr::ext_slice::ByteSlice>::char_indices Unexecuted instantiation: <[u8] as bstr::ext_slice::ByteSlice>::char_indices Unexecuted instantiation: <[u8] as bstr::ext_slice::ByteSlice>::char_indices Unexecuted instantiation: <[u8] as bstr::ext_slice::ByteSlice>::char_indices Unexecuted instantiation: <[u8] as bstr::ext_slice::ByteSlice>::char_indices Unexecuted instantiation: <[u8] as bstr::ext_slice::ByteSlice>::char_indices Unexecuted instantiation: <[u8] as bstr::ext_slice::ByteSlice>::char_indices Unexecuted instantiation: <[u8] as bstr::ext_slice::ByteSlice>::char_indices Unexecuted instantiation: <[u8] as bstr::ext_slice::ByteSlice>::char_indices Unexecuted instantiation: <[u8] as bstr::ext_slice::ByteSlice>::char_indices <[u8] as bstr::ext_slice::ByteSlice>::char_indices Line | Count | Source | 1834 | 242 | fn char_indices(&self) -> CharIndices<'_> { | 1835 | 242 | CharIndices::new(self.as_bytes()) | 1836 | 242 | } |
Unexecuted instantiation: <[u8] as bstr::ext_slice::ByteSlice>::char_indices <[u8] as bstr::ext_slice::ByteSlice>::char_indices Line | Count | Source | 1834 | 11.8k | fn char_indices(&self) -> CharIndices<'_> { | 1835 | 11.8k | CharIndices::new(self.as_bytes()) | 1836 | 11.8k | } |
Unexecuted instantiation: <[u8] as bstr::ext_slice::ByteSlice>::char_indices Unexecuted instantiation: <[u8] as bstr::ext_slice::ByteSlice>::char_indices Unexecuted instantiation: <[u8] as bstr::ext_slice::ByteSlice>::char_indices Unexecuted instantiation: <[u8] as bstr::ext_slice::ByteSlice>::char_indices Unexecuted instantiation: <[u8] as bstr::ext_slice::ByteSlice>::char_indices Unexecuted instantiation: <[u8] as bstr::ext_slice::ByteSlice>::char_indices Unexecuted instantiation: <[u8] as bstr::ext_slice::ByteSlice>::char_indices Unexecuted instantiation: <[u8] as bstr::ext_slice::ByteSlice>::char_indices Unexecuted instantiation: <[u8] as bstr::ext_slice::ByteSlice>::char_indices Unexecuted instantiation: <[u8] as bstr::ext_slice::ByteSlice>::char_indices Unexecuted instantiation: <[u8] as bstr::ext_slice::ByteSlice>::char_indices Unexecuted instantiation: <[u8] as bstr::ext_slice::ByteSlice>::char_indices Unexecuted instantiation: <[u8] as bstr::ext_slice::ByteSlice>::char_indices Unexecuted instantiation: <[u8] as bstr::ext_slice::ByteSlice>::char_indices Unexecuted instantiation: <[u8] as bstr::ext_slice::ByteSlice>::char_indices Unexecuted instantiation: <[u8] as bstr::ext_slice::ByteSlice>::char_indices Unexecuted instantiation: <[u8] as bstr::ext_slice::ByteSlice>::char_indices Unexecuted instantiation: <[u8] as bstr::ext_slice::ByteSlice>::char_indices Unexecuted instantiation: <[u8] as bstr::ext_slice::ByteSlice>::char_indices Unexecuted instantiation: <[u8] as bstr::ext_slice::ByteSlice>::char_indices |
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 | 0 | fn utf8_chunks(&self) -> Utf8Chunks<'_> { |
1872 | 0 | Utf8Chunks { bytes: self.as_bytes() } |
1873 | 0 | } Unexecuted instantiation: <_ as bstr::ext_slice::ByteSlice>::utf8_chunks Unexecuted instantiation: <_ as bstr::ext_slice::ByteSlice>::utf8_chunks Unexecuted instantiation: <_ as bstr::ext_slice::ByteSlice>::utf8_chunks |
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 | 0 | fn graphemes(&self) -> Graphemes<'_> { |
1904 | 0 | Graphemes::new(self.as_bytes()) |
1905 | 0 | } Unexecuted instantiation: <_ as bstr::ext_slice::ByteSlice>::graphemes Unexecuted instantiation: <_ as bstr::ext_slice::ByteSlice>::graphemes |
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 | 0 | fn grapheme_indices(&self) -> GraphemeIndices<'_> { |
1950 | 0 | GraphemeIndices::new(self.as_bytes()) |
1951 | 0 | } Unexecuted instantiation: <_ as bstr::ext_slice::ByteSlice>::grapheme_indices Unexecuted instantiation: <_ as bstr::ext_slice::ByteSlice>::grapheme_indices |
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 | 0 | fn words(&self) -> Words<'_> { |
1986 | 0 | Words::new(self.as_bytes()) |
1987 | 0 | } Unexecuted instantiation: <_ as bstr::ext_slice::ByteSlice>::words Unexecuted instantiation: <_ as bstr::ext_slice::ByteSlice>::words |
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 | 0 | fn word_indices(&self) -> WordIndices<'_> { |
2024 | 0 | WordIndices::new(self.as_bytes()) |
2025 | 0 | } Unexecuted instantiation: <_ as bstr::ext_slice::ByteSlice>::word_indices Unexecuted instantiation: <_ as bstr::ext_slice::ByteSlice>::word_indices |
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 | 0 | fn words_with_breaks(&self) -> WordsWithBreaks<'_> { |
2054 | 0 | WordsWithBreaks::new(self.as_bytes()) |
2055 | 0 | } Unexecuted instantiation: <_ as bstr::ext_slice::ByteSlice>::words_with_breaks Unexecuted instantiation: <_ as bstr::ext_slice::ByteSlice>::words_with_breaks |
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 | 0 | fn words_with_break_indices(&self) -> WordsWithBreakIndices<'_> { |
2091 | 0 | WordsWithBreakIndices::new(self.as_bytes()) |
2092 | 0 | } Unexecuted instantiation: <_ as bstr::ext_slice::ByteSlice>::words_with_break_indices Unexecuted instantiation: <_ as bstr::ext_slice::ByteSlice>::words_with_break_indices |
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 | 0 | fn sentences(&self) -> Sentences<'_> { |
2123 | 0 | Sentences::new(self.as_bytes()) |
2124 | 0 | } Unexecuted instantiation: <_ as bstr::ext_slice::ByteSlice>::sentences Unexecuted instantiation: <_ as bstr::ext_slice::ByteSlice>::sentences |
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 | 0 | fn sentence_indices(&self) -> SentenceIndices<'_> { |
2157 | 0 | SentenceIndices::new(self.as_bytes()) |
2158 | 0 | } Unexecuted instantiation: <_ as bstr::ext_slice::ByteSlice>::sentence_indices Unexecuted instantiation: <_ as bstr::ext_slice::ByteSlice>::sentence_indices |
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 | 34.5k | fn lines(&self) -> Lines<'_> { |
2188 | 34.5k | Lines::new(self.as_bytes()) |
2189 | 34.5k | } <[u8] as bstr::ext_slice::ByteSlice>::lines Line | Count | Source | 2187 | 4.04k | fn lines(&self) -> Lines<'_> { | 2188 | 4.04k | Lines::new(self.as_bytes()) | 2189 | 4.04k | } |
<[u8] as bstr::ext_slice::ByteSlice>::lines Line | Count | Source | 2187 | 4.04k | fn lines(&self) -> Lines<'_> { | 2188 | 4.04k | Lines::new(self.as_bytes()) | 2189 | 4.04k | } |
Unexecuted instantiation: <_ as bstr::ext_slice::ByteSlice>::lines <[u8] as bstr::ext_slice::ByteSlice>::lines Line | Count | Source | 2187 | 131 | fn lines(&self) -> Lines<'_> { | 2188 | 131 | Lines::new(self.as_bytes()) | 2189 | 131 | } |
Unexecuted instantiation: <[u8] as bstr::ext_slice::ByteSlice>::lines Unexecuted instantiation: <_ as bstr::ext_slice::ByteSlice>::lines Unexecuted instantiation: <[u8] as bstr::ext_slice::ByteSlice>::lines Unexecuted instantiation: <_ as bstr::ext_slice::ByteSlice>::lines Unexecuted instantiation: <[u8] as bstr::ext_slice::ByteSlice>::lines Unexecuted instantiation: <[u8] as bstr::ext_slice::ByteSlice>::lines Unexecuted instantiation: <[u8] as bstr::ext_slice::ByteSlice>::lines Unexecuted instantiation: <[u8] as bstr::ext_slice::ByteSlice>::lines <[u8] as bstr::ext_slice::ByteSlice>::lines Line | Count | Source | 2187 | 2.71k | fn lines(&self) -> Lines<'_> { | 2188 | 2.71k | Lines::new(self.as_bytes()) | 2189 | 2.71k | } |
Unexecuted instantiation: <[u8] as bstr::ext_slice::ByteSlice>::lines <[u8] as bstr::ext_slice::ByteSlice>::lines Line | Count | Source | 2187 | 2.03k | fn lines(&self) -> Lines<'_> { | 2188 | 2.03k | Lines::new(self.as_bytes()) | 2189 | 2.03k | } |
<[u8] as bstr::ext_slice::ByteSlice>::lines Line | Count | Source | 2187 | 14.7k | fn lines(&self) -> Lines<'_> { | 2188 | 14.7k | Lines::new(self.as_bytes()) | 2189 | 14.7k | } |
Unexecuted instantiation: <[u8] as bstr::ext_slice::ByteSlice>::lines Unexecuted instantiation: <[u8] as bstr::ext_slice::ByteSlice>::lines Unexecuted instantiation: <[u8] as bstr::ext_slice::ByteSlice>::lines <[u8] as bstr::ext_slice::ByteSlice>::lines Line | Count | Source | 2187 | 6.92k | fn lines(&self) -> Lines<'_> { | 2188 | 6.92k | Lines::new(self.as_bytes()) | 2189 | 6.92k | } |
Unexecuted instantiation: <[u8] as bstr::ext_slice::ByteSlice>::lines Unexecuted instantiation: <[u8] as bstr::ext_slice::ByteSlice>::lines |
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 | 70.5k | fn lines_with_terminator(&self) -> LinesWithTerminator<'_> { |
2232 | 70.5k | LinesWithTerminator::new(self.as_bytes()) |
2233 | 70.5k | } Unexecuted instantiation: <_ as bstr::ext_slice::ByteSlice>::lines_with_terminator Unexecuted instantiation: <[u8] as bstr::ext_slice::ByteSlice>::lines_with_terminator Unexecuted instantiation: <_ as bstr::ext_slice::ByteSlice>::lines_with_terminator Unexecuted instantiation: <[u8] as bstr::ext_slice::ByteSlice>::lines_with_terminator Unexecuted instantiation: <_ as bstr::ext_slice::ByteSlice>::lines_with_terminator <[u8] as bstr::ext_slice::ByteSlice>::lines_with_terminator Line | Count | Source | 2231 | 70.5k | fn lines_with_terminator(&self) -> LinesWithTerminator<'_> { | 2232 | 70.5k | LinesWithTerminator::new(self.as_bytes()) | 2233 | 70.5k | } |
Unexecuted instantiation: <[u8] as bstr::ext_slice::ByteSlice>::lines_with_terminator Unexecuted instantiation: <[u8] as bstr::ext_slice::ByteSlice>::lines_with_terminator Unexecuted instantiation: <[u8] as bstr::ext_slice::ByteSlice>::lines_with_terminator |
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 | 2.99M | fn trim(&self) -> &[u8] { |
2254 | 2.99M | self.trim_start().trim_end() |
2255 | 2.99M | } <[u8] as bstr::ext_slice::ByteSlice>::trim Line | Count | Source | 2253 | 2.98M | fn trim(&self) -> &[u8] { | 2254 | 2.98M | self.trim_start().trim_end() | 2255 | 2.98M | } |
<[u8] as bstr::ext_slice::ByteSlice>::trim Line | Count | Source | 2253 | 8.67k | fn trim(&self) -> &[u8] { | 2254 | 8.67k | self.trim_start().trim_end() | 2255 | 8.67k | } |
Unexecuted instantiation: <_ as bstr::ext_slice::ByteSlice>::trim Unexecuted instantiation: <[u8] as bstr::ext_slice::ByteSlice>::trim Unexecuted instantiation: <[u8] as bstr::ext_slice::ByteSlice>::trim Unexecuted instantiation: <_ as bstr::ext_slice::ByteSlice>::trim Unexecuted instantiation: <[u8] as bstr::ext_slice::ByteSlice>::trim Unexecuted instantiation: <[u8] as bstr::ext_slice::ByteSlice>::trim Unexecuted instantiation: <[u8] as bstr::ext_slice::ByteSlice>::trim Unexecuted instantiation: <[u8] as bstr::ext_slice::ByteSlice>::trim <[u8] as bstr::ext_slice::ByteSlice>::trim Line | Count | Source | 2253 | 2.71k | fn trim(&self) -> &[u8] { | 2254 | 2.71k | self.trim_start().trim_end() | 2255 | 2.71k | } |
Unexecuted instantiation: <[u8] as bstr::ext_slice::ByteSlice>::trim Unexecuted instantiation: <[u8] as bstr::ext_slice::ByteSlice>::trim Unexecuted instantiation: <[u8] as bstr::ext_slice::ByteSlice>::trim Unexecuted instantiation: <[u8] as bstr::ext_slice::ByteSlice>::trim Unexecuted instantiation: <[u8] as bstr::ext_slice::ByteSlice>::trim |
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 | 2.99M | fn trim_start(&self) -> &[u8] { |
2275 | 2.99M | let start = whitespace_len_fwd(self.as_bytes()); |
2276 | 2.99M | &self.as_bytes()[start..] |
2277 | 2.99M | } <[u8] as bstr::ext_slice::ByteSlice>::trim_start Line | Count | Source | 2274 | 2.98M | fn trim_start(&self) -> &[u8] { | 2275 | 2.98M | let start = whitespace_len_fwd(self.as_bytes()); | 2276 | 2.98M | &self.as_bytes()[start..] | 2277 | 2.98M | } |
<[u8] as bstr::ext_slice::ByteSlice>::trim_start Line | Count | Source | 2274 | 8.67k | fn trim_start(&self) -> &[u8] { | 2275 | 8.67k | let start = whitespace_len_fwd(self.as_bytes()); | 2276 | 8.67k | &self.as_bytes()[start..] | 2277 | 8.67k | } |
Unexecuted instantiation: <_ as bstr::ext_slice::ByteSlice>::trim_start Unexecuted instantiation: <[u8] as bstr::ext_slice::ByteSlice>::trim_start Unexecuted instantiation: <[u8] as bstr::ext_slice::ByteSlice>::trim_start Unexecuted instantiation: <_ as bstr::ext_slice::ByteSlice>::trim_start Unexecuted instantiation: <[u8] as bstr::ext_slice::ByteSlice>::trim_start Unexecuted instantiation: <[u8] as bstr::ext_slice::ByteSlice>::trim_start Unexecuted instantiation: <[u8] as bstr::ext_slice::ByteSlice>::trim_start Unexecuted instantiation: <[u8] as bstr::ext_slice::ByteSlice>::trim_start <[u8] as bstr::ext_slice::ByteSlice>::trim_start Line | Count | Source | 2274 | 2.71k | fn trim_start(&self) -> &[u8] { | 2275 | 2.71k | let start = whitespace_len_fwd(self.as_bytes()); | 2276 | 2.71k | &self.as_bytes()[start..] | 2277 | 2.71k | } |
Unexecuted instantiation: <[u8] as bstr::ext_slice::ByteSlice>::trim_start Unexecuted instantiation: <[u8] as bstr::ext_slice::ByteSlice>::trim_start Unexecuted instantiation: <[u8] as bstr::ext_slice::ByteSlice>::trim_start Unexecuted instantiation: <[u8] as bstr::ext_slice::ByteSlice>::trim_start Unexecuted instantiation: <[u8] as bstr::ext_slice::ByteSlice>::trim_start |
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 | 2.99M | fn trim_end(&self) -> &[u8] { |
2297 | 2.99M | let end = whitespace_len_rev(self.as_bytes()); |
2298 | 2.99M | &self.as_bytes()[..end] |
2299 | 2.99M | } <[u8] as bstr::ext_slice::ByteSlice>::trim_end Line | Count | Source | 2296 | 2.98M | fn trim_end(&self) -> &[u8] { | 2297 | 2.98M | let end = whitespace_len_rev(self.as_bytes()); | 2298 | 2.98M | &self.as_bytes()[..end] | 2299 | 2.98M | } |
<[u8] as bstr::ext_slice::ByteSlice>::trim_end Line | Count | Source | 2296 | 8.67k | fn trim_end(&self) -> &[u8] { | 2297 | 8.67k | let end = whitespace_len_rev(self.as_bytes()); | 2298 | 8.67k | &self.as_bytes()[..end] | 2299 | 8.67k | } |
Unexecuted instantiation: <_ as bstr::ext_slice::ByteSlice>::trim_end Unexecuted instantiation: <[u8] as bstr::ext_slice::ByteSlice>::trim_end Unexecuted instantiation: <[u8] as bstr::ext_slice::ByteSlice>::trim_end Unexecuted instantiation: <_ as bstr::ext_slice::ByteSlice>::trim_end Unexecuted instantiation: <[u8] as bstr::ext_slice::ByteSlice>::trim_end Unexecuted instantiation: <[u8] as bstr::ext_slice::ByteSlice>::trim_end Unexecuted instantiation: <[u8] as bstr::ext_slice::ByteSlice>::trim_end Unexecuted instantiation: <[u8] as bstr::ext_slice::ByteSlice>::trim_end <[u8] as bstr::ext_slice::ByteSlice>::trim_end Line | Count | Source | 2296 | 2.71k | fn trim_end(&self) -> &[u8] { | 2297 | 2.71k | let end = whitespace_len_rev(self.as_bytes()); | 2298 | 2.71k | &self.as_bytes()[..end] | 2299 | 2.71k | } |
Unexecuted instantiation: <[u8] as bstr::ext_slice::ByteSlice>::trim_end Unexecuted instantiation: <[u8] as bstr::ext_slice::ByteSlice>::trim_end Unexecuted instantiation: <[u8] as bstr::ext_slice::ByteSlice>::trim_end Unexecuted instantiation: <[u8] as bstr::ext_slice::ByteSlice>::trim_end Unexecuted instantiation: <[u8] as bstr::ext_slice::ByteSlice>::trim_end |
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 | 5.93k | fn trim_with<F: FnMut(char) -> bool>(&self, mut trim: F) -> &[u8] { |
2316 | 5.93k | self.trim_start_with(&mut trim).trim_end_with(&mut trim) |
2317 | 5.93k | } Unexecuted instantiation: <_ as bstr::ext_slice::ByteSlice>::trim_with::<_> Unexecuted instantiation: <_ as bstr::ext_slice::ByteSlice>::trim_with::<_> Unexecuted instantiation: <_ as bstr::ext_slice::ByteSlice>::trim_with::<_> <[u8] as bstr::ext_slice::ByteSlice>::trim_with::<<gix_credentials::protocol::Context>::destructure_url_in_place::{closure#1}>Line | Count | Source | 2315 | 5.93k | fn trim_with<F: FnMut(char) -> bool>(&self, mut trim: F) -> &[u8] { | 2316 | 5.93k | self.trim_start_with(&mut trim).trim_end_with(&mut trim) | 2317 | 5.93k | } |
|
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 | 5.93k | fn trim_start_with<F: FnMut(char) -> bool>(&self, mut trim: F) -> &[u8] { |
2334 | 2.14M | for (s, _, ch) in self.char_indices() { |
2335 | 2.14M | if !trim(ch) { |
2336 | 3.95k | return &self.as_bytes()[s..]; |
2337 | 2.14M | } |
2338 | | } |
2339 | 1.98k | b"" |
2340 | 5.93k | } Unexecuted instantiation: <_ as bstr::ext_slice::ByteSlice>::trim_start_with::<_> Unexecuted instantiation: <_ as bstr::ext_slice::ByteSlice>::trim_start_with::<_> Unexecuted instantiation: <_ as bstr::ext_slice::ByteSlice>::trim_start_with::<_> <[u8] as bstr::ext_slice::ByteSlice>::trim_start_with::<&mut <gix_credentials::protocol::Context>::destructure_url_in_place::{closure#1}>Line | Count | Source | 2333 | 5.93k | fn trim_start_with<F: FnMut(char) -> bool>(&self, mut trim: F) -> &[u8] { | 2334 | 2.14M | for (s, _, ch) in self.char_indices() { | 2335 | 2.14M | if !trim(ch) { | 2336 | 3.95k | return &self.as_bytes()[s..]; | 2337 | 2.14M | } | 2338 | | } | 2339 | 1.98k | b"" | 2340 | 5.93k | } |
|
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 | 5.93k | fn trim_end_with<F: FnMut(char) -> bool>(&self, mut trim: F) -> &[u8] { |
2357 | 13.5k | for (_, e, ch) in self.char_indices().rev() { |
2358 | 13.5k | if !trim(ch) { |
2359 | 3.95k | return &self.as_bytes()[..e]; |
2360 | 9.58k | } |
2361 | | } |
2362 | 1.98k | b"" |
2363 | 5.93k | } Unexecuted instantiation: <_ as bstr::ext_slice::ByteSlice>::trim_end_with::<_> Unexecuted instantiation: <_ as bstr::ext_slice::ByteSlice>::trim_end_with::<_> Unexecuted instantiation: <_ as bstr::ext_slice::ByteSlice>::trim_end_with::<_> <[u8] as bstr::ext_slice::ByteSlice>::trim_end_with::<&mut <gix_credentials::protocol::Context>::destructure_url_in_place::{closure#1}>Line | Count | Source | 2356 | 5.93k | fn trim_end_with<F: FnMut(char) -> bool>(&self, mut trim: F) -> &[u8] { | 2357 | 13.5k | for (_, e, ch) in self.char_indices().rev() { | 2358 | 13.5k | if !trim(ch) { | 2359 | 3.95k | return &self.as_bytes()[..e]; | 2360 | 9.58k | } | 2361 | | } | 2362 | 1.98k | b"" | 2363 | 5.93k | } |
|
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 | 0 | fn to_lowercase(&self) -> Vec<u8> { |
2413 | 0 | let mut buf = vec![]; |
2414 | 0 | self.to_lowercase_into(&mut buf); |
2415 | 0 | buf |
2416 | 0 | } Unexecuted instantiation: <_ as bstr::ext_slice::ByteSlice>::to_lowercase Unexecuted instantiation: <_ as bstr::ext_slice::ByteSlice>::to_lowercase |
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 | 0 | 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 | 0 | buf.reserve(self.as_bytes().len()); |
2483 | 0 | for (s, e, ch) in self.char_indices() { |
2484 | 0 | if ch == '\u{FFFD}' { |
2485 | 0 | buf.push_str(&self.as_bytes()[s..e]); |
2486 | 0 | } else if ch.is_ascii() { |
2487 | 0 | buf.push_char(ch.to_ascii_lowercase()); |
2488 | 0 | } else { |
2489 | 0 | for upper in ch.to_lowercase() { |
2490 | 0 | buf.push_char(upper); |
2491 | 0 | } |
2492 | | } |
2493 | | } |
2494 | 0 | } Unexecuted instantiation: <_ as bstr::ext_slice::ByteSlice>::to_lowercase_into Unexecuted instantiation: <_ as bstr::ext_slice::ByteSlice>::to_lowercase_into |
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 | 0 | fn to_ascii_lowercase(&self) -> Vec<u8> { |
2530 | 0 | self.as_bytes().to_ascii_lowercase() |
2531 | 0 | } Unexecuted instantiation: <_ as bstr::ext_slice::ByteSlice>::to_ascii_lowercase Unexecuted instantiation: <_ as bstr::ext_slice::ByteSlice>::to_ascii_lowercase Unexecuted instantiation: <_ as bstr::ext_slice::ByteSlice>::to_ascii_lowercase |
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 | 0 | fn make_ascii_lowercase(&mut self) { |
2567 | 0 | self.as_bytes_mut().make_ascii_lowercase(); |
2568 | 0 | } Unexecuted instantiation: <_ as bstr::ext_slice::ByteSlice>::make_ascii_lowercase Unexecuted instantiation: <_ as bstr::ext_slice::ByteSlice>::make_ascii_lowercase Unexecuted instantiation: <_ as bstr::ext_slice::ByteSlice>::make_ascii_lowercase |
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 | 0 | fn to_uppercase(&self) -> Vec<u8> { |
2618 | 0 | let mut buf = vec![]; |
2619 | 0 | self.to_uppercase_into(&mut buf); |
2620 | 0 | buf |
2621 | 0 | } Unexecuted instantiation: <_ as bstr::ext_slice::ByteSlice>::to_uppercase Unexecuted instantiation: <_ as bstr::ext_slice::ByteSlice>::to_uppercase |
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 | 0 | 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 | 0 | buf.reserve(self.as_bytes().len()); |
2685 | 0 | for (s, e, ch) in self.char_indices() { |
2686 | 0 | if ch == '\u{FFFD}' { |
2687 | 0 | buf.push_str(&self.as_bytes()[s..e]); |
2688 | 0 | } else if ch.is_ascii() { |
2689 | 0 | buf.push_char(ch.to_ascii_uppercase()); |
2690 | 0 | } else { |
2691 | 0 | for upper in ch.to_uppercase() { |
2692 | 0 | buf.push_char(upper); |
2693 | 0 | } |
2694 | | } |
2695 | | } |
2696 | 0 | } Unexecuted instantiation: <_ as bstr::ext_slice::ByteSlice>::to_uppercase_into Unexecuted instantiation: <_ as bstr::ext_slice::ByteSlice>::to_uppercase_into |
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 | 0 | fn to_ascii_uppercase(&self) -> Vec<u8> { |
2732 | 0 | self.as_bytes().to_ascii_uppercase() |
2733 | 0 | } Unexecuted instantiation: <_ as bstr::ext_slice::ByteSlice>::to_ascii_uppercase Unexecuted instantiation: <_ as bstr::ext_slice::ByteSlice>::to_ascii_uppercase Unexecuted instantiation: <_ as bstr::ext_slice::ByteSlice>::to_ascii_uppercase |
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 | 0 | fn make_ascii_uppercase(&mut self) { |
2769 | 0 | self.as_bytes_mut().make_ascii_uppercase(); |
2770 | 0 | } Unexecuted instantiation: <_ as bstr::ext_slice::ByteSlice>::make_ascii_uppercase Unexecuted instantiation: <_ as bstr::ext_slice::ByteSlice>::make_ascii_uppercase Unexecuted instantiation: <_ as bstr::ext_slice::ByteSlice>::make_ascii_uppercase |
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 | 0 | fn escape_bytes(&self) -> EscapeBytes<'_> { |
2810 | 0 | EscapeBytes::new(self.as_bytes()) |
2811 | 0 | } Unexecuted instantiation: <_ as bstr::ext_slice::ByteSlice>::escape_bytes Unexecuted instantiation: <_ as bstr::ext_slice::ByteSlice>::escape_bytes Unexecuted instantiation: <_ as bstr::ext_slice::ByteSlice>::escape_bytes |
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 | 0 | fn reverse_bytes(&mut self) { |
2837 | 0 | self.as_bytes_mut().reverse(); |
2838 | 0 | } Unexecuted instantiation: <_ as bstr::ext_slice::ByteSlice>::reverse_bytes Unexecuted instantiation: <_ as bstr::ext_slice::ByteSlice>::reverse_bytes Unexecuted instantiation: <_ as bstr::ext_slice::ByteSlice>::reverse_bytes |
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 | 0 | fn reverse_chars(&mut self) { |
2908 | 0 | let mut i = 0; |
2909 | | loop { |
2910 | 0 | let (_, size) = utf8::decode(&self.as_bytes()[i..]); |
2911 | 0 | if size == 0 { |
2912 | 0 | break; |
2913 | 0 | } |
2914 | 0 | if size > 1 { |
2915 | 0 | self.as_bytes_mut()[i..i + size].reverse_bytes(); |
2916 | 0 | } |
2917 | 0 | i += size; |
2918 | | } |
2919 | 0 | self.reverse_bytes(); |
2920 | 0 | } Unexecuted instantiation: <_ as bstr::ext_slice::ByteSlice>::reverse_chars Unexecuted instantiation: <_ as bstr::ext_slice::ByteSlice>::reverse_chars Unexecuted instantiation: <_ as bstr::ext_slice::ByteSlice>::reverse_chars |
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 | 0 | fn reverse_graphemes(&mut self) { |
2966 | | use crate::unicode::decode_grapheme; |
2967 | | |
2968 | 0 | let mut i = 0; |
2969 | | loop { |
2970 | 0 | let (_, size) = decode_grapheme(&self.as_bytes()[i..]); |
2971 | 0 | if size == 0 { |
2972 | 0 | break; |
2973 | 0 | } |
2974 | 0 | if size > 1 { |
2975 | 0 | self.as_bytes_mut()[i..i + size].reverse_bytes(); |
2976 | 0 | } |
2977 | 0 | i += size; |
2978 | | } |
2979 | 0 | self.reverse_bytes(); |
2980 | 0 | } Unexecuted instantiation: <_ as bstr::ext_slice::ByteSlice>::reverse_graphemes Unexecuted instantiation: <_ as bstr::ext_slice::ByteSlice>::reverse_graphemes |
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 | 0 | fn is_ascii(&self) -> bool { |
3001 | 0 | ascii::first_non_ascii_byte(self.as_bytes()) == self.as_bytes().len() |
3002 | 0 | } Unexecuted instantiation: <_ as bstr::ext_slice::ByteSlice>::is_ascii Unexecuted instantiation: <_ as bstr::ext_slice::ByteSlice>::is_ascii Unexecuted instantiation: <_ as bstr::ext_slice::ByteSlice>::is_ascii |
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 | 9.40k | fn is_utf8(&self) -> bool { |
3029 | 9.40k | utf8::validate(self.as_bytes()).is_ok() |
3030 | 9.40k | } Unexecuted instantiation: <_ as bstr::ext_slice::ByteSlice>::is_utf8 Unexecuted instantiation: <_ as bstr::ext_slice::ByteSlice>::is_utf8 Unexecuted instantiation: <_ as bstr::ext_slice::ByteSlice>::is_utf8 <[u8] as bstr::ext_slice::ByteSlice>::is_utf8 Line | Count | Source | 3028 | 9.40k | fn is_utf8(&self) -> bool { | 3029 | 9.40k | utf8::validate(self.as_bytes()).is_ok() | 3030 | 9.40k | } |
|
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 | 13.4M | fn last_byte(&self) -> Option<u8> { |
3050 | 13.4M | let bytes = self.as_bytes(); |
3051 | 13.4M | bytes.last().copied() |
3052 | 13.4M | } <[u8] as bstr::ext_slice::ByteSlice>::last_byte Line | Count | Source | 3049 | 10.3M | fn last_byte(&self) -> Option<u8> { | 3050 | 10.3M | let bytes = self.as_bytes(); | 3051 | 10.3M | bytes.last().copied() | 3052 | 10.3M | } |
<[u8] as bstr::ext_slice::ByteSlice>::last_byte Line | Count | Source | 3049 | 3.08M | fn last_byte(&self) -> Option<u8> { | 3050 | 3.08M | let bytes = self.as_bytes(); | 3051 | 3.08M | bytes.last().copied() | 3052 | 3.08M | } |
Unexecuted instantiation: <[u8] as bstr::ext_slice::ByteSlice>::last_byte Unexecuted instantiation: <[u8] as bstr::ext_slice::ByteSlice>::last_byte |
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 | 0 | fn find_non_ascii_byte(&self) -> Option<usize> { |
3071 | 0 | let index = ascii::first_non_ascii_byte(self.as_bytes()); |
3072 | 0 | if index == self.as_bytes().len() { |
3073 | 0 | None |
3074 | | } else { |
3075 | 0 | Some(index) |
3076 | | } |
3077 | 0 | } Unexecuted instantiation: <_ as bstr::ext_slice::ByteSlice>::find_non_ascii_byte Unexecuted instantiation: <_ as bstr::ext_slice::ByteSlice>::find_non_ascii_byte Unexecuted instantiation: <_ as bstr::ext_slice::ByteSlice>::find_non_ascii_byte |
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)] |
3097 | | pub struct Finder<'a>(memmem::Finder<'a>); |
3098 | | |
3099 | | impl<'a> Finder<'a> { |
3100 | | /// Create a new finder for the given needle. |
3101 | | #[inline] |
3102 | 2.09M | pub fn new<B: ?Sized + AsRef<[u8]>>(needle: &'a B) -> Finder<'a> { |
3103 | 2.09M | Finder(memmem::Finder::new(needle.as_ref())) |
3104 | 2.09M | } Unexecuted instantiation: <bstr::ext_slice::Finder>::new::<_> <bstr::ext_slice::Finder>::new::<[u8]> Line | Count | Source | 3102 | 2.07M | pub fn new<B: ?Sized + AsRef<[u8]>>(needle: &'a B) -> Finder<'a> { | 3103 | 2.07M | Finder(memmem::Finder::new(needle.as_ref())) | 3104 | 2.07M | } |
Unexecuted instantiation: <bstr::ext_slice::Finder>::new::<[u8]> Unexecuted instantiation: <bstr::ext_slice::Finder>::new::<_> Unexecuted instantiation: <bstr::ext_slice::Finder>::new::<[u8]> Unexecuted instantiation: <bstr::ext_slice::Finder>::new::<_> Unexecuted instantiation: <bstr::ext_slice::Finder>::new::<[u8]> Unexecuted instantiation: <bstr::ext_slice::Finder>::new::<[u8]> <bstr::ext_slice::Finder>::new::<[u8]> Line | Count | Source | 3102 | 2.66k | pub fn new<B: ?Sized + AsRef<[u8]>>(needle: &'a B) -> Finder<'a> { | 3103 | 2.66k | Finder(memmem::Finder::new(needle.as_ref())) | 3104 | 2.66k | } |
<bstr::ext_slice::Finder>::new::<[u8]> Line | Count | Source | 3102 | 10.4k | pub fn new<B: ?Sized + AsRef<[u8]>>(needle: &'a B) -> Finder<'a> { | 3103 | 10.4k | Finder(memmem::Finder::new(needle.as_ref())) | 3104 | 10.4k | } |
Unexecuted instantiation: <bstr::ext_slice::Finder>::new::<[u8]> Unexecuted instantiation: <bstr::ext_slice::Finder>::new::<[u8]> <bstr::ext_slice::Finder>::new::<[u8]> Line | Count | Source | 3102 | 6.25k | pub fn new<B: ?Sized + AsRef<[u8]>>(needle: &'a B) -> Finder<'a> { | 3103 | 6.25k | Finder(memmem::Finder::new(needle.as_ref())) | 3104 | 6.25k | } |
Unexecuted instantiation: <bstr::ext_slice::Finder>::new::<[u8]> <bstr::ext_slice::Finder>::new::<[u8]> Line | Count | Source | 3102 | 4.04k | pub fn new<B: ?Sized + AsRef<[u8]>>(needle: &'a B) -> Finder<'a> { | 3103 | 4.04k | Finder(memmem::Finder::new(needle.as_ref())) | 3104 | 4.04k | } |
|
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 | 0 | pub fn into_owned(self) -> Finder<'static> { |
3116 | 0 | Finder(self.0.into_owned()) |
3117 | 0 | } Unexecuted instantiation: <bstr::ext_slice::Finder>::into_owned Unexecuted instantiation: <bstr::ext_slice::Finder>::into_owned Unexecuted instantiation: <bstr::ext_slice::Finder>::into_owned |
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 | 0 | pub fn needle(&self) -> &[u8] { |
3127 | 0 | self.0.needle() |
3128 | 0 | } Unexecuted instantiation: <bstr::ext_slice::Finder>::needle Unexecuted instantiation: <bstr::ext_slice::Finder>::needle Unexecuted instantiation: <bstr::ext_slice::Finder>::needle |
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 | 2.09M | pub fn find<B: AsRef<[u8]>>(&self, haystack: B) -> Option<usize> { |
3159 | 2.09M | self.0.find(haystack.as_ref()) |
3160 | 2.09M | } Unexecuted instantiation: <bstr::ext_slice::Finder>::find::<_> <bstr::ext_slice::Finder>::find::<&[u8]> Line | Count | Source | 3158 | 2.07M | pub fn find<B: AsRef<[u8]>>(&self, haystack: B) -> Option<usize> { | 3159 | 2.07M | self.0.find(haystack.as_ref()) | 3160 | 2.07M | } |
Unexecuted instantiation: <bstr::ext_slice::Finder>::find::<&[u8]> Unexecuted instantiation: <bstr::ext_slice::Finder>::find::<_> Unexecuted instantiation: <bstr::ext_slice::Finder>::find::<&[u8]> Unexecuted instantiation: <bstr::ext_slice::Finder>::find::<_> Unexecuted instantiation: <bstr::ext_slice::Finder>::find::<&[u8]> Unexecuted instantiation: <bstr::ext_slice::Finder>::find::<&[u8]> <bstr::ext_slice::Finder>::find::<&[u8]> Line | Count | Source | 3158 | 2.66k | pub fn find<B: AsRef<[u8]>>(&self, haystack: B) -> Option<usize> { | 3159 | 2.66k | self.0.find(haystack.as_ref()) | 3160 | 2.66k | } |
<bstr::ext_slice::Finder>::find::<&[u8]> Line | Count | Source | 3158 | 10.4k | pub fn find<B: AsRef<[u8]>>(&self, haystack: B) -> Option<usize> { | 3159 | 10.4k | self.0.find(haystack.as_ref()) | 3160 | 10.4k | } |
Unexecuted instantiation: <bstr::ext_slice::Finder>::find::<&[u8]> Unexecuted instantiation: <bstr::ext_slice::Finder>::find::<&[u8]> <bstr::ext_slice::Finder>::find::<&[u8]> Line | Count | Source | 3158 | 6.25k | pub fn find<B: AsRef<[u8]>>(&self, haystack: B) -> Option<usize> { | 3159 | 6.25k | self.0.find(haystack.as_ref()) | 3160 | 6.25k | } |
Unexecuted instantiation: <bstr::ext_slice::Finder>::find::<&[u8]> <bstr::ext_slice::Finder>::find::<&[u8]> Line | Count | Source | 3158 | 4.04k | pub fn find<B: AsRef<[u8]>>(&self, haystack: B) -> Option<usize> { | 3159 | 4.04k | self.0.find(haystack.as_ref()) | 3160 | 4.04k | } |
|
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)] |
3180 | | pub struct FinderReverse<'a>(memmem::FinderRev<'a>); |
3181 | | |
3182 | | impl<'a> FinderReverse<'a> { |
3183 | | /// Create a new reverse finder for the given needle. |
3184 | | #[inline] |
3185 | 78.6k | pub fn new<B: ?Sized + AsRef<[u8]>>(needle: &'a B) -> FinderReverse<'a> { |
3186 | 78.6k | FinderReverse(memmem::FinderRev::new(needle.as_ref())) |
3187 | 78.6k | } Unexecuted instantiation: <bstr::ext_slice::FinderReverse>::new::<_> <bstr::ext_slice::FinderReverse>::new::<[u8]> Line | Count | Source | 3185 | 71.7k | pub fn new<B: ?Sized + AsRef<[u8]>>(needle: &'a B) -> FinderReverse<'a> { | 3186 | 71.7k | FinderReverse(memmem::FinderRev::new(needle.as_ref())) | 3187 | 71.7k | } |
Unexecuted instantiation: <bstr::ext_slice::FinderReverse>::new::<_> Unexecuted instantiation: <bstr::ext_slice::FinderReverse>::new::<_> Unexecuted instantiation: <bstr::ext_slice::FinderReverse>::new::<[u8]> Unexecuted instantiation: <bstr::ext_slice::FinderReverse>::new::<[u8]> <bstr::ext_slice::FinderReverse>::new::<[u8]> Line | Count | Source | 3185 | 6.92k | pub fn new<B: ?Sized + AsRef<[u8]>>(needle: &'a B) -> FinderReverse<'a> { | 3186 | 6.92k | FinderReverse(memmem::FinderRev::new(needle.as_ref())) | 3187 | 6.92k | } |
Unexecuted instantiation: <bstr::ext_slice::FinderReverse>::new::<[u8]> |
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 | 0 | pub fn into_owned(self) -> FinderReverse<'static> { |
3199 | 0 | FinderReverse(self.0.into_owned()) |
3200 | 0 | } Unexecuted instantiation: <bstr::ext_slice::FinderReverse>::into_owned Unexecuted instantiation: <bstr::ext_slice::FinderReverse>::into_owned Unexecuted instantiation: <bstr::ext_slice::FinderReverse>::into_owned |
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 | 0 | pub fn needle(&self) -> &[u8] { |
3210 | 0 | self.0.needle() |
3211 | 0 | } Unexecuted instantiation: <bstr::ext_slice::FinderReverse>::needle Unexecuted instantiation: <bstr::ext_slice::FinderReverse>::needle Unexecuted instantiation: <bstr::ext_slice::FinderReverse>::needle |
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 | 78.6k | pub fn rfind<B: AsRef<[u8]>>(&self, haystack: B) -> Option<usize> { |
3242 | 78.6k | self.0.rfind(haystack.as_ref()) |
3243 | 78.6k | } Unexecuted instantiation: <bstr::ext_slice::FinderReverse>::rfind::<_> <bstr::ext_slice::FinderReverse>::rfind::<&[u8]> Line | Count | Source | 3241 | 71.7k | pub fn rfind<B: AsRef<[u8]>>(&self, haystack: B) -> Option<usize> { | 3242 | 71.7k | self.0.rfind(haystack.as_ref()) | 3243 | 71.7k | } |
Unexecuted instantiation: <bstr::ext_slice::FinderReverse>::rfind::<_> Unexecuted instantiation: <bstr::ext_slice::FinderReverse>::rfind::<_> Unexecuted instantiation: <bstr::ext_slice::FinderReverse>::rfind::<&[u8]> Unexecuted instantiation: <bstr::ext_slice::FinderReverse>::rfind::<&[u8]> <bstr::ext_slice::FinderReverse>::rfind::<&[u8]> Line | Count | Source | 3241 | 6.92k | pub fn rfind<B: AsRef<[u8]>>(&self, haystack: B) -> Option<usize> { | 3242 | 6.92k | self.0.rfind(haystack.as_ref()) | 3243 | 6.92k | } |
Unexecuted instantiation: <bstr::ext_slice::FinderReverse>::rfind::<&[u8]> |
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)] |
3253 | | pub struct Find<'h, 'n> { |
3254 | | it: memmem::FindIter<'h, 'n>, |
3255 | | haystack: &'h [u8], |
3256 | | needle: &'n [u8], |
3257 | | } |
3258 | | |
3259 | | impl<'h, 'n> Find<'h, 'n> { |
3260 | 2.53k | fn new(haystack: &'h [u8], needle: &'n [u8]) -> Find<'h, 'n> { |
3261 | 2.53k | Find { it: memmem::find_iter(haystack, needle), haystack, needle } |
3262 | 2.53k | } Unexecuted instantiation: <bstr::ext_slice::Find>::new <bstr::ext_slice::Find>::new Line | Count | Source | 3260 | 2.53k | fn new(haystack: &'h [u8], needle: &'n [u8]) -> Find<'h, 'n> { | 3261 | 2.53k | Find { it: memmem::find_iter(haystack, needle), haystack, needle } | 3262 | 2.53k | } |
Unexecuted instantiation: <bstr::ext_slice::Find>::new |
3263 | | } |
3264 | | |
3265 | | impl<'h, 'n> Iterator for Find<'h, 'n> { |
3266 | | type Item = usize; |
3267 | | |
3268 | | #[inline] |
3269 | 13.9M | fn next(&mut self) -> Option<usize> { |
3270 | 13.9M | self.it.next() |
3271 | 13.9M | } Unexecuted instantiation: <bstr::ext_slice::Find as core::iter::traits::iterator::Iterator>::next <bstr::ext_slice::Find as core::iter::traits::iterator::Iterator>::next Line | Count | Source | 3269 | 13.9M | fn next(&mut self) -> Option<usize> { | 3270 | 13.9M | self.it.next() | 3271 | 13.9M | } |
Unexecuted instantiation: <bstr::ext_slice::Find as core::iter::traits::iterator::Iterator>::next |
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)] |
3281 | | pub struct FindReverse<'h, 'n> { |
3282 | | it: memmem::FindRevIter<'h, 'n>, |
3283 | | haystack: &'h [u8], |
3284 | | needle: &'n [u8], |
3285 | | } |
3286 | | |
3287 | | impl<'h, 'n> FindReverse<'h, 'n> { |
3288 | 0 | fn new(haystack: &'h [u8], needle: &'n [u8]) -> FindReverse<'h, 'n> { |
3289 | 0 | FindReverse { |
3290 | 0 | it: memmem::rfind_iter(haystack, needle), |
3291 | 0 | haystack, |
3292 | 0 | needle, |
3293 | 0 | } |
3294 | 0 | } Unexecuted instantiation: <bstr::ext_slice::FindReverse>::new Unexecuted instantiation: <bstr::ext_slice::FindReverse>::new Unexecuted instantiation: <bstr::ext_slice::FindReverse>::new |
3295 | | |
3296 | 0 | fn haystack(&self) -> &'h [u8] { |
3297 | 0 | self.haystack |
3298 | 0 | } Unexecuted instantiation: <bstr::ext_slice::FindReverse>::haystack Unexecuted instantiation: <bstr::ext_slice::FindReverse>::haystack Unexecuted instantiation: <bstr::ext_slice::FindReverse>::haystack |
3299 | | |
3300 | 0 | fn needle(&self) -> &'n [u8] { |
3301 | 0 | self.needle |
3302 | 0 | } Unexecuted instantiation: <bstr::ext_slice::FindReverse>::needle Unexecuted instantiation: <bstr::ext_slice::FindReverse>::needle Unexecuted instantiation: <bstr::ext_slice::FindReverse>::needle |
3303 | | } |
3304 | | |
3305 | | impl<'h, 'n> Iterator for FindReverse<'h, 'n> { |
3306 | | type Item = usize; |
3307 | | |
3308 | | #[inline] |
3309 | 0 | fn next(&mut self) -> Option<usize> { |
3310 | 0 | self.it.next() |
3311 | 0 | } Unexecuted instantiation: <bstr::ext_slice::FindReverse as core::iter::traits::iterator::Iterator>::next Unexecuted instantiation: <bstr::ext_slice::FindReverse as core::iter::traits::iterator::Iterator>::next Unexecuted instantiation: <bstr::ext_slice::FindReverse as core::iter::traits::iterator::Iterator>::next |
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)] |
3318 | | pub struct Bytes<'a> { |
3319 | | it: slice::Iter<'a, u8>, |
3320 | | } |
3321 | | |
3322 | | impl<'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 | 0 | pub fn as_bytes(&self) -> &'a [u8] { |
3328 | 0 | self.it.as_slice() |
3329 | 0 | } Unexecuted instantiation: <bstr::ext_slice::Bytes>::as_bytes Unexecuted instantiation: <bstr::ext_slice::Bytes>::as_bytes Unexecuted instantiation: <bstr::ext_slice::Bytes>::as_bytes |
3330 | | } |
3331 | | |
3332 | | impl<'a> Iterator for Bytes<'a> { |
3333 | | type Item = u8; |
3334 | | |
3335 | | #[inline] |
3336 | 33.7M | fn next(&mut self) -> Option<u8> { |
3337 | 33.7M | self.it.next().copied() |
3338 | 33.7M | } <bstr::ext_slice::Bytes as core::iter::traits::iterator::Iterator>::next Line | Count | Source | 3336 | 22.8k | fn next(&mut self) -> Option<u8> { | 3337 | 22.8k | self.it.next().copied() | 3338 | 22.8k | } |
Unexecuted instantiation: <bstr::ext_slice::Bytes as core::iter::traits::iterator::Iterator>::next <bstr::ext_slice::Bytes as core::iter::traits::iterator::Iterator>::next Line | Count | Source | 3336 | 33.6M | fn next(&mut self) -> Option<u8> { | 3337 | 33.6M | self.it.next().copied() | 3338 | 33.6M | } |
|
3339 | | |
3340 | | #[inline] |
3341 | 0 | fn size_hint(&self) -> (usize, Option<usize>) { |
3342 | 0 | self.it.size_hint() |
3343 | 0 | } Unexecuted instantiation: <bstr::ext_slice::Bytes as core::iter::traits::iterator::Iterator>::size_hint Unexecuted instantiation: <bstr::ext_slice::Bytes as core::iter::traits::iterator::Iterator>::size_hint Unexecuted instantiation: <bstr::ext_slice::Bytes as core::iter::traits::iterator::Iterator>::size_hint |
3344 | | } |
3345 | | |
3346 | | impl<'a> DoubleEndedIterator for Bytes<'a> { |
3347 | | #[inline] |
3348 | 0 | fn next_back(&mut self) -> Option<u8> { |
3349 | 0 | self.it.next_back().copied() |
3350 | 0 | } Unexecuted instantiation: <bstr::ext_slice::Bytes as core::iter::traits::double_ended::DoubleEndedIterator>::next_back Unexecuted instantiation: <bstr::ext_slice::Bytes as core::iter::traits::double_ended::DoubleEndedIterator>::next_back Unexecuted instantiation: <bstr::ext_slice::Bytes as core::iter::traits::double_ended::DoubleEndedIterator>::next_back |
3351 | | } |
3352 | | |
3353 | | impl<'a> ExactSizeIterator for Bytes<'a> { |
3354 | | #[inline] |
3355 | 0 | fn len(&self) -> usize { |
3356 | 0 | self.it.len() |
3357 | 0 | } Unexecuted instantiation: <bstr::ext_slice::Bytes as core::iter::traits::exact_size::ExactSizeIterator>::len Unexecuted instantiation: <bstr::ext_slice::Bytes as core::iter::traits::exact_size::ExactSizeIterator>::len Unexecuted instantiation: <bstr::ext_slice::Bytes as core::iter::traits::exact_size::ExactSizeIterator>::len |
3358 | | } |
3359 | | |
3360 | | impl<'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)] |
3374 | | pub struct Fields<'a> { |
3375 | | it: FieldsWith<'a, fn(char) -> bool>, |
3376 | | } |
3377 | | |
3378 | | #[cfg(feature = "unicode")] |
3379 | | impl<'a> Fields<'a> { |
3380 | 19.1k | fn new(bytes: &'a [u8]) -> Fields<'a> { |
3381 | 19.1k | Fields { it: bytes.fields_with(char::is_whitespace) } |
3382 | 19.1k | } <bstr::ext_slice::Fields>::new Line | Count | Source | 3380 | 19.1k | fn new(bytes: &'a [u8]) -> Fields<'a> { | 3381 | 19.1k | Fields { it: bytes.fields_with(char::is_whitespace) } | 3382 | 19.1k | } |
Unexecuted instantiation: <bstr::ext_slice::Fields>::new |
3383 | | } |
3384 | | |
3385 | | #[cfg(feature = "unicode")] |
3386 | | impl<'a> Iterator for Fields<'a> { |
3387 | | type Item = &'a [u8]; |
3388 | | |
3389 | | #[inline] |
3390 | 0 | fn next(&mut self) -> Option<&'a [u8]> { |
3391 | 0 | self.it.next() |
3392 | 0 | } Unexecuted instantiation: <bstr::ext_slice::Fields as core::iter::traits::iterator::Iterator>::next Unexecuted instantiation: <bstr::ext_slice::Fields as core::iter::traits::iterator::Iterator>::next |
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)] |
3405 | | pub struct FieldsWith<'a, F> { |
3406 | | f: F, |
3407 | | bytes: &'a [u8], |
3408 | | chars: CharIndices<'a>, |
3409 | | } |
3410 | | |
3411 | | impl<'a, F: FnMut(char) -> bool> FieldsWith<'a, F> { |
3412 | 19.1k | fn new(bytes: &'a [u8], f: F) -> FieldsWith<'a, F> { |
3413 | 19.1k | FieldsWith { f, bytes, chars: bytes.char_indices() } |
3414 | 19.1k | } <bstr::ext_slice::FieldsWith<fn(char) -> bool>>::new Line | Count | Source | 3412 | 19.1k | fn new(bytes: &'a [u8], f: F) -> FieldsWith<'a, F> { | 3413 | 19.1k | FieldsWith { f, bytes, chars: bytes.char_indices() } | 3414 | 19.1k | } |
Unexecuted instantiation: <bstr::ext_slice::FieldsWith<fn(char) -> bool>>::new Unexecuted instantiation: <bstr::ext_slice::FieldsWith<_>>::new |
3415 | | } |
3416 | | |
3417 | | impl<'a, F: FnMut(char) -> bool> Iterator for FieldsWith<'a, F> { |
3418 | | type Item = &'a [u8]; |
3419 | | |
3420 | | #[inline] |
3421 | 4.78M | fn next(&mut self) -> Option<&'a [u8]> { |
3422 | | let (start, mut end); |
3423 | | loop { |
3424 | 4.85M | match self.chars.next() { |
3425 | 16.7k | None => return None, |
3426 | 4.83M | Some((s, e, ch)) => { |
3427 | 4.83M | if !(self.f)(ch) { |
3428 | 4.76M | start = s; |
3429 | 4.76M | end = e; |
3430 | 4.76M | break; |
3431 | 70.8k | } |
3432 | | } |
3433 | | } |
3434 | | } |
3435 | 64.5M | for (_, e, ch) in self.chars.by_ref() { |
3436 | 64.5M | if (self.f)(ch) { |
3437 | 4.75M | break; |
3438 | 59.8M | } |
3439 | 59.8M | end = e; |
3440 | | } |
3441 | 4.76M | Some(&self.bytes[start..end]) |
3442 | 4.78M | } Unexecuted instantiation: <bstr::ext_slice::FieldsWith<_> as core::iter::traits::iterator::Iterator>::next Unexecuted instantiation: <bstr::ext_slice::FieldsWith<_> as core::iter::traits::iterator::Iterator>::next Unexecuted instantiation: <bstr::ext_slice::FieldsWith<_> as core::iter::traits::iterator::Iterator>::next Unexecuted instantiation: <bstr::ext_slice::FieldsWith<fn(char) -> bool> as core::iter::traits::iterator::Iterator>::next <bstr::ext_slice::FieldsWith<fn(char) -> bool> as core::iter::traits::iterator::Iterator>::next Line | Count | Source | 3421 | 42.1k | fn next(&mut self) -> Option<&'a [u8]> { | 3422 | | let (start, mut end); | 3423 | | loop { | 3424 | 57.4k | match self.chars.next() { | 3425 | 13.8k | None => return None, | 3426 | 43.5k | Some((s, e, ch)) => { | 3427 | 43.5k | if !(self.f)(ch) { | 3428 | 28.2k | start = s; | 3429 | 28.2k | end = e; | 3430 | 28.2k | break; | 3431 | 15.2k | } | 3432 | | } | 3433 | | } | 3434 | | } | 3435 | 71.1k | for (_, e, ch) in self.chars.by_ref() { | 3436 | 71.1k | if (self.f)(ch) { | 3437 | 19.6k | break; | 3438 | 51.4k | } | 3439 | 51.4k | end = e; | 3440 | | } | 3441 | 28.2k | Some(&self.bytes[start..end]) | 3442 | 42.1k | } |
<bstr::ext_slice::FieldsWith<fn(char) -> bool> as core::iter::traits::iterator::Iterator>::next Line | Count | Source | 3421 | 4.74M | fn next(&mut self) -> Option<&'a [u8]> { | 3422 | | let (start, mut end); | 3423 | | loop { | 3424 | 4.79M | match self.chars.next() { | 3425 | 2.89k | None => return None, | 3426 | 4.79M | Some((s, e, ch)) => { | 3427 | 4.79M | if !(self.f)(ch) { | 3428 | 4.73M | start = s; | 3429 | 4.73M | end = e; | 3430 | 4.73M | break; | 3431 | 55.5k | } | 3432 | | } | 3433 | | } | 3434 | | } | 3435 | 64.5M | for (_, e, ch) in self.chars.by_ref() { | 3436 | 64.5M | if (self.f)(ch) { | 3437 | 4.73M | break; | 3438 | 59.7M | } | 3439 | 59.7M | end = e; | 3440 | | } | 3441 | 4.73M | Some(&self.bytes[start..end]) | 3442 | 4.74M | } |
|
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)] |
3450 | | pub 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 | | |
3462 | | impl<'h, 's> Split<'h, 's> { |
3463 | 2.53k | fn new(haystack: &'h [u8], splitter: &'s [u8]) -> Split<'h, 's> { |
3464 | 2.53k | let finder = haystack.find_iter(splitter); |
3465 | 2.53k | Split { finder, last: 0, done: false } |
3466 | 2.53k | } Unexecuted instantiation: <bstr::ext_slice::Split>::new <bstr::ext_slice::Split>::new Line | Count | Source | 3463 | 2.53k | fn new(haystack: &'h [u8], splitter: &'s [u8]) -> Split<'h, 's> { | 3464 | 2.53k | let finder = haystack.find_iter(splitter); | 3465 | 2.53k | Split { finder, last: 0, done: false } | 3466 | 2.53k | } |
Unexecuted instantiation: <bstr::ext_slice::Split>::new |
3467 | | } |
3468 | | |
3469 | | impl<'h, 's> Iterator for Split<'h, 's> { |
3470 | | type Item = &'h [u8]; |
3471 | | |
3472 | | #[inline] |
3473 | 13.9M | fn next(&mut self) -> Option<&'h [u8]> { |
3474 | 13.9M | let haystack = self.finder.haystack; |
3475 | 13.9M | match self.finder.next() { |
3476 | 13.9M | Some(start) => { |
3477 | 13.9M | let next = &haystack[self.last..start]; |
3478 | 13.9M | self.last = start + self.finder.needle.len(); |
3479 | 13.9M | Some(next) |
3480 | | } |
3481 | | None => { |
3482 | 5.07k | if self.last >= haystack.len() { |
3483 | 2.60k | if !self.done { |
3484 | 69 | self.done = true; |
3485 | 69 | Some(b"") |
3486 | | } else { |
3487 | 2.53k | None |
3488 | | } |
3489 | | } else { |
3490 | 2.47k | let s = &haystack[self.last..]; |
3491 | 2.47k | self.last = haystack.len(); |
3492 | 2.47k | self.done = true; |
3493 | 2.47k | Some(s) |
3494 | | } |
3495 | | } |
3496 | | } |
3497 | 13.9M | } Unexecuted instantiation: <bstr::ext_slice::Split as core::iter::traits::iterator::Iterator>::next <bstr::ext_slice::Split as core::iter::traits::iterator::Iterator>::next Line | Count | Source | 3473 | 13.9M | fn next(&mut self) -> Option<&'h [u8]> { | 3474 | 13.9M | let haystack = self.finder.haystack; | 3475 | 13.9M | match self.finder.next() { | 3476 | 13.9M | Some(start) => { | 3477 | 13.9M | let next = &haystack[self.last..start]; | 3478 | 13.9M | self.last = start + self.finder.needle.len(); | 3479 | 13.9M | Some(next) | 3480 | | } | 3481 | | None => { | 3482 | 5.07k | if self.last >= haystack.len() { | 3483 | 2.60k | if !self.done { | 3484 | 69 | self.done = true; | 3485 | 69 | Some(b"") | 3486 | | } else { | 3487 | 2.53k | None | 3488 | | } | 3489 | | } else { | 3490 | 2.47k | let s = &haystack[self.last..]; | 3491 | 2.47k | self.last = haystack.len(); | 3492 | 2.47k | self.done = true; | 3493 | 2.47k | Some(s) | 3494 | | } | 3495 | | } | 3496 | | } | 3497 | 13.9M | } |
Unexecuted instantiation: <bstr::ext_slice::Split as core::iter::traits::iterator::Iterator>::next |
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)] |
3506 | | pub 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 | | |
3518 | | impl<'h, 's> SplitReverse<'h, 's> { |
3519 | 0 | fn new(haystack: &'h [u8], splitter: &'s [u8]) -> SplitReverse<'h, 's> { |
3520 | 0 | let finder = haystack.rfind_iter(splitter); |
3521 | 0 | SplitReverse { finder, last: haystack.len(), done: false } |
3522 | 0 | } Unexecuted instantiation: <bstr::ext_slice::SplitReverse>::new Unexecuted instantiation: <bstr::ext_slice::SplitReverse>::new Unexecuted instantiation: <bstr::ext_slice::SplitReverse>::new |
3523 | | } |
3524 | | |
3525 | | impl<'h, 's> Iterator for SplitReverse<'h, 's> { |
3526 | | type Item = &'h [u8]; |
3527 | | |
3528 | | #[inline] |
3529 | 0 | fn next(&mut self) -> Option<&'h [u8]> { |
3530 | 0 | let haystack = self.finder.haystack(); |
3531 | 0 | match self.finder.next() { |
3532 | 0 | Some(start) => { |
3533 | 0 | let nlen = self.finder.needle().len(); |
3534 | 0 | let next = &haystack[start + nlen..self.last]; |
3535 | 0 | self.last = start; |
3536 | 0 | Some(next) |
3537 | | } |
3538 | | None => { |
3539 | 0 | if self.last == 0 { |
3540 | 0 | if !self.done { |
3541 | 0 | self.done = true; |
3542 | 0 | Some(b"") |
3543 | | } else { |
3544 | 0 | None |
3545 | | } |
3546 | | } else { |
3547 | 0 | let s = &haystack[..self.last]; |
3548 | 0 | self.last = 0; |
3549 | 0 | self.done = true; |
3550 | 0 | Some(s) |
3551 | | } |
3552 | | } |
3553 | | } |
3554 | 0 | } Unexecuted instantiation: <bstr::ext_slice::SplitReverse as core::iter::traits::iterator::Iterator>::next Unexecuted instantiation: <bstr::ext_slice::SplitReverse as core::iter::traits::iterator::Iterator>::next Unexecuted instantiation: <bstr::ext_slice::SplitReverse as core::iter::traits::iterator::Iterator>::next |
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)] |
3563 | | pub struct SplitN<'h, 's> { |
3564 | | split: Split<'h, 's>, |
3565 | | limit: usize, |
3566 | | count: usize, |
3567 | | } |
3568 | | |
3569 | | impl<'h, 's> SplitN<'h, 's> { |
3570 | 0 | fn new( |
3571 | 0 | haystack: &'h [u8], |
3572 | 0 | splitter: &'s [u8], |
3573 | 0 | limit: usize, |
3574 | 0 | ) -> SplitN<'h, 's> { |
3575 | 0 | let split = haystack.split_str(splitter); |
3576 | 0 | SplitN { split, limit, count: 0 } |
3577 | 0 | } Unexecuted instantiation: <bstr::ext_slice::SplitN>::new Unexecuted instantiation: <bstr::ext_slice::SplitN>::new Unexecuted instantiation: <bstr::ext_slice::SplitN>::new |
3578 | | } |
3579 | | |
3580 | | impl<'h, 's> Iterator for SplitN<'h, 's> { |
3581 | | type Item = &'h [u8]; |
3582 | | |
3583 | | #[inline] |
3584 | 0 | fn next(&mut self) -> Option<&'h [u8]> { |
3585 | 0 | self.count += 1; |
3586 | 0 | if self.count > self.limit || self.split.done { |
3587 | 0 | None |
3588 | 0 | } else if self.count == self.limit { |
3589 | 0 | Some(&self.split.finder.haystack[self.split.last..]) |
3590 | | } else { |
3591 | 0 | self.split.next() |
3592 | | } |
3593 | 0 | } Unexecuted instantiation: <bstr::ext_slice::SplitN as core::iter::traits::iterator::Iterator>::next Unexecuted instantiation: <bstr::ext_slice::SplitN as core::iter::traits::iterator::Iterator>::next Unexecuted instantiation: <bstr::ext_slice::SplitN as core::iter::traits::iterator::Iterator>::next |
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)] |
3602 | | pub struct SplitNReverse<'h, 's> { |
3603 | | split: SplitReverse<'h, 's>, |
3604 | | limit: usize, |
3605 | | count: usize, |
3606 | | } |
3607 | | |
3608 | | impl<'h, 's> SplitNReverse<'h, 's> { |
3609 | 0 | fn new( |
3610 | 0 | haystack: &'h [u8], |
3611 | 0 | splitter: &'s [u8], |
3612 | 0 | limit: usize, |
3613 | 0 | ) -> SplitNReverse<'h, 's> { |
3614 | 0 | let split = haystack.rsplit_str(splitter); |
3615 | 0 | SplitNReverse { split, limit, count: 0 } |
3616 | 0 | } Unexecuted instantiation: <bstr::ext_slice::SplitNReverse>::new Unexecuted instantiation: <bstr::ext_slice::SplitNReverse>::new Unexecuted instantiation: <bstr::ext_slice::SplitNReverse>::new |
3617 | | } |
3618 | | |
3619 | | impl<'h, 's> Iterator for SplitNReverse<'h, 's> { |
3620 | | type Item = &'h [u8]; |
3621 | | |
3622 | | #[inline] |
3623 | 0 | fn next(&mut self) -> Option<&'h [u8]> { |
3624 | 0 | self.count += 1; |
3625 | 0 | if self.count > self.limit || self.split.done { |
3626 | 0 | None |
3627 | 0 | } else if self.count == self.limit { |
3628 | 0 | Some(&self.split.finder.haystack()[..self.split.last]) |
3629 | | } else { |
3630 | 0 | self.split.next() |
3631 | | } |
3632 | 0 | } Unexecuted instantiation: <bstr::ext_slice::SplitNReverse as core::iter::traits::iterator::Iterator>::next Unexecuted instantiation: <bstr::ext_slice::SplitNReverse as core::iter::traits::iterator::Iterator>::next Unexecuted instantiation: <bstr::ext_slice::SplitNReverse as core::iter::traits::iterator::Iterator>::next |
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)] |
3642 | | pub struct Lines<'a> { |
3643 | | it: LinesWithTerminator<'a>, |
3644 | | } |
3645 | | |
3646 | | impl<'a> Lines<'a> { |
3647 | 34.5k | fn new(bytes: &'a [u8]) -> Lines<'a> { |
3648 | 34.5k | Lines { it: LinesWithTerminator::new(bytes) } |
3649 | 34.5k | } <bstr::ext_slice::Lines>::new Line | Count | Source | 3647 | 32.4k | fn new(bytes: &'a [u8]) -> Lines<'a> { | 3648 | 32.4k | Lines { it: LinesWithTerminator::new(bytes) } | 3649 | 32.4k | } |
<bstr::ext_slice::Lines>::new Line | Count | Source | 3647 | 2.16k | fn new(bytes: &'a [u8]) -> Lines<'a> { | 3648 | 2.16k | Lines { it: LinesWithTerminator::new(bytes) } | 3649 | 2.16k | } |
Unexecuted instantiation: <bstr::ext_slice::Lines>::new |
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 | 0 | pub fn as_bytes(&self) -> &'a [u8] { |
3670 | 0 | self.it.bytes |
3671 | 0 | } Unexecuted instantiation: <bstr::ext_slice::Lines>::as_bytes Unexecuted instantiation: <bstr::ext_slice::Lines>::as_bytes Unexecuted instantiation: <bstr::ext_slice::Lines>::as_bytes |
3672 | | } |
3673 | | |
3674 | | impl<'a> Iterator for Lines<'a> { |
3675 | | type Item = &'a [u8]; |
3676 | | |
3677 | | #[inline] |
3678 | 6.74M | fn next(&mut self) -> Option<&'a [u8]> { |
3679 | 6.74M | Some(trim_last_terminator(self.it.next()?)) |
3680 | 6.74M | } <bstr::ext_slice::Lines as core::iter::traits::iterator::Iterator>::next Line | Count | Source | 3678 | 5.19M | fn next(&mut self) -> Option<&'a [u8]> { | 3679 | 5.19M | Some(trim_last_terminator(self.it.next()?)) | 3680 | 5.19M | } |
<bstr::ext_slice::Lines as core::iter::traits::iterator::Iterator>::next Line | Count | Source | 3678 | 1.54M | fn next(&mut self) -> Option<&'a [u8]> { | 3679 | 1.54M | Some(trim_last_terminator(self.it.next()?)) | 3680 | 1.54M | } |
Unexecuted instantiation: <bstr::ext_slice::Lines as core::iter::traits::iterator::Iterator>::next |
3681 | | } |
3682 | | |
3683 | | impl<'a> DoubleEndedIterator for Lines<'a> { |
3684 | | #[inline] |
3685 | 0 | fn next_back(&mut self) -> Option<Self::Item> { |
3686 | 0 | Some(trim_last_terminator(self.it.next_back()?)) |
3687 | 0 | } Unexecuted instantiation: <bstr::ext_slice::Lines as core::iter::traits::double_ended::DoubleEndedIterator>::next_back Unexecuted instantiation: <bstr::ext_slice::Lines as core::iter::traits::double_ended::DoubleEndedIterator>::next_back Unexecuted instantiation: <bstr::ext_slice::Lines as core::iter::traits::double_ended::DoubleEndedIterator>::next_back |
3688 | | } |
3689 | | |
3690 | | impl<'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)] |
3706 | | pub struct LinesWithTerminator<'a> { |
3707 | | bytes: &'a [u8], |
3708 | | } |
3709 | | |
3710 | | impl<'a> LinesWithTerminator<'a> { |
3711 | 105k | fn new(bytes: &'a [u8]) -> LinesWithTerminator<'a> { |
3712 | 105k | LinesWithTerminator { bytes } |
3713 | 105k | } <bstr::ext_slice::LinesWithTerminator>::new Line | Count | Source | 3711 | 103k | fn new(bytes: &'a [u8]) -> LinesWithTerminator<'a> { | 3712 | 103k | LinesWithTerminator { bytes } | 3713 | 103k | } |
<bstr::ext_slice::LinesWithTerminator>::new Line | Count | Source | 3711 | 2.16k | fn new(bytes: &'a [u8]) -> LinesWithTerminator<'a> { | 3712 | 2.16k | LinesWithTerminator { bytes } | 3713 | 2.16k | } |
Unexecuted instantiation: <bstr::ext_slice::LinesWithTerminator>::new |
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 | 0 | pub fn as_bytes(&self) -> &'a [u8] { |
3734 | 0 | self.bytes |
3735 | 0 | } Unexecuted instantiation: <bstr::ext_slice::LinesWithTerminator>::as_bytes Unexecuted instantiation: <bstr::ext_slice::LinesWithTerminator>::as_bytes Unexecuted instantiation: <bstr::ext_slice::LinesWithTerminator>::as_bytes |
3736 | | } |
3737 | | |
3738 | | impl<'a> Iterator for LinesWithTerminator<'a> { |
3739 | | type Item = &'a [u8]; |
3740 | | |
3741 | | #[inline] |
3742 | 8.36M | fn next(&mut self) -> Option<&'a [u8]> { |
3743 | 8.36M | match self.bytes.find_byte(b'\n') { |
3744 | 123k | None if self.bytes.is_empty() => None, |
3745 | | None => { |
3746 | 22.9k | let line = self.bytes; |
3747 | 22.9k | self.bytes = b""; |
3748 | 22.9k | Some(line) |
3749 | | } |
3750 | 8.24M | Some(end) => { |
3751 | 8.24M | let line = &self.bytes[..=end]; |
3752 | 8.24M | self.bytes = &self.bytes[end + 1..]; |
3753 | 8.24M | Some(line) |
3754 | | } |
3755 | | } |
3756 | 8.36M | } <bstr::ext_slice::LinesWithTerminator as core::iter::traits::iterator::Iterator>::next Line | Count | Source | 3742 | 6.82M | fn next(&mut self) -> Option<&'a [u8]> { | 3743 | 6.82M | match self.bytes.find_byte(b'\n') { | 3744 | 120k | None if self.bytes.is_empty() => None, | 3745 | | None => { | 3746 | 21.7k | let line = self.bytes; | 3747 | 21.7k | self.bytes = b""; | 3748 | 21.7k | Some(line) | 3749 | | } | 3750 | 6.70M | Some(end) => { | 3751 | 6.70M | let line = &self.bytes[..=end]; | 3752 | 6.70M | self.bytes = &self.bytes[end + 1..]; | 3753 | 6.70M | Some(line) | 3754 | | } | 3755 | | } | 3756 | 6.82M | } |
<bstr::ext_slice::LinesWithTerminator as core::iter::traits::iterator::Iterator>::next Line | Count | Source | 3742 | 1.54M | fn next(&mut self) -> Option<&'a [u8]> { | 3743 | 1.54M | match self.bytes.find_byte(b'\n') { | 3744 | 3.25k | None if self.bytes.is_empty() => None, | 3745 | | None => { | 3746 | 1.22k | let line = self.bytes; | 3747 | 1.22k | self.bytes = b""; | 3748 | 1.22k | Some(line) | 3749 | | } | 3750 | 1.53M | Some(end) => { | 3751 | 1.53M | let line = &self.bytes[..=end]; | 3752 | 1.53M | self.bytes = &self.bytes[end + 1..]; | 3753 | 1.53M | Some(line) | 3754 | | } | 3755 | | } | 3756 | 1.54M | } |
Unexecuted instantiation: <bstr::ext_slice::LinesWithTerminator as core::iter::traits::iterator::Iterator>::next |
3757 | | } |
3758 | | |
3759 | | impl<'a> DoubleEndedIterator for LinesWithTerminator<'a> { |
3760 | | #[inline] |
3761 | 0 | fn next_back(&mut self) -> Option<Self::Item> { |
3762 | 0 | let end = self.bytes.len().checked_sub(1)?; |
3763 | 0 | match self.bytes[..end].rfind_byte(b'\n') { |
3764 | | None => { |
3765 | 0 | let line = self.bytes; |
3766 | 0 | self.bytes = b""; |
3767 | 0 | Some(line) |
3768 | | } |
3769 | 0 | Some(end) => { |
3770 | 0 | let line = &self.bytes[end + 1..]; |
3771 | 0 | self.bytes = &self.bytes[..=end]; |
3772 | 0 | Some(line) |
3773 | | } |
3774 | | } |
3775 | 0 | } Unexecuted instantiation: <bstr::ext_slice::LinesWithTerminator as core::iter::traits::double_ended::DoubleEndedIterator>::next_back Unexecuted instantiation: <bstr::ext_slice::LinesWithTerminator as core::iter::traits::double_ended::DoubleEndedIterator>::next_back Unexecuted instantiation: <bstr::ext_slice::LinesWithTerminator as core::iter::traits::double_ended::DoubleEndedIterator>::next_back |
3776 | | } |
3777 | | |
3778 | | impl<'a> iter::FusedIterator for LinesWithTerminator<'a> {} |
3779 | | |
3780 | 6.71M | fn trim_last_terminator(mut s: &[u8]) -> &[u8] { |
3781 | 6.71M | if s.last_byte() == Some(b'\n') { |
3782 | 6.68M | s = &s[..s.len() - 1]; |
3783 | 6.68M | if s.last_byte() == Some(b'\r') { |
3784 | 2.18k | s = &s[..s.len() - 1]; |
3785 | 6.68M | } |
3786 | 22.9k | } |
3787 | 6.71M | s |
3788 | 6.71M | } bstr::ext_slice::trim_last_terminator Line | Count | Source | 3780 | 5.17M | fn trim_last_terminator(mut s: &[u8]) -> &[u8] { | 3781 | 5.17M | if s.last_byte() == Some(b'\n') { | 3782 | 5.14M | s = &s[..s.len() - 1]; | 3783 | 5.14M | if s.last_byte() == Some(b'\r') { | 3784 | 291 | s = &s[..s.len() - 1]; | 3785 | 5.14M | } | 3786 | 21.7k | } | 3787 | 5.17M | s | 3788 | 5.17M | } |
bstr::ext_slice::trim_last_terminator Line | Count | Source | 3780 | 1.54M | fn trim_last_terminator(mut s: &[u8]) -> &[u8] { | 3781 | 1.54M | if s.last_byte() == Some(b'\n') { | 3782 | 1.53M | s = &s[..s.len() - 1]; | 3783 | 1.53M | if s.last_byte() == Some(b'\r') { | 3784 | 1.89k | s = &s[..s.len() - 1]; | 3785 | 1.53M | } | 3786 | 1.22k | } | 3787 | 1.54M | s | 3788 | 1.54M | } |
Unexecuted instantiation: bstr::ext_slice::trim_last_terminator |
3789 | | |
3790 | | #[cfg(all(test, feature = "std"))] |
3791 | | mod 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 | | } |