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(&'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
95/// Iterator of GErr error nodes.
96///
97/// Produced by [`GErr::iter`].
98pub 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 &current {
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            // External errors have no children.
130            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}