I've created two libraries for text parsing and they have in common the ErrorType type with the message attribute, now after importing them in main() function I'd like to render the errors from both parsers, they are actually the same but they have different types followed by module name, can I solve it in some decent way? Do I need some third library just for this one error struct and import it as dependency in both parsers or can I use some generic type in main() for both ones?
How can I extract message from this heterogeneous SuperError enum, why All Errors shows empty list? BTW I seems it forces me to use fmt::Display, can I somehow reduce my code?
use thiserror::Error;
use std::fmt;
mod text_parser_1 {
#[derive(Debug)]
pub struct ErrorType {
pub message: String,
}
}
mod text_parser_2 {
#[derive(Debug)]
pub struct ErrorType {
pub message: String,
}
}
#[derive(Error, Debug)]
pub enum SuperError {
ErrorType1(text_parser_1::ErrorType),
ErrorType2(text_parser_2::ErrorType),
}
impl fmt::Display for SuperError {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
match *self {
SuperError::ErrorType1(text_parser_1::ErrorType { ref message }) => write!(f, "SuperError is here! {}", message),
SuperError::ErrorType2(text_parser_2::ErrorType { ref message }) => message.fmt(f),
}
}
}
fn main() {
let mut errors: Vec<SuperError> = vec![];
let test_events = vec!["error_type_1", "error_type_2"];
let result = test_events.iter().map(|&event| match event {
"error_type_1" => {
errors.push(SuperError::ErrorType1(text_parser_1::ErrorType { message: String::from("some error 1")}));
"error_type_1"
},
"error_type_2" => {
errors.push(SuperError::ErrorType2(text_parser_2::ErrorType { message: String::from("some error 2")}));
"error_type_2"
},
_ => "any",
});
println!("result {:?}", result); // to ensure both errors were matched
rerender_errors(errors);
}
fn rerender_errors(errors: Vec<SuperError>) {
println!("All Errors {:?}", errors);
}
Apologies for so many questions but I've encountered new problems, I found that in higher level I have to match both types everywhere, would it be possible to put parser errors in some generic error where I'd be able to get message directly like error.message? Why my fmt::Display for SuperError seems unused by e.g. println!, why is it required by compiler?
use thiserror::Error;
use std::fmt;
mod text_parser_1 {
#[derive(Debug)]
pub struct ErrorType {
pub message: String,
}
}
mod text_parser_2 {
#[derive(Debug)]
pub struct ErrorType {
pub message: String,
}
}
#[derive(Error, Debug)]
pub enum SuperError {
ErrorType1(text_parser_1::ErrorType),
ErrorType2(text_parser_2::ErrorType),
}
impl fmt::Display for SuperError {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
match *self {
SuperError::ErrorType1(text_parser_1::ErrorType { ref message }) => write!(f, "Why I'm not visible? {}", message), //why this formatter seems unused?
SuperError::ErrorType2(text_parser_2::ErrorType { ref message }) => message.fmt(f),
}
}
}
fn main() {
let mut errors: Vec<SuperError> = vec![];
let test_events = vec!["error_type_1", "error_type_2"];
let result: Vec<_> = test_events.iter().map(|&event| match event {
"error_type_1" => {
errors.push(SuperError::ErrorType1(text_parser_1::ErrorType { message: String::from("some error 1")}));
"error_type_1"
},
"error_type_2" => {
errors.push(SuperError::ErrorType2(text_parser_2::ErrorType { message: String::from("some error 2")}));
"error_type_2"
},
_ => "any",
}).collect();
println!("result {:?}", result);
rerender_errors(errors);
}
fn rerender_errors(errors: Vec<SuperError>) {
for msg in &errors {
//println!("error {:?}", msg.message); // would it be possible to get message directly form generic error?
match msg {
SuperError::ErrorType1(text_parser_1::ErrorType { ref message }) => println!("error 1 {:?}", message),
SuperError::ErrorType2(text_parser_2::ErrorType { ref message }) => println!("error 2 {:?}", message),
}
}
}