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))
124 }
125
126 #[inline]
127 fn last(mut self) -> Option<char> {
128 self.next_back()
130 }
131}
132
133#[stable(feature = "chars_debug_impl", since = "1.38.0")]
134impl fmt::Debug for Chars<'_> {
135 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
136 write!(f, "Chars(")?;
137 f.debug_list().entries(self.clone()).finish()?;
138 write!(f, ")")?;
139 Ok(())
140 }
141}
142
143#[stable(feature = "rust1", since = "1.0.0")]
144impl<'a> DoubleEndedIterator for Chars<'a> {
145 #[inline]
146 fn next_back(&mut self) -> Option<char> {
147 unsafe { next_code_point_reverse(&mut self.iter).map(|ch| char::from_u32_unchecked(ch)) }
150 }
151}
152
153#[cfg(not(feature = "ferrocene_subset"))]
154#[stable(feature = "fused", since = "1.26.0")]
155impl FusedIterator for Chars<'_> {}
156
157impl<'a> Chars<'a> {
158 #[stable(feature = "iter_to_slice", since = "1.4.0")]
176 #[must_use]
177 #[inline]
178 pub fn as_str(&self) -> &'a str {
179 unsafe { from_utf8_unchecked(self.iter.as_slice()) }
181 }
182}
183
184#[derive(Clone, Debug)]
192#[must_use = "iterators are lazy and do nothing unless consumed"]
193#[stable(feature = "rust1", since = "1.0.0")]
194pub struct CharIndices<'a> {
195 pub(super) front_offset: usize,
196 pub(super) iter: Chars<'a>,
197}
198
199#[stable(feature = "rust1", since = "1.0.0")]
200impl<'a> Iterator for CharIndices<'a> {
201 type Item = (usize, char);
202
203 #[inline]
204 fn next(&mut self) -> Option<(usize, char)> {
205 let pre_len = self.iter.iter.len();
206 match self.iter.next() {
207 None => None,
208 Some(ch) => {
209 let index = self.front_offset;
210 let len = self.iter.iter.len();
211 self.front_offset += pre_len - len;
212 Some((index, ch))
213 }
214 }
215 }
216
217 #[inline]
218 fn count(self) -> usize {
219 self.iter.count()
220 }
221
222 #[inline]
223 fn size_hint(&self) -> (usize, Option<usize>) {
224 self.iter.size_hint()
225 }
226
227 #[inline]
228 fn last(mut self) -> Option<(usize, char)> {
229 self.next_back()
231 }
232}
233
234#[stable(feature = "rust1", since = "1.0.0")]
235impl<'a> DoubleEndedIterator for CharIndices<'a> {
236 #[inline]
237 fn next_back(&mut self) -> Option<(usize, char)> {
238 self.iter.next_back().map(|ch| {
239 let index = self.front_offset + self.iter.iter.len();
240 (index, ch)
241 })
242 }
243}
244
245#[cfg(not(feature = "ferrocene_subset"))]
246#[stable(feature = "fused", since = "1.26.0")]
247impl FusedIterator for CharIndices<'_> {}
248
249impl<'a> CharIndices<'a> {
250 #[stable(feature = "iter_to_slice", since = "1.4.0")]
255 #[must_use]
256 #[inline]
257 pub fn as_str(&self) -> &'a str {
258 self.iter.as_str()
259 }
260
261 #[inline]
291 #[must_use]
292 #[stable(feature = "char_indices_offset", since = "1.82.0")]
293 pub fn offset(&self) -> usize {
294 self.front_offset
295 }
296}
297
298#[must_use = "iterators are lazy and do nothing unless consumed"]
305#[stable(feature = "rust1", since = "1.0.0")]
306#[derive(Clone, Debug)]
307pub struct Bytes<'a>(pub(super) Copied<slice::Iter<'a, u8>>);
308
309#[stable(feature = "rust1", since = "1.0.0")]
310impl Iterator for Bytes<'_> {
311 type Item = u8;
312
313 #[inline]
314 fn next(&mut self) -> Option<u8> {
315 self.0.next()
316 }
317
318 #[inline]
319 fn size_hint(&self) -> (usize, Option<usize>) {
320 self.0.size_hint()
321 }
322
323 #[inline]
324 fn count(self) -> usize {
325 self.0.count()
326 }
327
328 #[inline]
329 fn last(self) -> Option<Self::Item> {
330 self.0.last()
331 }
332
333 #[inline]
334 fn nth(&mut self, n: usize) -> Option<Self::Item> {
335 self.0.nth(n)
336 }
337
338 #[inline]
339 fn all<F>(&mut self, f: F) -> bool
340 where
341 F: FnMut(Self::Item) -> bool,
342 {
343 self.0.all(f)
344 }
345
346 #[inline]
347 fn any<F>(&mut self, f: F) -> bool
348 where
349 F: FnMut(Self::Item) -> bool,
350 {
351 self.0.any(f)
352 }
353
354 #[inline]
355 fn find<P>(&mut self, predicate: P) -> Option<Self::Item>
356 where
357 P: FnMut(&Self::Item) -> bool,
358 {
359 self.0.find(predicate)
360 }
361
362 #[inline]
363 fn position<P>(&mut self, predicate: P) -> Option<usize>
364 where
365 P: FnMut(Self::Item) -> bool,
366 {
367 self.0.position(predicate)
368 }
369
370 #[inline]
371 fn rposition<P>(&mut self, predicate: P) -> Option<usize>
372 where
373 P: FnMut(Self::Item) -> bool,
374 {
375 self.0.rposition(predicate)
376 }
377
378 #[cfg(not(feature = "ferrocene_subset"))]
379 #[inline]
380 unsafe fn __iterator_get_unchecked(&mut self, idx: usize) -> u8 {
381 unsafe { self.0.__iterator_get_unchecked(idx) }
384 }
385}
386
387#[cfg(not(feature = "ferrocene_subset"))]
388#[stable(feature = "rust1", since = "1.0.0")]
389impl DoubleEndedIterator for Bytes<'_> {
390 #[inline]
391 fn next_back(&mut self) -> Option<u8> {
392 self.0.next_back()
393 }
394
395 #[inline]
396 fn nth_back(&mut self, n: usize) -> Option<Self::Item> {
397 self.0.nth_back(n)
398 }
399
400 #[inline]
401 fn rfind<P>(&mut self, predicate: P) -> Option<Self::Item>
402 where
403 P: FnMut(&Self::Item) -> bool,
404 {
405 self.0.rfind(predicate)
406 }
407}
408
409#[cfg(not(feature = "ferrocene_subset"))]
410#[stable(feature = "rust1", since = "1.0.0")]
411impl ExactSizeIterator for Bytes<'_> {
412 #[inline]
413 fn len(&self) -> usize {
414 self.0.len()
415 }
416
417 #[inline]
418 fn is_empty(&self) -> bool {
419 self.0.is_empty()
420 }
421}
422
423#[cfg(not(feature = "ferrocene_subset"))]
424#[stable(feature = "fused", since = "1.26.0")]
425impl FusedIterator for Bytes<'_> {}
426
427#[cfg(not(feature = "ferrocene_subset"))]
428#[unstable(feature = "trusted_len", issue = "37572")]
429unsafe impl TrustedLen for Bytes<'_> {}
430
431#[cfg(not(feature = "ferrocene_subset"))]
432#[doc(hidden)]
433#[unstable(feature = "trusted_random_access", issue = "none")]
434unsafe impl TrustedRandomAccess for Bytes<'_> {}
435
436#[cfg(not(feature = "ferrocene_subset"))]
437#[doc(hidden)]
438#[unstable(feature = "trusted_random_access", issue = "none")]
439unsafe impl TrustedRandomAccessNoCoerce for Bytes<'_> {
440 const MAY_HAVE_SIDE_EFFECT: bool = false;
441}
442
443#[cfg(not(feature = "ferrocene_subset"))]
446macro_rules! derive_pattern_clone {
447 (clone $t:ident with |$s:ident| $e:expr) => {
448 impl<'a, P> Clone for $t<'a, P>
449 where
450 P: Pattern<Searcher<'a>: Clone>,
451 {
452 fn clone(&self) -> Self {
453 let $s = self;
454 $e
455 }
456 }
457 };
458}
459
460#[cfg(not(feature = "ferrocene_subset"))]
499macro_rules! generate_pattern_iterators {
500 {
501 forward:
503 $(#[$forward_iterator_attribute:meta])*
504 struct $forward_iterator:ident;
505
506 reverse:
508 $(#[$reverse_iterator_attribute:meta])*
509 struct $reverse_iterator:ident;
510
511 stability:
513 $(#[$common_stability_attribute:meta])*
514
515 internal:
517 $internal_iterator:ident yielding ($iterty:ty);
518
519 delegate $($t:tt)*
521 } => {
522 $(#[$forward_iterator_attribute])*
523 $(#[$common_stability_attribute])*
524 pub struct $forward_iterator<'a, P: Pattern>(pub(super) $internal_iterator<'a, P>);
525
526 $(#[$common_stability_attribute])*
527 impl<'a, P> fmt::Debug for $forward_iterator<'a, P>
528 where
529 P: Pattern<Searcher<'a>: fmt::Debug>,
530 {
531 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
532 f.debug_tuple(stringify!($forward_iterator))
533 .field(&self.0)
534 .finish()
535 }
536 }
537
538 $(#[$common_stability_attribute])*
539 impl<'a, P: Pattern> Iterator for $forward_iterator<'a, P> {
540 type Item = $iterty;
541
542 #[inline]
543 fn next(&mut self) -> Option<$iterty> {
544 self.0.next()
545 }
546 }
547
548 $(#[$common_stability_attribute])*
549 impl<'a, P> Clone for $forward_iterator<'a, P>
550 where
551 P: Pattern<Searcher<'a>: Clone>,
552 {
553 fn clone(&self) -> Self {
554 $forward_iterator(self.0.clone())
555 }
556 }
557
558 $(#[$reverse_iterator_attribute])*
559 $(#[$common_stability_attribute])*
560 pub struct $reverse_iterator<'a, P: Pattern>(pub(super) $internal_iterator<'a, P>);
561
562 $(#[$common_stability_attribute])*
563 impl<'a, P> fmt::Debug for $reverse_iterator<'a, P>
564 where
565 P: Pattern<Searcher<'a>: fmt::Debug>,
566 {
567 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
568 f.debug_tuple(stringify!($reverse_iterator))
569 .field(&self.0)
570 .finish()
571 }
572 }
573
574 $(#[$common_stability_attribute])*
575 impl<'a, P> Iterator for $reverse_iterator<'a, P>
576 where
577 P: Pattern<Searcher<'a>: ReverseSearcher<'a>>,
578 {
579 type Item = $iterty;
580
581 #[inline]
582 fn next(&mut self) -> Option<$iterty> {
583 self.0.next_back()
584 }
585 }
586
587 $(#[$common_stability_attribute])*
588 impl<'a, P> Clone for $reverse_iterator<'a, P>
589 where
590 P: Pattern<Searcher<'a>: Clone>,
591 {
592 fn clone(&self) -> Self {
593 $reverse_iterator(self.0.clone())
594 }
595 }
596
597 #[stable(feature = "fused", since = "1.26.0")]
598 impl<'a, P: Pattern> FusedIterator for $forward_iterator<'a, P> {}
599
600 #[stable(feature = "fused", since = "1.26.0")]
601 impl<'a, P> FusedIterator for $reverse_iterator<'a, P>
602 where
603 P: Pattern<Searcher<'a>: ReverseSearcher<'a>>,
604 {}
605
606 generate_pattern_iterators!($($t)* with $(#[$common_stability_attribute])*,
607 $forward_iterator,
608 $reverse_iterator, $iterty);
609 };
610 {
611 double ended; with $(#[$common_stability_attribute:meta])*,
612 $forward_iterator:ident,
613 $reverse_iterator:ident, $iterty:ty
614 } => {
615 $(#[$common_stability_attribute])*
616 impl<'a, P> DoubleEndedIterator for $forward_iterator<'a, P>
617 where
618 P: Pattern<Searcher<'a>: DoubleEndedSearcher<'a>>,
619 {
620 #[inline]
621 fn next_back(&mut self) -> Option<$iterty> {
622 self.0.next_back()
623 }
624 }
625
626 $(#[$common_stability_attribute])*
627 impl<'a, P> DoubleEndedIterator for $reverse_iterator<'a, P>
628 where
629 P: Pattern<Searcher<'a>: DoubleEndedSearcher<'a>>,
630 {
631 #[inline]
632 fn next_back(&mut self) -> Option<$iterty> {
633 self.0.next()
634 }
635 }
636 };
637 {
638 single ended; with $(#[$common_stability_attribute:meta])*,
639 $forward_iterator:ident,
640 $reverse_iterator:ident, $iterty:ty
641 } => {}
642}
643
644#[cfg(not(feature = "ferrocene_subset"))]
645derive_pattern_clone! {
646 clone SplitInternal
647 with |s| SplitInternal { matcher: s.matcher.clone(), ..*s }
648}
649
650pub(super) struct SplitInternal<'a, P: Pattern> {
651 pub(super) start: usize,
652 pub(super) end: usize,
653 pub(super) matcher: P::Searcher<'a>,
654 pub(super) allow_trailing_empty: bool,
655 pub(super) finished: bool,
656}
657
658impl<'a, P> fmt::Debug for SplitInternal<'a, P>
659where
660 P: Pattern<Searcher<'a>: fmt::Debug>,
661{
662 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
663 f.debug_struct("SplitInternal")
664 .field("start", &self.start)
665 .field("end", &self.end)
666 .field("matcher", &self.matcher)
667 .field("allow_trailing_empty", &self.allow_trailing_empty)
668 .field("finished", &self.finished)
669 .finish()
670 }
671}
672
673impl<'a, P: Pattern> SplitInternal<'a, P> {
674 #[inline]
675 fn get_end(&mut self) -> Option<&'a str> {
676 if !self.finished {
677 self.finished = true;
678
679 if self.allow_trailing_empty || self.end - self.start > 0 {
680 let string = unsafe { self.matcher.haystack().get_unchecked(self.start..self.end) };
682 return Some(string);
683 }
684 }
685
686 None
687 }
688
689 #[inline]
690 #[cfg(not(feature = "ferrocene_subset"))]
691 fn next(&mut self) -> Option<&'a str> {
692 if self.finished {
693 return None;
694 }
695
696 let haystack = self.matcher.haystack();
697 match self.matcher.next_match() {
698 Some((a, b)) => unsafe {
700 let elt = haystack.get_unchecked(self.start..a);
701 self.start = b;
702 Some(elt)
703 },
704 None => self.get_end(),
705 }
706 }
707
708 #[inline]
709 fn next_inclusive(&mut self) -> Option<&'a str> {
710 if self.finished {
711 return None;
712 }
713
714 let haystack = self.matcher.haystack();
715 match self.matcher.next_match() {
716 Some((_, b)) => unsafe {
720 let elt = haystack.get_unchecked(self.start..b);
721 self.start = b;
722 Some(elt)
723 },
724 None => self.get_end(),
725 }
726 }
727
728 #[inline]
729 #[cfg(not(feature = "ferrocene_subset"))]
730 fn next_back(&mut self) -> Option<&'a str>
731 where
732 P::Searcher<'a>: ReverseSearcher<'a>,
733 {
734 if self.finished {
735 return None;
736 }
737
738 if !self.allow_trailing_empty {
739 self.allow_trailing_empty = true;
740 match self.next_back() {
741 Some(elt) if !elt.is_empty() => return Some(elt),
742 _ => {
743 if self.finished {
744 return None;
745 }
746 }
747 }
748 }
749
750 let haystack = self.matcher.haystack();
751 match self.matcher.next_match_back() {
752 Some((a, b)) => unsafe {
754 let elt = haystack.get_unchecked(b..self.end);
755 self.end = a;
756 Some(elt)
757 },
758 None => unsafe {
760 self.finished = true;
761 Some(haystack.get_unchecked(self.start..self.end))
762 },
763 }
764 }
765
766 #[inline]
767 #[cfg(not(feature = "ferrocene_subset"))]
768 fn next_back_inclusive(&mut self) -> Option<&'a str>
769 where
770 P::Searcher<'a>: ReverseSearcher<'a>,
771 {
772 if self.finished {
773 return None;
774 }
775
776 if !self.allow_trailing_empty {
777 self.allow_trailing_empty = true;
778 match self.next_back_inclusive() {
779 Some(elt) if !elt.is_empty() => return Some(elt),
780 _ => {
781 if self.finished {
782 return None;
783 }
784 }
785 }
786 }
787
788 let haystack = self.matcher.haystack();
789 match self.matcher.next_match_back() {
790 Some((_, b)) => unsafe {
794 let elt = haystack.get_unchecked(b..self.end);
795 self.end = b;
796 Some(elt)
797 },
798 None => unsafe {
804 self.finished = true;
805 Some(haystack.get_unchecked(self.start..self.end))
806 },
807 }
808 }
809
810 #[inline]
811 #[cfg(not(feature = "ferrocene_subset"))]
812 fn remainder(&self) -> Option<&'a str> {
813 if self.finished {
815 return None;
816 }
817
818 Some(unsafe { self.matcher.haystack().get_unchecked(self.start..self.end) })
820 }
821}
822
823#[cfg(not(feature = "ferrocene_subset"))]
824generate_pattern_iterators! {
825 forward:
826 struct Split;
830 reverse:
831 struct RSplit;
835 stability:
836 #[stable(feature = "rust1", since = "1.0.0")]
837 internal:
838 SplitInternal yielding (&'a str);
839 delegate double ended;
840}
841
842#[cfg(not(feature = "ferrocene_subset"))]
843impl<'a, P: Pattern> Split<'a, P> {
844 #[inline]
860 #[unstable(feature = "str_split_remainder", issue = "77998")]
861 pub fn remainder(&self) -> Option<&'a str> {
862 self.0.remainder()
863 }
864}
865
866#[cfg(not(feature = "ferrocene_subset"))]
867impl<'a, P: Pattern> RSplit<'a, P> {
868 #[inline]
884 #[unstable(feature = "str_split_remainder", issue = "77998")]
885 pub fn remainder(&self) -> Option<&'a str> {
886 self.0.remainder()
887 }
888}
889
890#[cfg(not(feature = "ferrocene_subset"))]
891generate_pattern_iterators! {
892 forward:
893 struct SplitTerminator;
897 reverse:
898 struct RSplitTerminator;
902 stability:
903 #[stable(feature = "rust1", since = "1.0.0")]
904 internal:
905 SplitInternal yielding (&'a str);
906 delegate double ended;
907}
908
909#[cfg(not(feature = "ferrocene_subset"))]
910impl<'a, P: Pattern> SplitTerminator<'a, P> {
911 #[inline]
927 #[unstable(feature = "str_split_remainder", issue = "77998")]
928 pub fn remainder(&self) -> Option<&'a str> {
929 self.0.remainder()
930 }
931}
932
933#[cfg(not(feature = "ferrocene_subset"))]
934impl<'a, P: Pattern> RSplitTerminator<'a, P> {
935 #[inline]
951 #[unstable(feature = "str_split_remainder", issue = "77998")]
952 pub fn remainder(&self) -> Option<&'a str> {
953 self.0.remainder()
954 }
955}
956
957#[cfg(not(feature = "ferrocene_subset"))]
958derive_pattern_clone! {
959 clone SplitNInternal
960 with |s| SplitNInternal { iter: s.iter.clone(), ..*s }
961}
962
963#[cfg(not(feature = "ferrocene_subset"))]
964pub(super) struct SplitNInternal<'a, P: Pattern> {
965 pub(super) iter: SplitInternal<'a, P>,
966 pub(super) count: usize,
968}
969
970#[cfg(not(feature = "ferrocene_subset"))]
971impl<'a, P> fmt::Debug for SplitNInternal<'a, P>
972where
973 P: Pattern<Searcher<'a>: fmt::Debug>,
974{
975 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
976 f.debug_struct("SplitNInternal")
977 .field("iter", &self.iter)
978 .field("count", &self.count)
979 .finish()
980 }
981}
982
983#[cfg(not(feature = "ferrocene_subset"))]
984impl<'a, P: Pattern> SplitNInternal<'a, P> {
985 #[inline]
986 fn next(&mut self) -> Option<&'a str> {
987 match self.count {
988 0 => None,
989 1 => {
990 self.count = 0;
991 self.iter.get_end()
992 }
993 _ => {
994 self.count -= 1;
995 self.iter.next()
996 }
997 }
998 }
999
1000 #[inline]
1001 fn next_back(&mut self) -> Option<&'a str>
1002 where
1003 P::Searcher<'a>: ReverseSearcher<'a>,
1004 {
1005 match self.count {
1006 0 => None,
1007 1 => {
1008 self.count = 0;
1009 self.iter.get_end()
1010 }
1011 _ => {
1012 self.count -= 1;
1013 self.iter.next_back()
1014 }
1015 }
1016 }
1017
1018 #[inline]
1019 fn remainder(&self) -> Option<&'a str> {
1020 self.iter.remainder()
1021 }
1022}
1023
1024#[cfg(not(feature = "ferrocene_subset"))]
1025generate_pattern_iterators! {
1026 forward:
1027 struct SplitN;
1031 reverse:
1032 struct RSplitN;
1036 stability:
1037 #[stable(feature = "rust1", since = "1.0.0")]
1038 internal:
1039 SplitNInternal yielding (&'a str);
1040 delegate single ended;
1041}
1042
1043#[cfg(not(feature = "ferrocene_subset"))]
1044impl<'a, P: Pattern> SplitN<'a, P> {
1045 #[inline]
1061 #[unstable(feature = "str_split_remainder", issue = "77998")]
1062 pub fn remainder(&self) -> Option<&'a str> {
1063 self.0.remainder()
1064 }
1065}
1066
1067#[cfg(not(feature = "ferrocene_subset"))]
1068impl<'a, P: Pattern> RSplitN<'a, P> {
1069 #[inline]
1085 #[unstable(feature = "str_split_remainder", issue = "77998")]
1086 pub fn remainder(&self) -> Option<&'a str> {
1087 self.0.remainder()
1088 }
1089}
1090
1091#[cfg(not(feature = "ferrocene_subset"))]
1092derive_pattern_clone! {
1093 clone MatchIndicesInternal
1094 with |s| MatchIndicesInternal(s.0.clone())
1095}
1096
1097#[cfg(not(feature = "ferrocene_subset"))]
1098pub(super) struct MatchIndicesInternal<'a, P: Pattern>(pub(super) P::Searcher<'a>);
1099
1100#[cfg(not(feature = "ferrocene_subset"))]
1101impl<'a, P> fmt::Debug for MatchIndicesInternal<'a, P>
1102where
1103 P: Pattern<Searcher<'a>: fmt::Debug>,
1104{
1105 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
1106 f.debug_tuple("MatchIndicesInternal").field(&self.0).finish()
1107 }
1108}
1109
1110#[cfg(not(feature = "ferrocene_subset"))]
1111impl<'a, P: Pattern> MatchIndicesInternal<'a, P> {
1112 #[inline]
1113 fn next(&mut self) -> Option<(usize, &'a str)> {
1114 self.0
1115 .next_match()
1116 .map(|(start, end)| unsafe { (start, self.0.haystack().get_unchecked(start..end)) })
1118 }
1119
1120 #[inline]
1121 fn next_back(&mut self) -> Option<(usize, &'a str)>
1122 where
1123 P::Searcher<'a>: ReverseSearcher<'a>,
1124 {
1125 self.0
1126 .next_match_back()
1127 .map(|(start, end)| unsafe { (start, self.0.haystack().get_unchecked(start..end)) })
1129 }
1130}
1131
1132#[cfg(not(feature = "ferrocene_subset"))]
1133generate_pattern_iterators! {
1134 forward:
1135 struct MatchIndices;
1139 reverse:
1140 struct RMatchIndices;
1144 stability:
1145 #[stable(feature = "str_match_indices", since = "1.5.0")]
1146 internal:
1147 MatchIndicesInternal yielding ((usize, &'a str));
1148 delegate double ended;
1149}
1150
1151#[cfg(not(feature = "ferrocene_subset"))]
1152derive_pattern_clone! {
1153 clone MatchesInternal
1154 with |s| MatchesInternal(s.0.clone())
1155}
1156
1157#[cfg(not(feature = "ferrocene_subset"))]
1158pub(super) struct MatchesInternal<'a, P: Pattern>(pub(super) P::Searcher<'a>);
1159
1160#[cfg(not(feature = "ferrocene_subset"))]
1161impl<'a, P> fmt::Debug for MatchesInternal<'a, P>
1162where
1163 P: Pattern<Searcher<'a>: fmt::Debug>,
1164{
1165 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
1166 f.debug_tuple("MatchesInternal").field(&self.0).finish()
1167 }
1168}
1169
1170#[cfg(not(feature = "ferrocene_subset"))]
1171impl<'a, P: Pattern> MatchesInternal<'a, P> {
1172 #[inline]
1173 fn next(&mut self) -> Option<&'a str> {
1174 self.0.next_match().map(|(a, b)| unsafe {
1176 self.0.haystack().get_unchecked(a..b)
1178 })
1179 }
1180
1181 #[inline]
1182 fn next_back(&mut self) -> Option<&'a str>
1183 where
1184 P::Searcher<'a>: ReverseSearcher<'a>,
1185 {
1186 self.0.next_match_back().map(|(a, b)| unsafe {
1188 self.0.haystack().get_unchecked(a..b)
1190 })
1191 }
1192}
1193
1194#[cfg(not(feature = "ferrocene_subset"))]
1195generate_pattern_iterators! {
1196 forward:
1197 struct Matches;
1201 reverse:
1202 struct RMatches;
1206 stability:
1207 #[stable(feature = "str_matches", since = "1.2.0")]
1208 internal:
1209 MatchesInternal yielding (&'a str);
1210 delegate double ended;
1211}
1212
1213#[cfg(not(feature = "ferrocene_subset"))]
1220#[stable(feature = "rust1", since = "1.0.0")]
1221#[must_use = "iterators are lazy and do nothing unless consumed"]
1222#[derive(Clone, Debug)]
1223pub struct Lines<'a>(pub(super) Map<SplitInclusive<'a, char>, LinesMap>);
1224
1225#[cfg(not(feature = "ferrocene_subset"))]
1226#[stable(feature = "rust1", since = "1.0.0")]
1227impl<'a> Iterator for Lines<'a> {
1228 type Item = &'a str;
1229
1230 #[inline]
1231 fn next(&mut self) -> Option<&'a str> {
1232 self.0.next()
1233 }
1234
1235 #[inline]
1236 fn size_hint(&self) -> (usize, Option<usize>) {
1237 self.0.size_hint()
1238 }
1239
1240 #[inline]
1241 fn last(mut self) -> Option<&'a str> {
1242 self.next_back()
1243 }
1244}
1245
1246#[cfg(not(feature = "ferrocene_subset"))]
1247#[stable(feature = "rust1", since = "1.0.0")]
1248impl<'a> DoubleEndedIterator for Lines<'a> {
1249 #[inline]
1250 fn next_back(&mut self) -> Option<&'a str> {
1251 self.0.next_back()
1252 }
1253}
1254
1255#[cfg(not(feature = "ferrocene_subset"))]
1256#[stable(feature = "fused", since = "1.26.0")]
1257impl FusedIterator for Lines<'_> {}
1258
1259#[cfg(not(feature = "ferrocene_subset"))]
1260impl<'a> Lines<'a> {
1261 #[inline]
1278 #[must_use]
1279 #[unstable(feature = "str_lines_remainder", issue = "77998")]
1280 pub fn remainder(&self) -> Option<&'a str> {
1281 self.0.iter.remainder()
1282 }
1283}
1284
1285#[cfg(not(feature = "ferrocene_subset"))]
1289#[stable(feature = "rust1", since = "1.0.0")]
1290#[deprecated(since = "1.4.0", note = "use lines()/Lines instead now")]
1291#[must_use = "iterators are lazy and do nothing unless consumed"]
1292#[derive(Clone, Debug)]
1293#[allow(deprecated)]
1294pub struct LinesAny<'a>(pub(super) Lines<'a>);
1295
1296#[cfg(not(feature = "ferrocene_subset"))]
1297#[stable(feature = "rust1", since = "1.0.0")]
1298#[allow(deprecated)]
1299impl<'a> Iterator for LinesAny<'a> {
1300 type Item = &'a str;
1301
1302 #[inline]
1303 fn next(&mut self) -> Option<&'a str> {
1304 self.0.next()
1305 }
1306
1307 #[inline]
1308 fn size_hint(&self) -> (usize, Option<usize>) {
1309 self.0.size_hint()
1310 }
1311}
1312
1313#[cfg(not(feature = "ferrocene_subset"))]
1314#[stable(feature = "rust1", since = "1.0.0")]
1315#[allow(deprecated)]
1316impl<'a> DoubleEndedIterator for LinesAny<'a> {
1317 #[inline]
1318 fn next_back(&mut self) -> Option<&'a str> {
1319 self.0.next_back()
1320 }
1321}
1322
1323#[cfg(not(feature = "ferrocene_subset"))]
1324#[stable(feature = "fused", since = "1.26.0")]
1325#[allow(deprecated)]
1326impl FusedIterator for LinesAny<'_> {}
1327
1328#[cfg(not(feature = "ferrocene_subset"))]
1336#[stable(feature = "split_whitespace", since = "1.1.0")]
1337#[derive(Clone, Debug)]
1338pub struct SplitWhitespace<'a> {
1339 pub(super) inner: Filter<Split<'a, IsWhitespace>, IsNotEmpty>,
1340}
1341
1342#[cfg(not(feature = "ferrocene_subset"))]
1350#[stable(feature = "split_ascii_whitespace", since = "1.34.0")]
1351#[derive(Clone, Debug)]
1352pub struct SplitAsciiWhitespace<'a> {
1353 pub(super) inner:
1354 Map<Filter<SliceSplit<'a, u8, IsAsciiWhitespace>, BytesIsNotEmpty>, UnsafeBytesToStr>,
1355}
1356
1357#[stable(feature = "split_inclusive", since = "1.51.0")]
1367pub struct SplitInclusive<'a, P: Pattern>(pub(super) SplitInternal<'a, P>);
1368
1369#[cfg(not(feature = "ferrocene_subset"))]
1370#[stable(feature = "split_whitespace", since = "1.1.0")]
1371impl<'a> Iterator for SplitWhitespace<'a> {
1372 type Item = &'a str;
1373
1374 #[inline]
1375 fn next(&mut self) -> Option<&'a str> {
1376 self.inner.next()
1377 }
1378
1379 #[inline]
1380 fn size_hint(&self) -> (usize, Option<usize>) {
1381 self.inner.size_hint()
1382 }
1383
1384 #[inline]
1385 fn last(mut self) -> Option<&'a str> {
1386 self.next_back()
1387 }
1388}
1389
1390#[cfg(not(feature = "ferrocene_subset"))]
1391#[stable(feature = "split_whitespace", since = "1.1.0")]
1392impl<'a> DoubleEndedIterator for SplitWhitespace<'a> {
1393 #[inline]
1394 fn next_back(&mut self) -> Option<&'a str> {
1395 self.inner.next_back()
1396 }
1397}
1398
1399#[cfg(not(feature = "ferrocene_subset"))]
1400#[stable(feature = "fused", since = "1.26.0")]
1401impl FusedIterator for SplitWhitespace<'_> {}
1402
1403#[cfg(not(feature = "ferrocene_subset"))]
1404impl<'a> SplitWhitespace<'a> {
1405 #[inline]
1422 #[must_use]
1423 #[unstable(feature = "str_split_whitespace_remainder", issue = "77998")]
1424 pub fn remainder(&self) -> Option<&'a str> {
1425 self.inner.iter.remainder()
1426 }
1427}
1428
1429#[cfg(not(feature = "ferrocene_subset"))]
1430#[stable(feature = "split_ascii_whitespace", since = "1.34.0")]
1431impl<'a> Iterator for SplitAsciiWhitespace<'a> {
1432 type Item = &'a str;
1433
1434 #[inline]
1435 fn next(&mut self) -> Option<&'a str> {
1436 self.inner.next()
1437 }
1438
1439 #[inline]
1440 fn size_hint(&self) -> (usize, Option<usize>) {
1441 self.inner.size_hint()
1442 }
1443
1444 #[inline]
1445 fn last(mut self) -> Option<&'a str> {
1446 self.next_back()
1447 }
1448}
1449
1450#[cfg(not(feature = "ferrocene_subset"))]
1451#[stable(feature = "split_ascii_whitespace", since = "1.34.0")]
1452impl<'a> DoubleEndedIterator for SplitAsciiWhitespace<'a> {
1453 #[inline]
1454 fn next_back(&mut self) -> Option<&'a str> {
1455 self.inner.next_back()
1456 }
1457}
1458
1459#[cfg(not(feature = "ferrocene_subset"))]
1460#[stable(feature = "split_ascii_whitespace", since = "1.34.0")]
1461impl FusedIterator for SplitAsciiWhitespace<'_> {}
1462
1463#[cfg(not(feature = "ferrocene_subset"))]
1464impl<'a> SplitAsciiWhitespace<'a> {
1465 #[inline]
1484 #[must_use]
1485 #[unstable(feature = "str_split_whitespace_remainder", issue = "77998")]
1486 pub fn remainder(&self) -> Option<&'a str> {
1487 if self.inner.iter.iter.finished {
1488 return None;
1489 }
1490
1491 Some(unsafe { crate::str::from_utf8_unchecked(&self.inner.iter.iter.v) })
1493 }
1494}
1495
1496#[stable(feature = "split_inclusive", since = "1.51.0")]
1497impl<'a, P: Pattern> Iterator for SplitInclusive<'a, P> {
1498 type Item = &'a str;
1499
1500 #[inline]
1501 fn next(&mut self) -> Option<&'a str> {
1502 self.0.next_inclusive()
1503 }
1504}
1505
1506#[stable(feature = "split_inclusive", since = "1.51.0")]
1507impl<'a, P: Pattern<Searcher<'a>: fmt::Debug>> fmt::Debug for SplitInclusive<'a, P> {
1508 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
1509 f.debug_struct("SplitInclusive").field("0", &self.0).finish()
1510 }
1511}
1512
1513#[cfg(not(feature = "ferrocene_subset"))]
1515#[stable(feature = "split_inclusive", since = "1.51.0")]
1516impl<'a, P: Pattern<Searcher<'a>: Clone>> Clone for SplitInclusive<'a, P> {
1517 fn clone(&self) -> Self {
1518 SplitInclusive(self.0.clone())
1519 }
1520}
1521
1522#[cfg(not(feature = "ferrocene_subset"))]
1523#[stable(feature = "split_inclusive", since = "1.51.0")]
1524impl<'a, P: Pattern<Searcher<'a>: DoubleEndedSearcher<'a>>> DoubleEndedIterator
1525 for SplitInclusive<'a, P>
1526{
1527 #[inline]
1528 fn next_back(&mut self) -> Option<&'a str> {
1529 self.0.next_back_inclusive()
1530 }
1531}
1532
1533#[cfg(not(feature = "ferrocene_subset"))]
1534#[stable(feature = "split_inclusive", since = "1.51.0")]
1535impl<'a, P: Pattern> FusedIterator for SplitInclusive<'a, P> {}
1536
1537#[cfg(not(feature = "ferrocene_subset"))]
1538impl<'a, P: Pattern> SplitInclusive<'a, P> {
1539 #[inline]
1555 #[unstable(feature = "str_split_inclusive_remainder", issue = "77998")]
1556 pub fn remainder(&self) -> Option<&'a str> {
1557 self.0.remainder()
1558 }
1559}
1560
1561#[cfg(not(feature = "ferrocene_subset"))]
1568#[derive(Clone)]
1569#[stable(feature = "encode_utf16", since = "1.8.0")]
1570pub struct EncodeUtf16<'a> {
1571 pub(super) chars: Chars<'a>,
1572 pub(super) extra: u16,
1573}
1574
1575#[cfg(not(feature = "ferrocene_subset"))]
1576#[stable(feature = "collection_debug", since = "1.17.0")]
1577impl fmt::Debug for EncodeUtf16<'_> {
1578 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
1579 f.debug_struct("EncodeUtf16").finish_non_exhaustive()
1580 }
1581}
1582
1583#[cfg(not(feature = "ferrocene_subset"))]
1584#[stable(feature = "encode_utf16", since = "1.8.0")]
1585impl<'a> Iterator for EncodeUtf16<'a> {
1586 type Item = u16;
1587
1588 #[inline]
1589 fn next(&mut self) -> Option<u16> {
1590 if self.extra != 0 {
1591 let tmp = self.extra;
1592 self.extra = 0;
1593 return Some(tmp);
1594 }
1595
1596 let mut buf = [0; 2];
1597 self.chars.next().map(|ch| {
1598 let n = ch.encode_utf16(&mut buf).len();
1599 if n == 2 {
1600 self.extra = buf[1];
1601 }
1602 buf[0]
1603 })
1604 }
1605
1606 #[inline]
1607 fn size_hint(&self) -> (usize, Option<usize>) {
1608 let len = self.chars.iter.len();
1609 if self.extra == 0 {
1618 (len.div_ceil(3), Some(len))
1619 } else {
1620 (len.div_ceil(3) + 1, Some(len + 1))
1623 }
1624 }
1625}
1626
1627#[cfg(not(feature = "ferrocene_subset"))]
1628#[stable(feature = "fused", since = "1.26.0")]
1629impl FusedIterator for EncodeUtf16<'_> {}
1630
1631#[cfg(not(feature = "ferrocene_subset"))]
1633#[stable(feature = "str_escape", since = "1.34.0")]
1634#[derive(Clone, Debug)]
1635pub struct EscapeDebug<'a> {
1636 pub(super) inner: Chain<
1637 Flatten<option::IntoIter<char_mod::EscapeDebug>>,
1638 FlatMap<Chars<'a>, char_mod::EscapeDebug, CharEscapeDebugContinue>,
1639 >,
1640}
1641
1642#[cfg(not(feature = "ferrocene_subset"))]
1644#[stable(feature = "str_escape", since = "1.34.0")]
1645#[derive(Clone, Debug)]
1646pub struct EscapeDefault<'a> {
1647 pub(super) inner: FlatMap<Chars<'a>, char_mod::EscapeDefault, CharEscapeDefault>,
1648}
1649
1650#[cfg(not(feature = "ferrocene_subset"))]
1652#[stable(feature = "str_escape", since = "1.34.0")]
1653#[derive(Clone, Debug)]
1654pub struct EscapeUnicode<'a> {
1655 pub(super) inner: FlatMap<Chars<'a>, char_mod::EscapeUnicode, CharEscapeUnicode>,
1656}
1657
1658#[cfg(not(feature = "ferrocene_subset"))]
1659macro_rules! escape_types_impls {
1660 ($( $Name: ident ),+) => {$(
1661 #[stable(feature = "str_escape", since = "1.34.0")]
1662 impl<'a> fmt::Display for $Name<'a> {
1663 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
1664 self.clone().try_for_each(|c| f.write_char(c))
1665 }
1666 }
1667
1668 #[stable(feature = "str_escape", since = "1.34.0")]
1669 impl<'a> Iterator for $Name<'a> {
1670 type Item = char;
1671
1672 #[inline]
1673 fn next(&mut self) -> Option<char> { self.inner.next() }
1674
1675 #[inline]
1676 fn size_hint(&self) -> (usize, Option<usize>) { self.inner.size_hint() }
1677
1678 #[inline]
1679 fn try_fold<Acc, Fold, R>(&mut self, init: Acc, fold: Fold) -> R where
1680 Self: Sized, Fold: FnMut(Acc, Self::Item) -> R, R: Try<Output = Acc>
1681 {
1682 self.inner.try_fold(init, fold)
1683 }
1684
1685 #[inline]
1686 fn fold<Acc, Fold>(self, init: Acc, fold: Fold) -> Acc
1687 where Fold: FnMut(Acc, Self::Item) -> Acc,
1688 {
1689 self.inner.fold(init, fold)
1690 }
1691 }
1692
1693 #[stable(feature = "str_escape", since = "1.34.0")]
1694 impl<'a> FusedIterator for $Name<'a> {}
1695 )+}
1696}
1697
1698#[cfg(not(feature = "ferrocene_subset"))]
1699escape_types_impls!(EscapeDebug, EscapeDefault, EscapeUnicode);