]>
Commit | Line | Data |
---|---|---|
1b1a35ee XL |
1 | //! Iterators for `str` methods. |
2 | ||
3 | use crate::char; | |
4 | use crate::fmt::{self, Write}; | |
5 | use crate::iter::TrustedRandomAccess; | |
6 | use crate::iter::{Chain, FlatMap, Flatten}; | |
7 | use crate::iter::{Copied, Filter, FusedIterator, Map, TrustedLen}; | |
8 | use crate::ops::Try; | |
9 | use crate::option; | |
10 | use crate::slice::{self, Split as SliceSplit}; | |
11 | ||
12 | use super::from_utf8_unchecked; | |
13 | use super::pattern::Pattern; | |
14 | use super::pattern::{DoubleEndedSearcher, ReverseSearcher, Searcher}; | |
15 | use super::validations::{next_code_point, next_code_point_reverse, utf8_is_cont_byte}; | |
16 | use super::LinesAnyMap; | |
17 | use super::{BytesIsNotEmpty, UnsafeBytesToStr}; | |
18 | use super::{CharEscapeDebugContinue, CharEscapeDefault, CharEscapeUnicode}; | |
19 | use super::{IsAsciiWhitespace, IsNotEmpty, IsWhitespace}; | |
20 | ||
21 | /// An iterator over the [`char`]s of a string slice. | |
22 | /// | |
23 | /// | |
24 | /// This struct is created by the [`chars`] method on [`str`]. | |
25 | /// See its documentation for more. | |
26 | /// | |
27 | /// [`char`]: prim@char | |
28 | /// [`chars`]: str::chars | |
29 | #[derive(Clone)] | |
30 | #[stable(feature = "rust1", since = "1.0.0")] | |
31 | pub struct Chars<'a> { | |
32 | pub(super) iter: slice::Iter<'a, u8>, | |
33 | } | |
34 | ||
35 | #[stable(feature = "rust1", since = "1.0.0")] | |
36 | impl<'a> Iterator for Chars<'a> { | |
37 | type Item = char; | |
38 | ||
39 | #[inline] | |
40 | fn next(&mut self) -> Option<char> { | |
41 | next_code_point(&mut self.iter).map(|ch| { | |
42 | // SAFETY: `str` invariant says `ch` is a valid Unicode Scalar Value. | |
43 | unsafe { char::from_u32_unchecked(ch) } | |
44 | }) | |
45 | } | |
46 | ||
47 | #[inline] | |
48 | fn count(self) -> usize { | |
49 | // length in `char` is equal to the number of non-continuation bytes | |
5869c6ff | 50 | self.iter.filter(|&&byte| !utf8_is_cont_byte(byte)).count() |
1b1a35ee XL |
51 | } |
52 | ||
53 | #[inline] | |
54 | fn size_hint(&self) -> (usize, Option<usize>) { | |
55 | let len = self.iter.len(); | |
56 | // `(len + 3)` can't overflow, because we know that the `slice::Iter` | |
57 | // belongs to a slice in memory which has a maximum length of | |
58 | // `isize::MAX` (that's well below `usize::MAX`). | |
59 | ((len + 3) / 4, Some(len)) | |
60 | } | |
61 | ||
62 | #[inline] | |
63 | fn last(mut self) -> Option<char> { | |
64 | // No need to go through the entire string. | |
65 | self.next_back() | |
66 | } | |
67 | } | |
68 | ||
69 | #[stable(feature = "chars_debug_impl", since = "1.38.0")] | |
70 | impl fmt::Debug for Chars<'_> { | |
71 | fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { | |
72 | write!(f, "Chars(")?; | |
73 | f.debug_list().entries(self.clone()).finish()?; | |
74 | write!(f, ")")?; | |
75 | Ok(()) | |
76 | } | |
77 | } | |
78 | ||
79 | #[stable(feature = "rust1", since = "1.0.0")] | |
80 | impl<'a> DoubleEndedIterator for Chars<'a> { | |
81 | #[inline] | |
82 | fn next_back(&mut self) -> Option<char> { | |
83 | next_code_point_reverse(&mut self.iter).map(|ch| { | |
84 | // SAFETY: `str` invariant says `ch` is a valid Unicode Scalar Value. | |
85 | unsafe { char::from_u32_unchecked(ch) } | |
86 | }) | |
87 | } | |
88 | } | |
89 | ||
90 | #[stable(feature = "fused", since = "1.26.0")] | |
91 | impl FusedIterator for Chars<'_> {} | |
92 | ||
93 | impl<'a> Chars<'a> { | |
94 | /// Views the underlying data as a subslice of the original data. | |
95 | /// | |
96 | /// This has the same lifetime as the original slice, and so the | |
97 | /// iterator can continue to be used while this exists. | |
98 | /// | |
99 | /// # Examples | |
100 | /// | |
101 | /// ``` | |
102 | /// let mut chars = "abc".chars(); | |
103 | /// | |
104 | /// assert_eq!(chars.as_str(), "abc"); | |
105 | /// chars.next(); | |
106 | /// assert_eq!(chars.as_str(), "bc"); | |
107 | /// chars.next(); | |
108 | /// chars.next(); | |
109 | /// assert_eq!(chars.as_str(), ""); | |
110 | /// ``` | |
111 | #[stable(feature = "iter_to_slice", since = "1.4.0")] | |
112 | #[inline] | |
113 | pub fn as_str(&self) -> &'a str { | |
114 | // SAFETY: `Chars` is only made from a str, which guarantees the iter is valid UTF-8. | |
115 | unsafe { from_utf8_unchecked(self.iter.as_slice()) } | |
116 | } | |
117 | } | |
118 | ||
119 | /// An iterator over the [`char`]s of a string slice, and their positions. | |
120 | /// | |
121 | /// This struct is created by the [`char_indices`] method on [`str`]. | |
122 | /// See its documentation for more. | |
123 | /// | |
124 | /// [`char`]: prim@char | |
125 | /// [`char_indices`]: str::char_indices | |
126 | #[derive(Clone, Debug)] | |
127 | #[stable(feature = "rust1", since = "1.0.0")] | |
128 | pub struct CharIndices<'a> { | |
129 | pub(super) front_offset: usize, | |
130 | pub(super) iter: Chars<'a>, | |
131 | } | |
132 | ||
133 | #[stable(feature = "rust1", since = "1.0.0")] | |
134 | impl<'a> Iterator for CharIndices<'a> { | |
135 | type Item = (usize, char); | |
136 | ||
137 | #[inline] | |
138 | fn next(&mut self) -> Option<(usize, char)> { | |
139 | let pre_len = self.iter.iter.len(); | |
140 | match self.iter.next() { | |
141 | None => None, | |
142 | Some(ch) => { | |
143 | let index = self.front_offset; | |
144 | let len = self.iter.iter.len(); | |
145 | self.front_offset += pre_len - len; | |
146 | Some((index, ch)) | |
147 | } | |
148 | } | |
149 | } | |
150 | ||
151 | #[inline] | |
152 | fn count(self) -> usize { | |
153 | self.iter.count() | |
154 | } | |
155 | ||
156 | #[inline] | |
157 | fn size_hint(&self) -> (usize, Option<usize>) { | |
158 | self.iter.size_hint() | |
159 | } | |
160 | ||
161 | #[inline] | |
162 | fn last(mut self) -> Option<(usize, char)> { | |
163 | // No need to go through the entire string. | |
164 | self.next_back() | |
165 | } | |
166 | } | |
167 | ||
168 | #[stable(feature = "rust1", since = "1.0.0")] | |
169 | impl<'a> DoubleEndedIterator for CharIndices<'a> { | |
170 | #[inline] | |
171 | fn next_back(&mut self) -> Option<(usize, char)> { | |
172 | self.iter.next_back().map(|ch| { | |
173 | let index = self.front_offset + self.iter.iter.len(); | |
174 | (index, ch) | |
175 | }) | |
176 | } | |
177 | } | |
178 | ||
179 | #[stable(feature = "fused", since = "1.26.0")] | |
180 | impl FusedIterator for CharIndices<'_> {} | |
181 | ||
182 | impl<'a> CharIndices<'a> { | |
183 | /// Views the underlying data as a subslice of the original data. | |
184 | /// | |
185 | /// This has the same lifetime as the original slice, and so the | |
186 | /// iterator can continue to be used while this exists. | |
187 | #[stable(feature = "iter_to_slice", since = "1.4.0")] | |
188 | #[inline] | |
189 | pub fn as_str(&self) -> &'a str { | |
190 | self.iter.as_str() | |
191 | } | |
cdc7bbd5 XL |
192 | |
193 | /// Returns the byte position of the next character, or the length | |
194 | /// of the underlying string if there are no more characters. | |
195 | /// | |
196 | /// # Examples | |
197 | /// | |
198 | /// ``` | |
199 | /// #![feature(char_indices_offset)] | |
200 | /// let mut chars = "a楽".char_indices(); | |
201 | /// | |
202 | /// assert_eq!(chars.offset(), 0); | |
203 | /// assert_eq!(chars.next(), Some((0, 'a'))); | |
204 | /// | |
205 | /// assert_eq!(chars.offset(), 1); | |
206 | /// assert_eq!(chars.next(), Some((1, '楽'))); | |
207 | /// | |
208 | /// assert_eq!(chars.offset(), 4); | |
209 | /// assert_eq!(chars.next(), None); | |
210 | /// ``` | |
211 | #[inline] | |
212 | #[unstable(feature = "char_indices_offset", issue = "83871")] | |
213 | pub fn offset(&self) -> usize { | |
214 | self.front_offset | |
215 | } | |
1b1a35ee XL |
216 | } |
217 | ||
218 | /// An iterator over the bytes of a string slice. | |
219 | /// | |
220 | /// This struct is created by the [`bytes`] method on [`str`]. | |
221 | /// See its documentation for more. | |
222 | /// | |
223 | /// [`bytes`]: str::bytes | |
224 | #[stable(feature = "rust1", since = "1.0.0")] | |
225 | #[derive(Clone, Debug)] | |
226 | pub struct Bytes<'a>(pub(super) Copied<slice::Iter<'a, u8>>); | |
227 | ||
228 | #[stable(feature = "rust1", since = "1.0.0")] | |
229 | impl Iterator for Bytes<'_> { | |
230 | type Item = u8; | |
231 | ||
232 | #[inline] | |
233 | fn next(&mut self) -> Option<u8> { | |
234 | self.0.next() | |
235 | } | |
236 | ||
237 | #[inline] | |
238 | fn size_hint(&self) -> (usize, Option<usize>) { | |
239 | self.0.size_hint() | |
240 | } | |
241 | ||
242 | #[inline] | |
243 | fn count(self) -> usize { | |
244 | self.0.count() | |
245 | } | |
246 | ||
247 | #[inline] | |
248 | fn last(self) -> Option<Self::Item> { | |
249 | self.0.last() | |
250 | } | |
251 | ||
252 | #[inline] | |
253 | fn nth(&mut self, n: usize) -> Option<Self::Item> { | |
254 | self.0.nth(n) | |
255 | } | |
256 | ||
257 | #[inline] | |
258 | fn all<F>(&mut self, f: F) -> bool | |
259 | where | |
260 | F: FnMut(Self::Item) -> bool, | |
261 | { | |
262 | self.0.all(f) | |
263 | } | |
264 | ||
265 | #[inline] | |
266 | fn any<F>(&mut self, f: F) -> bool | |
267 | where | |
268 | F: FnMut(Self::Item) -> bool, | |
269 | { | |
270 | self.0.any(f) | |
271 | } | |
272 | ||
273 | #[inline] | |
274 | fn find<P>(&mut self, predicate: P) -> Option<Self::Item> | |
275 | where | |
276 | P: FnMut(&Self::Item) -> bool, | |
277 | { | |
278 | self.0.find(predicate) | |
279 | } | |
280 | ||
281 | #[inline] | |
282 | fn position<P>(&mut self, predicate: P) -> Option<usize> | |
283 | where | |
284 | P: FnMut(Self::Item) -> bool, | |
285 | { | |
286 | self.0.position(predicate) | |
287 | } | |
288 | ||
289 | #[inline] | |
290 | fn rposition<P>(&mut self, predicate: P) -> Option<usize> | |
291 | where | |
292 | P: FnMut(Self::Item) -> bool, | |
293 | { | |
294 | self.0.rposition(predicate) | |
295 | } | |
296 | ||
297 | #[inline] | |
136023e0 | 298 | #[doc(hidden)] |
1b1a35ee XL |
299 | unsafe fn __iterator_get_unchecked(&mut self, idx: usize) -> u8 { |
300 | // SAFETY: the caller must uphold the safety contract | |
301 | // for `Iterator::__iterator_get_unchecked`. | |
302 | unsafe { self.0.__iterator_get_unchecked(idx) } | |
303 | } | |
304 | } | |
305 | ||
306 | #[stable(feature = "rust1", since = "1.0.0")] | |
307 | impl DoubleEndedIterator for Bytes<'_> { | |
308 | #[inline] | |
309 | fn next_back(&mut self) -> Option<u8> { | |
310 | self.0.next_back() | |
311 | } | |
312 | ||
313 | #[inline] | |
314 | fn nth_back(&mut self, n: usize) -> Option<Self::Item> { | |
315 | self.0.nth_back(n) | |
316 | } | |
317 | ||
318 | #[inline] | |
319 | fn rfind<P>(&mut self, predicate: P) -> Option<Self::Item> | |
320 | where | |
321 | P: FnMut(&Self::Item) -> bool, | |
322 | { | |
323 | self.0.rfind(predicate) | |
324 | } | |
325 | } | |
326 | ||
327 | #[stable(feature = "rust1", since = "1.0.0")] | |
328 | impl ExactSizeIterator for Bytes<'_> { | |
329 | #[inline] | |
330 | fn len(&self) -> usize { | |
331 | self.0.len() | |
332 | } | |
333 | ||
334 | #[inline] | |
335 | fn is_empty(&self) -> bool { | |
336 | self.0.is_empty() | |
337 | } | |
338 | } | |
339 | ||
340 | #[stable(feature = "fused", since = "1.26.0")] | |
341 | impl FusedIterator for Bytes<'_> {} | |
342 | ||
343 | #[unstable(feature = "trusted_len", issue = "37572")] | |
344 | unsafe impl TrustedLen for Bytes<'_> {} | |
345 | ||
346 | #[doc(hidden)] | |
347 | #[unstable(feature = "trusted_random_access", issue = "none")] | |
348 | unsafe impl TrustedRandomAccess for Bytes<'_> { | |
6a06907d | 349 | const MAY_HAVE_SIDE_EFFECT: bool = false; |
1b1a35ee XL |
350 | } |
351 | ||
352 | /// This macro generates a Clone impl for string pattern API | |
353 | /// wrapper types of the form X<'a, P> | |
354 | macro_rules! derive_pattern_clone { | |
355 | (clone $t:ident with |$s:ident| $e:expr) => { | |
356 | impl<'a, P> Clone for $t<'a, P> | |
357 | where | |
358 | P: Pattern<'a, Searcher: Clone>, | |
359 | { | |
360 | fn clone(&self) -> Self { | |
361 | let $s = self; | |
362 | $e | |
363 | } | |
364 | } | |
365 | }; | |
366 | } | |
367 | ||
368 | /// This macro generates two public iterator structs | |
369 | /// wrapping a private internal one that makes use of the `Pattern` API. | |
370 | /// | |
371 | /// For all patterns `P: Pattern<'a>` the following items will be | |
372 | /// generated (generics omitted): | |
373 | /// | |
374 | /// struct $forward_iterator($internal_iterator); | |
375 | /// struct $reverse_iterator($internal_iterator); | |
376 | /// | |
377 | /// impl Iterator for $forward_iterator | |
378 | /// { /* internal ends up calling Searcher::next_match() */ } | |
379 | /// | |
380 | /// impl DoubleEndedIterator for $forward_iterator | |
381 | /// where P::Searcher: DoubleEndedSearcher | |
382 | /// { /* internal ends up calling Searcher::next_match_back() */ } | |
383 | /// | |
384 | /// impl Iterator for $reverse_iterator | |
385 | /// where P::Searcher: ReverseSearcher | |
386 | /// { /* internal ends up calling Searcher::next_match_back() */ } | |
387 | /// | |
388 | /// impl DoubleEndedIterator for $reverse_iterator | |
389 | /// where P::Searcher: DoubleEndedSearcher | |
390 | /// { /* internal ends up calling Searcher::next_match() */ } | |
391 | /// | |
392 | /// The internal one is defined outside the macro, and has almost the same | |
393 | /// semantic as a DoubleEndedIterator by delegating to `pattern::Searcher` and | |
394 | /// `pattern::ReverseSearcher` for both forward and reverse iteration. | |
395 | /// | |
396 | /// "Almost", because a `Searcher` and a `ReverseSearcher` for a given | |
397 | /// `Pattern` might not return the same elements, so actually implementing | |
398 | /// `DoubleEndedIterator` for it would be incorrect. | |
399 | /// (See the docs in `str::pattern` for more details) | |
400 | /// | |
401 | /// However, the internal struct still represents a single ended iterator from | |
402 | /// either end, and depending on pattern is also a valid double ended iterator, | |
403 | /// so the two wrapper structs implement `Iterator` | |
404 | /// and `DoubleEndedIterator` depending on the concrete pattern type, leading | |
405 | /// to the complex impls seen above. | |
406 | macro_rules! generate_pattern_iterators { | |
407 | { | |
408 | // Forward iterator | |
409 | forward: | |
410 | $(#[$forward_iterator_attribute:meta])* | |
411 | struct $forward_iterator:ident; | |
412 | ||
413 | // Reverse iterator | |
414 | reverse: | |
415 | $(#[$reverse_iterator_attribute:meta])* | |
416 | struct $reverse_iterator:ident; | |
417 | ||
418 | // Stability of all generated items | |
419 | stability: | |
420 | $(#[$common_stability_attribute:meta])* | |
421 | ||
422 | // Internal almost-iterator that is being delegated to | |
423 | internal: | |
424 | $internal_iterator:ident yielding ($iterty:ty); | |
425 | ||
426 | // Kind of delegation - either single ended or double ended | |
427 | delegate $($t:tt)* | |
428 | } => { | |
429 | $(#[$forward_iterator_attribute])* | |
430 | $(#[$common_stability_attribute])* | |
431 | pub struct $forward_iterator<'a, P: Pattern<'a>>(pub(super) $internal_iterator<'a, P>); | |
432 | ||
433 | $(#[$common_stability_attribute])* | |
434 | impl<'a, P> fmt::Debug for $forward_iterator<'a, P> | |
435 | where | |
436 | P: Pattern<'a, Searcher: fmt::Debug>, | |
437 | { | |
438 | fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { | |
439 | f.debug_tuple(stringify!($forward_iterator)) | |
440 | .field(&self.0) | |
441 | .finish() | |
442 | } | |
443 | } | |
444 | ||
445 | $(#[$common_stability_attribute])* | |
446 | impl<'a, P: Pattern<'a>> Iterator for $forward_iterator<'a, P> { | |
447 | type Item = $iterty; | |
448 | ||
449 | #[inline] | |
450 | fn next(&mut self) -> Option<$iterty> { | |
451 | self.0.next() | |
452 | } | |
453 | } | |
454 | ||
455 | $(#[$common_stability_attribute])* | |
456 | impl<'a, P> Clone for $forward_iterator<'a, P> | |
457 | where | |
458 | P: Pattern<'a, Searcher: Clone>, | |
459 | { | |
460 | fn clone(&self) -> Self { | |
461 | $forward_iterator(self.0.clone()) | |
462 | } | |
463 | } | |
464 | ||
465 | $(#[$reverse_iterator_attribute])* | |
466 | $(#[$common_stability_attribute])* | |
467 | pub struct $reverse_iterator<'a, P: Pattern<'a>>(pub(super) $internal_iterator<'a, P>); | |
468 | ||
469 | $(#[$common_stability_attribute])* | |
470 | impl<'a, P> fmt::Debug for $reverse_iterator<'a, P> | |
471 | where | |
472 | P: Pattern<'a, Searcher: fmt::Debug>, | |
473 | { | |
474 | fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { | |
475 | f.debug_tuple(stringify!($reverse_iterator)) | |
476 | .field(&self.0) | |
477 | .finish() | |
478 | } | |
479 | } | |
480 | ||
481 | $(#[$common_stability_attribute])* | |
482 | impl<'a, P> Iterator for $reverse_iterator<'a, P> | |
483 | where | |
484 | P: Pattern<'a, Searcher: ReverseSearcher<'a>>, | |
485 | { | |
486 | type Item = $iterty; | |
487 | ||
488 | #[inline] | |
489 | fn next(&mut self) -> Option<$iterty> { | |
490 | self.0.next_back() | |
491 | } | |
492 | } | |
493 | ||
494 | $(#[$common_stability_attribute])* | |
495 | impl<'a, P> Clone for $reverse_iterator<'a, P> | |
496 | where | |
497 | P: Pattern<'a, Searcher: Clone>, | |
498 | { | |
499 | fn clone(&self) -> Self { | |
500 | $reverse_iterator(self.0.clone()) | |
501 | } | |
502 | } | |
503 | ||
504 | #[stable(feature = "fused", since = "1.26.0")] | |
505 | impl<'a, P: Pattern<'a>> FusedIterator for $forward_iterator<'a, P> {} | |
506 | ||
507 | #[stable(feature = "fused", since = "1.26.0")] | |
508 | impl<'a, P> FusedIterator for $reverse_iterator<'a, P> | |
509 | where | |
510 | P: Pattern<'a, Searcher: ReverseSearcher<'a>>, | |
511 | {} | |
512 | ||
513 | generate_pattern_iterators!($($t)* with $(#[$common_stability_attribute])*, | |
514 | $forward_iterator, | |
515 | $reverse_iterator, $iterty); | |
516 | }; | |
517 | { | |
518 | double ended; with $(#[$common_stability_attribute:meta])*, | |
519 | $forward_iterator:ident, | |
520 | $reverse_iterator:ident, $iterty:ty | |
521 | } => { | |
522 | $(#[$common_stability_attribute])* | |
523 | impl<'a, P> DoubleEndedIterator for $forward_iterator<'a, P> | |
524 | where | |
525 | P: Pattern<'a, Searcher: DoubleEndedSearcher<'a>>, | |
526 | { | |
527 | #[inline] | |
528 | fn next_back(&mut self) -> Option<$iterty> { | |
529 | self.0.next_back() | |
530 | } | |
531 | } | |
532 | ||
533 | $(#[$common_stability_attribute])* | |
534 | impl<'a, P> DoubleEndedIterator for $reverse_iterator<'a, P> | |
535 | where | |
536 | P: Pattern<'a, Searcher: DoubleEndedSearcher<'a>>, | |
537 | { | |
538 | #[inline] | |
539 | fn next_back(&mut self) -> Option<$iterty> { | |
540 | self.0.next() | |
541 | } | |
542 | } | |
543 | }; | |
544 | { | |
545 | single ended; with $(#[$common_stability_attribute:meta])*, | |
546 | $forward_iterator:ident, | |
547 | $reverse_iterator:ident, $iterty:ty | |
548 | } => {} | |
549 | } | |
550 | ||
551 | derive_pattern_clone! { | |
552 | clone SplitInternal | |
553 | with |s| SplitInternal { matcher: s.matcher.clone(), ..*s } | |
554 | } | |
555 | ||
556 | pub(super) struct SplitInternal<'a, P: Pattern<'a>> { | |
557 | pub(super) start: usize, | |
558 | pub(super) end: usize, | |
559 | pub(super) matcher: P::Searcher, | |
560 | pub(super) allow_trailing_empty: bool, | |
561 | pub(super) finished: bool, | |
562 | } | |
563 | ||
564 | impl<'a, P> fmt::Debug for SplitInternal<'a, P> | |
565 | where | |
566 | P: Pattern<'a, Searcher: fmt::Debug>, | |
567 | { | |
568 | fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { | |
569 | f.debug_struct("SplitInternal") | |
570 | .field("start", &self.start) | |
571 | .field("end", &self.end) | |
572 | .field("matcher", &self.matcher) | |
573 | .field("allow_trailing_empty", &self.allow_trailing_empty) | |
574 | .field("finished", &self.finished) | |
575 | .finish() | |
576 | } | |
577 | } | |
578 | ||
579 | impl<'a, P: Pattern<'a>> SplitInternal<'a, P> { | |
580 | #[inline] | |
581 | fn get_end(&mut self) -> Option<&'a str> { | |
582 | if !self.finished && (self.allow_trailing_empty || self.end - self.start > 0) { | |
583 | self.finished = true; | |
584 | // SAFETY: `self.start` and `self.end` always lie on unicode boundaries. | |
585 | unsafe { | |
586 | let string = self.matcher.haystack().get_unchecked(self.start..self.end); | |
587 | Some(string) | |
588 | } | |
589 | } else { | |
590 | None | |
591 | } | |
592 | } | |
593 | ||
594 | #[inline] | |
595 | fn next(&mut self) -> Option<&'a str> { | |
596 | if self.finished { | |
597 | return None; | |
598 | } | |
599 | ||
600 | let haystack = self.matcher.haystack(); | |
601 | match self.matcher.next_match() { | |
602 | // SAFETY: `Searcher` guarantees that `a` and `b` lie on unicode boundaries. | |
603 | Some((a, b)) => unsafe { | |
604 | let elt = haystack.get_unchecked(self.start..a); | |
605 | self.start = b; | |
606 | Some(elt) | |
607 | }, | |
608 | None => self.get_end(), | |
609 | } | |
610 | } | |
611 | ||
612 | #[inline] | |
613 | fn next_inclusive(&mut self) -> Option<&'a str> { | |
614 | if self.finished { | |
615 | return None; | |
616 | } | |
617 | ||
618 | let haystack = self.matcher.haystack(); | |
619 | match self.matcher.next_match() { | |
620 | // SAFETY: `Searcher` guarantees that `b` lies on unicode boundary, | |
621 | // and self.start is either the start of the original string, | |
622 | // or `b` was assigned to it, so it also lies on unicode boundary. | |
623 | Some((_, b)) => unsafe { | |
624 | let elt = haystack.get_unchecked(self.start..b); | |
625 | self.start = b; | |
626 | Some(elt) | |
627 | }, | |
628 | None => self.get_end(), | |
629 | } | |
630 | } | |
631 | ||
632 | #[inline] | |
633 | fn next_back(&mut self) -> Option<&'a str> | |
634 | where | |
635 | P::Searcher: ReverseSearcher<'a>, | |
636 | { | |
637 | if self.finished { | |
638 | return None; | |
639 | } | |
640 | ||
641 | if !self.allow_trailing_empty { | |
642 | self.allow_trailing_empty = true; | |
643 | match self.next_back() { | |
644 | Some(elt) if !elt.is_empty() => return Some(elt), | |
645 | _ => { | |
646 | if self.finished { | |
647 | return None; | |
648 | } | |
649 | } | |
650 | } | |
651 | } | |
652 | ||
653 | let haystack = self.matcher.haystack(); | |
654 | match self.matcher.next_match_back() { | |
655 | // SAFETY: `Searcher` guarantees that `a` and `b` lie on unicode boundaries. | |
656 | Some((a, b)) => unsafe { | |
657 | let elt = haystack.get_unchecked(b..self.end); | |
658 | self.end = a; | |
659 | Some(elt) | |
660 | }, | |
661 | // SAFETY: `self.start` and `self.end` always lie on unicode boundaries. | |
662 | None => unsafe { | |
663 | self.finished = true; | |
664 | Some(haystack.get_unchecked(self.start..self.end)) | |
665 | }, | |
666 | } | |
667 | } | |
668 | ||
669 | #[inline] | |
670 | fn next_back_inclusive(&mut self) -> Option<&'a str> | |
671 | where | |
672 | P::Searcher: ReverseSearcher<'a>, | |
673 | { | |
674 | if self.finished { | |
675 | return None; | |
676 | } | |
677 | ||
678 | if !self.allow_trailing_empty { | |
679 | self.allow_trailing_empty = true; | |
680 | match self.next_back_inclusive() { | |
681 | Some(elt) if !elt.is_empty() => return Some(elt), | |
682 | _ => { | |
683 | if self.finished { | |
684 | return None; | |
685 | } | |
686 | } | |
687 | } | |
688 | } | |
689 | ||
690 | let haystack = self.matcher.haystack(); | |
691 | match self.matcher.next_match_back() { | |
692 | // SAFETY: `Searcher` guarantees that `b` lies on unicode boundary, | |
693 | // and self.end is either the end of the original string, | |
694 | // or `b` was assigned to it, so it also lies on unicode boundary. | |
695 | Some((_, b)) => unsafe { | |
696 | let elt = haystack.get_unchecked(b..self.end); | |
697 | self.end = b; | |
698 | Some(elt) | |
699 | }, | |
700 | // SAFETY: self.start is either the start of the original string, | |
701 | // or start of a substring that represents the part of the string that hasn't | |
702 | // iterated yet. Either way, it is guaranteed to lie on unicode boundary. | |
703 | // self.end is either the end of the original string, | |
704 | // or `b` was assigned to it, so it also lies on unicode boundary. | |
705 | None => unsafe { | |
706 | self.finished = true; | |
707 | Some(haystack.get_unchecked(self.start..self.end)) | |
708 | }, | |
709 | } | |
710 | } | |
29967ef6 XL |
711 | |
712 | #[inline] | |
713 | fn as_str(&self) -> &'a str { | |
714 | // `Self::get_end` doesn't change `self.start` | |
715 | if self.finished { | |
716 | return ""; | |
717 | } | |
718 | ||
719 | // SAFETY: `self.start` and `self.end` always lie on unicode boundaries. | |
720 | unsafe { self.matcher.haystack().get_unchecked(self.start..self.end) } | |
721 | } | |
1b1a35ee XL |
722 | } |
723 | ||
724 | generate_pattern_iterators! { | |
725 | forward: | |
726 | /// Created with the method [`split`]. | |
727 | /// | |
728 | /// [`split`]: str::split | |
729 | struct Split; | |
730 | reverse: | |
731 | /// Created with the method [`rsplit`]. | |
732 | /// | |
733 | /// [`rsplit`]: str::rsplit | |
734 | struct RSplit; | |
735 | stability: | |
736 | #[stable(feature = "rust1", since = "1.0.0")] | |
737 | internal: | |
738 | SplitInternal yielding (&'a str); | |
739 | delegate double ended; | |
740 | } | |
741 | ||
29967ef6 XL |
742 | impl<'a, P: Pattern<'a>> Split<'a, P> { |
743 | /// Returns remainder of the splitted string | |
744 | /// | |
745 | /// # Examples | |
746 | /// | |
747 | /// ``` | |
748 | /// #![feature(str_split_as_str)] | |
749 | /// let mut split = "Mary had a little lamb".split(' '); | |
750 | /// assert_eq!(split.as_str(), "Mary had a little lamb"); | |
751 | /// split.next(); | |
752 | /// assert_eq!(split.as_str(), "had a little lamb"); | |
753 | /// split.by_ref().for_each(drop); | |
754 | /// assert_eq!(split.as_str(), ""); | |
755 | /// ``` | |
756 | #[inline] | |
757 | #[unstable(feature = "str_split_as_str", issue = "77998")] | |
758 | pub fn as_str(&self) -> &'a str { | |
759 | self.0.as_str() | |
760 | } | |
761 | } | |
762 | ||
763 | impl<'a, P: Pattern<'a>> RSplit<'a, P> { | |
764 | /// Returns remainder of the splitted string | |
765 | /// | |
766 | /// # Examples | |
767 | /// | |
768 | /// ``` | |
769 | /// #![feature(str_split_as_str)] | |
770 | /// let mut split = "Mary had a little lamb".rsplit(' '); | |
771 | /// assert_eq!(split.as_str(), "Mary had a little lamb"); | |
772 | /// split.next(); | |
773 | /// assert_eq!(split.as_str(), "Mary had a little"); | |
774 | /// split.by_ref().for_each(drop); | |
775 | /// assert_eq!(split.as_str(), ""); | |
776 | /// ``` | |
777 | #[inline] | |
778 | #[unstable(feature = "str_split_as_str", issue = "77998")] | |
779 | pub fn as_str(&self) -> &'a str { | |
780 | self.0.as_str() | |
781 | } | |
782 | } | |
783 | ||
1b1a35ee XL |
784 | generate_pattern_iterators! { |
785 | forward: | |
786 | /// Created with the method [`split_terminator`]. | |
787 | /// | |
788 | /// [`split_terminator`]: str::split_terminator | |
789 | struct SplitTerminator; | |
790 | reverse: | |
791 | /// Created with the method [`rsplit_terminator`]. | |
792 | /// | |
793 | /// [`rsplit_terminator`]: str::rsplit_terminator | |
794 | struct RSplitTerminator; | |
795 | stability: | |
796 | #[stable(feature = "rust1", since = "1.0.0")] | |
797 | internal: | |
798 | SplitInternal yielding (&'a str); | |
799 | delegate double ended; | |
800 | } | |
801 | ||
29967ef6 XL |
802 | impl<'a, P: Pattern<'a>> SplitTerminator<'a, P> { |
803 | /// Returns remainder of the splitted string | |
804 | /// | |
805 | /// # Examples | |
806 | /// | |
807 | /// ``` | |
808 | /// #![feature(str_split_as_str)] | |
809 | /// let mut split = "A..B..".split_terminator('.'); | |
810 | /// assert_eq!(split.as_str(), "A..B.."); | |
811 | /// split.next(); | |
812 | /// assert_eq!(split.as_str(), ".B.."); | |
813 | /// split.by_ref().for_each(drop); | |
814 | /// assert_eq!(split.as_str(), ""); | |
815 | /// ``` | |
816 | #[inline] | |
817 | #[unstable(feature = "str_split_as_str", issue = "77998")] | |
818 | pub fn as_str(&self) -> &'a str { | |
819 | self.0.as_str() | |
820 | } | |
821 | } | |
822 | ||
823 | impl<'a, P: Pattern<'a>> RSplitTerminator<'a, P> { | |
824 | /// Returns remainder of the splitted string | |
825 | /// | |
826 | /// # Examples | |
827 | /// | |
828 | /// ``` | |
829 | /// #![feature(str_split_as_str)] | |
830 | /// let mut split = "A..B..".rsplit_terminator('.'); | |
831 | /// assert_eq!(split.as_str(), "A..B.."); | |
832 | /// split.next(); | |
833 | /// assert_eq!(split.as_str(), "A..B"); | |
834 | /// split.by_ref().for_each(drop); | |
835 | /// assert_eq!(split.as_str(), ""); | |
836 | /// ``` | |
837 | #[inline] | |
838 | #[unstable(feature = "str_split_as_str", issue = "77998")] | |
839 | pub fn as_str(&self) -> &'a str { | |
840 | self.0.as_str() | |
841 | } | |
842 | } | |
843 | ||
1b1a35ee XL |
844 | derive_pattern_clone! { |
845 | clone SplitNInternal | |
846 | with |s| SplitNInternal { iter: s.iter.clone(), ..*s } | |
847 | } | |
848 | ||
849 | pub(super) struct SplitNInternal<'a, P: Pattern<'a>> { | |
850 | pub(super) iter: SplitInternal<'a, P>, | |
851 | /// The number of splits remaining | |
852 | pub(super) count: usize, | |
853 | } | |
854 | ||
855 | impl<'a, P> fmt::Debug for SplitNInternal<'a, P> | |
856 | where | |
857 | P: Pattern<'a, Searcher: fmt::Debug>, | |
858 | { | |
859 | fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { | |
860 | f.debug_struct("SplitNInternal") | |
861 | .field("iter", &self.iter) | |
862 | .field("count", &self.count) | |
863 | .finish() | |
864 | } | |
865 | } | |
866 | ||
867 | impl<'a, P: Pattern<'a>> SplitNInternal<'a, P> { | |
868 | #[inline] | |
869 | fn next(&mut self) -> Option<&'a str> { | |
870 | match self.count { | |
871 | 0 => None, | |
872 | 1 => { | |
873 | self.count = 0; | |
874 | self.iter.get_end() | |
875 | } | |
876 | _ => { | |
877 | self.count -= 1; | |
878 | self.iter.next() | |
879 | } | |
880 | } | |
881 | } | |
882 | ||
883 | #[inline] | |
884 | fn next_back(&mut self) -> Option<&'a str> | |
885 | where | |
886 | P::Searcher: ReverseSearcher<'a>, | |
887 | { | |
888 | match self.count { | |
889 | 0 => None, | |
890 | 1 => { | |
891 | self.count = 0; | |
892 | self.iter.get_end() | |
893 | } | |
894 | _ => { | |
895 | self.count -= 1; | |
896 | self.iter.next_back() | |
897 | } | |
898 | } | |
899 | } | |
29967ef6 XL |
900 | |
901 | #[inline] | |
902 | fn as_str(&self) -> &'a str { | |
903 | self.iter.as_str() | |
904 | } | |
1b1a35ee XL |
905 | } |
906 | ||
907 | generate_pattern_iterators! { | |
908 | forward: | |
909 | /// Created with the method [`splitn`]. | |
910 | /// | |
911 | /// [`splitn`]: str::splitn | |
912 | struct SplitN; | |
913 | reverse: | |
914 | /// Created with the method [`rsplitn`]. | |
915 | /// | |
916 | /// [`rsplitn`]: str::rsplitn | |
917 | struct RSplitN; | |
918 | stability: | |
919 | #[stable(feature = "rust1", since = "1.0.0")] | |
920 | internal: | |
921 | SplitNInternal yielding (&'a str); | |
922 | delegate single ended; | |
923 | } | |
924 | ||
29967ef6 XL |
925 | impl<'a, P: Pattern<'a>> SplitN<'a, P> { |
926 | /// Returns remainder of the splitted string | |
927 | /// | |
928 | /// # Examples | |
929 | /// | |
930 | /// ``` | |
931 | /// #![feature(str_split_as_str)] | |
932 | /// let mut split = "Mary had a little lamb".splitn(3, ' '); | |
933 | /// assert_eq!(split.as_str(), "Mary had a little lamb"); | |
934 | /// split.next(); | |
935 | /// assert_eq!(split.as_str(), "had a little lamb"); | |
936 | /// split.by_ref().for_each(drop); | |
937 | /// assert_eq!(split.as_str(), ""); | |
938 | /// ``` | |
939 | #[inline] | |
940 | #[unstable(feature = "str_split_as_str", issue = "77998")] | |
941 | pub fn as_str(&self) -> &'a str { | |
942 | self.0.as_str() | |
943 | } | |
944 | } | |
945 | ||
946 | impl<'a, P: Pattern<'a>> RSplitN<'a, P> { | |
947 | /// Returns remainder of the splitted string | |
948 | /// | |
949 | /// # Examples | |
950 | /// | |
951 | /// ``` | |
952 | /// #![feature(str_split_as_str)] | |
953 | /// let mut split = "Mary had a little lamb".rsplitn(3, ' '); | |
954 | /// assert_eq!(split.as_str(), "Mary had a little lamb"); | |
955 | /// split.next(); | |
956 | /// assert_eq!(split.as_str(), "Mary had a little"); | |
957 | /// split.by_ref().for_each(drop); | |
958 | /// assert_eq!(split.as_str(), ""); | |
959 | /// ``` | |
960 | #[inline] | |
961 | #[unstable(feature = "str_split_as_str", issue = "77998")] | |
962 | pub fn as_str(&self) -> &'a str { | |
963 | self.0.as_str() | |
964 | } | |
965 | } | |
966 | ||
1b1a35ee XL |
967 | derive_pattern_clone! { |
968 | clone MatchIndicesInternal | |
969 | with |s| MatchIndicesInternal(s.0.clone()) | |
970 | } | |
971 | ||
972 | pub(super) struct MatchIndicesInternal<'a, P: Pattern<'a>>(pub(super) P::Searcher); | |
973 | ||
974 | impl<'a, P> fmt::Debug for MatchIndicesInternal<'a, P> | |
975 | where | |
976 | P: Pattern<'a, Searcher: fmt::Debug>, | |
977 | { | |
978 | fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { | |
979 | f.debug_tuple("MatchIndicesInternal").field(&self.0).finish() | |
980 | } | |
981 | } | |
982 | ||
983 | impl<'a, P: Pattern<'a>> MatchIndicesInternal<'a, P> { | |
984 | #[inline] | |
985 | fn next(&mut self) -> Option<(usize, &'a str)> { | |
986 | self.0 | |
987 | .next_match() | |
988 | // SAFETY: `Searcher` guarantees that `start` and `end` lie on unicode boundaries. | |
989 | .map(|(start, end)| unsafe { (start, self.0.haystack().get_unchecked(start..end)) }) | |
990 | } | |
991 | ||
992 | #[inline] | |
993 | fn next_back(&mut self) -> Option<(usize, &'a str)> | |
994 | where | |
995 | P::Searcher: ReverseSearcher<'a>, | |
996 | { | |
997 | self.0 | |
998 | .next_match_back() | |
999 | // SAFETY: `Searcher` guarantees that `start` and `end` lie on unicode boundaries. | |
1000 | .map(|(start, end)| unsafe { (start, self.0.haystack().get_unchecked(start..end)) }) | |
1001 | } | |
1002 | } | |
1003 | ||
1004 | generate_pattern_iterators! { | |
1005 | forward: | |
1006 | /// Created with the method [`match_indices`]. | |
1007 | /// | |
1008 | /// [`match_indices`]: str::match_indices | |
1009 | struct MatchIndices; | |
1010 | reverse: | |
1011 | /// Created with the method [`rmatch_indices`]. | |
1012 | /// | |
1013 | /// [`rmatch_indices`]: str::rmatch_indices | |
1014 | struct RMatchIndices; | |
1015 | stability: | |
1016 | #[stable(feature = "str_match_indices", since = "1.5.0")] | |
1017 | internal: | |
1018 | MatchIndicesInternal yielding ((usize, &'a str)); | |
1019 | delegate double ended; | |
1020 | } | |
1021 | ||
1022 | derive_pattern_clone! { | |
1023 | clone MatchesInternal | |
1024 | with |s| MatchesInternal(s.0.clone()) | |
1025 | } | |
1026 | ||
1027 | pub(super) struct MatchesInternal<'a, P: Pattern<'a>>(pub(super) P::Searcher); | |
1028 | ||
1029 | impl<'a, P> fmt::Debug for MatchesInternal<'a, P> | |
1030 | where | |
1031 | P: Pattern<'a, Searcher: fmt::Debug>, | |
1032 | { | |
1033 | fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { | |
1034 | f.debug_tuple("MatchesInternal").field(&self.0).finish() | |
1035 | } | |
1036 | } | |
1037 | ||
1038 | impl<'a, P: Pattern<'a>> MatchesInternal<'a, P> { | |
1039 | #[inline] | |
1040 | fn next(&mut self) -> Option<&'a str> { | |
1041 | // SAFETY: `Searcher` guarantees that `start` and `end` lie on unicode boundaries. | |
1042 | self.0.next_match().map(|(a, b)| unsafe { | |
1043 | // Indices are known to be on utf8 boundaries | |
1044 | self.0.haystack().get_unchecked(a..b) | |
1045 | }) | |
1046 | } | |
1047 | ||
1048 | #[inline] | |
1049 | fn next_back(&mut self) -> Option<&'a str> | |
1050 | where | |
1051 | P::Searcher: ReverseSearcher<'a>, | |
1052 | { | |
1053 | // SAFETY: `Searcher` guarantees that `start` and `end` lie on unicode boundaries. | |
1054 | self.0.next_match_back().map(|(a, b)| unsafe { | |
1055 | // Indices are known to be on utf8 boundaries | |
1056 | self.0.haystack().get_unchecked(a..b) | |
1057 | }) | |
1058 | } | |
1059 | } | |
1060 | ||
1061 | generate_pattern_iterators! { | |
1062 | forward: | |
1063 | /// Created with the method [`matches`]. | |
1064 | /// | |
1065 | /// [`matches`]: str::matches | |
1066 | struct Matches; | |
1067 | reverse: | |
1068 | /// Created with the method [`rmatches`]. | |
1069 | /// | |
1070 | /// [`rmatches`]: str::rmatches | |
1071 | struct RMatches; | |
1072 | stability: | |
1073 | #[stable(feature = "str_matches", since = "1.2.0")] | |
1074 | internal: | |
1075 | MatchesInternal yielding (&'a str); | |
1076 | delegate double ended; | |
1077 | } | |
1078 | ||
1079 | /// An iterator over the lines of a string, as string slices. | |
1080 | /// | |
1081 | /// This struct is created with the [`lines`] method on [`str`]. | |
1082 | /// See its documentation for more. | |
1083 | /// | |
1084 | /// [`lines`]: str::lines | |
1085 | #[stable(feature = "rust1", since = "1.0.0")] | |
1086 | #[derive(Clone, Debug)] | |
1087 | pub struct Lines<'a>(pub(super) Map<SplitTerminator<'a, char>, LinesAnyMap>); | |
1088 | ||
1089 | #[stable(feature = "rust1", since = "1.0.0")] | |
1090 | impl<'a> Iterator for Lines<'a> { | |
1091 | type Item = &'a str; | |
1092 | ||
1093 | #[inline] | |
1094 | fn next(&mut self) -> Option<&'a str> { | |
1095 | self.0.next() | |
1096 | } | |
1097 | ||
1098 | #[inline] | |
1099 | fn size_hint(&self) -> (usize, Option<usize>) { | |
1100 | self.0.size_hint() | |
1101 | } | |
1102 | ||
1103 | #[inline] | |
1104 | fn last(mut self) -> Option<&'a str> { | |
1105 | self.next_back() | |
1106 | } | |
1107 | } | |
1108 | ||
1109 | #[stable(feature = "rust1", since = "1.0.0")] | |
1110 | impl<'a> DoubleEndedIterator for Lines<'a> { | |
1111 | #[inline] | |
1112 | fn next_back(&mut self) -> Option<&'a str> { | |
1113 | self.0.next_back() | |
1114 | } | |
1115 | } | |
1116 | ||
1117 | #[stable(feature = "fused", since = "1.26.0")] | |
1118 | impl FusedIterator for Lines<'_> {} | |
1119 | ||
1120 | /// Created with the method [`lines_any`]. | |
1121 | /// | |
1122 | /// [`lines_any`]: str::lines_any | |
1123 | #[stable(feature = "rust1", since = "1.0.0")] | |
1124 | #[rustc_deprecated(since = "1.4.0", reason = "use lines()/Lines instead now")] | |
1125 | #[derive(Clone, Debug)] | |
1126 | #[allow(deprecated)] | |
1127 | pub struct LinesAny<'a>(pub(super) Lines<'a>); | |
1128 | ||
1129 | #[stable(feature = "rust1", since = "1.0.0")] | |
1130 | #[allow(deprecated)] | |
1131 | impl<'a> Iterator for LinesAny<'a> { | |
1132 | type Item = &'a str; | |
1133 | ||
1134 | #[inline] | |
1135 | fn next(&mut self) -> Option<&'a str> { | |
1136 | self.0.next() | |
1137 | } | |
1138 | ||
1139 | #[inline] | |
1140 | fn size_hint(&self) -> (usize, Option<usize>) { | |
1141 | self.0.size_hint() | |
1142 | } | |
1143 | } | |
1144 | ||
1145 | #[stable(feature = "rust1", since = "1.0.0")] | |
1146 | #[allow(deprecated)] | |
1147 | impl<'a> DoubleEndedIterator for LinesAny<'a> { | |
1148 | #[inline] | |
1149 | fn next_back(&mut self) -> Option<&'a str> { | |
1150 | self.0.next_back() | |
1151 | } | |
1152 | } | |
1153 | ||
1154 | #[stable(feature = "fused", since = "1.26.0")] | |
1155 | #[allow(deprecated)] | |
1156 | impl FusedIterator for LinesAny<'_> {} | |
1157 | ||
1158 | /// An iterator over the non-whitespace substrings of a string, | |
1159 | /// separated by any amount of whitespace. | |
1160 | /// | |
1161 | /// This struct is created by the [`split_whitespace`] method on [`str`]. | |
1162 | /// See its documentation for more. | |
1163 | /// | |
1164 | /// [`split_whitespace`]: str::split_whitespace | |
1165 | #[stable(feature = "split_whitespace", since = "1.1.0")] | |
1166 | #[derive(Clone, Debug)] | |
1167 | pub struct SplitWhitespace<'a> { | |
1168 | pub(super) inner: Filter<Split<'a, IsWhitespace>, IsNotEmpty>, | |
1169 | } | |
1170 | ||
1171 | /// An iterator over the non-ASCII-whitespace substrings of a string, | |
1172 | /// separated by any amount of ASCII whitespace. | |
1173 | /// | |
1174 | /// This struct is created by the [`split_ascii_whitespace`] method on [`str`]. | |
1175 | /// See its documentation for more. | |
1176 | /// | |
1177 | /// [`split_ascii_whitespace`]: str::split_ascii_whitespace | |
1178 | #[stable(feature = "split_ascii_whitespace", since = "1.34.0")] | |
1179 | #[derive(Clone, Debug)] | |
1180 | pub struct SplitAsciiWhitespace<'a> { | |
1181 | pub(super) inner: | |
1182 | Map<Filter<SliceSplit<'a, u8, IsAsciiWhitespace>, BytesIsNotEmpty>, UnsafeBytesToStr>, | |
1183 | } | |
1184 | ||
1185 | /// An iterator over the substrings of a string, | |
1186 | /// terminated by a substring matching to a predicate function | |
1187 | /// Unlike `Split`, it contains the matched part as a terminator | |
1188 | /// of the subslice. | |
1189 | /// | |
1190 | /// This struct is created by the [`split_inclusive`] method on [`str`]. | |
1191 | /// See its documentation for more. | |
1192 | /// | |
1193 | /// [`split_inclusive`]: str::split_inclusive | |
5869c6ff | 1194 | #[stable(feature = "split_inclusive", since = "1.51.0")] |
1b1a35ee XL |
1195 | pub struct SplitInclusive<'a, P: Pattern<'a>>(pub(super) SplitInternal<'a, P>); |
1196 | ||
1197 | #[stable(feature = "split_whitespace", since = "1.1.0")] | |
1198 | impl<'a> Iterator for SplitWhitespace<'a> { | |
1199 | type Item = &'a str; | |
1200 | ||
1201 | #[inline] | |
1202 | fn next(&mut self) -> Option<&'a str> { | |
1203 | self.inner.next() | |
1204 | } | |
1205 | ||
1206 | #[inline] | |
1207 | fn size_hint(&self) -> (usize, Option<usize>) { | |
1208 | self.inner.size_hint() | |
1209 | } | |
1210 | ||
1211 | #[inline] | |
1212 | fn last(mut self) -> Option<&'a str> { | |
1213 | self.next_back() | |
1214 | } | |
1215 | } | |
1216 | ||
1217 | #[stable(feature = "split_whitespace", since = "1.1.0")] | |
1218 | impl<'a> DoubleEndedIterator for SplitWhitespace<'a> { | |
1219 | #[inline] | |
1220 | fn next_back(&mut self) -> Option<&'a str> { | |
1221 | self.inner.next_back() | |
1222 | } | |
1223 | } | |
1224 | ||
1225 | #[stable(feature = "fused", since = "1.26.0")] | |
1226 | impl FusedIterator for SplitWhitespace<'_> {} | |
1227 | ||
6a06907d XL |
1228 | impl<'a> SplitWhitespace<'a> { |
1229 | /// Returns remainder of the splitted string | |
1230 | /// | |
1231 | /// # Examples | |
1232 | /// | |
1233 | /// ``` | |
1234 | /// #![feature(str_split_whitespace_as_str)] | |
1235 | /// | |
1236 | /// let mut split = "Mary had a little lamb".split_whitespace(); | |
1237 | /// assert_eq!(split.as_str(), "Mary had a little lamb"); | |
1238 | /// | |
1239 | /// split.next(); | |
1240 | /// assert_eq!(split.as_str(), "had a little lamb"); | |
1241 | /// | |
1242 | /// split.by_ref().for_each(drop); | |
1243 | /// assert_eq!(split.as_str(), ""); | |
1244 | /// ``` | |
1245 | #[inline] | |
1246 | #[unstable(feature = "str_split_whitespace_as_str", issue = "77998")] | |
1247 | pub fn as_str(&self) -> &'a str { | |
1248 | self.inner.iter.as_str() | |
1249 | } | |
1250 | } | |
1251 | ||
1b1a35ee XL |
1252 | #[stable(feature = "split_ascii_whitespace", since = "1.34.0")] |
1253 | impl<'a> Iterator for SplitAsciiWhitespace<'a> { | |
1254 | type Item = &'a str; | |
1255 | ||
1256 | #[inline] | |
1257 | fn next(&mut self) -> Option<&'a str> { | |
1258 | self.inner.next() | |
1259 | } | |
1260 | ||
1261 | #[inline] | |
1262 | fn size_hint(&self) -> (usize, Option<usize>) { | |
1263 | self.inner.size_hint() | |
1264 | } | |
1265 | ||
1266 | #[inline] | |
1267 | fn last(mut self) -> Option<&'a str> { | |
1268 | self.next_back() | |
1269 | } | |
1270 | } | |
1271 | ||
1272 | #[stable(feature = "split_ascii_whitespace", since = "1.34.0")] | |
1273 | impl<'a> DoubleEndedIterator for SplitAsciiWhitespace<'a> { | |
1274 | #[inline] | |
1275 | fn next_back(&mut self) -> Option<&'a str> { | |
1276 | self.inner.next_back() | |
1277 | } | |
1278 | } | |
1279 | ||
1280 | #[stable(feature = "split_ascii_whitespace", since = "1.34.0")] | |
1281 | impl FusedIterator for SplitAsciiWhitespace<'_> {} | |
1282 | ||
6a06907d XL |
1283 | impl<'a> SplitAsciiWhitespace<'a> { |
1284 | /// Returns remainder of the splitted string | |
1285 | /// | |
1286 | /// # Examples | |
1287 | /// | |
1288 | /// ``` | |
1289 | /// #![feature(str_split_whitespace_as_str)] | |
1290 | /// | |
1291 | /// let mut split = "Mary had a little lamb".split_ascii_whitespace(); | |
1292 | /// assert_eq!(split.as_str(), "Mary had a little lamb"); | |
1293 | /// | |
1294 | /// split.next(); | |
1295 | /// assert_eq!(split.as_str(), "had a little lamb"); | |
1296 | /// | |
1297 | /// split.by_ref().for_each(drop); | |
1298 | /// assert_eq!(split.as_str(), ""); | |
1299 | /// ``` | |
1300 | #[inline] | |
1301 | #[unstable(feature = "str_split_whitespace_as_str", issue = "77998")] | |
1302 | pub fn as_str(&self) -> &'a str { | |
1303 | if self.inner.iter.iter.finished { | |
1304 | return ""; | |
1305 | } | |
1306 | ||
1307 | // SAFETY: Slice is created from str. | |
1308 | unsafe { crate::str::from_utf8_unchecked(&self.inner.iter.iter.v) } | |
1309 | } | |
1310 | } | |
1311 | ||
5869c6ff | 1312 | #[stable(feature = "split_inclusive", since = "1.51.0")] |
1b1a35ee XL |
1313 | impl<'a, P: Pattern<'a>> Iterator for SplitInclusive<'a, P> { |
1314 | type Item = &'a str; | |
1315 | ||
1316 | #[inline] | |
1317 | fn next(&mut self) -> Option<&'a str> { | |
1318 | self.0.next_inclusive() | |
1319 | } | |
1320 | } | |
1321 | ||
5869c6ff | 1322 | #[stable(feature = "split_inclusive", since = "1.51.0")] |
1b1a35ee XL |
1323 | impl<'a, P: Pattern<'a, Searcher: fmt::Debug>> fmt::Debug for SplitInclusive<'a, P> { |
1324 | fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { | |
1325 | f.debug_struct("SplitInclusive").field("0", &self.0).finish() | |
1326 | } | |
1327 | } | |
1328 | ||
1329 | // FIXME(#26925) Remove in favor of `#[derive(Clone)]` | |
5869c6ff | 1330 | #[stable(feature = "split_inclusive", since = "1.51.0")] |
1b1a35ee XL |
1331 | impl<'a, P: Pattern<'a, Searcher: Clone>> Clone for SplitInclusive<'a, P> { |
1332 | fn clone(&self) -> Self { | |
1333 | SplitInclusive(self.0.clone()) | |
1334 | } | |
1335 | } | |
1336 | ||
5869c6ff | 1337 | #[stable(feature = "split_inclusive", since = "1.51.0")] |
1b1a35ee XL |
1338 | impl<'a, P: Pattern<'a, Searcher: ReverseSearcher<'a>>> DoubleEndedIterator |
1339 | for SplitInclusive<'a, P> | |
1340 | { | |
1341 | #[inline] | |
1342 | fn next_back(&mut self) -> Option<&'a str> { | |
1343 | self.0.next_back_inclusive() | |
1344 | } | |
1345 | } | |
1346 | ||
5869c6ff | 1347 | #[stable(feature = "split_inclusive", since = "1.51.0")] |
1b1a35ee XL |
1348 | impl<'a, P: Pattern<'a>> FusedIterator for SplitInclusive<'a, P> {} |
1349 | ||
29967ef6 XL |
1350 | impl<'a, P: Pattern<'a>> SplitInclusive<'a, P> { |
1351 | /// Returns remainder of the splitted string | |
1352 | /// | |
1353 | /// # Examples | |
1354 | /// | |
1355 | /// ``` | |
1356 | /// #![feature(str_split_inclusive_as_str)] | |
29967ef6 XL |
1357 | /// let mut split = "Mary had a little lamb".split_inclusive(' '); |
1358 | /// assert_eq!(split.as_str(), "Mary had a little lamb"); | |
1359 | /// split.next(); | |
1360 | /// assert_eq!(split.as_str(), "had a little lamb"); | |
1361 | /// split.by_ref().for_each(drop); | |
1362 | /// assert_eq!(split.as_str(), ""); | |
1363 | /// ``` | |
1364 | #[inline] | |
1365 | #[unstable(feature = "str_split_inclusive_as_str", issue = "77998")] | |
1366 | pub fn as_str(&self) -> &'a str { | |
1367 | self.0.as_str() | |
1368 | } | |
1369 | } | |
1370 | ||
1b1a35ee XL |
1371 | /// An iterator of [`u16`] over the string encoded as UTF-16. |
1372 | /// | |
1373 | /// This struct is created by the [`encode_utf16`] method on [`str`]. | |
1374 | /// See its documentation for more. | |
1375 | /// | |
1376 | /// [`encode_utf16`]: str::encode_utf16 | |
1377 | #[derive(Clone)] | |
1378 | #[stable(feature = "encode_utf16", since = "1.8.0")] | |
1379 | pub struct EncodeUtf16<'a> { | |
1380 | pub(super) chars: Chars<'a>, | |
1381 | pub(super) extra: u16, | |
1382 | } | |
1383 | ||
1384 | #[stable(feature = "collection_debug", since = "1.17.0")] | |
1385 | impl fmt::Debug for EncodeUtf16<'_> { | |
1386 | fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { | |
cdc7bbd5 | 1387 | f.debug_struct("EncodeUtf16").finish_non_exhaustive() |
1b1a35ee XL |
1388 | } |
1389 | } | |
1390 | ||
1391 | #[stable(feature = "encode_utf16", since = "1.8.0")] | |
1392 | impl<'a> Iterator for EncodeUtf16<'a> { | |
1393 | type Item = u16; | |
1394 | ||
1395 | #[inline] | |
1396 | fn next(&mut self) -> Option<u16> { | |
1397 | if self.extra != 0 { | |
1398 | let tmp = self.extra; | |
1399 | self.extra = 0; | |
1400 | return Some(tmp); | |
1401 | } | |
1402 | ||
1403 | let mut buf = [0; 2]; | |
1404 | self.chars.next().map(|ch| { | |
1405 | let n = ch.encode_utf16(&mut buf).len(); | |
1406 | if n == 2 { | |
1407 | self.extra = buf[1]; | |
1408 | } | |
1409 | buf[0] | |
1410 | }) | |
1411 | } | |
1412 | ||
1413 | #[inline] | |
1414 | fn size_hint(&self) -> (usize, Option<usize>) { | |
1415 | let (low, high) = self.chars.size_hint(); | |
1416 | // every char gets either one u16 or two u16, | |
1417 | // so this iterator is between 1 or 2 times as | |
1418 | // long as the underlying iterator. | |
1419 | (low, high.and_then(|n| n.checked_mul(2))) | |
1420 | } | |
1421 | } | |
1422 | ||
1423 | #[stable(feature = "fused", since = "1.26.0")] | |
1424 | impl FusedIterator for EncodeUtf16<'_> {} | |
1425 | ||
1426 | /// The return type of [`str::escape_debug`]. | |
1427 | #[stable(feature = "str_escape", since = "1.34.0")] | |
1428 | #[derive(Clone, Debug)] | |
1429 | pub struct EscapeDebug<'a> { | |
1430 | pub(super) inner: Chain< | |
1431 | Flatten<option::IntoIter<char::EscapeDebug>>, | |
1432 | FlatMap<Chars<'a>, char::EscapeDebug, CharEscapeDebugContinue>, | |
1433 | >, | |
1434 | } | |
1435 | ||
1436 | /// The return type of [`str::escape_default`]. | |
1437 | #[stable(feature = "str_escape", since = "1.34.0")] | |
1438 | #[derive(Clone, Debug)] | |
1439 | pub struct EscapeDefault<'a> { | |
1440 | pub(super) inner: FlatMap<Chars<'a>, char::EscapeDefault, CharEscapeDefault>, | |
1441 | } | |
1442 | ||
1443 | /// The return type of [`str::escape_unicode`]. | |
1444 | #[stable(feature = "str_escape", since = "1.34.0")] | |
1445 | #[derive(Clone, Debug)] | |
1446 | pub struct EscapeUnicode<'a> { | |
1447 | pub(super) inner: FlatMap<Chars<'a>, char::EscapeUnicode, CharEscapeUnicode>, | |
1448 | } | |
1449 | ||
1450 | macro_rules! escape_types_impls { | |
1451 | ($( $Name: ident ),+) => {$( | |
1452 | #[stable(feature = "str_escape", since = "1.34.0")] | |
1453 | impl<'a> fmt::Display for $Name<'a> { | |
1454 | fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { | |
1455 | self.clone().try_for_each(|c| f.write_char(c)) | |
1456 | } | |
1457 | } | |
1458 | ||
1459 | #[stable(feature = "str_escape", since = "1.34.0")] | |
1460 | impl<'a> Iterator for $Name<'a> { | |
1461 | type Item = char; | |
1462 | ||
1463 | #[inline] | |
1464 | fn next(&mut self) -> Option<char> { self.inner.next() } | |
1465 | ||
1466 | #[inline] | |
1467 | fn size_hint(&self) -> (usize, Option<usize>) { self.inner.size_hint() } | |
1468 | ||
1469 | #[inline] | |
1470 | fn try_fold<Acc, Fold, R>(&mut self, init: Acc, fold: Fold) -> R where | |
17df50a5 | 1471 | Self: Sized, Fold: FnMut(Acc, Self::Item) -> R, R: Try<Output = Acc> |
1b1a35ee XL |
1472 | { |
1473 | self.inner.try_fold(init, fold) | |
1474 | } | |
1475 | ||
1476 | #[inline] | |
1477 | fn fold<Acc, Fold>(self, init: Acc, fold: Fold) -> Acc | |
1478 | where Fold: FnMut(Acc, Self::Item) -> Acc, | |
1479 | { | |
1480 | self.inner.fold(init, fold) | |
1481 | } | |
1482 | } | |
1483 | ||
1484 | #[stable(feature = "str_escape", since = "1.34.0")] | |
1485 | impl<'a> FusedIterator for $Name<'a> {} | |
1486 | )+} | |
1487 | } | |
1488 | ||
1489 | escape_types_impls!(EscapeDebug, EscapeDefault, EscapeUnicode); |