Skip to main content

g_err/
query.rs

1use core::any::Any;
2use core::error::Error;
3
4use crate::{Config, DataSource, GErr, IdSource, iterator::GErrNode};
5
6impl<C: Config, D> GErr<C, D>
7where
8    C::Id: IdSource + 'static,
9    D: DataSource + 'static,
10{
11    /// Iterate over GErr's codes.
12    #[inline]
13    pub fn iter_by_code<'a, 'b>(
14        &'a self,
15        code: &'b str,
16    ) -> impl Iterator<Item = GErrNode<'a, C, D>> + 'a
17    where
18        'b: 'a,
19    {
20        self.iter().filter(move |item| match item {
21            GErrNode::Root(gerr) => gerr.code().is_some_and(|p| p == code),
22
23            GErrNode::LeafGErr(gerr) => gerr.code.as_ref().is_some_and(|p| p == code),
24
25            _ => false,
26        })
27    }
28
29    /// Iterate over GErr's tags.
30    #[inline]
31    pub fn iter_by_tag<'a, 'b>(
32        &'a self,
33        tag: &'b str,
34    ) -> impl Iterator<Item = GErrNode<'a, C, D>> + 'a
35    where
36        'b: 'a,
37    {
38        self.iter().filter(move |item| match item {
39            GErrNode::Root(gerr) => gerr
40                .tags()
41                .is_some_and(|tags| tags.iter().any(|t| t == tag)),
42
43            GErrNode::LeafGErr(gerr) => gerr
44                .tags
45                .as_ref()
46                .is_some_and(|tags| tags.iter().any(|t| t == tag)),
47
48            _ => false,
49        })
50    }
51
52    /// Iterate over GErr's id type.
53    #[inline]
54    pub fn iter_id<T>(&self) -> impl Iterator<Item = GErrNode<'_, C, D>>
55    where
56        T: Any,
57    {
58        self.iter().filter(|item| match item {
59            GErrNode::Root(gerr) => gerr.id().is_some_and(|id| (id as &dyn Any).is::<T>()),
60
61            GErrNode::LeafGErr(gerr) => gerr
62                .id
63                .as_ref()
64                .is_some_and(|id| (&**id as &dyn Any).is::<T>()),
65
66            _ => false,
67        })
68    }
69
70    /// Iterate over GErr's id.
71    #[inline]
72    pub fn iter_by_id<'a, 'b, T>(&'a self, value: &'b T) -> impl Iterator<Item = GErrNode<'a, C, D>>
73    where
74        T: Any + PartialEq,
75        'b: 'a,
76    {
77        self.iter().filter(move |item| match item {
78            GErrNode::Root(gerr) => gerr.id().is_some_and(|id| {
79                (id as &dyn Any)
80                    .downcast_ref::<T>()
81                    .is_some_and(|id| id == value)
82            }),
83            GErrNode::LeafGErr(gerr) => gerr.id.as_ref().is_some_and(|id| {
84                (&**id as &dyn Any)
85                    .downcast_ref::<T>()
86                    .is_some_and(|id| id == value)
87            }),
88
89            _ => false,
90        })
91    }
92
93    /// Iterate over GErr's data's type.
94    #[inline]
95    pub fn iter_data<T>(&self) -> impl Iterator<Item = GErrNode<'_, C, D>>
96    where
97        T: Any,
98    {
99        self.iter().filter(|item| match item {
100            GErrNode::Root(gerr) => gerr.data().is_some_and(|data| (data as &dyn Any).is::<T>()),
101
102            GErrNode::LeafGErr(gerr) => gerr
103                .data
104                .as_ref()
105                .is_some_and(|data| (&**data as &dyn Any).is::<T>()),
106
107            _ => false,
108        })
109    }
110
111    /// Iterate over GErr's data.
112    #[inline]
113    pub fn iter_by_data<'a, 'b, T>(
114        &'a self,
115        value: &'b T,
116    ) -> impl Iterator<Item = GErrNode<'a, C, D>>
117    where
118        T: Any + PartialEq,
119        'b: 'a,
120    {
121        self.iter().filter(move |item| match item {
122            GErrNode::Root(gerr) => gerr
123                .data()
124                .and_then(|data| (data as &dyn Any).downcast_ref::<T>())
125                .is_some_and(|data| data == value),
126
127            GErrNode::LeafGErr(gerr) => gerr
128                .data
129                .as_ref()
130                .and_then(|data| (&**data as &dyn Any).downcast_ref::<T>())
131                .is_some_and(|data| data == value),
132
133            _ => false,
134        })
135    }
136
137    /// Iterate over GErr's sources by source's type.
138    #[inline]
139    pub fn iter_source<E>(&self) -> impl Iterator<Item = GErrNode<'_, C, D>>
140    where
141        E: Error + 'static,
142    {
143        self.iter().filter_map(|item| match item {
144            GErrNode::LeafErr(err) if err.is::<E>() => Some(item),
145
146            GErrNode::LeafGErr(gerr) if (gerr as &dyn Error).is::<E>() => Some(item),
147
148            _ => None,
149        })
150    }
151}