pattern_3/
ext.rs

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, // FIXME: RFC 2089 or 2289
14        {
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, // FIXME: RFC 2089 or 2289
28        {
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 iterator
41        forward:
42            $(#[$forward_iterator_attribute:meta])*
43            struct $forward_iterator:ident;
44
45        // Reverse iterator
46        reverse:
47            $(#[$reverse_iterator_attribute:meta])*
48            struct $reverse_iterator:ident;
49
50        // Stability of all generated items
51        stability:
52            $(#[$common_stability_attribute:meta])*
53
54        // Internal almost-iterator that is being delegated to
55        internal:
56            $internal_iterator:ident yielding ($iterty:ty);
57
58        // Kind of delegation - either single ended or double ended
59        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, // FIXME: RFC 2089 or 2289
66            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, // FIXME: RFC 2089 or 2289
76        {
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, // FIXME: RFC 2089 or 2289
90            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, // FIXME: RFC 2089 or 2289
100        {
101            type Item = $iterty;
102
103            #[inline]
104            fn next(&mut self) -> Option<Self::Item> {
105                self.0.next_back()
106            }
107        }
108
109        // #[stable(feature = "fused", since = "1.26.0")]
110        impl<H, S> FusedIterator for $forward_iterator<H, S>
111        where
112            H: Haystack,
113            S: Searcher<H::Target>,
114            H::Target: Hay, // FIXME: RFC 2089 or 2289
115        {}
116
117        // #[stable(feature = "fused", since = "1.26.0")]
118        impl<H, S> FusedIterator for $reverse_iterator<H, S>
119        where
120            H: Haystack,
121            S: ReverseSearcher<H::Target>,
122            H::Target: Hay, // FIXME: RFC 2089 or 2289
123        {}
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, // FIXME: RFC 2089 or 2289
140        {
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, // FIXME: RFC 2089 or 2289
153        {
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
167//------------------------------------------------------------------------------
168// Starts with / Ends with
169//------------------------------------------------------------------------------
170
171pub fn starts_with<H, P>(haystack: H, needle: P) -> bool
172where
173    H: Haystack,
174    P: Needle<H>,
175    H::Target: Hay, // FIXME: RFC 2089 or 2289
176{
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, // FIXME: RFC 2089 or 2289
187{
188    needle.into_consumer().rconsume((*haystack).into()).is_some()
189}
190
191//------------------------------------------------------------------------------
192// Trim
193//------------------------------------------------------------------------------
194
195#[inline]
196pub fn trim_start<H, P>(haystack: H, needle: P) -> H
197where
198    H: Haystack,
199    P: Needle<H>,
200    H::Target: Hay, // FIXME: RFC 2089 or 2289
201{
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, // FIXME: RFC 2089 or 2289
217{
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, // FIXME: RFC 2089 or 2289
233{
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//------------------------------------------------------------------------------
246// Matches
247//------------------------------------------------------------------------------
248
249#[derive(Debug, Clone)]
250struct MatchesInternal<H, S>
251where
252    H: Haystack,
253    H::Target: Hay, // FIXME: RFC 2089 or 2289
254{
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, // FIXME: RFC 2089 or 2289
264{
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, // FIXME: RFC 2089 or 2289
285{
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, // FIXME: RFC 2089 or 2289
317{
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, // FIXME: RFC 2089 or 2289
330{
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, // FIXME: RFC 2089 or 2289
342{
343    needle.into_searcher()
344        .search((*haystack).into())
345        .is_some()
346}
347
348//------------------------------------------------------------------------------
349// MatchIndices
350//------------------------------------------------------------------------------
351
352struct MatchIndicesInternal<H, S>
353where
354    H: Haystack,
355    H::Target: Hay, // FIXME: RFC 2089 or 2289
356{
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, // FIXME: RFC 2089 or 2289
367{
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, // FIXME: RFC 2089 or 2289
381{
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, // FIXME: RFC 2089 or 2289
406{
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, // FIXME: RFC 2089 or 2289
418{
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, // FIXME: RFC 2089 or 2289
430{
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, // FIXME: RFC 2089 or 2289
442{
443    needle.into_searcher()
444        .rsearch((*haystack).into())
445        .map(|r| r.start)
446}
447
448//------------------------------------------------------------------------------
449// MatchRanges
450//------------------------------------------------------------------------------
451
452struct MatchRangesInternal<H, S>
453where
454    H: Haystack,
455    H::Target: Hay, // FIXME: RFC 2089 or 2289
456{
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, // FIXME: RFC 2089 or 2289
467{
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, // FIXME: RFC 2089 or 2289
481{
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, // FIXME: RFC 2089 or 2289
506{
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, // FIXME: RFC 2089 or 2289
518{
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, // FIXME: RFC 2089 or 2289
529{
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, // FIXME: RFC 2089 or 2289
540{
541    needle.into_searcher()
542        .rsearch((*haystack).into())
543}
544
545//------------------------------------------------------------------------------
546// Split
547//------------------------------------------------------------------------------
548
549#[derive(Debug, Clone)]
550struct SplitInternal<H, S>
551where
552    H: Haystack,
553    H::Target: Hay, // FIXME: RFC 2089 or 2289
554{
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, // FIXME: RFC 2089 or 2289
566{
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, // FIXME: RFC 2089 or 2289
596{
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, // FIXME: RFC 2089 or 2289
654{
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, // FIXME: RFC 2089 or 2289
669{
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, // FIXME: RFC 2089 or 2289
683{
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, // FIXME: RFC 2089 or 2289
698{
699    RSplitTerminator(SplitInternal {
700        searcher: needle.into_searcher(),
701        rest: haystack.into(),
702        finished: false,
703        allow_trailing_empty: false,
704    })
705}
706
707//------------------------------------------------------------------------------
708// SplitN
709//------------------------------------------------------------------------------
710
711#[derive(Clone, Debug)]
712struct SplitNInternal<H, S>
713where
714    H: Haystack,
715    H::Target: Hay, // FIXME: RFC 2089 or 2289
716{
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, // FIXME: RFC 2089 or 2289
727{
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, // FIXME: RFC 2089 or 2289
761{
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, // FIXME: RFC 2089 or 2289
806{
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, // FIXME: RFC 2089 or 2289
820{
821    RSplitN(SplitNInternal {
822        searcher: needle.into_searcher(),
823        rest: haystack.into(),
824        n,
825    })
826}
827
828//------------------------------------------------------------------------------
829// Replace
830//------------------------------------------------------------------------------
831
832pub 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, // FIXME: RFC 2089 or 2289
839{
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, // FIXME: RFC 2089 or 2289
858{
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}