match_string/
base.rs

1use core::slice;
2use std::{
3    cell::RefCell,
4    ops::{RangeTo, RangeToInclusive},
5    str::Chars,
6};
7
8use crate::dest;
9
10use std::collections::VecDeque;
11
12/// An iterator wrapper that supports checkpointing (snapshots and rollbacks).
13pub struct Checkpoint<I>
14where
15    I: Iterator,
16{
17    inner: I,
18    front: VecDeque<I::Item>,
19    trail: Vec<I::Item>,
20    in_trial: bool,
21}
22
23impl<I> Checkpoint<I>
24where
25    I: Iterator,
26    I::Item: Clone,
27{
28    pub fn new(inner: I) -> Self {
29        Checkpoint {
30            inner,
31            front: VecDeque::new(),
32            trail: Vec::new(),
33            in_trial: false,
34        }
35    }
36
37    pub fn begin(&mut self) {
38        self.trail.clear();
39        self.in_trial = true;
40    }
41
42    pub fn commit(&mut self) {
43        self.trail.clear();
44        self.in_trial = false;
45    }
46
47    pub fn rollback(&mut self) {
48        // Move trail items to the front in original order
49        while let Some(it) = self.trail.pop() {
50            self.front.push_front(it);
51        }
52        self.in_trial = false;
53    }
54}
55
56impl<I> Iterator for Checkpoint<I>
57where
58    I: Iterator,
59    I::Item: Clone,
60{
61    type Item = I::Item;
62
63    fn next(&mut self) -> Option<Self::Item> {
64        if let Some(it) = self.front.pop_front() {
65            return Some(it);
66        }
67        match self.inner.next() {
68            Some(it) => {
69                if self.in_trial {
70                    // store a clone for potential rollback and return the original
71                    self.trail.push(it.clone());
72                    Some(it)
73                } else {
74                    Some(it)
75                }
76            }
77            None => None,
78        }
79    }
80}
81
82impl<I> PeekableExt for Checkpoint<I>
83where
84    I: Iterator + PeekableExt,
85    I::Item: Clone,
86{
87    fn peek(&mut self) -> Option<&Self::Item> {
88        if let Some(front) = self.front.front() {
89            return Some(front);
90        }
91        self.inner.peek()
92    }
93}
94
95impl<I> Clone for Checkpoint<I>
96where
97    I: Iterator + Clone,
98    I::Item: Clone,
99{
100    fn clone(&self) -> Self {
101        Checkpoint {
102            inner: self.inner.clone(),
103            front: self.front.clone(),
104            trail: self.trail.clone(),
105            in_trial: self.in_trial,
106        }
107    }
108}
109
110/// A trait for types that can be checked for satisfaction against another type.
111pub trait Satisfies<T> {
112    fn satisfies(&self, item: &T) -> bool;
113}
114
115impl<T> Satisfies<T> for T
116where
117    T: PartialEq,
118{
119    fn satisfies(&self, item: &T) -> bool {
120        self == item
121    }
122}
123
124/// A trait for types that can receive matched items.
125pub trait Destination<Item> {
126    fn pickup(&mut self, _item: Item) {}
127}
128
129impl<T> Destination<&T> for Vec<T>
130where
131    T: Clone,
132{
133    fn pickup(&mut self, item: &T) {
134        self.push(item.clone());
135    }
136}
137
138impl Destination<char> for String {
139    fn pickup(&mut self, item: char) {
140        self.push(item);
141    }
142}
143
144impl<T> Destination<char> for Vec<T> where T: Destination<char> {}
145
146/// A trait for iterable reference types.
147pub trait Iterable<'a> {
148    type Iter: Iterator;
149    /// Get an iterator over the reference.
150    fn get_iter(&'a self) -> Self::Iter;
151}
152
153/// A trait for iterators that support peeking at the next item without consuming it.
154pub trait PeekableExt: Iterator {
155    /// Peek at the next item without consuming it.
156    fn peek(&mut self) -> Option<&Self::Item>;
157}
158
159impl<I> PeekableExt for std::iter::Peekable<I>
160where
161    I: Iterator,
162{
163    fn peek(&mut self) -> Option<&Self::Item> {
164        std::iter::Peekable::peek(self)
165    }
166}
167
168/// A trait for pattern types that can match against a reference iterator.
169pub trait Pattern<'a, Reference>
170where
171    Reference: Iterator,
172{
173    type Iter: Iterator;
174    type Dest;
175    /// Get an iterator over the pattern's items.
176    fn get_iter(&'a self) -> Self::Iter;
177    /// Get a mutable reference to the pattern's internal destination, if any.
178    fn get_dest_mut(&self) -> Option<std::cell::RefMut<'_, Self::Dest>> {
179        None
180    }
181    /// Match the pattern against the reference iterator.
182    fn matches<'s, R>(&'a self, reference: &'s R) -> bool
183    where
184        R: Iterable<'s, Iter = Reference> + 's,
185        Self::Dest: Destination<Reference::Item>,
186        Reference: PeekableExt,
187        Reference::Item: Satisfies<<Self::Iter as Iterator>::Item>,
188    {
189        let mut iter = reference.get_iter();
190        self.consume(&mut iter) && iter.peek().is_none()
191    }
192    /// Consume items from the reference iterator, optionally storing matched items in a destination.
193    fn consume_with_dest(
194        &'a self,
195        reference_iter: &mut Reference,
196        dest: Option<&RefCell<Self::Dest>>,
197    ) -> bool
198    where
199        Reference: PeekableExt,
200        Self::Dest: Destination<Reference::Item>,
201        Reference::Item: Satisfies<<Self::Iter as Iterator>::Item>,
202    {
203        // Use either the provided destination or the pattern's internal one,
204        // then run a single consumption loop (avoids duplicating logic).
205        let mut maybe_dest = dest
206            .map(|dref| dref.borrow_mut())
207            .or_else(|| self.get_dest_mut());
208        self.get_iter().all(|pat_item| match reference_iter.peek() {
209            Some(item) if item.satisfies(&pat_item) => {
210                if let Some(consumed) = reference_iter.next() {
211                    if let Some(d) = maybe_dest.as_mut() {
212                        d.pickup(consumed)
213                    }
214                    true
215                } else {
216                    false
217                }
218            }
219            _ => false,
220        })
221    }
222
223    /// Consume items from the reference iterator.
224    fn consume(&'a self, reference_iter: &mut Reference) -> bool
225    where
226        Reference: PeekableExt,
227        Self::Dest: Destination<Reference::Item>,
228        Reference::Item: Satisfies<<Self::Iter as Iterator>::Item>,
229    {
230        self.consume_with_dest(reference_iter, None)
231    }
232}
233
234impl<'a> Iterable<'a> for &'a str {
235    type Iter = Checkpoint<std::iter::Peekable<Chars<'a>>>;
236    fn get_iter(&'a self) -> Self::Iter {
237        Checkpoint::new(self.chars().peekable())
238    }
239}
240
241impl<'a, Reference> Pattern<'a, Reference> for &'a str
242where
243    Reference: Iterator<Item = char> + PeekableExt,
244{
245    type Iter = Checkpoint<std::iter::Peekable<Chars<'a>>>;
246    type Dest = String;
247    fn get_iter(&'a self) -> Self::Iter {
248        Checkpoint::new(self.chars().peekable())
249    }
250}
251
252impl<'a> Iterable<'a> for String {
253    type Iter = Checkpoint<std::iter::Peekable<Chars<'a>>>;
254    fn get_iter(&'a self) -> Self::Iter {
255        Checkpoint::new(self.chars().peekable())
256    }
257}
258
259impl<'a, Reference> Pattern<'a, Reference> for String
260where
261    Reference: Iterator<Item = char> + PeekableExt,
262{
263    type Iter = Checkpoint<std::iter::Peekable<Chars<'a>>>;
264    type Dest = String;
265    fn get_iter(&'a self) -> Self::Iter {
266        Checkpoint::new(self.chars().peekable())
267    }
268}
269
270impl<'a, T> Iterable<'a> for &'a [T]
271where
272    T: 'a,
273{
274    type Iter = std::iter::Peekable<slice::Iter<'a, T>>;
275    fn get_iter(&'a self) -> Self::Iter {
276        self.iter().peekable()
277    }
278}
279
280impl<'a, T, Reference> Pattern<'a, Reference> for &'a [T]
281where
282    T: 'a,
283    Reference: Iterator<Item = &'a T> + PeekableExt,
284    T: Clone,
285    Reference::Item: Satisfies<&'a T>,
286{
287    type Iter = std::iter::Peekable<slice::Iter<'a, T>>;
288    type Dest = Vec<T>;
289    fn get_iter(&'a self) -> Self::Iter {
290        self.iter().peekable()
291    }
292}
293
294impl<'a, T> Iterable<'a> for Vec<T>
295where
296    T: 'a,
297{
298    type Iter = std::iter::Peekable<slice::Iter<'a, T>>;
299    fn get_iter(&'a self) -> Self::Iter {
300        self.iter().peekable()
301    }
302}
303
304impl<'a, T, Reference> Pattern<'a, Reference> for Vec<T>
305where
306    T: 'a,
307    Reference: Iterator<Item = &'a T> + PeekableExt,
308    T: Clone,
309    Reference::Item: Satisfies<&'a T>,
310{
311    type Iter = std::iter::Peekable<slice::Iter<'a, T>>;
312    type Dest = Vec<T>;
313    fn get_iter(&'a self) -> Self::Iter {
314        self.iter().peekable()
315    }
316}
317
318/// A pattern that matches either of two sub-patterns.
319pub struct Or<A, B>(pub A, pub B);
320
321impl<'a, Reference, A, B, D> Pattern<'a, Reference> for Or<A, B>
322where
323    Reference: Iterator + Clone + PeekableExt,
324    A: Pattern<'a, Reference, Dest = D>,
325    B: Pattern<'a, Reference, Dest = D>,
326    D: Destination<Reference::Item> + Clone,
327    Reference::Item: Satisfies<<<A as Pattern<'a, Reference>>::Iter as Iterator>::Item>,
328    Reference::Item: Satisfies<<<B as Pattern<'a, Reference>>::Iter as Iterator>::Item>,
329{
330    type Iter = std::iter::Peekable<core::iter::Empty<Reference::Item>>;
331    type Dest = D;
332
333    fn get_iter(&'a self) -> Self::Iter {
334        core::iter::empty().peekable()
335    }
336
337    fn consume(&'a self, reference: &mut Reference) -> bool
338    where
339        Reference::Item: Satisfies<<Self::Iter as Iterator>::Item>,
340    {
341        // Delegate to the more general `consume_with_dest`, avoiding
342        // duplicate snapshot/restore logic.
343        self.consume_with_dest(reference, None)
344    }
345
346    fn consume_with_dest(
347        &'a self,
348        reference: &mut Reference,
349        dest: Option<&RefCell<Self::Dest>>,
350    ) -> bool
351    where
352        Reference::Item: Satisfies<<Self::Iter as Iterator>::Item>,
353    {
354        let orig = reference.clone();
355
356        // Snapshot any provided dest value so we can restore on failure
357        let provided_backup = dest.as_ref().map(|d| d.borrow().clone());
358
359        // Try A: take a brief borrow to snapshot internal dest if available
360        let a_internal_backup = match self.0.get_dest_mut() {
361            Some(d) => {
362                let b = d.clone();
363                drop(d);
364                Some(b)
365            }
366            None => None,
367        };
368
369        if A::consume_with_dest(&self.0, reference, dest) {
370            return true;
371        }
372
373        *reference = orig.clone();
374
375        if let Some(b) = a_internal_backup {
376            if let Some(mut d) = self.0.get_dest_mut() {
377                *d = b.clone();
378            }
379        }
380
381        if let Some(b) = provided_backup.clone() {
382            if let Some(dref) = dest {
383                *dref.borrow_mut() = b;
384            }
385        }
386
387        // Try B: snapshot (may be same underlying dest)
388        let b_internal_backup = match self.1.get_dest_mut() {
389            Some(d) => {
390                let b = d.clone();
391                drop(d);
392                Some(b)
393            }
394            None => None,
395        };
396
397        if B::consume_with_dest(&self.1, reference, dest) {
398            return true;
399        }
400
401        *reference = orig;
402
403        if let Some(b) = b_internal_backup {
404            if let Some(mut d) = self.1.get_dest_mut() {
405                *d = b;
406            }
407        }
408
409        if let Some(b) = provided_backup {
410            if let Some(dref) = dest {
411                *dref.borrow_mut() = b;
412            }
413        }
414
415        false
416    }
417}
418
419impl<'a, Reference, A, B, DA, DB> Pattern<'a, Reference> for (A, B)
420where
421    Reference: Iterator + PeekableExt,
422    A: Pattern<'a, Reference, Dest = DA>,
423    B: Pattern<'a, Reference, Dest = DB>,
424    DA: Destination<Reference::Item> + Clone,
425    DB: Destination<Reference::Item> + Clone,
426    Reference::Item: Satisfies<<<A as Pattern<'a, Reference>>::Iter as Iterator>::Item>,
427    Reference::Item: Satisfies<<<B as Pattern<'a, Reference>>::Iter as Iterator>::Item>,
428    Reference::Item: Clone,
429{
430    type Iter = std::iter::Peekable<core::iter::Empty<Reference::Item>>;
431    type Dest = (DA, DB);
432
433    fn get_iter(&'a self) -> Self::Iter {
434        core::iter::empty().peekable()
435    }
436
437    fn consume(&'a self, reference: &mut Reference) -> bool
438    where
439        Reference::Item: Satisfies<<Self::Iter as Iterator>::Item>,
440    {
441        self.0.consume(reference) && self.1.consume(reference)
442    }
443
444    fn consume_with_dest(
445        &'a self,
446        reference_iter: &mut Reference,
447        dest: Option<&RefCell<Self::Dest>>,
448    ) -> bool
449    where
450        Reference::Item: Satisfies<<Self::Iter as Iterator>::Item>,
451    {
452        if let Some(dref) = dest {
453            // snapshot current tuple dest
454            let snapshot = dref.borrow().clone();
455            // create inner temp dests
456            let a_temp = RefCell::new(snapshot.0);
457            let b_temp = RefCell::new(snapshot.1);
458
459            // try to consume both parts routing to temp dests
460            if A::consume_with_dest(&self.0, reference_iter, Some(&a_temp))
461                && B::consume_with_dest(&self.1, reference_iter, Some(&b_temp))
462            {
463                // commit back into original dest
464                let mut d = dref.borrow_mut();
465                d.0 = a_temp.into_inner();
466                d.1 = b_temp.into_inner();
467                return true;
468            }
469            return false;
470        }
471
472        self.consume(reference_iter)
473    }
474}
475
476/// A trait for types that can collect captured items into a destination.
477pub trait Collector<Inner, Item> {
478    fn commit(out: &RefCell<Self>, captured: Inner);
479}
480
481impl<Inner, Item> Collector<Inner, Item> for Inner
482where
483    Inner: Destination<Item> + Clone,
484{
485    fn commit(out: &RefCell<Self>, captured: Inner) {
486        *out.borrow_mut() = captured;
487    }
488}
489
490impl<Inner, Item> Collector<Inner, Item> for Vec<Inner>
491where
492    Inner: Destination<Item> + Default + Clone,
493{
494    fn commit(out: &RefCell<Self>, captured: Inner) {
495        out.borrow_mut().push(captured);
496    }
497}
498
499/// A pattern that captures matched items into a destination.
500pub struct To<'a, A, D>(pub A, pub &'a dest::Dest<D>);
501
502impl<'a, Reference, A, OutD, InD> Pattern<'a, Reference> for To<'a, A, OutD>
503where
504    Reference: Iterator + PeekableExt,
505    A: Pattern<'a, Reference, Dest = InD>,
506    InD: Destination<Reference::Item> + Default + Clone,
507    OutD: Collector<InD, Reference::Item> + Destination<Reference::Item> + Clone,
508{
509    type Iter = <A as Pattern<'a, Reference>>::Iter;
510    type Dest = OutD;
511
512    fn get_iter(&'a self) -> Self::Iter {
513        self.0.get_iter()
514    }
515
516    fn get_dest_mut(&self) -> Option<std::cell::RefMut<'_, Self::Dest>> {
517        Some(self.1.borrow_mut())
518    }
519
520    fn consume(&'a self, reference: &mut Reference) -> bool
521    where
522        Reference::Item: Satisfies<<Self::Iter as Iterator>::Item>,
523    {
524        self.consume_with_dest(reference, None)
525    }
526
527    fn consume_with_dest(
528        &'a self,
529        reference: &mut Reference,
530        dest: Option<&RefCell<Self::Dest>>,
531    ) -> bool
532    where
533        Reference: PeekableExt,
534        Reference::Item: Satisfies<<Self::Iter as Iterator>::Item>,
535    {
536        let outer = self.1.as_refcell();
537        let provided_target = match dest {
538            Some(d) => d,
539            None => outer,
540        };
541
542        let inner_temp = RefCell::new(InD::default());
543        if A::consume_with_dest(&self.0, reference, Some(&inner_temp)) {
544            let captured = inner_temp.into_inner();
545            <OutD as Collector<InD, Reference::Item>>::commit(provided_target, captured.clone());
546            if !std::ptr::eq(
547                provided_target as *const RefCell<OutD>,
548                outer as *const RefCell<OutD>,
549            ) {
550                <OutD as Collector<InD, Reference::Item>>::commit(outer, captured);
551            }
552
553            true
554        } else {
555            false
556        }
557    }
558}
559
560/// A pattern that matches a sequence of sub-patterns.
561pub struct Seq<A, const N: usize>(pub [A; N]);
562
563impl<'a, Reference, A, D, const N: usize> Pattern<'a, Reference> for Seq<A, N>
564where
565    Reference: Iterator + Clone + PeekableExt,
566    A: Pattern<'a, Reference, Dest = D>,
567    D: Destination<Reference::Item> + Default,
568    Reference::Item: Satisfies<<<A as Pattern<'a, Reference>>::Iter as Iterator>::Item>,
569{
570    type Iter = core::iter::Peekable<core::iter::Empty<Reference::Item>>;
571    type Dest = Vec<D>;
572
573    fn get_iter(&'a self) -> Self::Iter {
574        core::iter::empty().peekable()
575    }
576
577    fn consume_with_dest(
578        &'a self,
579        reference: &mut Reference,
580        dest: Option<&RefCell<Self::Dest>>,
581    ) -> bool
582    where
583        Reference::Item: Satisfies<<Self::Iter as Iterator>::Item>,
584    {
585        let mut trial = reference.clone();
586
587        let mut temp: Vec<D> = Vec::new();
588
589        for child in &self.0 {
590            let inner = RefCell::new(D::default());
591            if !A::consume_with_dest(child, &mut trial, Some(&inner)) {
592                return false;
593            }
594            temp.push(inner.into_inner());
595        }
596
597        *reference = trial;
598
599        if let Some(dref) = dest {
600            let mut d = dref.borrow_mut();
601            d.extend(temp);
602        }
603
604        true
605    }
606}
607
608impl<Item, A, B> Destination<Item> for (A, B)
609where
610    A: Destination<Item>,
611    B: Destination<Item>,
612    Item: Clone,
613{
614    fn pickup(&mut self, item: Item) {
615        let a_item = item.clone();
616        self.0.pickup(a_item);
617        self.1.pickup(item);
618    }
619}
620
621impl<'a, Reference, A, D> Pattern<'a, Reference> for RangeTo<A>
622where
623    Reference: Iterator + Clone + PeekableExt,
624    A: Pattern<'a, Reference, Dest = D>,
625    D: Destination<Reference::Item> + Default + Clone,
626    Reference::Item: Satisfies<<<A as Pattern<'a, Reference>>::Iter as Iterator>::Item> + Clone,
627{
628    type Iter = core::iter::Empty<Reference::Item>;
629    type Dest = Vec<D>;
630
631    fn get_iter(&'a self) -> Self::Iter {
632        core::iter::empty()
633    }
634
635    fn consume_with_dest(
636        &'a self,
637        reference: &mut Reference,
638        dest: Option<&RefCell<Self::Dest>>,
639    ) -> bool
640    where
641        Reference::Item: Satisfies<<Self::Iter as Iterator>::Item>,
642    {
643        match dest {
644            Some(dref) => {
645                loop {
646                    let mut trial = reference.clone();
647                    let inner_dest = RefCell::new(D::default());
648                    if !A::consume_with_dest(&self.end, &mut trial, Some(&inner_dest)) {
649                        break;
650                    }
651                    // compute how many items trial consumed by comparing remainders
652                    let rem_orig: Vec<Reference::Item> = reference.clone().collect();
653                    let rem_trial: Vec<Reference::Item> = trial.clone().collect();
654                    let consumed = rem_orig.len().saturating_sub(rem_trial.len());
655                    if consumed == 0 {
656                        break;
657                    }
658                    for _ in 0..consumed {
659                        reference.next();
660                    }
661                    dref.borrow_mut().push(inner_dest.into_inner());
662                }
663                true
664            }
665            None => {
666                loop {
667                    let mut trial = reference.clone();
668                    if !A::consume(&self.end, &mut trial) {
669                        break;
670                    }
671                    let rem_orig: Vec<Reference::Item> = reference.clone().collect();
672                    let rem_trial: Vec<Reference::Item> = trial.clone().collect();
673                    let consumed = rem_orig.len().saturating_sub(rem_trial.len());
674                    if consumed == 0 {
675                        break;
676                    }
677                    for _ in 0..consumed {
678                        reference.next();
679                    }
680                }
681                true
682            }
683        }
684    }
685}
686
687impl<'a, Reference, A, D> Pattern<'a, Reference> for RangeToInclusive<A>
688where
689    Reference: Iterator + Clone + PeekableExt,
690    A: Pattern<'a, Reference, Dest = D>,
691    D: Destination<Reference::Item> + Default + Clone,
692    Reference::Item: Satisfies<<<A as Pattern<'a, Reference>>::Iter as Iterator>::Item> + Clone,
693{
694    type Iter = core::iter::Empty<Reference::Item>;
695    type Dest = Vec<D>;
696
697    fn get_iter(&'a self) -> Self::Iter {
698        core::iter::empty()
699    }
700
701    fn consume_with_dest(
702        &'a self,
703        reference: &mut Reference,
704        dest: Option<&RefCell<Self::Dest>>,
705    ) -> bool
706    where
707        Reference::Item: Satisfies<<Self::Iter as Iterator>::Item>,
708    {
709        // require at least one successful match; empty-child guard removed
710
711        match dest {
712            Some(dref) => {
713                let mut any = false;
714                loop {
715                    let mut trial = reference.clone();
716                    let inner_dest = RefCell::new(D::default());
717                    if !A::consume_with_dest(&self.end, &mut trial, Some(&inner_dest)) {
718                        break;
719                    }
720                    let rem_orig: Vec<Reference::Item> = reference.clone().collect();
721                    let rem_trial: Vec<Reference::Item> = trial.clone().collect();
722                    let consumed = rem_orig.len().saturating_sub(rem_trial.len());
723                    if consumed == 0 {
724                        break;
725                    }
726                    for _ in 0..consumed {
727                        reference.next();
728                    }
729                    dref.borrow_mut().push(inner_dest.into_inner());
730                    any = true;
731                }
732                any
733            }
734            None => {
735                let mut any = false;
736                loop {
737                    let mut trial = reference.clone();
738                    if !A::consume(&self.end, &mut trial) {
739                        break;
740                    }
741                    let rem_orig: Vec<Reference::Item> = reference.clone().collect();
742                    let rem_trial: Vec<Reference::Item> = trial.clone().collect();
743                    let consumed = rem_orig.len().saturating_sub(rem_trial.len());
744                    if consumed == 0 {
745                        break;
746                    }
747                    for _ in 0..consumed {
748                        reference.next();
749                    }
750                    any = true;
751                }
752                any
753            }
754        }
755    }
756}
757
758/// A pattern that matches a sequence of sub-patterns separated by a separator pattern.
759pub struct Sep<Sep, P>(pub Sep, pub P);
760
761/// A pattern that matches one or more occurrences of a sub-pattern separated by a separator pattern.
762pub struct Sep1<Sep, P>(pub Sep, pub P);
763
764impl<'a, Reference, SepT, PatT, SD, PD> Pattern<'a, Reference> for Sep<SepT, PatT>
765where
766    Reference: Iterator + Clone + PeekableExt,
767    SepT: Pattern<'a, Reference, Dest = SD>,
768    PatT: Pattern<'a, Reference, Dest = PD>,
769    SD: Destination<Reference::Item> + Default + Clone,
770    PD: Destination<Reference::Item> + Default + Clone,
771    Reference::Item: Satisfies<<<SepT as Pattern<'a, Reference>>::Iter as Iterator>::Item>
772        + Satisfies<<<PatT as Pattern<'a, Reference>>::Iter as Iterator>::Item>
773        + Clone,
774{
775    type Iter = core::iter::Empty<Reference::Item>;
776    type Dest = Vec<(SD, PD)>;
777
778    fn get_iter(&'a self) -> Self::Iter {
779        core::iter::empty()
780    }
781
782    fn consume_with_dest(
783        &'a self,
784        reference: &mut Reference,
785        dest: Option<&RefCell<Self::Dest>>,
786    ) -> bool
787    where
788        Reference::Item: Satisfies<<Self::Iter as Iterator>::Item>,
789    {
790        // Collect matches into a temp vector, committing only on success
791        let mut temp: Vec<(SD, PD)> = Vec::new();
792
793        loop {
794            // Try to parse a pattern occurrence (for Sep this may fail immediately)
795            let mut trial = reference.clone();
796            let pat_dest = RefCell::new(PD::default());
797            if !PatT::consume_with_dest(&self.1, &mut trial, Some(&pat_dest)) {
798                break;
799            }
800
801            // Try to parse a separator following the pattern; separator may be absent
802            let sep_dest = RefCell::new(SD::default());
803            let mut trial_after_sep = trial.clone();
804            if SepT::consume_with_dest(&self.0, &mut trial_after_sep, Some(&sep_dest)) {
805                // separator consumed; advance trial to after separator
806                trial = trial_after_sep;
807            }
808
809            // compute how many items were consumed and advance the real iterator
810            let rem_orig: Vec<Reference::Item> = reference.clone().collect();
811            let rem_trial: Vec<Reference::Item> = trial.clone().collect();
812            let consumed = rem_orig.len().saturating_sub(rem_trial.len());
813            if consumed == 0 {
814                break;
815            }
816            for _ in 0..consumed {
817                reference.next();
818            }
819
820            temp.push((sep_dest.into_inner(), pat_dest.into_inner()));
821        }
822
823        if let Some(dref) = dest {
824            let mut d = dref.borrow_mut();
825            d.extend(temp);
826        }
827
828        true
829    }
830}
831
832impl<'a, Reference, SepT, PatT, SD, PD> Pattern<'a, Reference> for Sep1<SepT, PatT>
833where
834    Reference: Iterator + Clone + PeekableExt,
835    SepT: Pattern<'a, Reference, Dest = SD>,
836    PatT: Pattern<'a, Reference, Dest = PD>,
837    SD: Destination<Reference::Item> + Default + Clone,
838    PD: Destination<Reference::Item> + Default + Clone,
839    Reference::Item: Satisfies<<<SepT as Pattern<'a, Reference>>::Iter as Iterator>::Item>
840        + Satisfies<<<PatT as Pattern<'a, Reference>>::Iter as Iterator>::Item>
841        + Clone,
842{
843    type Iter = core::iter::Empty<Reference::Item>;
844    type Dest = Vec<(SD, PD)>;
845
846    fn get_iter(&'a self) -> Self::Iter {
847        core::iter::empty()
848    }
849
850    fn consume_with_dest(
851        &'a self,
852        reference: &mut Reference,
853        dest: Option<&RefCell<Self::Dest>>,
854    ) -> bool
855    where
856        Reference::Item: Satisfies<<Self::Iter as Iterator>::Item>,
857    {
858        // Require at least one occurrence
859        let mut temp: Vec<(SD, PD)> = Vec::new();
860
861        // First element must be a pattern
862        let mut trial = reference.clone();
863        let first_pat = RefCell::new(PD::default());
864        if !PatT::consume_with_dest(&self.1, &mut trial, Some(&first_pat)) {
865            return false;
866        }
867
868        // Try optional separator after first element
869        let first_sep = RefCell::new(SD::default());
870        let mut trial_after_sep = trial.clone();
871        if SepT::consume_with_dest(&self.0, &mut trial_after_sep, Some(&first_sep)) {
872            trial = trial_after_sep;
873        }
874
875        // advance real iterator and record
876        let rem_orig: Vec<Reference::Item> = reference.clone().collect();
877        let rem_trial: Vec<Reference::Item> = trial.clone().collect();
878        let consumed = rem_orig.len().saturating_sub(rem_trial.len());
879        for _ in 0..consumed {
880            reference.next();
881        }
882        temp.push((first_sep.into_inner(), first_pat.into_inner()));
883
884        // subsequent (sep, pat)*
885        loop {
886            let mut trial = reference.clone();
887
888            // try separator then pattern
889            let sep_temp = RefCell::new(SD::default());
890            if !SepT::consume_with_dest(&self.0, &mut trial, Some(&sep_temp)) {
891                break;
892            }
893            let pat_temp = RefCell::new(PD::default());
894            if !PatT::consume_with_dest(&self.1, &mut trial, Some(&pat_temp)) {
895                break;
896            }
897
898            let rem_orig: Vec<Reference::Item> = reference.clone().collect();
899            let rem_trial: Vec<Reference::Item> = trial.clone().collect();
900            let consumed = rem_orig.len().saturating_sub(rem_trial.len());
901            if consumed == 0 {
902                break;
903            }
904            for _ in 0..consumed {
905                reference.next();
906            }
907
908            temp.push((sep_temp.into_inner(), pat_temp.into_inner()));
909        }
910
911        if let Some(dref) = dest {
912            let mut d = dref.borrow_mut();
913            d.extend(temp);
914        }
915
916        true
917    }
918}