grp_core/error/structs.rs
1use std::fmt::Display;
2
3use color_print::cformat;
4
5use crate::error::tools::Notes;
6
7/// # Error
8/// This is the _error struct_ used in all the lib
9/// it implements some based functionality to show the error
10/// in a beautifull format.
11///
12/// There are to basic ways to create a new error,
13/// with a preset and additional information, or a custom, for
14/// your own error.
15///
16/// ## Example 1
17/// ~~~
18/// use grp_core::{ErrorType, Error};
19///
20/// Error::new(
21/// ErrorType::ResponseParsing,
22/// vec!["description", "{}"]
23/// );
24/// ~~~
25///
26/// Error contains a vector to emulate various parameter to allow a more
27/// usefull message to the user. In this case, the `ErrorType::ResponseParsing`
28/// needs at least 2 parameters, one for the description of the error,
29/// and other for the text that generates the error.
30///
31/// ## Example 2
32/// ~~~
33/// use grp_core::{ErrorType, Error};
34///
35/// Error::new_custom(
36/// "Custom error message",
37/// vec!["something whent wrong after...", "don't be afraid"] // here, every item is trated as a new line (if printed)
38/// );
39/// ~~~
40///
41/// You also can create custom errors using the _build in_ method _new_custom_
42/// this is usefull if you whant to canvert between error in your aplication,
43/// a good example is present in _https://github.com/feraxhp/grp_, where the
44/// errors from git2 are parsed to grp_core errors, in order to keep the
45/// same error throughout all the aplication.
46///
47/// ## Example 3
48/// ~~~
49/// use grp_core::{ErrorType, Error};
50///
51/// let normal_error = Error::new(
52/// ErrorType::ResponseParsing,
53/// vec!["description", "{}"]
54/// );
55///
56/// let error_custom = Error::new_custom(
57/// "Custom error message",
58/// vec!["something whent wrong after...", "don't be afraid"] // here, every item is trated as a new line (if printed)
59/// );
60///
61/// let collection_error = Error::colection(vec![normal_error, error_custom]);
62/// ~~~
63///
64/// There is a 3 type and is a collection, this allows to return multiple errors
65/// in just one `grp_core::Error`. usefull for paggination errors, or concations of multiple
66/// of them.
67#[derive(Debug, Clone)]
68pub struct Error {
69 pub(super) etype: String,
70 pub message: String,
71 pub content: Vec<String>,
72}
73
74#[allow(dead_code)]
75impl Error {
76 pub fn new<P, K, M>(
77 etype: &'static str,
78 message: M,
79 detail: P,
80 explanation: Vec<String>,
81 notes: Vec<K>,
82 ) -> Error
83 where
84 P: Display,
85 M: Display,
86 K: Display,
87 {
88 let notes_legth = notes.len();
89 let mut content: Vec<String> = Vec::with_capacity(notes_legth + 1 + explanation.len());
90
91 content.push(cformat!("<y>* {}</>", detail));
92 content.extend(explanation);
93
94 if notes_legth > 0 {
95 content.push(cformat!(""));
96 content.push(cformat!("<g># notes</>"));
97 content.extend(notes.iter().as_notes());
98 }
99
100 Error {
101 etype: format!("custom::{}", etype),
102 message: message.to_string(),
103 content
104 }
105 }
106
107 pub fn collection(errors: Vec<Error>) -> Error {
108 let mut content = Vec::new();
109 for error in errors {
110 content.push(cformat!("\n*<r>{}</>",error.message));
111 content.extend(error.content.iter().map(|s| format!(" {}", s)));
112 }
113 Error {
114 etype: "".to_string(),
115 message: "Multiple errors found".to_string(),
116 content: content
117 }
118 }
119
120 pub fn get_type(&self) -> String { self.etype.to_owned() }
121
122 pub fn show(&self) { self.show_with_offset(0); }
123 pub fn show_with_offset(&self, offset: usize) {
124 self.content.iter().for_each(|line| {
125 eprintln!("{:width$}{}", "", line, width = offset);
126 });
127 }
128}