im_rope/
pattern.rs

1//! Implementing types for pattern search
2//!
3//! This module provides the [`Pattern`] trait for types that can be used with
4//! methods such as [`Rope::find_all`], along with some types that power its
5//! implementation. These types are mostly implementation details, but they leak
6//! out in a few obscure places such as the bound on [`FindAll`](crate::FindAll)'s
7//! [`DoubleEndedIterator`] implementation, and so they are exposed and
8//! documented. Nonetheless, it should rarely be necessary for users of this
9//! crate to refer by name to any types defined in this module.
10
11use crate::accessor::{Accessor, OwningAccessor};
12use crate::{CharIndices, Rope};
13use memchr::memmem;
14use sealed::sealed;
15use static_cow::{Borrowed, IntoOwning, Owned, StaticCow, ToOwning};
16use std::collections::VecDeque;
17use std::iter::{DoubleEndedIterator, FusedIterator, Iterator};
18use std::ops::Range;
19
20/// Trait for types that can be matched on.
21///
22/// This sealed trait provides ad-hoc polymorphism for methods such as
23/// [`find`](Rope::find) which involve searching a rope for a substring,
24/// Similarly to the standard library trait [`std::str::pattern::Pattern`], the
25/// type of `Pattern` provided determines the match condition:
26///
27/// | Pattern type             | Match condition                           |
28/// |--------------------------|-------------------------------------------|
29/// | `&str`                   | is substring                              |
30/// | `String`, `&String`      | is substring                              |
31/// | `Rope`, `&Rope`          | is substring                              |
32/// | `char`                   | is contained in rope                      |
33/// | `&[char]`, `Vec<char>`   | any char in slice is contained in rope    |
34/// | `F: Fn(char) -> bool`    | `F` returns `true` for a char in rope     |
35///
36/// The type of pattern likewise determines the complexity of the search. In the
37/// following table, `N` represents the length of the needle, or when the needle
38/// is a predicate, its execution time. `H` represents the length of the hasystack.
39/// Note most search algorithms allocate O(N) temprorary storage regardless of
40/// whether the needle is borrowed or owned.
41///
42/// | Pattern type             | Time complexity            | Space complexity |
43/// |--------------------------|----------------------------|------------------|
44/// | `&str`                   | O(N + H log H)             | O(N)             |
45/// | `String`, `&String`      | O(N + H log H)             | O(N)             |
46/// | `Rope`, `&Rope`          | O(N + H log H)             | O(N)             |
47/// | `char`                   | O(H log H)                 | O(1)             |
48/// | `&[char]`                | O(N log N + H log H log N) | O(N)             |
49/// | `Vec<char>`              | O(N log N + H log H log N) | O(1)             |
50/// | `F: Fn(char) -> bool`    | O(NH log H)                | O(1)             |
51///
52/// All of this trait's methods are `#[doc(hidden)]` and are excluded from this
53/// crate's semantic versioning contract.
54
55#[sealed]
56pub trait Pattern {
57    /// For some patterns, this type is returned along with the match range to
58    /// indicate what was matched. Patterns that match on character predicates
59    /// or sets of characters have an output of `char`. Patterns that match on
60    /// a single string just output `()`.
61    type Output;
62
63    /// The equivalent owned version of this pattern. This type appears in the
64    /// signature of [`FindAll::into_owning`](crate::FindAll::into_owning) but
65    /// is otherwise uninteresting for consumers of this crate.
66    type Owned: Pattern;
67
68    /// The type which implements forward search for this pattern. This type
69    /// in bounds on iterator implementations on `FindAll` but is otherwise
70    /// uninteresting for consumers of this crate.
71    type FindAllImpl<A>: Iterator<Item = (Range<usize>, Self::Output)> + FusedIterator
72    where
73        A: Accessor;
74
75    /// The type which implements reverse search for this pattern. This type
76    /// in bounds on iterator implementations on `RFindAll` but is otherwise
77    /// uninteresting for consumers of this crate.
78    type RFindAllImpl<A>: Iterator<Item = (Range<usize>, Self::Output)> + FusedIterator
79    where
80        A: Accessor;
81
82    #[doc(hidden)]
83    fn _find_all<A>(self, accessor: A) -> Self::FindAllImpl<A>
84    where
85        A: Accessor;
86    #[doc(hidden)]
87    fn _rfind_all<A>(self, accessor: A) -> Self::RFindAllImpl<A>
88    where
89        A: Accessor;
90    #[doc(hidden)]
91    fn _is_prefix(self, haystack: &Rope) -> bool;
92    #[doc(hidden)]
93    fn _is_suffix(self, haystack: &Rope) -> bool;
94
95    // We want a further bound of IntoOwning<Owning = <Self::Owned as
96    // Pattern>::FindAllImpl<A::Owning>> on FindAllImpl and RFindAllImpl, but a
97    // compiler bug (https://github.com/rust-lang/rust/issues/107160) prevents
98    // this from working. These next four methods are a workaround.
99
100    #[doc(hidden)]
101    fn _convert_to_owning<A>(
102        finder: &Self::FindAllImpl<A>,
103    ) -> <Self::Owned as Pattern>::FindAllImpl<OwningAccessor>
104    where
105        A: Accessor;
106    #[doc(hidden)]
107    fn _convert_into_owning<A>(
108        finder: Self::FindAllImpl<A>,
109    ) -> <Self::Owned as Pattern>::FindAllImpl<OwningAccessor>
110    where
111        A: Accessor;
112    #[doc(hidden)]
113    fn _rconvert_to_owning<A>(
114        finder: &Self::RFindAllImpl<A>,
115    ) -> <Self::Owned as Pattern>::RFindAllImpl<OwningAccessor>
116    where
117        A: Accessor;
118    #[doc(hidden)]
119    fn _rconvert_into_owning<A>(
120        finder: Self::RFindAllImpl<A>,
121    ) -> <Self::Owned as Pattern>::RFindAllImpl<OwningAccessor>
122    where
123        A: Accessor;
124}
125
126#[sealed]
127impl<F> Pattern for F
128where
129    F: Fn(char) -> bool,
130{
131    type Output = char;
132    type Owned = F;
133
134    type FindAllImpl<A> = FindPred<A, F, false> where A: Accessor;
135    type RFindAllImpl<A> = FindPred<A, F, true> where A: Accessor;
136
137    fn _find_all<A>(self, haystack: A) -> Self::FindAllImpl<A>
138    where
139        A: Accessor,
140    {
141        FindPred::new(haystack, self)
142    }
143
144    fn _rfind_all<A>(self, haystack: A) -> Self::RFindAllImpl<A>
145    where
146        A: Accessor,
147    {
148        FindPred::new(haystack, self)
149    }
150
151    fn _is_prefix(self, haystack: &Rope) -> bool {
152        haystack.front().map_or(false, self)
153    }
154
155    fn _is_suffix(self, haystack: &Rope) -> bool {
156        haystack.back().map_or(false, self)
157    }
158
159    fn _convert_to_owning<A>(
160        finder: &Self::FindAllImpl<A>,
161    ) -> <Self::Owned as Pattern>::FindAllImpl<OwningAccessor>
162    where
163        A: Accessor,
164    {
165        finder.to_owning()
166    }
167    fn _convert_into_owning<A>(
168        finder: Self::FindAllImpl<A>,
169    ) -> <Self::Owned as Pattern>::FindAllImpl<OwningAccessor>
170    where
171        A: Accessor,
172    {
173        finder.into_owning()
174    }
175    fn _rconvert_to_owning<A>(
176        finder: &Self::RFindAllImpl<A>,
177    ) -> <Self::Owned as Pattern>::RFindAllImpl<OwningAccessor>
178    where
179        A: Accessor,
180    {
181        finder.to_owning()
182    }
183    fn _rconvert_into_owning<A>(
184        finder: Self::RFindAllImpl<A>,
185    ) -> <Self::Owned as Pattern>::RFindAllImpl<OwningAccessor>
186    where
187        A: Accessor,
188    {
189        finder.into_owning()
190    }
191}
192
193#[sealed]
194impl Pattern for char {
195    type Output = char;
196    type Owned = Self;
197
198    type FindAllImpl<A> = FindChar<A, false> where A: Accessor;
199    type RFindAllImpl<A> = FindChar<A, true> where A: Accessor;
200
201    fn _find_all<A>(self, accessor: A) -> Self::FindAllImpl<A>
202    where
203        A: Accessor,
204    {
205        FindChar::new(accessor, self)
206    }
207
208    fn _rfind_all<A>(self, accessor: A) -> Self::RFindAllImpl<A>
209    where
210        A: Accessor,
211    {
212        FindChar::new(accessor, self)
213    }
214
215    fn _is_prefix(self, haystack: &Rope) -> bool {
216        haystack.front() == Some(self)
217    }
218
219    fn _is_suffix(self, haystack: &Rope) -> bool {
220        haystack.back() == Some(self)
221    }
222
223    fn _convert_to_owning<A>(
224        finder: &Self::FindAllImpl<A>,
225    ) -> <Self::Owned as Pattern>::FindAllImpl<OwningAccessor>
226    where
227        A: Accessor,
228    {
229        finder.to_owning()
230    }
231
232    fn _convert_into_owning<A>(
233        finder: Self::FindAllImpl<A>,
234    ) -> <Self::Owned as Pattern>::FindAllImpl<OwningAccessor>
235    where
236        A: Accessor,
237    {
238        finder.into_owning()
239    }
240
241    fn _rconvert_to_owning<A>(
242        finder: &Self::RFindAllImpl<A>,
243    ) -> <Self::Owned as Pattern>::RFindAllImpl<OwningAccessor>
244    where
245        A: Accessor,
246    {
247        finder.to_owning()
248    }
249
250    fn _rconvert_into_owning<A>(
251        finder: Self::RFindAllImpl<A>,
252    ) -> <Self::Owned as Pattern>::RFindAllImpl<OwningAccessor>
253    where
254        A: Accessor,
255    {
256        finder.into_owning()
257    }
258}
259
260#[sealed]
261impl<'a> Pattern for &'a [char] {
262    type Output = char;
263    type Owned = Vec<char>;
264
265    type FindAllImpl<A> = FindChars<A, false> where A:Accessor;
266
267    type RFindAllImpl<A> = FindChars<A, true> where A:Accessor;
268
269    fn _find_all<A>(self, accessor: A) -> Self::FindAllImpl<A>
270    where
271        A: Accessor,
272    {
273        FindChars::new(accessor, Borrowed(self))
274    }
275
276    fn _rfind_all<A>(self, accessor: A) -> Self::RFindAllImpl<A>
277    where
278        A: Accessor,
279    {
280        FindChars::new(accessor, Borrowed(self))
281    }
282
283    fn _is_prefix(self, haystack: &Rope) -> bool {
284        haystack.front().map_or(false, |c| self.contains(&c))
285    }
286
287    fn _is_suffix(self, haystack: &Rope) -> bool {
288        haystack.back().map_or(false, |c| self.contains(&c))
289    }
290
291    fn _convert_to_owning<A>(
292        finder: &Self::FindAllImpl<A>,
293    ) -> <Self::Owned as Pattern>::FindAllImpl<OwningAccessor>
294    where
295        A: Accessor,
296    {
297        finder.to_owning()
298    }
299
300    fn _convert_into_owning<A>(
301        finder: Self::FindAllImpl<A>,
302    ) -> <Self::Owned as Pattern>::FindAllImpl<OwningAccessor>
303    where
304        A: Accessor,
305    {
306        finder.into_owning()
307    }
308
309    fn _rconvert_to_owning<A>(
310        finder: &Self::RFindAllImpl<A>,
311    ) -> <Self::Owned as Pattern>::RFindAllImpl<OwningAccessor>
312    where
313        A: Accessor,
314    {
315        finder.to_owning()
316    }
317
318    fn _rconvert_into_owning<A>(
319        finder: Self::RFindAllImpl<A>,
320    ) -> <Self::Owned as Pattern>::RFindAllImpl<OwningAccessor>
321    where
322        A: Accessor,
323    {
324        finder.into_owning()
325    }
326}
327
328#[sealed]
329impl Pattern for Vec<char> {
330    type Output = char;
331    type Owned = Vec<char>;
332
333    type FindAllImpl<A> = FindChars<A, false> where A:Accessor;
334
335    type RFindAllImpl<A> = FindChars<A, true> where A:Accessor;
336
337    fn _find_all<A>(self, accessor: A) -> Self::FindAllImpl<A>
338    where
339        A: Accessor,
340    {
341        FindChars::new(accessor, Owned(self))
342    }
343
344    fn _rfind_all<A>(self, accessor: A) -> Self::RFindAllImpl<A>
345    where
346        A: Accessor,
347    {
348        FindChars::new(accessor, Owned(self))
349    }
350
351    fn _is_prefix(self, haystack: &Rope) -> bool {
352        haystack.front().map_or(false, |c| self.contains(&c))
353    }
354
355    fn _is_suffix(self, haystack: &Rope) -> bool {
356        haystack.back().map_or(false, |c| self.contains(&c))
357    }
358
359    fn _convert_to_owning<A>(
360        finder: &Self::FindAllImpl<A>,
361    ) -> <Self::Owned as Pattern>::FindAllImpl<OwningAccessor>
362    where
363        A: Accessor,
364    {
365        finder.to_owning()
366    }
367
368    fn _convert_into_owning<A>(
369        finder: Self::FindAllImpl<A>,
370    ) -> <Self::Owned as Pattern>::FindAllImpl<OwningAccessor>
371    where
372        A: Accessor,
373    {
374        finder.into_owning()
375    }
376
377    fn _rconvert_to_owning<A>(
378        finder: &Self::RFindAllImpl<A>,
379    ) -> <Self::Owned as Pattern>::RFindAllImpl<OwningAccessor>
380    where
381        A: Accessor,
382    {
383        finder.to_owning()
384    }
385
386    fn _rconvert_into_owning<A>(
387        finder: Self::RFindAllImpl<A>,
388    ) -> <Self::Owned as Pattern>::RFindAllImpl<OwningAccessor>
389    where
390        A: Accessor,
391    {
392        finder.into_owning()
393    }
394}
395
396#[sealed]
397impl<'a> Pattern for &'a Vec<char> {
398    type Output = char;
399    type Owned = Vec<char>;
400
401    type FindAllImpl<A> = FindChars<A, false> where A:Accessor;
402
403    type RFindAllImpl<A> = FindChars<A, true> where A:Accessor;
404
405    fn _find_all<A>(self, accessor: A) -> Self::FindAllImpl<A>
406    where
407        A: Accessor,
408    {
409        FindChars::new(accessor, Borrowed(self.as_ref()))
410    }
411
412    fn _rfind_all<A>(self, accessor: A) -> Self::RFindAllImpl<A>
413    where
414        A: Accessor,
415    {
416        FindChars::new(accessor, Borrowed(self.as_ref()))
417    }
418
419    fn _is_prefix(self, haystack: &Rope) -> bool {
420        haystack.front().map_or(false, |c| self.contains(&c))
421    }
422
423    fn _is_suffix(self, haystack: &Rope) -> bool {
424        haystack.back().map_or(false, |c| self.contains(&c))
425    }
426
427    fn _convert_to_owning<A>(
428        finder: &Self::FindAllImpl<A>,
429    ) -> <Self::Owned as Pattern>::FindAllImpl<OwningAccessor>
430    where
431        A: Accessor,
432    {
433        finder.to_owning()
434    }
435
436    fn _convert_into_owning<A>(
437        finder: Self::FindAllImpl<A>,
438    ) -> <Self::Owned as Pattern>::FindAllImpl<OwningAccessor>
439    where
440        A: Accessor,
441    {
442        finder.into_owning()
443    }
444
445    fn _rconvert_to_owning<A>(
446        finder: &Self::RFindAllImpl<A>,
447    ) -> <Self::Owned as Pattern>::RFindAllImpl<OwningAccessor>
448    where
449        A: Accessor,
450    {
451        finder.to_owning()
452    }
453
454    fn _rconvert_into_owning<A>(
455        finder: Self::RFindAllImpl<A>,
456    ) -> <Self::Owned as Pattern>::RFindAllImpl<OwningAccessor>
457    where
458        A: Accessor,
459    {
460        finder.into_owning()
461    }
462}
463
464#[sealed]
465impl<'n> Pattern for &'n str {
466    type Output = ();
467    type Owned = String;
468
469    type FindAllImpl<A> = FindStr<'n, A> where A:Accessor;
470    type RFindAllImpl<A> = RFindStr<'n, A> where A:Accessor;
471
472    fn _find_all<A>(self, haystack: A) -> Self::FindAllImpl<A>
473    where
474        A: Accessor,
475    {
476        FindStr::borrowed(haystack, self)
477    }
478
479    fn _rfind_all<A>(self, haystack: A) -> Self::RFindAllImpl<A>
480    where
481        A: Accessor,
482    {
483        RFindStr::borrowed(haystack, self)
484    }
485
486    fn _is_prefix(self, haystack: &Rope) -> bool {
487        if self.len() > haystack.len() {
488            return false;
489        }
490
491        let mut needle_bytes = self.as_bytes();
492        let mut chunks = haystack.as_ref().leaves();
493
494        while !needle_bytes.is_empty() {
495            let chunk = chunks.next().expect("haystack at least as long as needle");
496            let len = std::cmp::min(needle_bytes.len(), chunk.len());
497            if needle_bytes[..len].ne(&chunk[..len]) {
498                return false;
499            }
500            needle_bytes = &needle_bytes[len..];
501        }
502
503        true
504    }
505
506    fn _is_suffix(self, haystack: &Rope) -> bool {
507        if self.len() > haystack.len() {
508            return false;
509        }
510
511        let mut needle_bytes = self.as_bytes();
512        let mut chunks = haystack.as_ref().leaves();
513
514        while !needle_bytes.is_empty() {
515            let chunk = chunks
516                .next_back()
517                .expect("haystack at least as long as needle");
518            let len = std::cmp::min(needle_bytes.len(), chunk.len());
519            if needle_bytes[needle_bytes.len() - len..].ne(&chunk[chunk.len() - len..]) {
520                return false;
521            }
522            needle_bytes = &needle_bytes[..needle_bytes.len() - len];
523        }
524
525        true
526    }
527
528    fn _convert_to_owning<A>(
529        finder: &Self::FindAllImpl<A>,
530    ) -> <Self::Owned as Pattern>::FindAllImpl<OwningAccessor>
531    where
532        A: Accessor,
533    {
534        finder.to_owning()
535    }
536
537    fn _convert_into_owning<A>(
538        finder: Self::FindAllImpl<A>,
539    ) -> <Self::Owned as Pattern>::FindAllImpl<OwningAccessor>
540    where
541        A: Accessor,
542    {
543        finder.into_owning()
544    }
545
546    fn _rconvert_to_owning<A>(
547        finder: &Self::RFindAllImpl<A>,
548    ) -> <Self::Owned as Pattern>::RFindAllImpl<OwningAccessor>
549    where
550        A: Accessor,
551    {
552        finder.to_owning()
553    }
554
555    fn _rconvert_into_owning<A>(
556        finder: Self::RFindAllImpl<A>,
557    ) -> <Self::Owned as Pattern>::RFindAllImpl<OwningAccessor>
558    where
559        A: Accessor,
560    {
561        finder.into_owning()
562    }
563}
564
565#[sealed]
566impl Pattern for String {
567    type Output = ();
568    type Owned = Self;
569
570    type FindAllImpl<A> = FindStr<'static, A> where A:Accessor;
571
572    type RFindAllImpl<A> = RFindStr<'static, A> where A:Accessor;
573
574    fn _find_all<A>(self, haystack: A) -> Self::FindAllImpl<A>
575    where
576        A: Accessor,
577    {
578        FindStr::owned(haystack, self.as_str())
579    }
580
581    fn _rfind_all<A>(self, haystack: A) -> Self::RFindAllImpl<A>
582    where
583        A: Accessor,
584    {
585        RFindStr::owned(haystack, self.as_str())
586    }
587
588    fn _is_prefix(self, haystack: &Rope) -> bool {
589        self.as_str()._is_prefix(haystack)
590    }
591
592    fn _is_suffix(self, haystack: &Rope) -> bool {
593        self.as_str()._is_suffix(haystack)
594    }
595
596    fn _convert_to_owning<A>(
597        finder: &Self::FindAllImpl<A>,
598    ) -> <Self::Owned as Pattern>::FindAllImpl<OwningAccessor>
599    where
600        A: Accessor,
601    {
602        finder.to_owning()
603    }
604
605    fn _convert_into_owning<A>(
606        finder: Self::FindAllImpl<A>,
607    ) -> <Self::Owned as Pattern>::FindAllImpl<OwningAccessor>
608    where
609        A: Accessor,
610    {
611        finder.into_owning()
612    }
613
614    fn _rconvert_to_owning<A>(
615        finder: &Self::RFindAllImpl<A>,
616    ) -> <Self::Owned as Pattern>::RFindAllImpl<OwningAccessor>
617    where
618        A: Accessor,
619    {
620        finder.to_owning()
621    }
622
623    fn _rconvert_into_owning<A>(
624        finder: Self::RFindAllImpl<A>,
625    ) -> <Self::Owned as Pattern>::RFindAllImpl<OwningAccessor>
626    where
627        A: Accessor,
628    {
629        finder.into_owning()
630    }
631}
632
633#[sealed]
634impl<'n> Pattern for &'n String {
635    type Output = ();
636    type Owned = String;
637
638    type FindAllImpl<A> = FindStr<'n, A> where A:Accessor;
639    type RFindAllImpl<A> = RFindStr<'n, A> where A:Accessor;
640
641    fn _find_all<A>(self, accessor: A) -> Self::FindAllImpl<A>
642    where
643        A: Accessor,
644    {
645        self.as_str()._find_all(accessor)
646    }
647
648    fn _rfind_all<A>(self, accessor: A) -> Self::RFindAllImpl<A>
649    where
650        A: Accessor,
651    {
652        self.as_str()._rfind_all(accessor)
653    }
654
655    fn _is_prefix(self, haystack: &Rope) -> bool {
656        self.as_str()._is_prefix(haystack)
657    }
658
659    fn _is_suffix(self, haystack: &Rope) -> bool {
660        self.as_str()._is_suffix(haystack)
661    }
662
663    fn _convert_to_owning<A>(
664        finder: &Self::FindAllImpl<A>,
665    ) -> <Self::Owned as Pattern>::FindAllImpl<OwningAccessor>
666    where
667        A: Accessor,
668    {
669        <&'n str>::_convert_to_owning(finder)
670    }
671
672    fn _convert_into_owning<A>(
673        finder: Self::FindAllImpl<A>,
674    ) -> <Self::Owned as Pattern>::FindAllImpl<OwningAccessor>
675    where
676        A: Accessor,
677    {
678        <&'n str>::_convert_into_owning(finder)
679    }
680
681    fn _rconvert_to_owning<A>(
682        finder: &Self::RFindAllImpl<A>,
683    ) -> <Self::Owned as Pattern>::RFindAllImpl<OwningAccessor>
684    where
685        A: Accessor,
686    {
687        <&'n str>::_rconvert_to_owning(finder)
688    }
689
690    fn _rconvert_into_owning<A>(
691        finder: Self::RFindAllImpl<A>,
692    ) -> <Self::Owned as Pattern>::RFindAllImpl<OwningAccessor>
693    where
694        A: Accessor,
695    {
696        <&'n str>::_rconvert_into_owning(finder)
697    }
698}
699
700#[sealed]
701impl<'n> Pattern for &'n Rope {
702    type Output = ();
703    type Owned = Rope;
704
705    type FindAllImpl<A> = FindStr<'static, A> where A:Accessor;
706    type RFindAllImpl<A>  = RFindStr<'static, A> where A:Accessor;
707
708    fn _find_all<A>(self, haystack: A) -> Self::FindAllImpl<A>
709    where
710        A: Accessor,
711    {
712        let needle: String = self.into();
713        needle._find_all(haystack)
714    }
715
716    fn _rfind_all<A>(self, haystack: A) -> Self::RFindAllImpl<A>
717    where
718        A: Accessor,
719    {
720        let needle: String = self.into();
721        needle._rfind_all(haystack)
722    }
723
724    fn _is_prefix(self, haystack: &Rope) -> bool {
725        if self.len() > haystack.len() {
726            return false;
727        }
728
729        let needle_chunks = self.as_ref().leaves();
730        let mut haystack_chunks = haystack.as_ref().leaves();
731        let mut haystack_chunk: &[u8] = &[];
732
733        for mut needle_chunk in needle_chunks {
734            while !needle_chunk.is_empty() {
735                while haystack_chunk.is_empty() {
736                    haystack_chunk = haystack_chunks
737                        .next()
738                        .expect("haystack at least as long as needle");
739                }
740                let len = std::cmp::min(needle_chunk.len(), haystack_chunk.len());
741                if needle_chunk[..len].ne(&haystack_chunk[..len]) {
742                    return false;
743                }
744                needle_chunk = &needle_chunk[len..];
745                haystack_chunk = &haystack_chunk[len..];
746            }
747        }
748
749        true
750    }
751
752    fn _is_suffix(self, haystack: &Rope) -> bool {
753        if self.len() > haystack.len() {
754            return false;
755        }
756
757        let needle_chunks = self.as_ref().leaves().rev();
758        let mut haystack_chunks = haystack.as_ref().leaves().rev();
759        let mut haystack_chunk: &[u8] = &[];
760
761        for mut needle_chunk in needle_chunks {
762            while !needle_chunk.is_empty() {
763                while haystack_chunk.is_empty() {
764                    haystack_chunk = haystack_chunks
765                        .next()
766                        .expect("haystack at least as long as needle");
767                }
768                let len = std::cmp::min(needle_chunk.len(), haystack_chunk.len());
769                if needle_chunk[needle_chunk.len() - len..]
770                    .ne(&haystack_chunk[haystack_chunk.len() - len..])
771                {
772                    return false;
773                }
774                needle_chunk = &needle_chunk[..needle_chunk.len() - len];
775                haystack_chunk = &haystack_chunk[..haystack_chunk.len() - len];
776            }
777        }
778        true
779    }
780
781    fn _convert_to_owning<A>(
782        finder: &Self::FindAllImpl<A>,
783    ) -> <Self::Owned as Pattern>::FindAllImpl<OwningAccessor>
784    where
785        A: Accessor,
786    {
787        finder.to_owning()
788    }
789
790    fn _convert_into_owning<A>(
791        finder: Self::FindAllImpl<A>,
792    ) -> <Self::Owned as Pattern>::FindAllImpl<OwningAccessor>
793    where
794        A: Accessor,
795    {
796        finder.into_owning()
797    }
798
799    fn _rconvert_to_owning<A>(
800        finder: &Self::RFindAllImpl<A>,
801    ) -> <Self::Owned as Pattern>::RFindAllImpl<OwningAccessor>
802    where
803        A: Accessor,
804    {
805        finder.to_owning()
806    }
807
808    fn _rconvert_into_owning<A>(
809        finder: Self::RFindAllImpl<A>,
810    ) -> <Self::Owned as Pattern>::RFindAllImpl<OwningAccessor>
811    where
812        A: Accessor,
813    {
814        finder.into_owning()
815    }
816}
817
818#[sealed]
819impl Pattern for Rope {
820    type Output = ();
821    type Owned = Self;
822
823    type FindAllImpl<A> = FindStr<'static, A> where A:Accessor;
824    type RFindAllImpl<A>  = RFindStr<'static, A> where A:Accessor;
825
826    fn _find_all<A>(self, haystack: A) -> Self::FindAllImpl<A>
827    where
828        A: Accessor,
829    {
830        let needle: String = self.into();
831        needle._find_all(haystack)
832    }
833
834    fn _rfind_all<A>(self, haystack: A) -> Self::RFindAllImpl<A>
835    where
836        A: Accessor,
837    {
838        let needle: String = self.into();
839        needle._rfind_all(haystack)
840    }
841
842    fn _is_prefix(self, haystack: &Rope) -> bool {
843        (&self)._is_prefix(haystack)
844    }
845
846    fn _is_suffix(self, haystack: &Rope) -> bool {
847        (&self)._is_suffix(haystack)
848    }
849
850    fn _convert_to_owning<A>(
851        finder: &Self::FindAllImpl<A>,
852    ) -> <Self::Owned as Pattern>::FindAllImpl<OwningAccessor>
853    where
854        A: Accessor,
855    {
856        finder.to_owning()
857    }
858
859    fn _convert_into_owning<A>(
860        finder: Self::FindAllImpl<A>,
861    ) -> <Self::Owned as Pattern>::FindAllImpl<OwningAccessor>
862    where
863        A: Accessor,
864    {
865        finder.into_owning()
866    }
867
868    fn _rconvert_to_owning<A>(
869        finder: &Self::RFindAllImpl<A>,
870    ) -> <Self::Owned as Pattern>::RFindAllImpl<OwningAccessor>
871    where
872        A: Accessor,
873    {
874        finder.to_owning()
875    }
876
877    fn _rconvert_into_owning<A>(
878        finder: Self::RFindAllImpl<A>,
879    ) -> <Self::Owned as Pattern>::RFindAllImpl<OwningAccessor>
880    where
881        A: Accessor,
882    {
883        finder.into_owning()
884    }
885}
886
887/// Finder implementation for predicates.
888pub struct FindPred<A, F, const REV: bool> {
889    hayspout: CharIndices<A>,
890    pred: std::rc::Rc<F>,
891}
892
893impl<A, F, const REV: bool> FindPred<A, F, REV>
894where
895    F: Fn(char) -> bool,
896    A: Accessor,
897{
898    fn new(haystack: A, pred: F) -> FindPred<A, F, REV> {
899        FindPred {
900            hayspout: CharIndices::new(haystack),
901            pred: std::rc::Rc::new(pred),
902        }
903    }
904}
905
906impl<A, F, const REV: bool> ToOwning for FindPred<A, F, REV>
907where
908    F: Fn(char) -> bool,
909    A: Accessor,
910{
911    type Owning = FindPred<A::Owning, F, REV>;
912
913    fn to_owning(&self) -> Self::Owning {
914        FindPred {
915            hayspout: self.hayspout.to_owning(),
916            pred: self.pred.to_owning(),
917        }
918    }
919}
920
921impl<A, F, const REV: bool> IntoOwning for FindPred<A, F, REV>
922where
923    F: Fn(char) -> bool,
924    A: Accessor,
925{
926    fn into_owning(self) -> Self::Owning {
927        FindPred {
928            hayspout: self.hayspout.into_owning(),
929            pred: self.pred.into_owning(),
930        }
931    }
932}
933
934impl<A, F, const REV: bool> Iterator for FindPred<A, F, REV>
935where
936    A: Accessor,
937    F: Fn(char) -> bool,
938{
939    type Item = (Range<usize>, char);
940
941    fn next(&mut self) -> Option<Self::Item> {
942        loop {
943            let (i, c) = if REV {
944                self.hayspout.next_back()?
945            } else {
946                self.hayspout.next()?
947            };
948            if (self.pred)(c) {
949                return Some((i..i + c.len_utf8(), c));
950            }
951        }
952    }
953
954    fn size_hint(&self) -> (usize, Option<usize>) {
955        let (_, max) = self.hayspout.size_hint();
956        (0, max)
957    }
958
959    fn last(mut self) -> Option<Self::Item> {
960        self.next_back()
961    }
962}
963
964impl<A, F, const REV: bool> DoubleEndedIterator for FindPred<A, F, REV>
965where
966    A: Accessor,
967    F: Fn(char) -> bool,
968{
969    fn next_back(&mut self) -> Option<Self::Item> {
970        loop {
971            let (i, c) = if REV {
972                self.hayspout.next()?
973            } else {
974                self.hayspout.next_back()?
975            };
976            if (self.pred)(c) {
977                return Some((i..i + c.len_utf8(), c));
978            }
979        }
980    }
981}
982
983impl<A, F, const REV: bool> FusedIterator for FindPred<A, F, REV>
984where
985    A: Accessor,
986    F: Fn(char) -> bool,
987{
988}
989
990/// Finder implementation for character lists.
991pub struct FindChars<A, const REV: bool> {
992    inner: FindCharsImpl<A, REV>,
993}
994enum FindCharsImpl<A, const REV: bool> {
995    One(FindMemchr<A, Memchr1Helper, REV>),
996    Two(FindMemchr<A, Memchr2Helper, REV>),
997    Three(FindMemchr<A, Memchr3Helper, REV>),
998    Generic(FindCharsGeneric<A, REV>),
999}
1000
1001/// Finder implementation for characters.
1002pub struct FindChar<A, const REV: bool> {
1003    inner: FindCharImpl<A, REV>,
1004}
1005
1006enum FindCharImpl<A, const REV: bool> {
1007    Ascii(FindMemchr<A, Memchr1Helper, REV>),
1008    Generic(FindCharGeneric<A, REV>),
1009}
1010
1011impl<A, const REV: bool> FindChars<A, REV>
1012where
1013    A: Accessor,
1014{
1015    fn new<N: StaticCow<[char]>>(haystack: A, needle: N) -> FindChars<A, REV> {
1016        FindChars {
1017            inner: match &*needle {
1018                [a] if a.is_ascii() => FindCharsImpl::One(FindMemchr::new(haystack, *a as u8)),
1019                [a, b] if a.is_ascii() && b.is_ascii() => {
1020                    FindCharsImpl::Two(FindMemchr::new(haystack, (*a as u8, *b as u8)))
1021                }
1022                [a, b, c] if a.is_ascii() && b.is_ascii() && c.is_ascii() => {
1023                    FindCharsImpl::Three(FindMemchr::new(haystack, (*a as u8, *b as u8, *c as u8)))
1024                }
1025                _ => FindCharsImpl::Generic(FindCharsGeneric::new(haystack, needle.into_owned())),
1026            },
1027        }
1028    }
1029}
1030
1031impl<A, const REV: bool> ToOwning for FindChars<A, REV>
1032where
1033    A: Accessor,
1034{
1035    type Owning = FindChars<A::Owning, REV>;
1036
1037    fn to_owning(&self) -> Self::Owning {
1038        FindChars {
1039            inner: match &self.inner {
1040                FindCharsImpl::One(iter) => FindCharsImpl::One(iter.to_owning()),
1041                FindCharsImpl::Two(iter) => FindCharsImpl::Two(iter.to_owning()),
1042                FindCharsImpl::Three(iter) => FindCharsImpl::Three(iter.to_owning()),
1043                FindCharsImpl::Generic(iter) => FindCharsImpl::Generic(iter.to_owning()),
1044            },
1045        }
1046    }
1047}
1048
1049impl<A, const REV: bool> IntoOwning for FindChars<A, REV>
1050where
1051    A: Accessor,
1052{
1053    fn into_owning(self) -> Self::Owning {
1054        FindChars {
1055            inner: match self.inner {
1056                FindCharsImpl::One(iter) => FindCharsImpl::One(iter.into_owning()),
1057                FindCharsImpl::Two(iter) => FindCharsImpl::Two(iter.into_owning()),
1058                FindCharsImpl::Three(iter) => FindCharsImpl::Three(iter.into_owning()),
1059                FindCharsImpl::Generic(iter) => FindCharsImpl::Generic(iter.into_owning()),
1060            },
1061        }
1062    }
1063}
1064
1065impl<A, const REV: bool> Iterator for FindChars<A, REV>
1066where
1067    A: Accessor,
1068{
1069    type Item = (Range<usize>, char);
1070
1071    fn next(&mut self) -> Option<Self::Item> {
1072        match &mut self.inner {
1073            FindCharsImpl::One(iter) => iter.next(),
1074            FindCharsImpl::Two(iter) => iter.next(),
1075            FindCharsImpl::Three(iter) => iter.next(),
1076            FindCharsImpl::Generic(iter) => iter.next(),
1077        }
1078    }
1079
1080    fn size_hint(&self) -> (usize, Option<usize>) {
1081        match &self.inner {
1082            FindCharsImpl::One(iter) => iter.size_hint(),
1083            FindCharsImpl::Two(iter) => iter.size_hint(),
1084            FindCharsImpl::Three(iter) => iter.size_hint(),
1085            FindCharsImpl::Generic(iter) => iter.size_hint(),
1086        }
1087    }
1088
1089    fn last(mut self) -> Option<Self::Item> {
1090        self.next_back()
1091    }
1092}
1093
1094impl<A, const REV: bool> DoubleEndedIterator for FindChars<A, REV>
1095where
1096    A: Accessor,
1097{
1098    fn next_back(&mut self) -> Option<Self::Item> {
1099        match &mut self.inner {
1100            FindCharsImpl::One(iter) => iter.next_back(),
1101            FindCharsImpl::Two(iter) => iter.next_back(),
1102            FindCharsImpl::Three(iter) => iter.next_back(),
1103            FindCharsImpl::Generic(iter) => iter.next_back(),
1104        }
1105    }
1106}
1107
1108impl<A, const REV: bool> FusedIterator for FindChars<A, REV> where A: Accessor {}
1109
1110impl<A, const REV: bool> FindChar<A, REV>
1111where
1112    A: Accessor,
1113{
1114    fn new(haystack: A, needle: char) -> FindChar<A, REV> {
1115        FindChar {
1116            inner: if needle.is_ascii() {
1117                FindCharImpl::Ascii(FindMemchr::new(haystack, needle as u8))
1118            } else {
1119                FindCharImpl::Generic(FindCharGeneric::new(haystack, needle))
1120            },
1121        }
1122    }
1123}
1124
1125impl<A, const REV: bool> ToOwning for FindChar<A, REV>
1126where
1127    A: Accessor,
1128{
1129    type Owning = FindChar<A::Owning, REV>;
1130
1131    fn to_owning(&self) -> Self::Owning {
1132        FindChar {
1133            inner: match &self.inner {
1134                FindCharImpl::Ascii(iter) => FindCharImpl::Ascii(iter.to_owning()),
1135                FindCharImpl::Generic(iter) => FindCharImpl::Generic(iter.to_owning()),
1136            },
1137        }
1138    }
1139}
1140
1141impl<A, const REV: bool> IntoOwning for FindChar<A, REV>
1142where
1143    A: Accessor,
1144{
1145    fn into_owning(self) -> Self::Owning {
1146        FindChar {
1147            inner: match self.inner {
1148                FindCharImpl::Ascii(iter) => FindCharImpl::Ascii(iter.into_owning()),
1149                FindCharImpl::Generic(iter) => FindCharImpl::Generic(iter.into_owning()),
1150            },
1151        }
1152    }
1153}
1154
1155impl<A, const REV: bool> Iterator for FindChar<A, REV>
1156where
1157    A: Accessor,
1158{
1159    type Item = (Range<usize>, char);
1160
1161    fn next(&mut self) -> Option<Self::Item> {
1162        match &mut self.inner {
1163            FindCharImpl::Ascii(iter) => iter.next(),
1164            FindCharImpl::Generic(iter) => iter.next(),
1165        }
1166    }
1167
1168    fn size_hint(&self) -> (usize, Option<usize>) {
1169        match &self.inner {
1170            FindCharImpl::Ascii(iter) => iter.size_hint(),
1171            FindCharImpl::Generic(iter) => iter.size_hint(),
1172        }
1173    }
1174
1175    fn last(mut self) -> Option<Self::Item> {
1176        self.next_back()
1177    }
1178}
1179
1180impl<A, const REV: bool> DoubleEndedIterator for FindChar<A, REV>
1181where
1182    A: Accessor,
1183{
1184    fn next_back(&mut self) -> Option<Self::Item> {
1185        match &mut self.inner {
1186            FindCharImpl::Ascii(iter) => iter.next_back(),
1187            FindCharImpl::Generic(iter) => iter.next_back(),
1188        }
1189    }
1190}
1191
1192impl<A, const REV: bool> FusedIterator for FindChar<A, REV> where A: Accessor {}
1193
1194struct FindCharsGeneric<A, const REV: bool> {
1195    hayspout: CharIndices<A>,
1196    needle: Vec<char>,
1197}
1198
1199impl<A, const REV: bool> FindCharsGeneric<A, REV>
1200where
1201    A: Accessor,
1202{
1203    fn new(haystack: A, mut needle: Vec<char>) -> FindCharsGeneric<A, REV> {
1204        needle.sort_unstable();
1205        FindCharsGeneric {
1206            hayspout: CharIndices::new(haystack),
1207            needle,
1208        }
1209    }
1210}
1211
1212impl<A, const REV: bool> ToOwning for FindCharsGeneric<A, REV>
1213where
1214    A: Accessor,
1215{
1216    type Owning = FindCharsGeneric<A::Owning, REV>;
1217
1218    fn to_owning(&self) -> Self::Owning {
1219        FindCharsGeneric {
1220            hayspout: self.hayspout.to_owning(),
1221            needle: self.needle.to_owning(),
1222        }
1223    }
1224}
1225
1226impl<A, const REV: bool> IntoOwning for FindCharsGeneric<A, REV>
1227where
1228    A: Accessor,
1229{
1230    fn into_owning(self) -> Self::Owning {
1231        FindCharsGeneric {
1232            hayspout: self.hayspout.into_owning(),
1233            needle: self.needle.into_owning(),
1234        }
1235    }
1236}
1237
1238impl<A, const REV: bool> Iterator for FindCharsGeneric<A, REV>
1239where
1240    A: Accessor,
1241{
1242    type Item = (Range<usize>, char);
1243
1244    fn next(&mut self) -> Option<Self::Item> {
1245        loop {
1246            let (i, c) = if REV {
1247                self.hayspout.next_back()?
1248            } else {
1249                self.hayspout.next()?
1250            };
1251            if self.needle.binary_search(&c).is_ok() {
1252                return Some((i..i + c.len_utf8(), c));
1253            }
1254        }
1255    }
1256
1257    fn size_hint(&self) -> (usize, Option<usize>) {
1258        let (_, max) = self.hayspout.size_hint();
1259        (0, max)
1260    }
1261
1262    fn last(mut self) -> Option<Self::Item> {
1263        self.next_back()
1264    }
1265}
1266
1267impl<A, const REV: bool> DoubleEndedIterator for FindCharsGeneric<A, REV>
1268where
1269    A: Accessor,
1270{
1271    fn next_back(&mut self) -> Option<Self::Item> {
1272        loop {
1273            let (i, c) = if REV {
1274                self.hayspout.next()?
1275            } else {
1276                self.hayspout.next_back()?
1277            };
1278            if self.needle.binary_search(&c).is_ok() {
1279                return Some((i..i + c.len_utf8(), c));
1280            }
1281        }
1282    }
1283}
1284
1285impl<A, const REV: bool> FusedIterator for FindCharsGeneric<A, REV> where A: Accessor {}
1286
1287struct FindCharGeneric<A, const REV: bool> {
1288    hayspout: CharIndices<A>,
1289    needle: char,
1290}
1291
1292impl<A, const REV: bool> FindCharGeneric<A, REV>
1293where
1294    A: Accessor,
1295{
1296    fn new(haystack: A, needle: char) -> FindCharGeneric<A, REV> {
1297        FindCharGeneric {
1298            hayspout: CharIndices::new(haystack),
1299            needle,
1300        }
1301    }
1302}
1303
1304impl<A, const REV: bool> ToOwning for FindCharGeneric<A, REV>
1305where
1306    A: Accessor,
1307{
1308    type Owning = FindCharGeneric<A::Owning, REV>;
1309
1310    fn to_owning(&self) -> Self::Owning {
1311        FindCharGeneric {
1312            hayspout: self.hayspout.to_owning(),
1313            needle: self.needle.to_owning(),
1314        }
1315    }
1316}
1317
1318impl<A, const REV: bool> IntoOwning for FindCharGeneric<A, REV>
1319where
1320    A: Accessor,
1321{
1322    fn into_owning(self) -> Self::Owning {
1323        FindCharGeneric {
1324            hayspout: self.hayspout.into_owning(),
1325            needle: self.needle.into_owning(),
1326        }
1327    }
1328}
1329
1330impl<A, const REV: bool> Iterator for FindCharGeneric<A, REV>
1331where
1332    A: Accessor,
1333{
1334    type Item = (Range<usize>, char);
1335
1336    fn next(&mut self) -> Option<Self::Item> {
1337        loop {
1338            let (i, c) = if REV {
1339                self.hayspout.next_back()?
1340            } else {
1341                self.hayspout.next()?
1342            };
1343            if self.needle == c {
1344                return Some((i..i + c.len_utf8(), c));
1345            }
1346        }
1347    }
1348
1349    fn size_hint(&self) -> (usize, Option<usize>) {
1350        let (_, max) = self.hayspout.size_hint();
1351        (0, max)
1352    }
1353
1354    fn last(mut self) -> Option<Self::Item> {
1355        self.next_back()
1356    }
1357}
1358
1359impl<A, const REV: bool> DoubleEndedIterator for FindCharGeneric<A, REV>
1360where
1361    A: Accessor,
1362{
1363    fn next_back(&mut self) -> Option<Self::Item> {
1364        loop {
1365            let (i, c) = if REV {
1366                self.hayspout.next()?
1367            } else {
1368                self.hayspout.next_back()?
1369            };
1370            if self.needle == c {
1371                return Some((i..i + c.len_utf8(), c));
1372            }
1373        }
1374    }
1375}
1376
1377impl<A, const REV: bool> FusedIterator for FindCharGeneric<A, REV> where A: Accessor {}
1378
1379trait MemchrHelper {
1380    type Needle: Copy;
1381    type Output<'a>: Iterator<Item = usize> + DoubleEndedIterator;
1382
1383    fn build(needle: Self::Needle, haystack: &[u8]) -> Self::Output<'_>;
1384}
1385
1386enum Memchr1Helper {}
1387impl MemchrHelper for Memchr1Helper {
1388    type Needle = u8;
1389    type Output<'a> = memchr::Memchr<'a>;
1390
1391    fn build(needle: Self::Needle, haystack: &[u8]) -> Self::Output<'_> {
1392        memchr::memchr_iter(needle, haystack)
1393    }
1394}
1395
1396enum Memchr2Helper {}
1397impl MemchrHelper for Memchr2Helper {
1398    type Needle = (u8, u8);
1399    type Output<'a> = memchr::Memchr2<'a>;
1400
1401    fn build(needle: Self::Needle, haystack: &[u8]) -> Self::Output<'_> {
1402        memchr::memchr2_iter(needle.0, needle.1, haystack)
1403    }
1404}
1405
1406enum Memchr3Helper {}
1407impl MemchrHelper for Memchr3Helper {
1408    type Needle = (u8, u8, u8);
1409    type Output<'a> = memchr::Memchr3<'a>;
1410
1411    fn build(needle: Self::Needle, haystack: &[u8]) -> Self::Output<'_> {
1412        memchr::memchr3_iter(needle.0, needle.1, needle.2, haystack)
1413    }
1414}
1415
1416struct FindMemchr<A, H, const REV: bool>
1417where
1418    H: MemchrHelper,
1419{
1420    haystack: A,
1421    needle: H::Needle,
1422    front_matches: VecDeque<(Range<usize>, char)>,
1423    back_matches: VecDeque<(Range<usize>, char)>,
1424}
1425
1426impl<A, H, const REV: bool> FindMemchr<A, H, REV>
1427where
1428    A: Accessor,
1429    H: MemchrHelper,
1430{
1431    fn new(haystack: A, needle: H::Needle) -> FindMemchr<A, H, REV> {
1432        FindMemchr {
1433            haystack,
1434            needle,
1435            front_matches: VecDeque::with_capacity(64),
1436            back_matches: VecDeque::with_capacity(64),
1437        }
1438    }
1439
1440    fn forward(&mut self) -> Option<(Range<usize>, char)> {
1441        while self.front_matches.is_empty() {
1442            if let Some((range, chunk)) = self.haystack.front_chunk() {
1443                for i in H::build(self.needle, chunk) {
1444                    #[allow(clippy::range_plus_one)]
1445                    self.front_matches
1446                        .push_back((range.start + i..range.start + i + 1, chunk[i] as char));
1447                }
1448            } else {
1449                break;
1450            }
1451        }
1452
1453        self.front_matches
1454            .pop_front()
1455            .or_else(|| self.back_matches.pop_back())
1456    }
1457
1458    fn backward(&mut self) -> Option<(Range<usize>, char)> {
1459        while self.back_matches.is_empty() {
1460            if let Some((range, chunk)) = self.haystack.back_chunk() {
1461                for i in H::build(self.needle, chunk).rev() {
1462                    #[allow(clippy::range_plus_one)]
1463                    self.back_matches
1464                        .push_back((range.start + i..range.start + i + 1, chunk[i] as char));
1465                }
1466            } else {
1467                break;
1468            }
1469        }
1470
1471        self.back_matches
1472            .pop_front()
1473            .or_else(|| self.front_matches.pop_back())
1474    }
1475}
1476
1477impl<A, H, const REV: bool> ToOwning for FindMemchr<A, H, REV>
1478where
1479    A: Accessor,
1480    H: MemchrHelper,
1481{
1482    type Owning = FindMemchr<A::Owning, H, REV>;
1483
1484    fn to_owning(&self) -> Self::Owning {
1485        FindMemchr {
1486            haystack: self.haystack.to_owning(),
1487            needle: self.needle.to_owning(),
1488            front_matches: self.front_matches.to_owning(),
1489            back_matches: self.back_matches.to_owning(),
1490        }
1491    }
1492}
1493
1494impl<A, H, const REV: bool> IntoOwning for FindMemchr<A, H, REV>
1495where
1496    A: Accessor,
1497    H: MemchrHelper,
1498{
1499    fn into_owning(self) -> Self::Owning {
1500        FindMemchr {
1501            haystack: self.haystack.into_owning(),
1502            needle: self.needle.into_owning(),
1503            front_matches: self.front_matches.into_owning(),
1504            back_matches: self.back_matches.into_owning(),
1505        }
1506    }
1507}
1508
1509impl<A, H, const REV: bool> Iterator for FindMemchr<A, H, REV>
1510where
1511    A: Accessor,
1512    H: MemchrHelper,
1513{
1514    type Item = (Range<usize>, char);
1515
1516    fn next(&mut self) -> Option<Self::Item> {
1517        if REV {
1518            self.backward()
1519        } else {
1520            self.forward()
1521        }
1522    }
1523
1524    fn size_hint(&self) -> (usize, Option<usize>) {
1525        let min = self.front_matches.len() + self.back_matches.len();
1526        let max = min + (self.haystack.back_index() - self.haystack.front_index());
1527        (min, Some(max))
1528    }
1529
1530    fn last(mut self) -> Option<Self::Item> {
1531        self.next_back()
1532    }
1533}
1534
1535impl<A, H, const REV: bool> DoubleEndedIterator for FindMemchr<A, H, REV>
1536where
1537    A: Accessor,
1538    H: MemchrHelper,
1539{
1540    fn next_back(&mut self) -> Option<Self::Item> {
1541        if REV {
1542            self.forward()
1543        } else {
1544            self.backward()
1545        }
1546    }
1547}
1548
1549impl<A, H, const REV: bool> FusedIterator for FindMemchr<A, H, REV>
1550where
1551    A: Accessor,
1552    H: MemchrHelper,
1553{
1554}
1555
1556/// Finder implementation for strings.
1557pub struct FindStr<'n, A> {
1558    inner: FindStrImpl<'n, A>,
1559}
1560
1561enum FindStrImpl<'n, A> {
1562    Nonempty(FindNonemptyStr<'n, A>),
1563    Empty(FindEmpty<A, false>),
1564}
1565
1566impl<'n, A> FindStr<'n, A>
1567where
1568    A: Accessor,
1569{
1570    fn borrowed(haystack: A, needle: &'n str) -> FindStr<'n, A> {
1571        FindStr {
1572            inner: if needle.is_empty() {
1573                FindStrImpl::Empty(FindEmpty::new(haystack))
1574            } else {
1575                FindStrImpl::Nonempty(FindNonemptyStr::borrowed(haystack, needle))
1576            },
1577        }
1578    }
1579
1580    fn owned(haystack: A, needle: &'n str) -> FindStr<'static, A> {
1581        FindStr {
1582            inner: if needle.is_empty() {
1583                FindStrImpl::Empty(FindEmpty::new(haystack))
1584            } else {
1585                FindStrImpl::Nonempty(FindNonemptyStr::owned(haystack, needle))
1586            },
1587        }
1588    }
1589}
1590
1591impl<'n, A> ToOwning for FindStr<'n, A>
1592where
1593    A: Accessor,
1594{
1595    type Owning = FindStr<'static, A::Owning>;
1596
1597    fn to_owning(&self) -> Self::Owning {
1598        FindStr {
1599            inner: match &self.inner {
1600                FindStrImpl::Nonempty(iter) => FindStrImpl::Nonempty(iter.to_owning()),
1601                FindStrImpl::Empty(iter) => FindStrImpl::Empty(iter.to_owning()),
1602            },
1603        }
1604    }
1605}
1606
1607impl<'n, A> IntoOwning for FindStr<'n, A>
1608where
1609    A: Accessor,
1610{
1611    fn into_owning(self) -> Self::Owning {
1612        FindStr {
1613            inner: match self.inner {
1614                FindStrImpl::Nonempty(iter) => FindStrImpl::Nonempty(iter.into_owning()),
1615                FindStrImpl::Empty(iter) => FindStrImpl::Empty(iter.into_owning()),
1616            },
1617        }
1618    }
1619}
1620
1621impl<'n, A> Iterator for FindStr<'n, A>
1622where
1623    A: Accessor,
1624{
1625    type Item = (Range<usize>, ());
1626
1627    fn next(&mut self) -> Option<Self::Item> {
1628        match &mut self.inner {
1629            FindStrImpl::Nonempty(iter) => iter.next(),
1630            FindStrImpl::Empty(iter) => iter.next(),
1631        }
1632    }
1633
1634    fn size_hint(&self) -> (usize, Option<usize>) {
1635        match &self.inner {
1636            FindStrImpl::Nonempty(iter) => iter.size_hint(),
1637            FindStrImpl::Empty(iter) => iter.size_hint(),
1638        }
1639    }
1640}
1641
1642impl<'n, A> FusedIterator for FindStr<'n, A> where A: Accessor {}
1643
1644/// Reverse finder implementation for strings.
1645pub struct RFindStr<'n, A> {
1646    inner: RFindStrImpl<'n, A>,
1647}
1648
1649enum RFindStrImpl<'n, A> {
1650    Nonempty(RFindNonemptyStr<'n, A>),
1651    Empty(FindEmpty<A, true>),
1652}
1653
1654impl<'n, A> RFindStr<'n, A>
1655where
1656    A: Accessor,
1657{
1658    fn borrowed(haystack: A, needle: &'n str) -> RFindStr<'n, A> {
1659        RFindStr {
1660            inner: if needle.is_empty() {
1661                RFindStrImpl::Empty(FindEmpty::new(haystack))
1662            } else {
1663                RFindStrImpl::Nonempty(RFindNonemptyStr::borrowed(haystack, needle))
1664            },
1665        }
1666    }
1667
1668    fn owned(haystack: A, needle: &'n str) -> RFindStr<'static, A> {
1669        RFindStr {
1670            inner: if needle.is_empty() {
1671                RFindStrImpl::Empty(FindEmpty::new(haystack))
1672            } else {
1673                RFindStrImpl::Nonempty(RFindNonemptyStr::owned(haystack, needle))
1674            },
1675        }
1676    }
1677}
1678
1679impl<'n, A> ToOwning for RFindStr<'n, A>
1680where
1681    A: Accessor,
1682{
1683    type Owning = RFindStr<'static, A::Owning>;
1684
1685    fn to_owning(&self) -> Self::Owning {
1686        RFindStr {
1687            inner: match &self.inner {
1688                RFindStrImpl::Nonempty(iter) => RFindStrImpl::Nonempty(iter.to_owning()),
1689                RFindStrImpl::Empty(iter) => RFindStrImpl::Empty(iter.to_owning()),
1690            },
1691        }
1692    }
1693}
1694
1695impl<'n, A> IntoOwning for RFindStr<'n, A>
1696where
1697    A: Accessor,
1698{
1699    fn into_owning(self) -> Self::Owning {
1700        RFindStr {
1701            inner: match self.inner {
1702                RFindStrImpl::Nonempty(iter) => RFindStrImpl::Nonempty(iter.into_owning()),
1703                RFindStrImpl::Empty(iter) => RFindStrImpl::Empty(iter.into_owning()),
1704            },
1705        }
1706    }
1707}
1708
1709impl<'n, A> Iterator for RFindStr<'n, A>
1710where
1711    A: Accessor,
1712{
1713    type Item = (Range<usize>, ());
1714
1715    fn next(&mut self) -> Option<Self::Item> {
1716        match &mut self.inner {
1717            RFindStrImpl::Nonempty(iter) => iter.next(),
1718            RFindStrImpl::Empty(iter) => iter.next(),
1719        }
1720    }
1721
1722    fn size_hint(&self) -> (usize, Option<usize>) {
1723        match &self.inner {
1724            RFindStrImpl::Nonempty(iter) => iter.size_hint(),
1725            RFindStrImpl::Empty(iter) => iter.size_hint(),
1726        }
1727    }
1728}
1729
1730impl<'n, A> FusedIterator for RFindStr<'n, A> where A: Accessor {}
1731
1732struct FindEmpty<A, const REV: bool> {
1733    hayspout: CharIndices<A>,
1734    back: Option<usize>,
1735}
1736
1737impl<A, const REV: bool> FindEmpty<A, REV>
1738where
1739    A: Accessor,
1740{
1741    fn new(haystack: A) -> FindEmpty<A, REV> {
1742        FindEmpty {
1743            back: Some(haystack.back_index()),
1744            hayspout: CharIndices::new(haystack),
1745        }
1746    }
1747
1748    fn forward(&mut self) -> Option<(Range<usize>, ())> {
1749        if let Some((i, _)) = self.hayspout.next() {
1750            Some((i..i, ()))
1751        } else {
1752            self.back.take().map(|i| (i..i, ()))
1753        }
1754    }
1755
1756    fn backward(&mut self) -> Option<(Range<usize>, ())> {
1757        if let Some(i) = self.back.take() {
1758            Some((i..i, ()))
1759        } else {
1760            self.hayspout.next_back().map(|(i, _)| (i..i, ()))
1761        }
1762    }
1763}
1764
1765impl<A, const REV: bool> ToOwning for FindEmpty<A, REV>
1766where
1767    A: Accessor,
1768{
1769    type Owning = FindEmpty<A::Owning, REV>;
1770
1771    fn to_owning(&self) -> Self::Owning {
1772        FindEmpty {
1773            hayspout: self.hayspout.to_owning(),
1774            back: self.back.to_owning(),
1775        }
1776    }
1777}
1778
1779impl<A, const REV: bool> IntoOwning for FindEmpty<A, REV>
1780where
1781    A: Accessor,
1782{
1783    fn into_owning(self) -> Self::Owning {
1784        FindEmpty {
1785            hayspout: self.hayspout.into_owning(),
1786            back: self.back.into_owning(),
1787        }
1788    }
1789}
1790
1791impl<A, const REV: bool> Iterator for FindEmpty<A, REV>
1792where
1793    A: Accessor,
1794{
1795    type Item = (Range<usize>, ());
1796
1797    fn next(&mut self) -> Option<Self::Item> {
1798        if REV {
1799            self.backward()
1800        } else {
1801            self.forward()
1802        }
1803    }
1804
1805    fn size_hint(&self) -> (usize, Option<usize>) {
1806        let (min, max) = self.hayspout.size_hint();
1807        let more: usize = self.back.is_some().into();
1808        (min + more, max.map(|n| n + more))
1809    }
1810
1811    fn last(mut self) -> Option<Self::Item> {
1812        self.next_back()
1813    }
1814}
1815
1816impl<A, const REV: bool> DoubleEndedIterator for FindEmpty<A, REV>
1817where
1818    A: Accessor,
1819{
1820    fn next_back(&mut self) -> Option<Self::Item> {
1821        if REV {
1822            self.forward()
1823        } else {
1824            self.backward()
1825        }
1826    }
1827}
1828
1829struct FindNonemptyStr<'n, A> {
1830    haystack: A,
1831    finder: memmem::Finder<'n>,
1832    window: VecDeque<u8>,
1833    matches: VecDeque<(Range<usize>, ())>,
1834    window_start_index: usize,
1835}
1836
1837impl<'n, A> FindNonemptyStr<'n, A>
1838where
1839    A: Accessor,
1840{
1841    fn borrowed(haystack: A, needle: &'n str) -> FindNonemptyStr<'n, A> {
1842        let match_capacity = (haystack.back_index() - haystack.front_index()).saturating_add(63);
1843        let window_capacity =
1844            match_capacity.saturating_add(haystack.back_index() - haystack.front_index());
1845        FindNonemptyStr {
1846            window_start_index: haystack.front_index(),
1847            haystack,
1848            finder: memmem::Finder::new(needle),
1849            window: VecDeque::with_capacity(window_capacity),
1850            matches: VecDeque::with_capacity(match_capacity),
1851        }
1852    }
1853
1854    fn owned(haystack: A, needle: &'n str) -> FindNonemptyStr<'static, A> {
1855        let match_capacity = (haystack.back_index() - haystack.front_index()).saturating_add(63);
1856        let window_capacity =
1857            match_capacity.saturating_add(haystack.back_index() - haystack.front_index());
1858        FindNonemptyStr {
1859            window_start_index: haystack.front_index(),
1860            haystack,
1861            finder: memmem::Finder::new(needle).into_owned(),
1862            window: VecDeque::with_capacity(window_capacity),
1863            matches: VecDeque::with_capacity(match_capacity),
1864        }
1865    }
1866}
1867
1868impl<'n, A> ToOwning for FindNonemptyStr<'n, A>
1869where
1870    A: Accessor,
1871{
1872    type Owning = FindNonemptyStr<'static, A::Owning>;
1873
1874    fn to_owning(&self) -> Self::Owning {
1875        FindNonemptyStr {
1876            haystack: self.haystack.to_owning(),
1877            finder: self.finder.clone().into_owned(),
1878            window: self.window.to_owning(),
1879            matches: self.matches.to_owning(),
1880            window_start_index: self.window_start_index.to_owning(),
1881        }
1882    }
1883}
1884
1885impl<'n, A> IntoOwning for FindNonemptyStr<'n, A>
1886where
1887    A: Accessor,
1888{
1889    fn into_owning(self) -> Self::Owning {
1890        FindNonemptyStr {
1891            haystack: self.haystack.into_owning(),
1892            finder: self.finder.into_owned(),
1893            window: self.window.into_owning(),
1894            matches: self.matches.into_owning(),
1895            window_start_index: self.window_start_index.into_owning(),
1896        }
1897    }
1898}
1899
1900impl<'n, A> Iterator for FindNonemptyStr<'n, A>
1901where
1902    A: Accessor,
1903{
1904    type Item = (Range<usize>, ());
1905
1906    fn next(&mut self) -> Option<Self::Item> {
1907        let needle_len = self.finder.needle().len();
1908
1909        while self.matches.is_empty() {
1910            while self.window.len() / 2 < needle_len {
1911                match self.haystack.front_chunk() {
1912                    Some((_, chunk)) => {
1913                        self.window.extend(chunk);
1914                    }
1915                    None => {
1916                        break;
1917                    }
1918                }
1919            }
1920
1921            if self.window.len() < needle_len {
1922                break;
1923            }
1924
1925            for i in self.finder.find_iter(self.window.make_contiguous()) {
1926                self.matches.push_back((
1927                    self.window_start_index + i..self.window_start_index + i + needle_len,
1928                    (),
1929                ));
1930            }
1931
1932            let cutoff = self.window.len() - needle_len + 1;
1933            self.window.drain(..cutoff);
1934            self.window_start_index += cutoff;
1935        }
1936
1937        self.matches.pop_front()
1938    }
1939
1940    fn size_hint(&self) -> (usize, Option<usize>) {
1941        (
1942            self.matches.len(),
1943            Some(
1944                self.matches.len()
1945                    + (self.window.len()
1946                        + (self.haystack.back_index() - self.haystack.front_index())
1947                        + 1)
1948                    .saturating_sub(self.finder.needle().len()),
1949            ),
1950        )
1951    }
1952}
1953
1954impl<'n, A> FusedIterator for FindNonemptyStr<'n, A> where A: Accessor {}
1955
1956struct RFindNonemptyStr<'n, A> {
1957    haystack: A,
1958    finder: memmem::FinderRev<'n>,
1959    window: VecDeque<u8>,
1960    matches: VecDeque<(Range<usize>, ())>,
1961    window_start_index: usize,
1962}
1963
1964impl<'n, A> RFindNonemptyStr<'n, A>
1965where
1966    A: Accessor,
1967{
1968    fn borrowed(haystack: A, needle: &'n str) -> RFindNonemptyStr<'n, A> {
1969        let match_capacity = (haystack.back_index() - haystack.front_index()).saturating_add(63);
1970        let window_capacity =
1971            match_capacity.saturating_add(haystack.back_index() - haystack.front_index());
1972        RFindNonemptyStr {
1973            window_start_index: haystack.back_index(),
1974            haystack,
1975            finder: memmem::FinderRev::new(needle),
1976            window: VecDeque::with_capacity(window_capacity),
1977            matches: VecDeque::with_capacity(match_capacity),
1978        }
1979    }
1980
1981    fn owned(haystack: A, needle: &'n str) -> RFindNonemptyStr<'static, A> {
1982        let match_capacity = (haystack.back_index() - haystack.front_index()).saturating_add(63);
1983        let window_capacity =
1984            match_capacity.saturating_add(haystack.back_index() - haystack.front_index());
1985        RFindNonemptyStr {
1986            window_start_index: haystack.back_index(),
1987            haystack,
1988            finder: memmem::FinderRev::new(needle).into_owned(),
1989            window: VecDeque::with_capacity(window_capacity),
1990            matches: VecDeque::with_capacity(match_capacity),
1991        }
1992    }
1993}
1994
1995impl<'n, A> ToOwning for RFindNonemptyStr<'n, A>
1996where
1997    A: Accessor,
1998{
1999    type Owning = RFindNonemptyStr<'static, A::Owning>;
2000
2001    fn to_owning(&self) -> Self::Owning {
2002        RFindNonemptyStr {
2003            haystack: self.haystack.to_owning(),
2004            finder: self.finder.clone().into_owned(),
2005            window: self.window.to_owning(),
2006            matches: self.matches.to_owning(),
2007            window_start_index: self.window_start_index.to_owning(),
2008        }
2009    }
2010}
2011
2012impl<'n, A> IntoOwning for RFindNonemptyStr<'n, A>
2013where
2014    A: Accessor,
2015{
2016    fn into_owning(self) -> Self::Owning {
2017        RFindNonemptyStr {
2018            haystack: self.haystack.into_owning(),
2019            finder: self.finder.into_owned(),
2020            window: self.window.into_owning(),
2021            matches: self.matches.into_owning(),
2022            window_start_index: self.window_start_index.into_owning(),
2023        }
2024    }
2025}
2026
2027impl<'n, A> Iterator for RFindNonemptyStr<'n, A>
2028where
2029    A: Accessor,
2030{
2031    type Item = (Range<usize>, ());
2032
2033    fn next(&mut self) -> Option<Self::Item> {
2034        let needle_len = self.finder.needle().len();
2035
2036        while self.matches.is_empty() {
2037            while self.window.len() / 2 < needle_len {
2038                match self.haystack.back_chunk() {
2039                    Some((_, chunk)) => {
2040                        for byte in chunk.iter().rev() {
2041                            self.window.push_front(*byte);
2042                        }
2043                        self.window_start_index -= chunk.len();
2044                    }
2045                    None => {
2046                        break;
2047                    }
2048                }
2049            }
2050
2051            if self.window.len() < needle_len {
2052                break;
2053            }
2054
2055            for i in self.finder.rfind_iter(self.window.make_contiguous()) {
2056                self.matches.push_back((
2057                    self.window_start_index + i..self.window_start_index + i + needle_len,
2058                    (),
2059                ));
2060            }
2061
2062            let cutoff = needle_len - 1;
2063            self.window.truncate(cutoff);
2064        }
2065
2066        self.matches.pop_front()
2067    }
2068
2069    fn size_hint(&self) -> (usize, Option<usize>) {
2070        (
2071            self.matches.len(),
2072            Some(
2073                self.matches.len()
2074                    + (self.window.len()
2075                        + (self.haystack.back_index() - self.haystack.front_index())
2076                        + 1)
2077                    .saturating_sub(self.finder.needle().len()),
2078            ),
2079        )
2080    }
2081}
2082
2083#[cfg(test)]
2084pub(crate) mod tests {
2085    use super::*;
2086    use proptest::prelude::*;
2087    #[derive(Debug, Copy, Clone)]
2088    pub(crate) struct CharStrategy;
2089
2090    impl Strategy for CharStrategy {
2091        type Tree = prop::char::CharValueTree;
2092
2093        type Value = char;
2094
2095        fn new_tree(
2096            &self,
2097            runner: &mut prop::test_runner::TestRunner,
2098        ) -> prop::strategy::NewTree<Self> {
2099            if runner.rng().gen_bool(0.5) {
2100                any::<char>().new_tree(runner)
2101            } else {
2102                prop::char::range('\0', '\u{7F}').new_tree(runner)
2103            }
2104        }
2105    }
2106
2107    #[derive(Debug, Copy, Clone)]
2108    pub(crate) struct CharsetStrategy;
2109
2110    impl Strategy for CharsetStrategy {
2111        type Tree = prop::collection::VecValueTree<prop::char::CharValueTree>;
2112
2113        type Value = Vec<char>;
2114
2115        fn new_tree(
2116            &self,
2117            runner: &mut prop::test_runner::TestRunner,
2118        ) -> prop::strategy::NewTree<Self> {
2119            if runner.rng().gen_bool(0.5) {
2120                prop::collection::vec(any::<char>(), 0..8).new_tree(runner)
2121            } else {
2122                prop::collection::vec(prop::char::range('\0', '\u{7F}'), 1..=3).new_tree(runner)
2123            }
2124        }
2125    }
2126
2127    #[derive(Debug, Clone)]
2128    pub(crate) enum CharPattern {
2129        Pred(Vec<char>),
2130        Char(char),
2131        Chars(Vec<char>),
2132        CharsVec(Vec<char>),
2133        CharsVecRef(Vec<char>),
2134    }
2135
2136    impl CharPattern {
2137        pub(crate) fn to_pred(&self) -> Box<dyn Fn(char) -> bool + 'static> {
2138            match self {
2139                Self::Pred(v) | Self::Chars(v) | Self::CharsVec(v) | Self::CharsVecRef(v) => {
2140                    vec_to_pred(v.clone())
2141                }
2142                Self::Char(ch) => {
2143                    let ch = *ch;
2144                    Box::new(move |other| other == ch)
2145                }
2146            }
2147        }
2148    }
2149
2150    fn vec_to_pred(v: Vec<char>) -> Box<dyn Fn(char) -> bool + 'static> {
2151        Box::new(move |ch| v.contains(&ch))
2152    }
2153
2154    pub(crate) enum CharPatternFinder<A, const REV: bool> {
2155        Pred(crate::pattern::FindPred<A, Box<dyn Fn(char) -> bool + 'static>, REV>),
2156        Char(crate::pattern::FindChar<A, REV>),
2157        Chars(crate::pattern::FindChars<A, REV>),
2158    }
2159
2160    impl<A, const REV: bool> ToOwning for CharPatternFinder<A, REV>
2161    where
2162        A: Accessor,
2163    {
2164        type Owning = CharPatternFinder<A::Owning, REV>;
2165
2166        fn to_owning(&self) -> Self::Owning {
2167            match self {
2168                CharPatternFinder::Pred(p) => CharPatternFinder::Pred(p.to_owning()),
2169                CharPatternFinder::Char(p) => CharPatternFinder::Char(p.to_owning()),
2170                CharPatternFinder::Chars(p) => CharPatternFinder::Chars(p.to_owning()),
2171            }
2172        }
2173    }
2174
2175    impl<A, const REV: bool> IntoOwning for CharPatternFinder<A, REV>
2176    where
2177        A: Accessor,
2178    {
2179        fn into_owning(self) -> Self::Owning {
2180            match self {
2181                CharPatternFinder::Pred(p) => CharPatternFinder::Pred(p.into_owning()),
2182                CharPatternFinder::Char(p) => CharPatternFinder::Char(p.into_owning()),
2183                CharPatternFinder::Chars(p) => CharPatternFinder::Chars(p.into_owning()),
2184            }
2185        }
2186    }
2187
2188    impl<A, const REV: bool> Iterator for CharPatternFinder<A, REV>
2189    where
2190        A: Accessor,
2191    {
2192        type Item = (Range<usize>, char);
2193
2194        fn next(&mut self) -> Option<Self::Item> {
2195            match self {
2196                CharPatternFinder::Pred(iter) => iter.next(),
2197                CharPatternFinder::Char(iter) => iter.next(),
2198                CharPatternFinder::Chars(iter) => iter.next(),
2199            }
2200        }
2201
2202        fn size_hint(&self) -> (usize, Option<usize>) {
2203            match self {
2204                CharPatternFinder::Pred(iter) => iter.size_hint(),
2205                CharPatternFinder::Char(iter) => iter.size_hint(),
2206                CharPatternFinder::Chars(iter) => iter.size_hint(),
2207            }
2208        }
2209
2210        fn last(self) -> Option<Self::Item> {
2211            match self {
2212                CharPatternFinder::Pred(iter) => iter.last(),
2213                CharPatternFinder::Char(iter) => iter.last(),
2214                CharPatternFinder::Chars(iter) => iter.last(),
2215            }
2216        }
2217    }
2218
2219    impl<A, const REV: bool> DoubleEndedIterator for CharPatternFinder<A, REV>
2220    where
2221        A: Accessor,
2222    {
2223        fn next_back(&mut self) -> Option<Self::Item> {
2224            match self {
2225                CharPatternFinder::Pred(iter) => iter.next_back(),
2226                CharPatternFinder::Char(iter) => iter.next_back(),
2227                CharPatternFinder::Chars(iter) => iter.next_back(),
2228            }
2229        }
2230    }
2231
2232    impl<A, const REV: bool> FusedIterator for CharPatternFinder<A, REV> where A: Accessor {}
2233
2234    #[sealed::sealed]
2235    impl Pattern for &CharPattern {
2236        type Output = char;
2237
2238        type Owned = Self;
2239
2240        type FindAllImpl<A> = CharPatternFinder<A, false> where A: Accessor;
2241
2242        type RFindAllImpl<A> = CharPatternFinder<A, true> where A: Accessor;
2243
2244        fn _find_all<A>(self, accessor: A) -> Self::FindAllImpl<A>
2245        where
2246            A: Accessor,
2247        {
2248            match self {
2249                CharPattern::Pred(v) => {
2250                    CharPatternFinder::Pred(vec_to_pred(v.clone())._find_all(accessor))
2251                }
2252                CharPattern::Char(ch) => CharPatternFinder::Char(ch._find_all(accessor)),
2253                CharPattern::Chars(v) => CharPatternFinder::Chars(v.as_slice()._find_all(accessor)),
2254                CharPattern::CharsVec(v) => CharPatternFinder::Chars(v.clone()._find_all(accessor)),
2255                CharPattern::CharsVecRef(v) => CharPatternFinder::Chars(v._find_all(accessor)),
2256            }
2257        }
2258
2259        fn _rfind_all<A>(self, accessor: A) -> Self::RFindAllImpl<A>
2260        where
2261            A: Accessor,
2262        {
2263            match self {
2264                CharPattern::Pred(v) => {
2265                    CharPatternFinder::Pred(vec_to_pred(v.clone())._rfind_all(accessor))
2266                }
2267                CharPattern::Char(ch) => CharPatternFinder::Char(ch._rfind_all(accessor)),
2268                CharPattern::Chars(v) => {
2269                    CharPatternFinder::Chars(v.as_slice()._rfind_all(accessor))
2270                }
2271                CharPattern::CharsVec(v) => {
2272                    CharPatternFinder::Chars(v.clone()._rfind_all(accessor))
2273                }
2274                CharPattern::CharsVecRef(v) => CharPatternFinder::Chars(v._rfind_all(accessor)),
2275            }
2276        }
2277
2278        fn _is_prefix(self, haystack: &Rope) -> bool {
2279            match self {
2280                CharPattern::Pred(v) => vec_to_pred(v.clone())._is_prefix(haystack),
2281                CharPattern::Char(ch) => ch._is_prefix(haystack),
2282                CharPattern::Chars(v) => v.as_slice()._is_prefix(haystack),
2283                CharPattern::CharsVec(v) => v.clone()._is_prefix(haystack),
2284                CharPattern::CharsVecRef(v) => v._is_prefix(haystack),
2285            }
2286        }
2287
2288        fn _is_suffix(self, haystack: &Rope) -> bool {
2289            match self {
2290                CharPattern::Pred(v) => vec_to_pred(v.clone())._is_suffix(haystack),
2291                CharPattern::Char(ch) => ch._is_suffix(haystack),
2292                CharPattern::Chars(v) => v.as_slice()._is_suffix(haystack),
2293                CharPattern::CharsVec(v) => v.clone()._is_suffix(haystack),
2294                CharPattern::CharsVecRef(v) => v._is_suffix(haystack),
2295            }
2296        }
2297
2298        fn _convert_to_owning<A>(
2299            finder: &Self::FindAllImpl<A>,
2300        ) -> <Self::Owned as Pattern>::FindAllImpl<OwningAccessor>
2301        where
2302            A: Accessor,
2303        {
2304            match finder {
2305                CharPatternFinder::Pred(f) => {
2306                    CharPatternFinder::Pred(
2307                        Box::<dyn Fn(char) -> bool + 'static>::_convert_to_owning(f),
2308                    )
2309                }
2310                CharPatternFinder::Char(f) => CharPatternFinder::Char(char::_convert_to_owning(f)),
2311                CharPatternFinder::Chars(f) => {
2312                    CharPatternFinder::Chars(Vec::<char>::_convert_to_owning(f))
2313                }
2314            }
2315        }
2316
2317        fn _convert_into_owning<A>(
2318            finder: Self::FindAllImpl<A>,
2319        ) -> <Self::Owned as Pattern>::FindAllImpl<OwningAccessor>
2320        where
2321            A: Accessor,
2322        {
2323            match finder {
2324                CharPatternFinder::Pred(f) => {
2325                    CharPatternFinder::Pred(
2326                        Box::<dyn Fn(char) -> bool + 'static>::_convert_into_owning(f),
2327                    )
2328                }
2329                CharPatternFinder::Char(f) => {
2330                    CharPatternFinder::Char(char::_convert_into_owning(f))
2331                }
2332                CharPatternFinder::Chars(f) => {
2333                    CharPatternFinder::Chars(Vec::<char>::_convert_into_owning(f))
2334                }
2335            }
2336        }
2337
2338        fn _rconvert_to_owning<A>(
2339            finder: &Self::RFindAllImpl<A>,
2340        ) -> <Self::Owned as Pattern>::RFindAllImpl<OwningAccessor>
2341        where
2342            A: Accessor,
2343        {
2344            match finder {
2345                CharPatternFinder::Pred(f) => {
2346                    CharPatternFinder::Pred(
2347                        Box::<dyn Fn(char) -> bool + 'static>::_rconvert_to_owning(f),
2348                    )
2349                }
2350                CharPatternFinder::Char(f) => CharPatternFinder::Char(char::_rconvert_to_owning(f)),
2351                CharPatternFinder::Chars(f) => {
2352                    CharPatternFinder::Chars(Vec::<char>::_rconvert_to_owning(f))
2353                }
2354            }
2355        }
2356
2357        fn _rconvert_into_owning<A>(
2358            finder: Self::RFindAllImpl<A>,
2359        ) -> <Self::Owned as Pattern>::RFindAllImpl<OwningAccessor>
2360        where
2361            A: Accessor,
2362        {
2363            match finder {
2364                CharPatternFinder::Pred(f) => {
2365                    CharPatternFinder::Pred(
2366                        Box::<dyn Fn(char) -> bool + 'static>::_rconvert_into_owning(f),
2367                    )
2368                }
2369                CharPatternFinder::Char(f) => {
2370                    CharPatternFinder::Char(char::_rconvert_into_owning(f))
2371                }
2372                CharPatternFinder::Chars(f) => {
2373                    CharPatternFinder::Chars(Vec::<char>::_rconvert_into_owning(f))
2374                }
2375            }
2376        }
2377    }
2378
2379    pub(crate) enum CharPatternValueTree {
2380        Pred(prop::collection::VecValueTree<prop::char::CharValueTree>),
2381        Char(prop::char::CharValueTree),
2382        Chars(prop::collection::VecValueTree<prop::char::CharValueTree>),
2383        CharsVec(prop::collection::VecValueTree<prop::char::CharValueTree>),
2384        CharsVecRef(prop::collection::VecValueTree<prop::char::CharValueTree>),
2385    }
2386
2387    impl prop::strategy::ValueTree for CharPatternValueTree {
2388        type Value = CharPattern;
2389
2390        fn current(&self) -> Self::Value {
2391            match self {
2392                CharPatternValueTree::Pred(t) => CharPattern::Pred(t.current()),
2393                CharPatternValueTree::Char(t) => CharPattern::Char(t.current()),
2394                CharPatternValueTree::Chars(t) => CharPattern::Chars(t.current()),
2395                CharPatternValueTree::CharsVec(t) => CharPattern::CharsVec(t.current()),
2396                CharPatternValueTree::CharsVecRef(t) => CharPattern::CharsVecRef(t.current()),
2397            }
2398        }
2399
2400        fn simplify(&mut self) -> bool {
2401            match self {
2402                CharPatternValueTree::Pred(t)
2403                | CharPatternValueTree::Chars(t)
2404                | CharPatternValueTree::CharsVec(t)
2405                | CharPatternValueTree::CharsVecRef(t) => t.simplify(),
2406                CharPatternValueTree::Char(t) => t.simplify(),
2407            }
2408        }
2409
2410        fn complicate(&mut self) -> bool {
2411            match self {
2412                CharPatternValueTree::Pred(t)
2413                | CharPatternValueTree::Chars(t)
2414                | CharPatternValueTree::CharsVec(t)
2415                | CharPatternValueTree::CharsVecRef(t) => t.complicate(),
2416                CharPatternValueTree::Char(t) => t.complicate(),
2417            }
2418        }
2419    }
2420
2421    #[derive(Debug, Copy, Clone)]
2422    pub(crate) struct CharPatternStrategy;
2423
2424    impl Strategy for CharPatternStrategy {
2425        type Tree = CharPatternValueTree;
2426        type Value = CharPattern;
2427
2428        fn new_tree(
2429            &self,
2430            runner: &mut proptest::test_runner::TestRunner,
2431        ) -> proptest::strategy::NewTree<Self> {
2432            let char_strategy = if runner.rng().gen_bool(0.5) {
2433                any::<char>()
2434            } else {
2435                prop::char::range('\0', '\u{7f}')
2436            };
2437
2438            match runner.rng().gen_range(0..5) {
2439                0 => Ok(CharPatternValueTree::Pred(
2440                    prop::collection::vec(char_strategy, 0..7).new_tree(runner)?,
2441                )),
2442                1 => Ok(CharPatternValueTree::Char(char_strategy.new_tree(runner)?)),
2443                2 => Ok(CharPatternValueTree::Chars(
2444                    prop::collection::vec(char_strategy, 0..7).new_tree(runner)?,
2445                )),
2446                3 => Ok(CharPatternValueTree::CharsVec(
2447                    prop::collection::vec(char_strategy, 0..7).new_tree(runner)?,
2448                )),
2449                4 => Ok(CharPatternValueTree::CharsVecRef(
2450                    prop::collection::vec(char_strategy, 0..7).new_tree(runner)?,
2451                )),
2452                _ => unreachable!(),
2453            }
2454        }
2455    }
2456
2457    impl Arbitrary for CharPattern {
2458        type Parameters = ();
2459
2460        fn arbitrary_with(_args: Self::Parameters) -> Self::Strategy {
2461            CharPatternStrategy
2462        }
2463
2464        type Strategy = CharPatternStrategy;
2465    }
2466
2467    #[derive(Debug, Copy, Clone)]
2468    pub(crate) enum StringHow {
2469        Str,
2470        String,
2471        StringRef,
2472        Rope,
2473        RopeRef,
2474    }
2475
2476    #[derive(Debug, Clone)]
2477    pub(crate) struct StringPattern {
2478        string: String,
2479        how: StringHow,
2480    }
2481
2482    impl std::fmt::Display for StringPattern {
2483        fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
2484            self.string.fmt(f)
2485        }
2486    }
2487
2488    #[sealed::sealed]
2489    impl<'a> Pattern for &'a StringPattern {
2490        type Output = ();
2491        type Owned = Self;
2492
2493        type FindAllImpl<A> = crate::pattern::FindStr<'a, A> where A: Accessor;
2494
2495        type RFindAllImpl<A> = crate::pattern::RFindStr<'a, A> where A: Accessor;
2496
2497        fn _find_all<A>(self, accessor: A) -> Self::FindAllImpl<A>
2498        where
2499            A: Accessor,
2500        {
2501            match self.how {
2502                StringHow::Str => self.string.as_str()._find_all(accessor),
2503                StringHow::String => self.string.clone()._find_all(accessor),
2504                StringHow::StringRef => (&self.string)._find_all(accessor),
2505                StringHow::Rope => Rope::from(&self.string)._find_all(accessor),
2506                StringHow::RopeRef => (&Rope::from(&self.string))._find_all(accessor),
2507            }
2508        }
2509
2510        fn _rfind_all<A>(self, accessor: A) -> Self::RFindAllImpl<A>
2511        where
2512            A: Accessor,
2513        {
2514            match self.how {
2515                StringHow::Str => self.string.as_str()._rfind_all(accessor),
2516                StringHow::String => self.string.clone()._rfind_all(accessor),
2517                StringHow::StringRef => (&self.string)._rfind_all(accessor),
2518                StringHow::Rope => Rope::from(&self.string)._rfind_all(accessor),
2519                StringHow::RopeRef => (&Rope::from(&self.string))._rfind_all(accessor),
2520            }
2521        }
2522
2523        fn _is_prefix(self, haystack: &Rope) -> bool {
2524            match self.how {
2525                StringHow::Str => self.string.as_str()._is_prefix(haystack),
2526                StringHow::String => self.string.clone()._is_prefix(haystack),
2527                StringHow::StringRef => (&self.string)._is_prefix(haystack),
2528                StringHow::Rope => Rope::from(&self.string)._is_prefix(haystack),
2529                StringHow::RopeRef => (&Rope::from(&self.string))._is_prefix(haystack),
2530            }
2531        }
2532
2533        fn _is_suffix(self, haystack: &Rope) -> bool {
2534            match self.how {
2535                StringHow::Str => self.string.as_str()._is_suffix(haystack),
2536                StringHow::String => self.string.clone()._is_suffix(haystack),
2537                StringHow::StringRef => (&self.string)._is_suffix(haystack),
2538                StringHow::Rope => Rope::from(&self.string)._is_suffix(haystack),
2539                StringHow::RopeRef => (&Rope::from(&self.string))._is_suffix(haystack),
2540            }
2541        }
2542
2543        fn _convert_to_owning<A>(
2544            finder: &Self::FindAllImpl<A>,
2545        ) -> <Self::Owned as Pattern>::FindAllImpl<OwningAccessor>
2546        where
2547            A: Accessor,
2548        {
2549            finder.to_owning()
2550        }
2551
2552        fn _convert_into_owning<A>(
2553            finder: Self::FindAllImpl<A>,
2554        ) -> <Self::Owned as Pattern>::FindAllImpl<OwningAccessor>
2555        where
2556            A: Accessor,
2557        {
2558            finder.into_owning()
2559        }
2560
2561        fn _rconvert_to_owning<A>(
2562            finder: &Self::RFindAllImpl<A>,
2563        ) -> <Self::Owned as Pattern>::RFindAllImpl<OwningAccessor>
2564        where
2565            A: Accessor,
2566        {
2567            finder.to_owning()
2568        }
2569
2570        fn _rconvert_into_owning<A>(
2571            finder: Self::RFindAllImpl<A>,
2572        ) -> <Self::Owned as Pattern>::RFindAllImpl<OwningAccessor>
2573        where
2574            A: Accessor,
2575        {
2576            finder.into_owning()
2577        }
2578    }
2579
2580    pub(crate) struct StringPatternValueTree {
2581        tree: prop::string::RegexGeneratorValueTree<String>,
2582        how: StringHow,
2583    }
2584
2585    impl prop::strategy::ValueTree for StringPatternValueTree {
2586        type Value = StringPattern;
2587
2588        fn current(&self) -> Self::Value {
2589            StringPattern {
2590                string: self.tree.current(),
2591                how: self.how,
2592            }
2593        }
2594
2595        fn simplify(&mut self) -> bool {
2596            self.tree.simplify()
2597        }
2598
2599        fn complicate(&mut self) -> bool {
2600            self.tree.complicate()
2601        }
2602    }
2603
2604    #[derive(Debug, Clone)]
2605    pub(crate) struct StringPatternStrategy(String);
2606
2607    impl Strategy for StringPatternStrategy {
2608        type Tree = StringPatternValueTree;
2609
2610        type Value = StringPattern;
2611
2612        fn new_tree(
2613            &self,
2614            runner: &mut proptest::test_runner::TestRunner,
2615        ) -> proptest::strategy::NewTree<Self> {
2616            let how = match runner.rng().gen_range(0..5) {
2617                0 => StringHow::Str,
2618                1 => StringHow::String,
2619                2 => StringHow::StringRef,
2620                3 => StringHow::Rope,
2621                4 => StringHow::RopeRef,
2622                _ => unreachable!(),
2623            };
2624
2625            Ok(StringPatternValueTree {
2626                tree: prop::string::string_regex(self.0.as_str())
2627                    .unwrap()
2628                    .new_tree(runner)?,
2629                how,
2630            })
2631        }
2632    }
2633
2634    pub(crate) fn string_pattern(s: &str) -> StringPatternStrategy {
2635        StringPatternStrategy(s.to_owned())
2636    }
2637}