1use 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#[sealed]
56pub trait Pattern {
57 type Output;
62
63 type Owned: Pattern;
67
68 type FindAllImpl<A>: Iterator<Item = (Range<usize>, Self::Output)> + FusedIterator
72 where
73 A: Accessor;
74
75 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 #[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
887pub 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
990pub 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
1001pub 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
1556pub 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
1644pub 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}