#![allow(warnings)]
use std::io;
use std::convert::Infallible;
use std::net::{AddrParseError, IpAddr};
use std::num::TryFromIntError;
extern crate derive_constructors_proc;
pub use derive_constructors_proc::*;
#[constructor(
named(with_age_and_name),
pattern(From),
fields(age, name),
defaults(
id("Jorge".to_string()),
family_names(vec ! ["Rico", "Vivas"])
)
)]
#[constructor(
named(try_with_age_and_name),
pattern(TryFrom),
fields(age, name),
defaults(
id("Jorge".to_string()),
family_names(vec ! ["Rico", "Vivas"])
),
error_enum_metadata(# [derive(Debug, PartialEq)]),
error_enum_named(GetWithAgeAndNameError),
)]
#[derive(From, Debug, PartialEq)]
pub struct CharacterInfo {
age: u8,
name: &'static str,
#[no_from("Jorge".to_string())]
id: String,
#[no_from(vec ! ["Rico", "Vivas"])]
family_names: Vec<&'static str>,
#[no_from]
appeared_in_movies: u8,
}
#[derive(From, Debug)]
pub enum MyError {
IO(std::io::Error),
#[no_from]
CustomIOError(io::Error),
MyTwoIo { io_err: io::Error, other_io_err: io::Error },
}
#[derive(Debug, From)]
enum MyNumErrors {
IO(std::io::Error),
Infallible(Infallible),
TryFromIntError(TryFromIntError),
}
pub trait FlattenError<Ok, InternalError, ExternalError> {
fn flatten_err<Error>(self) -> Result<Ok, Error> where Error: From<InternalError> + From<ExternalError>;
fn flatten_err_ext(self) -> Result<Ok, ExternalError> where InternalError: Into<ExternalError>;
fn flatten_err_int(self) -> Result<Ok, InternalError> where ExternalError: Into<InternalError>;
}
impl<Ok, InternalError, ExternalError> FlattenError<Ok, InternalError, ExternalError> for Result<Result<Ok, InternalError>, ExternalError> {
fn flatten_err<ResError>(self) -> Result<Ok, ResError> where ResError: From<InternalError> + From<ExternalError> {
match self {
Err(external_error) => Result::Err(external_error.into()),
Ok(internal_result) => {
match internal_result {
Err(internal_error) => Result::Err(internal_error.into()),
Ok(value) => Result::Ok(value),
}
}
}
}
fn flatten_err_ext(self) -> Result<Ok, ExternalError> where InternalError: Into<ExternalError> {
match self {
Err(external_error) => Result::Err(external_error),
Ok(internal_result) => {
match internal_result {
Err(internal_error) => Result::Err(internal_error.into()),
Ok(value) => Result::Ok(value),
}
}
}
}
fn flatten_err_int(self) -> Result<Ok, InternalError> where ExternalError: Into<InternalError> {
match self {
Err(external_error) => Result::Err(external_error.into()),
Ok(internal_result) => {
match internal_result {
Err(internal_error) => Result::Err(internal_error),
Ok(value) => Result::Ok(value),
}
}
}
}
}
#[test]
fn test() {
assert_eq!(
CharacterInfo::from((23, "Jorge")),
CharacterInfo { age: 23, name: "Jorge", id: "Jorge".to_string(), family_names: vec!["Rico", "Vivas"], appeared_in_movies: 0 }
);
assert_eq!(
CharacterInfo::try_with_age_and_name(2003, "Jorge"),
Err(GetWithAgeAndNameError::AgeError(u8::try_from(2003).unwrap_err()))
);
let error =
std::fs::read_to_string("").map(|_| std::fs::read_to_string("").map(|_| std::fs::read_to_string("")))
.flatten_err::<MyNumErrors>().flatten_err_ext();
let is_io_error = match error.unwrap_err() {
MyNumErrors::IO(_) => true,
_ => false,
};
assert!(is_io_error);
let my_two_errors_is_two_errors = match MyError::from((
std::fs::read_to_string("").expect_err(""),
std::fs::read_to_string("").expect_err("")
)) {
MyError::MyTwoIo { .. } => true,
_ => false,
};
assert!(my_two_errors_is_two_errors);
}