1use alloc::vec;
9use alloc::vec::Vec;
10use core::error::Error;
11use core::fmt::{Debug, Display};
12
13use crate::gerr::Source;
14use crate::{Config, DataSource, GErr, GErrBox, GErrSource, IdSource};
15
16impl<'a, C: Config, D> IntoIterator for &'a GErr<C, D>
17where
18 C::Id: IdSource + 'static,
19 D: DataSource + 'static,
20{
21 type Item = GErrNode<'a, C, D>;
22 type IntoIter = GErrTree<'a, C, D>;
23
24 #[inline]
25 fn into_iter(self) -> Self::IntoIter {
26 self.iter()
27 }
28}
29
30impl<'a, C: Config, D> IntoIterator for &'a GErrBox<C, D>
31where
32 C::Id: IdSource + 'static,
33 D: DataSource + 'static,
34{
35 type Item = GErrNode<'a, C, D>;
36 type IntoIter = GErrTree<'a, C, D>;
37
38 #[inline]
39 fn into_iter(self) -> Self::IntoIter {
40 (*self).iter()
41 }
42}
43
44impl<C: Config, D> GErr<C, D>
45where
46 C::Id: IdSource + 'static,
47 D: DataSource + 'static,
48{
49 #[inline]
51 pub fn iter(&self) -> GErrTree<'_, C, D> {
52 GErrTree {
53 nodes: vec![GErrNode::Root(self)],
54 }
55 }
56}
57
58pub enum GErrNode<'a, C: Config, D> {
62 Root(&'a GErr<C, D>),
63 LeafErr(&'a (dyn Error + Send + Sync + 'static)),
64 LeafGErr(&'a GErrSource),
65}
66
67impl<'a, C: Config, D> Display for GErrNode<'a, C, D>
68where
69 C::Id: IdSource + 'static,
70 D: DataSource + 'static,
71{
72 fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
73 match self {
74 Self::Root(root) => write!(f, "{}", root),
75 Self::LeafErr(err) => write!(f, "{}", err),
76 Self::LeafGErr(gerr) => write!(f, "{}", gerr),
77 }
78 }
79}
80
81impl<'a, C: Config, D> Debug for GErrNode<'a, C, D>
82where
83 C::Id: IdSource + 'static,
84 D: DataSource + 'static,
85{
86 fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
87 match self {
88 Self::Root(root) => write!(f, "root: {:#?}", root),
89 Self::LeafErr(err) => write!(f, "err: {:#?}", err),
90 Self::LeafGErr(gerr) => write!(f, "gerr: {:#?}", gerr),
91 }
92 }
93}
94
95pub struct GErrTree<'a, C: Config, D> {
99 nodes: Vec<GErrNode<'a, C, D>>,
100}
101
102impl<'a, C: Config, D> Iterator for GErrTree<'a, C, D>
103where
104 C::Id: IdSource + 'static,
105 D: DataSource + 'static,
106{
107 type Item = GErrNode<'a, C, D>;
108
109 fn next(&mut self) -> Option<Self::Item> {
110 let current = self.nodes.pop()?;
111
112 match ¤t {
113 GErrNode::Root(gerr) => {
114 if let Some(sources) = gerr.sources() {
115 for source in sources.iter().rev() {
116 match &source {
117 Source::Err(err) => {
118 self.nodes.push(GErrNode::LeafErr(err.as_ref()));
119 }
120
121 Source::GErr(gerr) => {
122 self.nodes.push(GErrNode::LeafGErr(gerr.as_ref()));
123 }
124 }
125 }
126 }
127 }
128
129 GErrNode::LeafErr(_) => {}
131
132 GErrNode::LeafGErr(gerr) => {
133 if let Some(sources) = gerr.sources.as_deref() {
134 for source in sources.iter().rev() {
135 match &source {
136 Source::Err(err) => {
137 self.nodes.push(GErrNode::LeafErr(err.as_ref()));
138 }
139
140 Source::GErr(gerr) => {
141 self.nodes.push(GErrNode::LeafGErr(gerr.as_ref()));
142 }
143 }
144 }
145 }
146 }
147 }
148
149 Some(current)
150 }
151}