1use haystack::{Hay, Haystack, Span};
2use needle::{Needle, Searcher, ReverseSearcher, DoubleEndedSearcher, Consumer, ReverseConsumer, DoubleEndedConsumer};
3use std::iter::FusedIterator;
4use std::ops::Range;
5use std::fmt;
6
7macro_rules! generate_clone_and_debug {
8 ($name:ident, $field:tt) => {
9 impl<H, S> Clone for $name<H, S>
10 where
11 H: Haystack + Clone,
12 S: Clone,
13 H::Target: Hay, {
15 fn clone(&self) -> Self {
16 $name { $field: self.$field.clone() }
17 }
18 fn clone_from(&mut self, src: &Self) {
19 self.$field.clone_from(&src.$field);
20 }
21 }
22
23 impl<H, S> fmt::Debug for $name<H, S>
24 where
25 H: Haystack + fmt::Debug,
26 S: fmt::Debug,
27 H::Target: Hay, {
29 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
30 f.debug_tuple(stringify!($name))
31 .field(&self.$field)
32 .finish()
33 }
34 }
35 }
36}
37
38macro_rules! generate_pattern_iterators {
39 {
40 forward:
42 $(#[$forward_iterator_attribute:meta])*
43 struct $forward_iterator:ident;
44
45 reverse:
47 $(#[$reverse_iterator_attribute:meta])*
48 struct $reverse_iterator:ident;
49
50 stability:
52 $(#[$common_stability_attribute:meta])*
53
54 internal:
56 $internal_iterator:ident yielding ($iterty:ty);
57
58 delegate $($t:tt)*
60 } => {
61 $(#[$forward_iterator_attribute])*
62 $(#[$common_stability_attribute])*
63 pub struct $forward_iterator<H, S>($internal_iterator<H, S>)
64 where
65 H::Target: Hay, H: Haystack;
67
68 generate_clone_and_debug!($forward_iterator, 0);
69
70 $(#[$common_stability_attribute])*
71 impl<H, S> Iterator for $forward_iterator<H, S>
72 where
73 H: Haystack,
74 S: Searcher<H::Target>,
75 H::Target: Hay, {
77 type Item = $iterty;
78
79 #[inline]
80 fn next(&mut self) -> Option<Self::Item> {
81 self.0.next()
82 }
83 }
84
85 $(#[$reverse_iterator_attribute])*
86 $(#[$common_stability_attribute])*
87 pub struct $reverse_iterator<H, S>($internal_iterator<H, S>)
88 where
89 H::Target: Hay, H: Haystack;
91
92 generate_clone_and_debug!($reverse_iterator, 0);
93
94 $(#[$common_stability_attribute])*
95 impl<H, S> Iterator for $reverse_iterator<H, S>
96 where
97 H: Haystack,
98 S: ReverseSearcher<H::Target>,
99 H::Target: Hay, {
101 type Item = $iterty;
102
103 #[inline]
104 fn next(&mut self) -> Option<Self::Item> {
105 self.0.next_back()
106 }
107 }
108
109 impl<H, S> FusedIterator for $forward_iterator<H, S>
111 where
112 H: Haystack,
113 S: Searcher<H::Target>,
114 H::Target: Hay, {}
116
117 impl<H, S> FusedIterator for $reverse_iterator<H, S>
119 where
120 H: Haystack,
121 S: ReverseSearcher<H::Target>,
122 H::Target: Hay, {}
124
125 generate_pattern_iterators!($($t)* with $(#[$common_stability_attribute])*,
126 $forward_iterator,
127 $reverse_iterator);
128 };
129 {
130 double ended; with $(#[$common_stability_attribute:meta])*,
131 $forward_iterator:ident,
132 $reverse_iterator:ident
133 } => {
134 $(#[$common_stability_attribute])*
135 impl<H, S> DoubleEndedIterator for $forward_iterator<H, S>
136 where
137 H: Haystack,
138 S: DoubleEndedSearcher<H::Target>,
139 H::Target: Hay, {
141 #[inline]
142 fn next_back(&mut self) -> Option<Self::Item> {
143 self.0.next_back()
144 }
145 }
146
147 $(#[$common_stability_attribute])*
148 impl<H, S> DoubleEndedIterator for $reverse_iterator<H, S>
149 where
150 H: Haystack,
151 S: DoubleEndedSearcher<H::Target>,
152 H::Target: Hay, {
154 #[inline]
155 fn next_back(&mut self) -> Option<Self::Item> {
156 self.0.next()
157 }
158 }
159 };
160 {
161 single ended; with $(#[$common_stability_attribute:meta])*,
162 $forward_iterator:ident,
163 $reverse_iterator:ident
164 } => {}
165}
166
167pub fn starts_with<H, P>(haystack: H, needle: P) -> bool
172where
173 H: Haystack,
174 P: Needle<H>,
175 H::Target: Hay, {
177 needle.into_consumer().consume((*haystack).into()).is_some()
178}
179
180#[inline]
181pub fn ends_with<H, P>(haystack: H, needle: P) -> bool
182where
183 H: Haystack,
184 P: Needle<H>,
185 P::Consumer: ReverseConsumer<H::Target>,
186 H::Target: Hay, {
188 needle.into_consumer().rconsume((*haystack).into()).is_some()
189}
190
191#[inline]
196pub fn trim_start<H, P>(haystack: H, needle: P) -> H
197where
198 H: Haystack,
199 P: Needle<H>,
200 H::Target: Hay, {
202 let range = {
203 let hay = &*haystack;
204 let start = needle.into_consumer().trim_start(hay);
205 let end = hay.end_index();
206 start..end
207 };
208 unsafe { haystack.slice_unchecked(range) }
209}
210
211pub fn trim_end<H, P>(haystack: H, needle: P) -> H
212where
213 H: Haystack,
214 P: Needle<H>,
215 P::Consumer: ReverseConsumer<H::Target>,
216 H::Target: Hay, {
218 let range = {
219 let hay = &*haystack;
220 let start = hay.start_index();
221 let end = needle.into_consumer().trim_end(hay);
222 start..end
223 };
224 unsafe { haystack.slice_unchecked(range) }
225}
226
227pub fn trim<H, P>(haystack: H, needle: P) -> H
228where
229 H: Haystack,
230 P: Needle<H>,
231 P::Consumer: DoubleEndedConsumer<H::Target>,
232 H::Target: Hay, {
234 let mut checker = needle.into_consumer();
235 let range = {
236 let hay = &*haystack;
237 let end = checker.trim_end(hay);
238 let hay = unsafe { Hay::slice_unchecked(hay, hay.start_index()..end) };
239 let start = checker.trim_start(hay);
240 start..end
241 };
242 unsafe { haystack.slice_unchecked(range) }
243}
244
245#[derive(Debug, Clone)]
250struct MatchesInternal<H, S>
251where
252 H: Haystack,
253 H::Target: Hay, {
255 searcher: S,
256 rest: Span<H>,
257}
258
259impl<H, S> MatchesInternal<H, S>
260where
261 H: Haystack,
262 S: Searcher<H::Target>,
263 H::Target: Hay, {
265 #[inline]
266 fn next_spanned(&mut self) -> Option<Span<H>> {
267 let rest = self.rest.take();
268 let range = self.searcher.search(rest.borrow())?;
269 let [_, middle, right] = unsafe { rest.split_around(range) };
270 self.rest = right;
271 Some(middle)
272 }
273
274 #[inline]
275 fn next(&mut self) -> Option<H> {
276 Some(Span::into(self.next_spanned()?))
277 }
278}
279
280impl<H, S> MatchesInternal<H, S>
281where
282 H: Haystack,
283 S: ReverseSearcher<H::Target>,
284 H::Target: Hay, {
286 #[inline]
287 fn next_back_spanned(&mut self) -> Option<Span<H>> {
288 let rest = self.rest.take();
289 let range = self.searcher.rsearch(rest.borrow())?;
290 let [left, middle, _] = unsafe { rest.split_around(range) };
291 self.rest = left;
292 Some(middle)
293 }
294
295 #[inline]
296 fn next_back(&mut self) -> Option<H> {
297 Some(Span::into(self.next_back_spanned()?))
298 }
299}
300
301generate_pattern_iterators! {
302 forward:
303 struct Matches;
304 reverse:
305 struct RMatches;
306 stability:
307 internal:
308 MatchesInternal yielding (H);
309 delegate double ended;
310}
311
312pub fn matches<H, P>(haystack: H, needle: P) -> Matches<H, P::Searcher>
313where
314 H: Haystack,
315 P: Needle<H>,
316 H::Target: Hay, {
318 Matches(MatchesInternal {
319 searcher: needle.into_searcher(),
320 rest: haystack.into(),
321 })
322}
323
324pub fn rmatches<H, P>(haystack: H, needle: P) -> RMatches<H, P::Searcher>
325where
326 H: Haystack,
327 P: Needle<H>,
328 P::Searcher: ReverseSearcher<H::Target>,
329 H::Target: Hay, {
331 RMatches(MatchesInternal {
332 searcher: needle.into_searcher(),
333 rest: haystack.into(),
334 })
335}
336
337pub fn contains<H, P>(haystack: H, needle: P) -> bool
338where
339 H: Haystack,
340 P: Needle<H>,
341 H::Target: Hay, {
343 needle.into_searcher()
344 .search((*haystack).into())
345 .is_some()
346}
347
348struct MatchIndicesInternal<H, S>
353where
354 H: Haystack,
355 H::Target: Hay, {
357 inner: MatchesInternal<H, S>,
358}
359
360generate_clone_and_debug!(MatchIndicesInternal, inner);
361
362impl<H, S> MatchIndicesInternal<H, S>
363where
364 H: Haystack,
365 S: Searcher<H::Target>,
366 H::Target: Hay, {
368 #[inline]
369 fn next(&mut self) -> Option<(<H::Target as Hay>::Index, H)> {
370 let span = self.inner.next_spanned()?;
371 let index = span.original_range().start;
372 Some((index, Span::into(span)))
373 }
374}
375
376impl<H, S> MatchIndicesInternal<H, S>
377where
378 H: Haystack,
379 S: ReverseSearcher<H::Target>,
380 H::Target: Hay, {
382 #[inline]
383 fn next_back(&mut self) -> Option<(<H::Target as Hay>::Index, H)> {
384 let span = self.inner.next_back_spanned()?;
385 let index = span.original_range().start;
386 Some((index, Span::into(span)))
387 }
388}
389
390generate_pattern_iterators! {
391 forward:
392 struct MatchIndices;
393 reverse:
394 struct RMatchIndices;
395 stability:
396 internal:
397 MatchIndicesInternal yielding ((<H::Target as Hay>::Index, H));
398 delegate double ended;
399}
400
401pub fn match_indices<H, P>(haystack: H, needle: P) -> MatchIndices<H, P::Searcher>
402where
403 H: Haystack,
404 P: Needle<H>,
405 H::Target: Hay, {
407 MatchIndices(MatchIndicesInternal {
408 inner: matches(haystack, needle).0,
409 })
410}
411
412pub fn rmatch_indices<H, P>(haystack: H, needle: P) -> RMatchIndices<H, P::Searcher>
413where
414 H: Haystack,
415 P: Needle<H>,
416 P::Searcher: ReverseSearcher<H::Target>,
417 H::Target: Hay, {
419 RMatchIndices(MatchIndicesInternal {
420 inner: rmatches(haystack, needle).0,
421 })
422}
423
424#[inline]
425pub fn find<H, P>(haystack: H, needle: P) -> Option<<H::Target as Hay>::Index>
426where
427 H: Haystack,
428 P: Needle<H>,
429 H::Target: Hay, {
431 needle.into_searcher()
432 .search((*haystack).into())
433 .map(|r| r.start)
434}
435
436pub fn rfind<H, P>(haystack: H, needle: P) -> Option<<H::Target as Hay>::Index>
437where
438 H: Haystack,
439 P: Needle<H>,
440 P::Searcher: ReverseSearcher<H::Target>,
441 H::Target: Hay, {
443 needle.into_searcher()
444 .rsearch((*haystack).into())
445 .map(|r| r.start)
446}
447
448struct MatchRangesInternal<H, S>
453where
454 H: Haystack,
455 H::Target: Hay, {
457 inner: MatchesInternal<H, S>,
458}
459
460generate_clone_and_debug!(MatchRangesInternal, inner);
461
462impl<H, S> MatchRangesInternal<H, S>
463where
464 H: Haystack,
465 S: Searcher<H::Target>,
466 H::Target: Hay, {
468 #[inline]
469 fn next(&mut self) -> Option<(Range<<H::Target as Hay>::Index>, H)> {
470 let span = self.inner.next_spanned()?;
471 let range = span.original_range();
472 Some((range, Span::into(span)))
473 }
474}
475
476impl<H, S> MatchRangesInternal<H, S>
477where
478 H: Haystack,
479 S: ReverseSearcher<H::Target>,
480 H::Target: Hay, {
482 #[inline]
483 fn next_back(&mut self) -> Option<(Range<<H::Target as Hay>::Index>, H)> {
484 let span = self.inner.next_back_spanned()?;
485 let range = span.original_range();
486 Some((range, Span::into(span)))
487 }
488}
489
490generate_pattern_iterators! {
491 forward:
492 struct MatchRanges;
493 reverse:
494 struct RMatchRanges;
495 stability:
496 internal:
497 MatchRangesInternal yielding ((Range<<H::Target as Hay>::Index>, H));
498 delegate double ended;
499}
500
501pub fn match_ranges<H, P>(haystack: H, needle: P) -> MatchRanges<H, P::Searcher>
502where
503 H: Haystack,
504 P: Needle<H>,
505 H::Target: Hay, {
507 MatchRanges(MatchRangesInternal {
508 inner: matches(haystack, needle).0,
509 })
510}
511
512pub fn rmatch_ranges<H, P>(haystack: H, needle: P) -> RMatchRanges<H, P::Searcher>
513where
514 H: Haystack,
515 P: Needle<H>,
516 P::Searcher: ReverseSearcher<H::Target>,
517 H::Target: Hay, {
519 RMatchRanges(MatchRangesInternal {
520 inner: rmatches(haystack, needle).0,
521 })
522}
523
524pub fn find_range<H, P>(haystack: H, needle: P) -> Option<Range<<H::Target as Hay>::Index>>
525where
526 H: Haystack,
527 P: Needle<H>,
528 H::Target: Hay, {
530 needle.into_searcher()
531 .search((*haystack).into())
532}
533
534pub fn rfind_range<H, P>(haystack: H, needle: P) -> Option<Range<<H::Target as Hay>::Index>>
535where
536 H: Haystack,
537 P: Needle<H>,
538 P::Searcher: ReverseSearcher<H::Target>,
539 H::Target: Hay, {
541 needle.into_searcher()
542 .rsearch((*haystack).into())
543}
544
545#[derive(Debug, Clone)]
550struct SplitInternal<H, S>
551where
552 H: Haystack,
553 H::Target: Hay, {
555 searcher: S,
556 rest: Span<H>,
557 finished: bool,
558 allow_trailing_empty: bool,
559}
560
561impl<H, S> SplitInternal<H, S>
562where
563 H: Haystack,
564 S: Searcher<H::Target>,
565 H::Target: Hay, {
567 #[inline]
568 fn next(&mut self) -> Option<H> {
569 if self.finished {
570 return None;
571 }
572
573 let mut rest = self.rest.take();
574 match self.searcher.search(rest.borrow()) {
575 Some(subrange) => {
576 let [left, _, right] = unsafe { rest.split_around(subrange) };
577 self.rest = right;
578 rest = left;
579 }
580 None => {
581 self.finished = true;
582 if !self.allow_trailing_empty && rest.is_empty() {
583 return None;
584 }
585 }
586 }
587 Some(Span::into(rest))
588 }
589}
590
591impl<H, S> SplitInternal<H, S>
592where
593 H: Haystack,
594 S: ReverseSearcher<H::Target>,
595 H::Target: Hay, {
597 #[inline]
598 fn next_back(&mut self) -> Option<H> {
599 if self.finished {
600 return None;
601 }
602
603 let rest = self.rest.take();
604 let after = match self.searcher.rsearch(rest.borrow()) {
605 Some(range) => {
606 let [left, _, right] = unsafe { rest.split_around(range) };
607 self.rest = left;
608 right
609 }
610 None => {
611 self.finished = true;
612 rest
613 }
614 };
615
616 if !self.allow_trailing_empty {
617 self.allow_trailing_empty = true;
618 if after.is_empty() {
619 return self.next_back();
620 }
621 }
622
623 Some(Span::into(after))
624 }
625}
626
627generate_pattern_iterators! {
628 forward:
629 struct Split;
630 reverse:
631 struct RSplit;
632 stability:
633 internal:
634 SplitInternal yielding (H);
635 delegate double ended;
636}
637
638generate_pattern_iterators! {
639 forward:
640 struct SplitTerminator;
641 reverse:
642 struct RSplitTerminator;
643 stability:
644 internal:
645 SplitInternal yielding (H);
646 delegate double ended;
647}
648
649pub fn split<H, P>(haystack: H, needle: P) -> Split<H, P::Searcher>
650where
651 H: Haystack,
652 P: Needle<H>,
653 H::Target: Hay, {
655 Split(SplitInternal {
656 searcher: needle.into_searcher(),
657 rest: haystack.into(),
658 finished: false,
659 allow_trailing_empty: true,
660 })
661}
662
663pub fn rsplit<H, P>(haystack: H, needle: P) -> RSplit<H, P::Searcher>
664where
665 H: Haystack,
666 P: Needle<H>,
667 P::Searcher: ReverseSearcher<H::Target>,
668 H::Target: Hay, {
670 RSplit(SplitInternal {
671 searcher: needle.into_searcher(),
672 rest: haystack.into(),
673 finished: false,
674 allow_trailing_empty: true,
675 })
676}
677
678pub fn split_terminator<H, P>(haystack: H, needle: P) -> SplitTerminator<H, P::Searcher>
679where
680 H: Haystack,
681 P: Needle<H>,
682 H::Target: Hay, {
684 SplitTerminator(SplitInternal {
685 searcher: needle.into_searcher(),
686 rest: haystack.into(),
687 finished: false,
688 allow_trailing_empty: false,
689 })
690}
691
692pub fn rsplit_terminator<H, P>(haystack: H, needle: P) -> RSplitTerminator<H, P::Searcher>
693where
694 H: Haystack,
695 P: Needle<H>,
696 P::Searcher: ReverseSearcher<H::Target>,
697 H::Target: Hay, {
699 RSplitTerminator(SplitInternal {
700 searcher: needle.into_searcher(),
701 rest: haystack.into(),
702 finished: false,
703 allow_trailing_empty: false,
704 })
705}
706
707#[derive(Clone, Debug)]
712struct SplitNInternal<H, S>
713where
714 H: Haystack,
715 H::Target: Hay, {
717 searcher: S,
718 rest: Span<H>,
719 n: usize,
720}
721
722impl<H, S> SplitNInternal<H, S>
723where
724 H: Haystack,
725 S: Searcher<H::Target>,
726 H::Target: Hay, {
728 #[inline]
729 fn next(&mut self) -> Option<H> {
730 let mut rest = self.rest.take();
731 match self.n {
732 0 => {
733 return None;
734 }
735 1 => {
736 self.n = 0;
737 }
738 n => {
739 match self.searcher.search(rest.borrow()) {
740 Some(range) => {
741 let [left, _, right] = unsafe { rest.split_around(range) };
742 self.n = n - 1;
743 self.rest = right;
744 rest = left;
745 }
746 None => {
747 self.n = 0;
748 }
749 }
750 }
751 }
752 Some(Span::into(rest))
753 }
754}
755
756impl<H, S> SplitNInternal<H, S>
757where
758 H: Haystack,
759 S: ReverseSearcher<H::Target>,
760 H::Target: Hay, {
762 #[inline]
763 fn next_back(&mut self) -> Option<H> {
764 let mut rest = self.rest.take();
765 match self.n {
766 0 => {
767 return None;
768 }
769 1 => {
770 self.n = 0;
771 }
772 n => {
773 match self.searcher.rsearch(rest.borrow()) {
774 Some(range) => {
775 let [left, _, right] = unsafe { rest.split_around(range) };
776 self.n = n - 1;
777 self.rest = left;
778 rest = right;
779 }
780 None => {
781 self.n = 0;
782 }
783 }
784 }
785 }
786 Some(Span::into(rest))
787 }
788}
789
790generate_pattern_iterators! {
791 forward:
792 struct SplitN;
793 reverse:
794 struct RSplitN;
795 stability:
796 internal:
797 SplitNInternal yielding (H);
798 delegate single ended;
799}
800
801pub fn splitn<H, P>(haystack: H, n: usize, needle: P) -> SplitN<H, P::Searcher>
802where
803 H: Haystack,
804 P: Needle<H>,
805 H::Target: Hay, {
807 SplitN(SplitNInternal {
808 searcher: needle.into_searcher(),
809 rest: haystack.into(),
810 n,
811 })
812}
813
814pub fn rsplitn<H, P>(haystack: H, n: usize, needle: P) -> RSplitN<H, P::Searcher>
815where
816 H: Haystack,
817 P: Needle<H>,
818 P::Searcher: ReverseSearcher<H::Target>,
819 H::Target: Hay, {
821 RSplitN(SplitNInternal {
822 searcher: needle.into_searcher(),
823 rest: haystack.into(),
824 n,
825 })
826}
827
828pub fn replace_with<H, P, F, W>(src: H, from: P, mut replacer: F, mut writer: W)
833where
834 H: Haystack,
835 P: Needle<H>,
836 F: FnMut(H) -> H,
837 W: FnMut(H),
838 H::Target: Hay, {
840 let mut searcher = from.into_searcher();
841 let mut src = Span::from(src);
842 while let Some(range) = searcher.search(src.borrow()) {
843 let [left, middle, right] = unsafe { src.split_around(range) };
844 writer(Span::into(left));
845 writer(replacer(Span::into(middle)));
846 src = right;
847 }
848 writer(Span::into(src));
849}
850
851pub fn replacen_with<H, P, F, W>(src: H, from: P, mut replacer: F, mut n: usize, mut writer: W)
852where
853 H: Haystack,
854 P: Needle<H>,
855 F: FnMut(H) -> H,
856 W: FnMut(H),
857 H::Target: Hay, {
859 let mut searcher = from.into_searcher();
860 let mut src = Span::from(src);
861 loop {
862 if n == 0 {
863 break;
864 }
865 n -= 1;
866 if let Some(range) = searcher.search(src.borrow()) {
867 let [left, middle, right] = unsafe { src.split_around(range) };
868 writer(Span::into(left));
869 writer(replacer(Span::into(middle)));
870 src = right;
871 } else {
872 break;
873 }
874 }
875 writer(Span::into(src));
876}