1#[cfg(not(feature = "ferrocene_subset"))]
4use super::pattern::{DoubleEndedSearcher, Pattern, ReverseSearcher, Searcher};
5use super::validations::{next_code_point, next_code_point_reverse};
6#[cfg(not(feature = "ferrocene_subset"))]
7use super::{
8 BytesIsNotEmpty, CharEscapeDebugContinue, CharEscapeDefault, CharEscapeUnicode,
9 IsAsciiWhitespace, IsNotEmpty, IsWhitespace, LinesMap, UnsafeBytesToStr, from_utf8_unchecked,
10};
11#[cfg(not(feature = "ferrocene_subset"))]
12use crate::fmt::{self, Write};
13#[cfg(not(feature = "ferrocene_subset"))]
14use crate::iter::{
15 Chain, Copied, Filter, FlatMap, Flatten, FusedIterator, Map, TrustedLen, TrustedRandomAccess,
16 TrustedRandomAccessNoCoerce,
17};
18use crate::num::NonZero;
19#[cfg(not(feature = "ferrocene_subset"))]
20use crate::ops::Try;
21#[cfg(not(feature = "ferrocene_subset"))]
22use crate::slice::{self, Split as SliceSplit};
23#[cfg(not(feature = "ferrocene_subset"))]
24use crate::{char as char_mod, option};
25
26#[cfg(feature = "ferrocene_subset")]
28#[rustfmt::skip]
29use {
30 super::{
31 from_utf8_unchecked,
32 pattern::{Pattern, Searcher},
33 },
34 crate::{fmt, iter::Copied, slice},
35};
36
37#[derive(Clone)]
46#[must_use = "iterators are lazy and do nothing unless consumed"]
47#[stable(feature = "rust1", since = "1.0.0")]
48pub struct Chars<'a> {
49 pub(super) iter: slice::Iter<'a, u8>,
50}
51
52#[stable(feature = "rust1", since = "1.0.0")]
53impl<'a> Iterator for Chars<'a> {
54 type Item = char;
55
56 #[inline]
57 fn next(&mut self) -> Option<char> {
58 unsafe { next_code_point(&mut self.iter).map(|ch| char::from_u32_unchecked(ch)) }
61 }
62
63 #[inline]
64 fn count(self) -> usize {
65 super::count::count_chars(self.as_str())
66 }
67
68 #[inline]
69 fn advance_by(&mut self, mut remainder: usize) -> Result<(), NonZero<usize>> {
70 const CHUNK_SIZE: usize = 32;
71
72 if remainder >= CHUNK_SIZE {
73 let mut chunks = self.iter.as_slice().as_chunks::<CHUNK_SIZE>().0.iter();
74 let mut bytes_skipped: usize = 0;
75
76 while remainder > CHUNK_SIZE
77 && let Some(chunk) = chunks.next()
78 {
79 bytes_skipped += CHUNK_SIZE;
80
81 let mut start_bytes = [false; CHUNK_SIZE];
82
83 for i in 0..CHUNK_SIZE {
84 start_bytes[i] = !super::validations::utf8_is_cont_byte(chunk[i]);
85 }
86
87 remainder -= start_bytes.into_iter().map(|i| i as u8).sum::<u8>() as usize;
88 }
89
90 unsafe { self.iter.advance_by(bytes_skipped).unwrap_unchecked() };
93
94 while self.iter.len() > 0 {
96 let b = self.iter.as_slice()[0];
97 if !super::validations::utf8_is_cont_byte(b) {
98 break;
99 }
100 unsafe { self.iter.advance_by(1).unwrap_unchecked() };
102 }
103 }
104
105 while (remainder > 0) && (self.iter.len() > 0) {
106 remainder -= 1;
107 let b = self.iter.as_slice()[0];
108 let slurp = super::validations::utf8_char_width(b);
109 unsafe { self.iter.advance_by(slurp).unwrap_unchecked() };
112 }
113
114 NonZero::new(remainder).map_or(Ok(()), Err)
115 }
116
117 #[inline]
118 fn size_hint(&self) -> (usize, Option<usize>) {
119 let len = self.iter.len();
120 (len.div_ceil(4), Some(len))
121 }
122
123 #[inline]
124 fn last(mut self) -> Option<char> {
125 self.next_back()
127 }
128}
129
130#[stable(feature = "chars_debug_impl", since = "1.38.0")]
131impl fmt::Debug for Chars<'_> {
132 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
133 write!(f, "Chars(")?;
134 f.debug_list().entries(self.clone()).finish()?;
135 write!(f, ")")?;
136 Ok(())
137 }
138}
139
140#[stable(feature = "rust1", since = "1.0.0")]
141impl<'a> DoubleEndedIterator for Chars<'a> {
142 #[inline]
143 fn next_back(&mut self) -> Option<char> {
144 unsafe { next_code_point_reverse(&mut self.iter).map(|ch| char::from_u32_unchecked(ch)) }
147 }
148}
149
150#[cfg(not(feature = "ferrocene_subset"))]
151#[stable(feature = "fused", since = "1.26.0")]
152impl FusedIterator for Chars<'_> {}
153
154impl<'a> Chars<'a> {
155 #[stable(feature = "iter_to_slice", since = "1.4.0")]
173 #[must_use]
174 #[inline]
175 pub fn as_str(&self) -> &'a str {
176 unsafe { from_utf8_unchecked(self.iter.as_slice()) }
178 }
179}
180
181#[derive(Clone, Debug)]
189#[must_use = "iterators are lazy and do nothing unless consumed"]
190#[stable(feature = "rust1", since = "1.0.0")]
191pub struct CharIndices<'a> {
192 pub(super) front_offset: usize,
193 pub(super) iter: Chars<'a>,
194}
195
196#[stable(feature = "rust1", since = "1.0.0")]
197impl<'a> Iterator for CharIndices<'a> {
198 type Item = (usize, char);
199
200 #[inline]
201 fn next(&mut self) -> Option<(usize, char)> {
202 let pre_len = self.iter.iter.len();
203 match self.iter.next() {
204 None => None,
205 Some(ch) => {
206 let index = self.front_offset;
207 let len = self.iter.iter.len();
208 self.front_offset += pre_len - len;
209 Some((index, ch))
210 }
211 }
212 }
213
214 #[inline]
215 fn count(self) -> usize {
216 self.iter.count()
217 }
218
219 #[inline]
220 fn size_hint(&self) -> (usize, Option<usize>) {
221 self.iter.size_hint()
222 }
223
224 #[inline]
225 fn last(mut self) -> Option<(usize, char)> {
226 self.next_back()
228 }
229}
230
231#[stable(feature = "rust1", since = "1.0.0")]
232impl<'a> DoubleEndedIterator for CharIndices<'a> {
233 #[inline]
234 fn next_back(&mut self) -> Option<(usize, char)> {
235 self.iter.next_back().map(|ch| {
236 let index = self.front_offset + self.iter.iter.len();
237 (index, ch)
238 })
239 }
240}
241
242#[cfg(not(feature = "ferrocene_subset"))]
243#[stable(feature = "fused", since = "1.26.0")]
244impl FusedIterator for CharIndices<'_> {}
245
246impl<'a> CharIndices<'a> {
247 #[stable(feature = "iter_to_slice", since = "1.4.0")]
252 #[must_use]
253 #[inline]
254 pub fn as_str(&self) -> &'a str {
255 self.iter.as_str()
256 }
257
258 #[inline]
288 #[must_use]
289 #[stable(feature = "char_indices_offset", since = "1.82.0")]
290 pub fn offset(&self) -> usize {
291 self.front_offset
292 }
293}
294
295#[must_use = "iterators are lazy and do nothing unless consumed"]
302#[stable(feature = "rust1", since = "1.0.0")]
303#[derive(Clone, Debug)]
304pub struct Bytes<'a>(pub(super) Copied<slice::Iter<'a, u8>>);
305
306#[stable(feature = "rust1", since = "1.0.0")]
307impl Iterator for Bytes<'_> {
308 type Item = u8;
309
310 #[inline]
311 fn next(&mut self) -> Option<u8> {
312 self.0.next()
313 }
314
315 #[inline]
316 fn size_hint(&self) -> (usize, Option<usize>) {
317 self.0.size_hint()
318 }
319
320 #[inline]
321 fn count(self) -> usize {
322 self.0.count()
323 }
324
325 #[inline]
326 fn last(self) -> Option<Self::Item> {
327 self.0.last()
328 }
329
330 #[inline]
331 fn nth(&mut self, n: usize) -> Option<Self::Item> {
332 self.0.nth(n)
333 }
334
335 #[inline]
336 fn all<F>(&mut self, f: F) -> bool
337 where
338 F: FnMut(Self::Item) -> bool,
339 {
340 self.0.all(f)
341 }
342
343 #[inline]
344 fn any<F>(&mut self, f: F) -> bool
345 where
346 F: FnMut(Self::Item) -> bool,
347 {
348 self.0.any(f)
349 }
350
351 #[inline]
352 fn find<P>(&mut self, predicate: P) -> Option<Self::Item>
353 where
354 P: FnMut(&Self::Item) -> bool,
355 {
356 self.0.find(predicate)
357 }
358
359 #[inline]
360 fn position<P>(&mut self, predicate: P) -> Option<usize>
361 where
362 P: FnMut(Self::Item) -> bool,
363 {
364 self.0.position(predicate)
365 }
366
367 #[inline]
368 fn rposition<P>(&mut self, predicate: P) -> Option<usize>
369 where
370 P: FnMut(Self::Item) -> bool,
371 {
372 self.0.rposition(predicate)
373 }
374
375 #[cfg(not(feature = "ferrocene_subset"))]
376 #[inline]
377 unsafe fn __iterator_get_unchecked(&mut self, idx: usize) -> u8 {
378 unsafe { self.0.__iterator_get_unchecked(idx) }
381 }
382}
383
384#[cfg(not(feature = "ferrocene_subset"))]
385#[stable(feature = "rust1", since = "1.0.0")]
386impl DoubleEndedIterator for Bytes<'_> {
387 #[inline]
388 fn next_back(&mut self) -> Option<u8> {
389 self.0.next_back()
390 }
391
392 #[inline]
393 fn nth_back(&mut self, n: usize) -> Option<Self::Item> {
394 self.0.nth_back(n)
395 }
396
397 #[inline]
398 fn rfind<P>(&mut self, predicate: P) -> Option<Self::Item>
399 where
400 P: FnMut(&Self::Item) -> bool,
401 {
402 self.0.rfind(predicate)
403 }
404}
405
406#[cfg(not(feature = "ferrocene_subset"))]
407#[stable(feature = "rust1", since = "1.0.0")]
408impl ExactSizeIterator for Bytes<'_> {
409 #[inline]
410 fn len(&self) -> usize {
411 self.0.len()
412 }
413
414 #[inline]
415 fn is_empty(&self) -> bool {
416 self.0.is_empty()
417 }
418}
419
420#[cfg(not(feature = "ferrocene_subset"))]
421#[stable(feature = "fused", since = "1.26.0")]
422impl FusedIterator for Bytes<'_> {}
423
424#[cfg(not(feature = "ferrocene_subset"))]
425#[unstable(feature = "trusted_len", issue = "37572")]
426unsafe impl TrustedLen for Bytes<'_> {}
427
428#[cfg(not(feature = "ferrocene_subset"))]
429#[doc(hidden)]
430#[unstable(feature = "trusted_random_access", issue = "none")]
431unsafe impl TrustedRandomAccess for Bytes<'_> {}
432
433#[cfg(not(feature = "ferrocene_subset"))]
434#[doc(hidden)]
435#[unstable(feature = "trusted_random_access", issue = "none")]
436unsafe impl TrustedRandomAccessNoCoerce for Bytes<'_> {
437 const MAY_HAVE_SIDE_EFFECT: bool = false;
438}
439
440#[cfg(not(feature = "ferrocene_subset"))]
443macro_rules! derive_pattern_clone {
444 (clone $t:ident with |$s:ident| $e:expr) => {
445 impl<'a, P> Clone for $t<'a, P>
446 where
447 P: Pattern<Searcher<'a>: Clone>,
448 {
449 fn clone(&self) -> Self {
450 let $s = self;
451 $e
452 }
453 }
454 };
455}
456
457#[cfg(not(feature = "ferrocene_subset"))]
496macro_rules! generate_pattern_iterators {
497 {
498 forward:
500 $(#[$forward_iterator_attribute:meta])*
501 struct $forward_iterator:ident;
502
503 reverse:
505 $(#[$reverse_iterator_attribute:meta])*
506 struct $reverse_iterator:ident;
507
508 stability:
510 $(#[$common_stability_attribute:meta])*
511
512 internal:
514 $internal_iterator:ident yielding ($iterty:ty);
515
516 delegate $($t:tt)*
518 } => {
519 $(#[$forward_iterator_attribute])*
520 $(#[$common_stability_attribute])*
521 pub struct $forward_iterator<'a, P: Pattern>(pub(super) $internal_iterator<'a, P>);
522
523 $(#[$common_stability_attribute])*
524 impl<'a, P> fmt::Debug for $forward_iterator<'a, P>
525 where
526 P: Pattern<Searcher<'a>: fmt::Debug>,
527 {
528 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
529 f.debug_tuple(stringify!($forward_iterator))
530 .field(&self.0)
531 .finish()
532 }
533 }
534
535 $(#[$common_stability_attribute])*
536 impl<'a, P: Pattern> Iterator for $forward_iterator<'a, P> {
537 type Item = $iterty;
538
539 #[inline]
540 fn next(&mut self) -> Option<$iterty> {
541 self.0.next()
542 }
543 }
544
545 $(#[$common_stability_attribute])*
546 impl<'a, P> Clone for $forward_iterator<'a, P>
547 where
548 P: Pattern<Searcher<'a>: Clone>,
549 {
550 fn clone(&self) -> Self {
551 $forward_iterator(self.0.clone())
552 }
553 }
554
555 $(#[$reverse_iterator_attribute])*
556 $(#[$common_stability_attribute])*
557 pub struct $reverse_iterator<'a, P: Pattern>(pub(super) $internal_iterator<'a, P>);
558
559 $(#[$common_stability_attribute])*
560 impl<'a, P> fmt::Debug for $reverse_iterator<'a, P>
561 where
562 P: Pattern<Searcher<'a>: fmt::Debug>,
563 {
564 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
565 f.debug_tuple(stringify!($reverse_iterator))
566 .field(&self.0)
567 .finish()
568 }
569 }
570
571 $(#[$common_stability_attribute])*
572 impl<'a, P> Iterator for $reverse_iterator<'a, P>
573 where
574 P: Pattern<Searcher<'a>: ReverseSearcher<'a>>,
575 {
576 type Item = $iterty;
577
578 #[inline]
579 fn next(&mut self) -> Option<$iterty> {
580 self.0.next_back()
581 }
582 }
583
584 $(#[$common_stability_attribute])*
585 impl<'a, P> Clone for $reverse_iterator<'a, P>
586 where
587 P: Pattern<Searcher<'a>: Clone>,
588 {
589 fn clone(&self) -> Self {
590 $reverse_iterator(self.0.clone())
591 }
592 }
593
594 #[stable(feature = "fused", since = "1.26.0")]
595 impl<'a, P: Pattern> FusedIterator for $forward_iterator<'a, P> {}
596
597 #[stable(feature = "fused", since = "1.26.0")]
598 impl<'a, P> FusedIterator for $reverse_iterator<'a, P>
599 where
600 P: Pattern<Searcher<'a>: ReverseSearcher<'a>>,
601 {}
602
603 generate_pattern_iterators!($($t)* with $(#[$common_stability_attribute])*,
604 $forward_iterator,
605 $reverse_iterator, $iterty);
606 };
607 {
608 double ended; with $(#[$common_stability_attribute:meta])*,
609 $forward_iterator:ident,
610 $reverse_iterator:ident, $iterty:ty
611 } => {
612 $(#[$common_stability_attribute])*
613 impl<'a, P> DoubleEndedIterator for $forward_iterator<'a, P>
614 where
615 P: Pattern<Searcher<'a>: DoubleEndedSearcher<'a>>,
616 {
617 #[inline]
618 fn next_back(&mut self) -> Option<$iterty> {
619 self.0.next_back()
620 }
621 }
622
623 $(#[$common_stability_attribute])*
624 impl<'a, P> DoubleEndedIterator for $reverse_iterator<'a, P>
625 where
626 P: Pattern<Searcher<'a>: DoubleEndedSearcher<'a>>,
627 {
628 #[inline]
629 fn next_back(&mut self) -> Option<$iterty> {
630 self.0.next()
631 }
632 }
633 };
634 {
635 single ended; with $(#[$common_stability_attribute:meta])*,
636 $forward_iterator:ident,
637 $reverse_iterator:ident, $iterty:ty
638 } => {}
639}
640
641#[cfg(not(feature = "ferrocene_subset"))]
642derive_pattern_clone! {
643 clone SplitInternal
644 with |s| SplitInternal { matcher: s.matcher.clone(), ..*s }
645}
646
647pub(super) struct SplitInternal<'a, P: Pattern> {
648 pub(super) start: usize,
649 pub(super) end: usize,
650 pub(super) matcher: P::Searcher<'a>,
651 pub(super) allow_trailing_empty: bool,
652 pub(super) finished: bool,
653}
654
655impl<'a, P> fmt::Debug for SplitInternal<'a, P>
656where
657 P: Pattern<Searcher<'a>: fmt::Debug>,
658{
659 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
660 f.debug_struct("SplitInternal")
661 .field("start", &self.start)
662 .field("end", &self.end)
663 .field("matcher", &self.matcher)
664 .field("allow_trailing_empty", &self.allow_trailing_empty)
665 .field("finished", &self.finished)
666 .finish()
667 }
668}
669
670impl<'a, P: Pattern> SplitInternal<'a, P> {
671 #[inline]
672 fn get_end(&mut self) -> Option<&'a str> {
673 if !self.finished {
674 self.finished = true;
675
676 if self.allow_trailing_empty || self.end - self.start > 0 {
677 let string = unsafe { self.matcher.haystack().get_unchecked(self.start..self.end) };
679 return Some(string);
680 }
681 }
682
683 None
684 }
685
686 #[inline]
687 #[cfg(not(feature = "ferrocene_subset"))]
688 fn next(&mut self) -> Option<&'a str> {
689 if self.finished {
690 return None;
691 }
692
693 let haystack = self.matcher.haystack();
694 match self.matcher.next_match() {
695 Some((a, b)) => unsafe {
697 let elt = haystack.get_unchecked(self.start..a);
698 self.start = b;
699 Some(elt)
700 },
701 None => self.get_end(),
702 }
703 }
704
705 #[inline]
706 fn next_inclusive(&mut self) -> Option<&'a str> {
707 if self.finished {
708 return None;
709 }
710
711 let haystack = self.matcher.haystack();
712 match self.matcher.next_match() {
713 Some((_, b)) => unsafe {
717 let elt = haystack.get_unchecked(self.start..b);
718 self.start = b;
719 Some(elt)
720 },
721 None => self.get_end(),
722 }
723 }
724
725 #[inline]
726 #[cfg(not(feature = "ferrocene_subset"))]
727 fn next_back(&mut self) -> Option<&'a str>
728 where
729 P::Searcher<'a>: ReverseSearcher<'a>,
730 {
731 if self.finished {
732 return None;
733 }
734
735 if !self.allow_trailing_empty {
736 self.allow_trailing_empty = true;
737 match self.next_back() {
738 Some(elt) if !elt.is_empty() => return Some(elt),
739 _ => {
740 if self.finished {
741 return None;
742 }
743 }
744 }
745 }
746
747 let haystack = self.matcher.haystack();
748 match self.matcher.next_match_back() {
749 Some((a, b)) => unsafe {
751 let elt = haystack.get_unchecked(b..self.end);
752 self.end = a;
753 Some(elt)
754 },
755 None => unsafe {
757 self.finished = true;
758 Some(haystack.get_unchecked(self.start..self.end))
759 },
760 }
761 }
762
763 #[inline]
764 #[cfg(not(feature = "ferrocene_subset"))]
765 fn next_back_inclusive(&mut self) -> Option<&'a str>
766 where
767 P::Searcher<'a>: ReverseSearcher<'a>,
768 {
769 if self.finished {
770 return None;
771 }
772
773 if !self.allow_trailing_empty {
774 self.allow_trailing_empty = true;
775 match self.next_back_inclusive() {
776 Some(elt) if !elt.is_empty() => return Some(elt),
777 _ => {
778 if self.finished {
779 return None;
780 }
781 }
782 }
783 }
784
785 let haystack = self.matcher.haystack();
786 match self.matcher.next_match_back() {
787 Some((_, b)) => unsafe {
791 let elt = haystack.get_unchecked(b..self.end);
792 self.end = b;
793 Some(elt)
794 },
795 None => unsafe {
801 self.finished = true;
802 Some(haystack.get_unchecked(self.start..self.end))
803 },
804 }
805 }
806
807 #[inline]
808 #[cfg(not(feature = "ferrocene_subset"))]
809 fn remainder(&self) -> Option<&'a str> {
810 if self.finished {
812 return None;
813 }
814
815 Some(unsafe { self.matcher.haystack().get_unchecked(self.start..self.end) })
817 }
818}
819
820#[cfg(not(feature = "ferrocene_subset"))]
821generate_pattern_iterators! {
822 forward:
823 struct Split;
827 reverse:
828 struct RSplit;
832 stability:
833 #[stable(feature = "rust1", since = "1.0.0")]
834 internal:
835 SplitInternal yielding (&'a str);
836 delegate double ended;
837}
838
839#[cfg(not(feature = "ferrocene_subset"))]
840impl<'a, P: Pattern> Split<'a, P> {
841 #[inline]
857 #[unstable(feature = "str_split_remainder", issue = "77998")]
858 pub fn remainder(&self) -> Option<&'a str> {
859 self.0.remainder()
860 }
861}
862
863#[cfg(not(feature = "ferrocene_subset"))]
864impl<'a, P: Pattern> RSplit<'a, P> {
865 #[inline]
881 #[unstable(feature = "str_split_remainder", issue = "77998")]
882 pub fn remainder(&self) -> Option<&'a str> {
883 self.0.remainder()
884 }
885}
886
887#[cfg(not(feature = "ferrocene_subset"))]
888generate_pattern_iterators! {
889 forward:
890 struct SplitTerminator;
894 reverse:
895 struct RSplitTerminator;
899 stability:
900 #[stable(feature = "rust1", since = "1.0.0")]
901 internal:
902 SplitInternal yielding (&'a str);
903 delegate double ended;
904}
905
906#[cfg(not(feature = "ferrocene_subset"))]
907impl<'a, P: Pattern> SplitTerminator<'a, P> {
908 #[inline]
924 #[unstable(feature = "str_split_remainder", issue = "77998")]
925 pub fn remainder(&self) -> Option<&'a str> {
926 self.0.remainder()
927 }
928}
929
930#[cfg(not(feature = "ferrocene_subset"))]
931impl<'a, P: Pattern> RSplitTerminator<'a, P> {
932 #[inline]
948 #[unstable(feature = "str_split_remainder", issue = "77998")]
949 pub fn remainder(&self) -> Option<&'a str> {
950 self.0.remainder()
951 }
952}
953
954#[cfg(not(feature = "ferrocene_subset"))]
955derive_pattern_clone! {
956 clone SplitNInternal
957 with |s| SplitNInternal { iter: s.iter.clone(), ..*s }
958}
959
960#[cfg(not(feature = "ferrocene_subset"))]
961pub(super) struct SplitNInternal<'a, P: Pattern> {
962 pub(super) iter: SplitInternal<'a, P>,
963 pub(super) count: usize,
965}
966
967#[cfg(not(feature = "ferrocene_subset"))]
968impl<'a, P> fmt::Debug for SplitNInternal<'a, P>
969where
970 P: Pattern<Searcher<'a>: fmt::Debug>,
971{
972 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
973 f.debug_struct("SplitNInternal")
974 .field("iter", &self.iter)
975 .field("count", &self.count)
976 .finish()
977 }
978}
979
980#[cfg(not(feature = "ferrocene_subset"))]
981impl<'a, P: Pattern> SplitNInternal<'a, P> {
982 #[inline]
983 fn next(&mut self) -> Option<&'a str> {
984 match self.count {
985 0 => None,
986 1 => {
987 self.count = 0;
988 self.iter.get_end()
989 }
990 _ => {
991 self.count -= 1;
992 self.iter.next()
993 }
994 }
995 }
996
997 #[inline]
998 fn next_back(&mut self) -> Option<&'a str>
999 where
1000 P::Searcher<'a>: ReverseSearcher<'a>,
1001 {
1002 match self.count {
1003 0 => None,
1004 1 => {
1005 self.count = 0;
1006 self.iter.get_end()
1007 }
1008 _ => {
1009 self.count -= 1;
1010 self.iter.next_back()
1011 }
1012 }
1013 }
1014
1015 #[inline]
1016 fn remainder(&self) -> Option<&'a str> {
1017 self.iter.remainder()
1018 }
1019}
1020
1021#[cfg(not(feature = "ferrocene_subset"))]
1022generate_pattern_iterators! {
1023 forward:
1024 struct SplitN;
1028 reverse:
1029 struct RSplitN;
1033 stability:
1034 #[stable(feature = "rust1", since = "1.0.0")]
1035 internal:
1036 SplitNInternal yielding (&'a str);
1037 delegate single ended;
1038}
1039
1040#[cfg(not(feature = "ferrocene_subset"))]
1041impl<'a, P: Pattern> SplitN<'a, P> {
1042 #[inline]
1058 #[unstable(feature = "str_split_remainder", issue = "77998")]
1059 pub fn remainder(&self) -> Option<&'a str> {
1060 self.0.remainder()
1061 }
1062}
1063
1064#[cfg(not(feature = "ferrocene_subset"))]
1065impl<'a, P: Pattern> RSplitN<'a, P> {
1066 #[inline]
1082 #[unstable(feature = "str_split_remainder", issue = "77998")]
1083 pub fn remainder(&self) -> Option<&'a str> {
1084 self.0.remainder()
1085 }
1086}
1087
1088#[cfg(not(feature = "ferrocene_subset"))]
1089derive_pattern_clone! {
1090 clone MatchIndicesInternal
1091 with |s| MatchIndicesInternal(s.0.clone())
1092}
1093
1094#[cfg(not(feature = "ferrocene_subset"))]
1095pub(super) struct MatchIndicesInternal<'a, P: Pattern>(pub(super) P::Searcher<'a>);
1096
1097#[cfg(not(feature = "ferrocene_subset"))]
1098impl<'a, P> fmt::Debug for MatchIndicesInternal<'a, P>
1099where
1100 P: Pattern<Searcher<'a>: fmt::Debug>,
1101{
1102 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
1103 f.debug_tuple("MatchIndicesInternal").field(&self.0).finish()
1104 }
1105}
1106
1107#[cfg(not(feature = "ferrocene_subset"))]
1108impl<'a, P: Pattern> MatchIndicesInternal<'a, P> {
1109 #[inline]
1110 fn next(&mut self) -> Option<(usize, &'a str)> {
1111 self.0
1112 .next_match()
1113 .map(|(start, end)| unsafe { (start, self.0.haystack().get_unchecked(start..end)) })
1115 }
1116
1117 #[inline]
1118 fn next_back(&mut self) -> Option<(usize, &'a str)>
1119 where
1120 P::Searcher<'a>: ReverseSearcher<'a>,
1121 {
1122 self.0
1123 .next_match_back()
1124 .map(|(start, end)| unsafe { (start, self.0.haystack().get_unchecked(start..end)) })
1126 }
1127}
1128
1129#[cfg(not(feature = "ferrocene_subset"))]
1130generate_pattern_iterators! {
1131 forward:
1132 struct MatchIndices;
1136 reverse:
1137 struct RMatchIndices;
1141 stability:
1142 #[stable(feature = "str_match_indices", since = "1.5.0")]
1143 internal:
1144 MatchIndicesInternal yielding ((usize, &'a str));
1145 delegate double ended;
1146}
1147
1148#[cfg(not(feature = "ferrocene_subset"))]
1149derive_pattern_clone! {
1150 clone MatchesInternal
1151 with |s| MatchesInternal(s.0.clone())
1152}
1153
1154#[cfg(not(feature = "ferrocene_subset"))]
1155pub(super) struct MatchesInternal<'a, P: Pattern>(pub(super) P::Searcher<'a>);
1156
1157#[cfg(not(feature = "ferrocene_subset"))]
1158impl<'a, P> fmt::Debug for MatchesInternal<'a, P>
1159where
1160 P: Pattern<Searcher<'a>: fmt::Debug>,
1161{
1162 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
1163 f.debug_tuple("MatchesInternal").field(&self.0).finish()
1164 }
1165}
1166
1167#[cfg(not(feature = "ferrocene_subset"))]
1168impl<'a, P: Pattern> MatchesInternal<'a, P> {
1169 #[inline]
1170 fn next(&mut self) -> Option<&'a str> {
1171 self.0.next_match().map(|(a, b)| unsafe {
1173 self.0.haystack().get_unchecked(a..b)
1175 })
1176 }
1177
1178 #[inline]
1179 fn next_back(&mut self) -> Option<&'a str>
1180 where
1181 P::Searcher<'a>: ReverseSearcher<'a>,
1182 {
1183 self.0.next_match_back().map(|(a, b)| unsafe {
1185 self.0.haystack().get_unchecked(a..b)
1187 })
1188 }
1189}
1190
1191#[cfg(not(feature = "ferrocene_subset"))]
1192generate_pattern_iterators! {
1193 forward:
1194 struct Matches;
1198 reverse:
1199 struct RMatches;
1203 stability:
1204 #[stable(feature = "str_matches", since = "1.2.0")]
1205 internal:
1206 MatchesInternal yielding (&'a str);
1207 delegate double ended;
1208}
1209
1210#[cfg(not(feature = "ferrocene_subset"))]
1217#[stable(feature = "rust1", since = "1.0.0")]
1218#[must_use = "iterators are lazy and do nothing unless consumed"]
1219#[derive(Clone, Debug)]
1220pub struct Lines<'a>(pub(super) Map<SplitInclusive<'a, char>, LinesMap>);
1221
1222#[cfg(not(feature = "ferrocene_subset"))]
1223#[stable(feature = "rust1", since = "1.0.0")]
1224impl<'a> Iterator for Lines<'a> {
1225 type Item = &'a str;
1226
1227 #[inline]
1228 fn next(&mut self) -> Option<&'a str> {
1229 self.0.next()
1230 }
1231
1232 #[inline]
1233 fn size_hint(&self) -> (usize, Option<usize>) {
1234 self.0.size_hint()
1235 }
1236
1237 #[inline]
1238 fn last(mut self) -> Option<&'a str> {
1239 self.next_back()
1240 }
1241}
1242
1243#[cfg(not(feature = "ferrocene_subset"))]
1244#[stable(feature = "rust1", since = "1.0.0")]
1245impl<'a> DoubleEndedIterator for Lines<'a> {
1246 #[inline]
1247 fn next_back(&mut self) -> Option<&'a str> {
1248 self.0.next_back()
1249 }
1250}
1251
1252#[cfg(not(feature = "ferrocene_subset"))]
1253#[stable(feature = "fused", since = "1.26.0")]
1254impl FusedIterator for Lines<'_> {}
1255
1256#[cfg(not(feature = "ferrocene_subset"))]
1257impl<'a> Lines<'a> {
1258 #[inline]
1275 #[must_use]
1276 #[unstable(feature = "str_lines_remainder", issue = "77998")]
1277 pub fn remainder(&self) -> Option<&'a str> {
1278 self.0.iter.remainder()
1279 }
1280}
1281
1282#[cfg(not(feature = "ferrocene_subset"))]
1286#[stable(feature = "rust1", since = "1.0.0")]
1287#[deprecated(since = "1.4.0", note = "use lines()/Lines instead now")]
1288#[must_use = "iterators are lazy and do nothing unless consumed"]
1289#[derive(Clone, Debug)]
1290#[allow(deprecated)]
1291pub struct LinesAny<'a>(pub(super) Lines<'a>);
1292
1293#[cfg(not(feature = "ferrocene_subset"))]
1294#[stable(feature = "rust1", since = "1.0.0")]
1295#[allow(deprecated)]
1296impl<'a> Iterator for LinesAny<'a> {
1297 type Item = &'a str;
1298
1299 #[inline]
1300 fn next(&mut self) -> Option<&'a str> {
1301 self.0.next()
1302 }
1303
1304 #[inline]
1305 fn size_hint(&self) -> (usize, Option<usize>) {
1306 self.0.size_hint()
1307 }
1308}
1309
1310#[cfg(not(feature = "ferrocene_subset"))]
1311#[stable(feature = "rust1", since = "1.0.0")]
1312#[allow(deprecated)]
1313impl<'a> DoubleEndedIterator for LinesAny<'a> {
1314 #[inline]
1315 fn next_back(&mut self) -> Option<&'a str> {
1316 self.0.next_back()
1317 }
1318}
1319
1320#[cfg(not(feature = "ferrocene_subset"))]
1321#[stable(feature = "fused", since = "1.26.0")]
1322#[allow(deprecated)]
1323impl FusedIterator for LinesAny<'_> {}
1324
1325#[cfg(not(feature = "ferrocene_subset"))]
1333#[stable(feature = "split_whitespace", since = "1.1.0")]
1334#[derive(Clone, Debug)]
1335pub struct SplitWhitespace<'a> {
1336 pub(super) inner: Filter<Split<'a, IsWhitespace>, IsNotEmpty>,
1337}
1338
1339#[cfg(not(feature = "ferrocene_subset"))]
1347#[stable(feature = "split_ascii_whitespace", since = "1.34.0")]
1348#[derive(Clone, Debug)]
1349pub struct SplitAsciiWhitespace<'a> {
1350 pub(super) inner:
1351 Map<Filter<SliceSplit<'a, u8, IsAsciiWhitespace>, BytesIsNotEmpty>, UnsafeBytesToStr>,
1352}
1353
1354#[stable(feature = "split_inclusive", since = "1.51.0")]
1364pub struct SplitInclusive<'a, P: Pattern>(pub(super) SplitInternal<'a, P>);
1365
1366#[cfg(not(feature = "ferrocene_subset"))]
1367#[stable(feature = "split_whitespace", since = "1.1.0")]
1368impl<'a> Iterator for SplitWhitespace<'a> {
1369 type Item = &'a str;
1370
1371 #[inline]
1372 fn next(&mut self) -> Option<&'a str> {
1373 self.inner.next()
1374 }
1375
1376 #[inline]
1377 fn size_hint(&self) -> (usize, Option<usize>) {
1378 self.inner.size_hint()
1379 }
1380
1381 #[inline]
1382 fn last(mut self) -> Option<&'a str> {
1383 self.next_back()
1384 }
1385}
1386
1387#[cfg(not(feature = "ferrocene_subset"))]
1388#[stable(feature = "split_whitespace", since = "1.1.0")]
1389impl<'a> DoubleEndedIterator for SplitWhitespace<'a> {
1390 #[inline]
1391 fn next_back(&mut self) -> Option<&'a str> {
1392 self.inner.next_back()
1393 }
1394}
1395
1396#[cfg(not(feature = "ferrocene_subset"))]
1397#[stable(feature = "fused", since = "1.26.0")]
1398impl FusedIterator for SplitWhitespace<'_> {}
1399
1400#[cfg(not(feature = "ferrocene_subset"))]
1401impl<'a> SplitWhitespace<'a> {
1402 #[inline]
1419 #[must_use]
1420 #[unstable(feature = "str_split_whitespace_remainder", issue = "77998")]
1421 pub fn remainder(&self) -> Option<&'a str> {
1422 self.inner.iter.remainder()
1423 }
1424}
1425
1426#[cfg(not(feature = "ferrocene_subset"))]
1427#[stable(feature = "split_ascii_whitespace", since = "1.34.0")]
1428impl<'a> Iterator for SplitAsciiWhitespace<'a> {
1429 type Item = &'a str;
1430
1431 #[inline]
1432 fn next(&mut self) -> Option<&'a str> {
1433 self.inner.next()
1434 }
1435
1436 #[inline]
1437 fn size_hint(&self) -> (usize, Option<usize>) {
1438 self.inner.size_hint()
1439 }
1440
1441 #[inline]
1442 fn last(mut self) -> Option<&'a str> {
1443 self.next_back()
1444 }
1445}
1446
1447#[cfg(not(feature = "ferrocene_subset"))]
1448#[stable(feature = "split_ascii_whitespace", since = "1.34.0")]
1449impl<'a> DoubleEndedIterator for SplitAsciiWhitespace<'a> {
1450 #[inline]
1451 fn next_back(&mut self) -> Option<&'a str> {
1452 self.inner.next_back()
1453 }
1454}
1455
1456#[cfg(not(feature = "ferrocene_subset"))]
1457#[stable(feature = "split_ascii_whitespace", since = "1.34.0")]
1458impl FusedIterator for SplitAsciiWhitespace<'_> {}
1459
1460#[cfg(not(feature = "ferrocene_subset"))]
1461impl<'a> SplitAsciiWhitespace<'a> {
1462 #[inline]
1481 #[must_use]
1482 #[unstable(feature = "str_split_whitespace_remainder", issue = "77998")]
1483 pub fn remainder(&self) -> Option<&'a str> {
1484 if self.inner.iter.iter.finished {
1485 return None;
1486 }
1487
1488 Some(unsafe { crate::str::from_utf8_unchecked(&self.inner.iter.iter.v) })
1490 }
1491}
1492
1493#[stable(feature = "split_inclusive", since = "1.51.0")]
1494impl<'a, P: Pattern> Iterator for SplitInclusive<'a, P> {
1495 type Item = &'a str;
1496
1497 #[inline]
1498 fn next(&mut self) -> Option<&'a str> {
1499 self.0.next_inclusive()
1500 }
1501}
1502
1503#[stable(feature = "split_inclusive", since = "1.51.0")]
1504impl<'a, P: Pattern<Searcher<'a>: fmt::Debug>> fmt::Debug for SplitInclusive<'a, P> {
1505 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
1506 f.debug_struct("SplitInclusive").field("0", &self.0).finish()
1507 }
1508}
1509
1510#[cfg(not(feature = "ferrocene_subset"))]
1512#[stable(feature = "split_inclusive", since = "1.51.0")]
1513impl<'a, P: Pattern<Searcher<'a>: Clone>> Clone for SplitInclusive<'a, P> {
1514 fn clone(&self) -> Self {
1515 SplitInclusive(self.0.clone())
1516 }
1517}
1518
1519#[cfg(not(feature = "ferrocene_subset"))]
1520#[stable(feature = "split_inclusive", since = "1.51.0")]
1521impl<'a, P: Pattern<Searcher<'a>: DoubleEndedSearcher<'a>>> DoubleEndedIterator
1522 for SplitInclusive<'a, P>
1523{
1524 #[inline]
1525 fn next_back(&mut self) -> Option<&'a str> {
1526 self.0.next_back_inclusive()
1527 }
1528}
1529
1530#[cfg(not(feature = "ferrocene_subset"))]
1531#[stable(feature = "split_inclusive", since = "1.51.0")]
1532impl<'a, P: Pattern> FusedIterator for SplitInclusive<'a, P> {}
1533
1534#[cfg(not(feature = "ferrocene_subset"))]
1535impl<'a, P: Pattern> SplitInclusive<'a, P> {
1536 #[inline]
1552 #[unstable(feature = "str_split_inclusive_remainder", issue = "77998")]
1553 pub fn remainder(&self) -> Option<&'a str> {
1554 self.0.remainder()
1555 }
1556}
1557
1558#[cfg(not(feature = "ferrocene_subset"))]
1565#[derive(Clone)]
1566#[stable(feature = "encode_utf16", since = "1.8.0")]
1567pub struct EncodeUtf16<'a> {
1568 pub(super) chars: Chars<'a>,
1569 pub(super) extra: u16,
1570}
1571
1572#[cfg(not(feature = "ferrocene_subset"))]
1573#[stable(feature = "collection_debug", since = "1.17.0")]
1574impl fmt::Debug for EncodeUtf16<'_> {
1575 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
1576 f.debug_struct("EncodeUtf16").finish_non_exhaustive()
1577 }
1578}
1579
1580#[cfg(not(feature = "ferrocene_subset"))]
1581#[stable(feature = "encode_utf16", since = "1.8.0")]
1582impl<'a> Iterator for EncodeUtf16<'a> {
1583 type Item = u16;
1584
1585 #[inline]
1586 fn next(&mut self) -> Option<u16> {
1587 if self.extra != 0 {
1588 let tmp = self.extra;
1589 self.extra = 0;
1590 return Some(tmp);
1591 }
1592
1593 let mut buf = [0; 2];
1594 self.chars.next().map(|ch| {
1595 let n = ch.encode_utf16(&mut buf).len();
1596 if n == 2 {
1597 self.extra = buf[1];
1598 }
1599 buf[0]
1600 })
1601 }
1602
1603 #[inline]
1604 fn size_hint(&self) -> (usize, Option<usize>) {
1605 let len = self.chars.iter.len();
1606 if self.extra == 0 {
1612 (len.div_ceil(3), Some(len))
1613 } else {
1614 (len.div_ceil(3) + 1, Some(len + 1))
1617 }
1618 }
1619}
1620
1621#[cfg(not(feature = "ferrocene_subset"))]
1622#[stable(feature = "fused", since = "1.26.0")]
1623impl FusedIterator for EncodeUtf16<'_> {}
1624
1625#[cfg(not(feature = "ferrocene_subset"))]
1627#[stable(feature = "str_escape", since = "1.34.0")]
1628#[derive(Clone, Debug)]
1629pub struct EscapeDebug<'a> {
1630 pub(super) inner: Chain<
1631 Flatten<option::IntoIter<char_mod::EscapeDebug>>,
1632 FlatMap<Chars<'a>, char_mod::EscapeDebug, CharEscapeDebugContinue>,
1633 >,
1634}
1635
1636#[cfg(not(feature = "ferrocene_subset"))]
1638#[stable(feature = "str_escape", since = "1.34.0")]
1639#[derive(Clone, Debug)]
1640pub struct EscapeDefault<'a> {
1641 pub(super) inner: FlatMap<Chars<'a>, char_mod::EscapeDefault, CharEscapeDefault>,
1642}
1643
1644#[cfg(not(feature = "ferrocene_subset"))]
1646#[stable(feature = "str_escape", since = "1.34.0")]
1647#[derive(Clone, Debug)]
1648pub struct EscapeUnicode<'a> {
1649 pub(super) inner: FlatMap<Chars<'a>, char_mod::EscapeUnicode, CharEscapeUnicode>,
1650}
1651
1652#[cfg(not(feature = "ferrocene_subset"))]
1653macro_rules! escape_types_impls {
1654 ($( $Name: ident ),+) => {$(
1655 #[stable(feature = "str_escape", since = "1.34.0")]
1656 impl<'a> fmt::Display for $Name<'a> {
1657 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
1658 self.clone().try_for_each(|c| f.write_char(c))
1659 }
1660 }
1661
1662 #[stable(feature = "str_escape", since = "1.34.0")]
1663 impl<'a> Iterator for $Name<'a> {
1664 type Item = char;
1665
1666 #[inline]
1667 fn next(&mut self) -> Option<char> { self.inner.next() }
1668
1669 #[inline]
1670 fn size_hint(&self) -> (usize, Option<usize>) { self.inner.size_hint() }
1671
1672 #[inline]
1673 fn try_fold<Acc, Fold, R>(&mut self, init: Acc, fold: Fold) -> R where
1674 Self: Sized, Fold: FnMut(Acc, Self::Item) -> R, R: Try<Output = Acc>
1675 {
1676 self.inner.try_fold(init, fold)
1677 }
1678
1679 #[inline]
1680 fn fold<Acc, Fold>(self, init: Acc, fold: Fold) -> Acc
1681 where Fold: FnMut(Acc, Self::Item) -> Acc,
1682 {
1683 self.inner.fold(init, fold)
1684 }
1685 }
1686
1687 #[stable(feature = "str_escape", since = "1.34.0")]
1688 impl<'a> FusedIterator for $Name<'a> {}
1689 )+}
1690}
1691
1692#[cfg(not(feature = "ferrocene_subset"))]
1693escape_types_impls!(EscapeDebug, EscapeDefault, EscapeUnicode);