problemo/problems/
problems.rs1use super::super::{error::*, implementation::*, problem::*, receiver::*};
2
3use std::{any::*, collections::*, error::Error, fmt, slice::*};
4
5pub const PROBLEMS_DISPLAY_PREFIX: &str = "• ";
7
8#[derive(Debug, Default)]
21pub struct Problems {
22 pub problems: Vector<Problem>,
24
25 pub critical_error_types: HashSet<TypeId>,
27}
28
29impl Problems {
30 pub fn with_capacity(capacity: usize) -> Self {
32 Vector::with_capacity(capacity).into()
33 }
34
35 pub fn is_empty(&self) -> bool {
37 self.problems.is_empty()
38 }
39
40 pub fn count(&self) -> usize {
42 self.problems.len()
43 }
44
45 pub fn iter(&self) -> Iter<'_, Problem> {
47 self.into_iter()
48 }
49
50 pub fn handle_type_as_critical<ErrorT>(&mut self)
52 where
53 ErrorT: Any + Error,
54 {
55 self.critical_error_types.insert(TypeId::of::<ErrorT>());
56 }
57
58 pub fn is_critical(&self, problem: &Problem) -> bool {
60 problem
61 .top()
62 .map(|cause| self.is_error_critical(&cause.error))
63 .unwrap_or(false)
64 }
65
66 pub fn is_error_critical(&self, error: &CapturedError) -> bool {
68 self.critical_error_types.contains(&error.type_id())
69 }
70
71 pub fn add<ProblemT>(&mut self, problem: ProblemT)
73 where
74 ProblemT: Into<Problem>,
75 {
76 self.problems.push(problem.into())
77 }
78
79 pub fn check(self) -> Result<(), Self> {
81 if self.is_empty() { Ok(()) } else { Err(self) }
82 }
83
84 pub fn iter_unique<'this>(&'this self) -> impl Iterator<Item = &'this Problem> {
89 iter_unique_problems(&self.problems)
90 }
91}
92
93impl IntoProblem for Problems {
94 fn into_problem(self) -> Problem {
95 self.into()
96 }
97}
98
99impl ProblemReceiver for Problems {
100 fn give(&mut self, problem: Problem) -> Result<(), Problem> {
101 match self.is_critical(&problem) {
103 true => Err(problem),
105
106 false => {
108 self.add(problem);
109 Ok(())
110 }
111 }
112 }
113}
114
115impl fmt::Display for Problems {
116 fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
117 let mut iterator = self.into_iter().peekable();
118 while let Some(problem) = iterator.next() {
119 write!(formatter, "{}{}", PROBLEMS_DISPLAY_PREFIX, problem)?;
120 if iterator.peek().is_some() {
121 writeln!(formatter)?;
122 }
123 }
124 Ok(())
125 }
126}
127
128impl From<Problems> for Problem {
129 fn from(mut problems: Problems) -> Self {
130 if !problems.is_empty() {
131 problems.problems.remove(0)
132 } else {
133 Problem::default()
134 }
135 }
136}
137
138impl From<Vector<Problem>> for Problems {
139 fn from(problems: Vector<Problem>) -> Self {
140 Self {
141 problems,
142 critical_error_types: Default::default(),
143 }
144 }
145}
146
147impl<'this> IntoIterator for &'this Problems {
148 type Item = &'this Problem;
149 type IntoIter = Iter<'this, Problem>;
150
151 fn into_iter(self) -> Self::IntoIter {
152 self.problems.iter()
153 }
154}
155
156impl FromIterator<Problem> for Problems {
157 fn from_iter<IntoIteratorT>(iterator: IntoIteratorT) -> Self
158 where
159 IntoIteratorT: IntoIterator<Item = Problem>,
160 {
161 iterator.into_iter().collect::<Vector<_>>().into()
162 }
163}
164
165impl<ErrorT> FromIterator<ErrorT> for Problems
166where
167 ErrorT: 'static + Error + Send + Sync,
168{
169 fn from_iter<IntoIteratorT>(iterator: IntoIteratorT) -> Self
170 where
171 IntoIteratorT: IntoIterator<Item = ErrorT>,
172 {
173 Self::from_iter(iterator.into_iter().map(Problem::from))
174 }
175}