Skip to main content

g_err/
query.rs

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