Skip to main content

g_err/
iterator.rs

1//! Iterator for [`GErr`].
2//!
3//! Iterate over GErr's tree of root and leaf nodes.
4//!
5//! Produce iterator using [`GErr::iter`] method producing [`GErrTree`].
6//!
7//! [`GErrTree`] is traversed by DFS method.
8use 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    /// Produces iterator of GErr's nodes(including self).
50    #[inline]
51    pub fn iter(&self) -> GErrTree<'_, C, D> {
52        GErrTree {
53            nodes: vec![GErrNode::Root(self)],
54        }
55    }
56}
57
58/// A node in GErrTree.
59///
60/// Contained by [`GErrTree`].
61pub enum GErrNode<'a, C: Config, D> {
62    /// Root of GErr.
63    Root(&'a GErr<C, D>),
64    /// non-gerr source node.
65    LeafErr(&'a (dyn Error + Send + Sync + 'static)),
66    /// gerr or any error convertible to [`GErrSource`] node.
67    LeafGErr(&'a GErrSource),
68}
69
70impl<'a, C: Config, D> Display for GErrNode<'a, C, D>
71where
72    C::Id: IdSource + 'static,
73    D: DataSource + 'static,
74{
75    fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
76        match self {
77            Self::Root(root) => write!(f, "{}", root),
78            Self::LeafErr(err) => write!(f, "{}", err),
79            Self::LeafGErr(gerr) => write!(f, "{}", gerr),
80        }
81    }
82}
83
84impl<'a, C: Config, D> Debug for GErrNode<'a, C, D>
85where
86    C::Id: IdSource + 'static,
87    D: DataSource + 'static,
88{
89    fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
90        match self {
91            Self::Root(root) => write!(f, "root: {:#?}", root),
92            Self::LeafErr(err) => write!(f, "err: {:#?}", err),
93            Self::LeafGErr(gerr) => write!(f, "gerr: {:#?}", gerr),
94        }
95    }
96}
97
98/// Iterator of GErr error nodes.
99///
100/// Produced by [`GErr::iter`].
101pub struct GErrTree<'a, C: Config, D> {
102    nodes: Vec<GErrNode<'a, C, D>>,
103}
104
105impl<'a, C: Config, D> Iterator for GErrTree<'a, C, D>
106where
107    C::Id: IdSource + 'static,
108    D: DataSource + 'static,
109{
110    type Item = GErrNode<'a, C, D>;
111
112    fn next(&mut self) -> Option<Self::Item> {
113        let current = self.nodes.pop()?;
114
115        match &current {
116            GErrNode::Root(gerr) => {
117                if let Some(sources) = gerr.sources() {
118                    for source in sources.iter().rev() {
119                        match &source {
120                            Source::Err(err) => {
121                                self.nodes.push(GErrNode::LeafErr(err.as_ref()));
122                            }
123
124                            Source::GErr(gerr) => {
125                                self.nodes.push(GErrNode::LeafGErr(gerr.as_ref()));
126                            }
127                        }
128                    }
129                }
130            }
131
132            // External errors have no children.
133            GErrNode::LeafErr(_) => {}
134
135            GErrNode::LeafGErr(gerr) => {
136                if let Some(sources) = gerr.sources.as_deref() {
137                    for source in sources.iter().rev() {
138                        match &source {
139                            Source::Err(err) => {
140                                self.nodes.push(GErrNode::LeafErr(err.as_ref()));
141                            }
142
143                            Source::GErr(gerr) => {
144                                self.nodes.push(GErrNode::LeafGErr(gerr.as_ref()));
145                            }
146                        }
147                    }
148                }
149            }
150        }
151
152        Some(current)
153    }
154}