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