Improve Error

This commit is contained in:
Jaby
2022-09-19 21:06:44 +02:00
committed by Jaby
parent 1541c1e777
commit c4ed9bc10f
5 changed files with 64 additions and 37 deletions

View File

@@ -2,64 +2,89 @@ use std::{boxed::Box, io::{Read, Write}, path::PathBuf};
pub type Output = Box<dyn Write>;
pub type Input = Box<dyn Read>;
pub type Result<T> = std::result::Result<T, Error>;
pub struct Error {
pub exit_code: i32,
pub text: String,
pub exit_code: i32,
pub action: String,
pub text: String,
}
impl Error {
pub fn new(text: String, exit_code: Option<i32>) -> Error {
Error{exit_code: Self::get_exit_code(exit_code), text}
const DEFAULT_EXITCODE:i32 = -1;
pub fn from_text(text: String) -> Error {
Error{exit_code: Self::DEFAULT_EXITCODE, action: String::new(), text}
}
pub fn try_or_new<T, S>(result: std::result::Result<T, S>, exit_code: Option<i32>) -> Result<T> where S: std::fmt::Display {
pub fn from_error<T>(error: T) -> Error where T: std::fmt::Display {
Error::from_text(error.to_string())
}
pub fn not_implemented(function: &str) -> Error {
Error::from_text(format!("{} not implemented yet", function))
}
pub fn try_or_new<T, S>(result: std::result::Result<T, S>) -> Result<T, Error> where S: std::fmt::Display {
Self::try_or_new_with_action(String::new(), result)
}
pub fn try_or_new_with_action<T, S>(action: String, result: std::result::Result<T, S>) -> Result<T, Error> where S: std::fmt::Display {
match result {
Ok(value) => Ok(value),
Err(error) => Err(Error::new(error.to_string(), exit_code)),
Err(error) => Err(Error{exit_code: Self::DEFAULT_EXITCODE, action, text: error.to_string()}),
}
}
pub fn ok_or_new<T, F>(option: Option<T>, error_text: F, code: Option<i32>) -> Result<T> where F: Fn () -> String{
Ok(option.ok_or(Error::new(error_text(), code))?)
}
fn get_exit_code(exit_code: Option<i32>) -> i32 {
match exit_code {
Some(exit_code) => exit_code,
None => -1,
}
pub fn ok_or_new<T, F>(option: Option<T>, error_text: F) -> Result<T, Error> where F: Fn () -> String{
Ok(option.ok_or(Error{exit_code: Self::DEFAULT_EXITCODE, action: String::new(), text: error_text()})?)
}
}
pub fn open_output(output_file: Option<PathBuf>) -> Result<Output> {
impl std::fmt::Display for Error {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
if self.action.is_empty() {
write!(f, "{}", self.text)
}
else {
write!(f, "{}:{}", self.action, self.text)
}
}
}
impl std::convert::From<std::io::Error> for Error {
fn from(error: std::io::Error) -> Self {
Error{exit_code: -1, action: String::new(), text: error.to_string()}
}
}
pub fn open_output(output_file: Option<PathBuf>) -> Result<Output, Error> {
match output_file {
Some(output_path) => Ok(Box::new(Error::try_or_new(std::fs::File::create(output_path), None)?)),
Some(output_path) => Ok(Box::new(std::fs::File::create(output_path)?)),
None => Ok(Box::new(std::io::stdout())),
}
}
pub fn open_input(input_file: Option<PathBuf>) -> Result<Input> {
pub fn open_input(input_file: Option<PathBuf>) -> Result<Input, Error> {
match input_file {
Some(input_path) => Ok(Box::new(Error::try_or_new(std::fs::File::open(input_path), None)?)),
Some(input_path) => Ok(Box::new(std::fs::File::open(input_path)?)),
None => Ok(Box::new(std::io::stdin())),
}
}
pub fn os_str_to_string(input: &std::ffi::OsStr, name: &str) -> Result<String> {
Ok(Error::ok_or_new(input.to_str(), ||format!("Converting {} to UTF-8 failed", name), None)?.to_owned())
pub fn os_str_to_string(input: &std::ffi::OsStr, name: &str) -> Result<String, Error> {
Ok(Error::ok_or_new(input.to_str(), ||format!("Converting {} to UTF-8 failed", name))?.to_owned())
}
pub fn get_file_name_from_path_buf(input: &PathBuf, name: &str) -> Result<String> {
os_str_to_string(Error::ok_or_new(input.file_name(), ||format!("No {} file name found", name), None)?, name)
pub fn get_file_name_from_path_buf(input: &PathBuf, name: &str) -> Result<String, Error> {
os_str_to_string(Error::ok_or_new(input.file_name(), ||format!("No {} file name found", name))?, name)
}
pub fn input_to_vec(input: Input) -> Result<Vec<u8>> {
pub fn input_to_vec(input: Input) -> Result<Vec<u8>, Error> {
let mut data = Vec::new();
for byte in input.bytes() {
data.push(Error::try_or_new(byte, None)?);
data.push(byte?);
}
Ok(data)