rama_core/matcher/
iter.rs

1use crate::{Context, context::Extensions};
2
3use super::Matcher;
4
5/// Extension to apply matcher operations to an [`Iterator`] of [`Matcher`]s.
6pub trait IteratorMatcherExt<'a, M, State, Request>: Iterator<Item = &'a M> + 'a
7where
8    M: Matcher<State, Request>,
9{
10    /// Matches in case all [`Matcher`] elements match for the given `Request`
11    /// within the specified [`crate::Context`].
12    fn matches_and(
13        self,
14        ext: Option<&mut Extensions>,
15        ctx: &Context<State>,
16        request: &Request,
17    ) -> bool;
18
19    /// Matches in case any of the [`Matcher`] elements match for the given `Request`
20    /// within the specified [`crate::Context`].
21    fn matches_or(
22        self,
23        ext: Option<&mut Extensions>,
24        ctx: &Context<State>,
25        request: &Request,
26    ) -> bool;
27}
28
29impl<'a, I, M, State, Request> IteratorMatcherExt<'a, M, State, Request> for I
30where
31    I: Iterator<Item = &'a M> + 'a,
32    M: Matcher<State, Request>,
33{
34    fn matches_and(
35        self,
36        ext: Option<&mut Extensions>,
37        ctx: &Context<State>,
38        request: &Request,
39    ) -> bool {
40        match ext {
41            None => {
42                for matcher in self {
43                    if !matcher.matches(None, ctx, request) {
44                        return false;
45                    }
46                }
47                true
48            }
49            Some(ext) => {
50                let mut inner_ext = Extensions::new();
51                for matcher in self {
52                    if !matcher.matches(Some(&mut inner_ext), ctx, request) {
53                        return false;
54                    }
55                }
56                ext.extend(inner_ext);
57                true
58            }
59        }
60    }
61
62    fn matches_or(
63        self,
64        ext: Option<&mut Extensions>,
65        ctx: &Context<State>,
66        request: &Request,
67    ) -> bool {
68        let mut it = self.peekable();
69        if it.peek().is_none() {
70            return true;
71        }
72
73        match ext {
74            None => {
75                for matcher in it {
76                    if matcher.matches(None, ctx, request) {
77                        return true;
78                    }
79                }
80                false
81            }
82            Some(ext) => {
83                let mut inner_ext = Extensions::new();
84                for matcher in it {
85                    if matcher.matches(Some(&mut inner_ext), ctx, request) {
86                        ext.extend(inner_ext);
87                        return true;
88                    }
89                    inner_ext.clear();
90                }
91                false
92            }
93        }
94    }
95}