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