use std::process; use super::log; use ct::errors::*; pub trait CtUnwrap { fn ct_unwrap(self) -> T; } impl CtUnwrap for CtResult { fn ct_unwrap(self) -> T { match self { Err(e) => handle_error(&e), Ok(t) => t, } } } impl CtUnwrap for IoResult { fn ct_unwrap(self) -> T { match self { Err(e) => handle_io_error(&e, 0), Ok(t) => t, } } } pub fn handle_error(e: &CtError) -> ! { match e { CtError::IoError(e) => handle_io_error(e, 0), CtError::JsonError(e) => handle_json_error(e), CtError::ADError(e) => handle_app_dirs_error(e), CtError::GlobError(e) => handle_glob_error(e), CtError::Own(s) => handle_own_error(s), } } fn handle_io_error(e: &IoError, code_offset: i32) -> ! { let exit = |code| process::exit(code + code_offset); match e.kind() { std::io::ErrorKind::NotFound => { bunt::writeln!( log::err(), "{$red}IO Error{/$}: File not found\nFull error: {}", e ) .ct_unwrap(); exit(100) } std::io::ErrorKind::PermissionDenied => { bunt::writeln!( log::err(), "{$red}IO Error{/$}: Permission denied\nFull error: {}", e ) .ct_unwrap(); exit(101) } std::io::ErrorKind::AlreadyExists => { bunt::writeln!( log::err(), "{$red}IO Error{/$}: File already exists\nFull error: {}", e ) .ct_unwrap(); exit(102) } std::io::ErrorKind::WouldBlock => { bunt::writeln!( log::err(), "{$red}IO Error{/$}: Operation would block\nFull error: {}", e ) .ct_unwrap(); exit(103) } std::io::ErrorKind::InvalidInput => { bunt::writeln!(log::err(), "{$red}IO Error{/$}: \nFull error: {}", e).ct_unwrap(); exit(104) } std::io::ErrorKind::InvalidData => { bunt::writeln!( log::err(), "{$red}IO Error{/$}: Read data was not valid \ (e.g. not UTF-8 if read into a string)\nFull error: {}", e ) .ct_unwrap(); exit(105) } std::io::ErrorKind::TimedOut => { bunt::writeln!( log::err(), "{$red}IO Error{/$}: Operation timed out\nFull error: {}", e ) .ct_unwrap(); exit(106) } std::io::ErrorKind::WriteZero => { bunt::writeln!( log::err(), "{$red}IO Error{/$}: Could not write everything that was requested\nFull error: {}", e ) .ct_unwrap(); exit(107) } std::io::ErrorKind::Interrupted => { bunt::writeln!( log::err(), "{$red}IO Error{/$}: Operation was interrupted.\nFull error: {}", e ) .ct_unwrap(); exit(108) } std::io::ErrorKind::Other => { bunt::writeln!(log::err(), "{$red}IO Error{/$}: Other\nFull error: {}", e).ct_unwrap(); exit(109) } std::io::ErrorKind::UnexpectedEof => { bunt::writeln!( log::err(), "{$red}IO Error{/$}: Unexpected End of File\nFull error: {}", e ) .ct_unwrap(); exit(110) } _ => { eprintln!("Weird IO Error occured: {}", e); todo!() } } } fn handle_json_error(e: &JsonError) -> ! { // serde_json has some good printing already bunt::writeln!(log::err(), "{$red}JSON Error{/$}: {}", e).ct_unwrap(); process::exit(400) } fn handle_app_dirs_error(e: &AppDirsError) -> ! { match e { AppDirsError::Io(e) => { bunt::writeln!(log::err(), "{$red}AppDir/IO Error{/$}: ").ct_unwrap(); handle_io_error(e, 102) } AppDirsError::NotSupported => { bunt::writeln!( log::err(), "{$red}System Error{/$}: App directories not supported on this system!" ) .ct_unwrap(); process::exit(200) } AppDirsError::InvalidAppInfo => { bunt::writeln!(log::err(), "{$red}Internal Error{/$}: Invalid App Info").ct_unwrap(); process::exit(201) } } } fn handle_glob_error(e: &GlobError) -> ! { bunt::writeln!( log::err(), "{$red}Glob error on path{/$}: {}", e.path().as_os_str().to_string_lossy() ) .ct_unwrap(); handle_io_error(e.error(), 200) } fn handle_own_error(msg: &str) -> ! { bunt::writeln!(log::err(), "{$red}CT Error{/$}: {}", msg).ct_unwrap(); process::exit(1) }