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 #[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 #[inline]
32 pub fn iter_tags(&self) -> impl Iterator<Item = &str> {
33 self.tags().into_iter().flatten().map(Cow::as_ref)
34 }
35
36 #[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 #[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 #[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 #[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 #[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 #[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}