1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150
// See the COPYRIGHT file at the top-level directory of this distribution. // Licensed under MIT license<LICENSE-MIT or http://opensource.org/licenses/MIT> //! Checked EXceptions for Rust. //! //! See the [enumx book](https://oooutlk.github.io/enumx/) for more. //! //! # Features //! //! 1. Use `Result!( Type throws A,B,.. )`, `ret!()`, `throw!()` to simulate //! checked exceptions in Rust //! //! 2. `#[ty_pat] match` for "type as pattern matching" in match expressions. //! //! 3. Optional backtrace support. //! //! 4. Fallback as `impl std::error::Error`. //! //! # Examples //! //! ```rust //! use enumx::export::*; //! use enumx::predefined::*; //! use cex::*; //! //! // accepts even numbers; rejects odd ones and report an error `String` //! #[cex] //! fn check_even( a: u32 ) -> Result!( u32 throws String ) { //! if a % 2 == 1 { //! throw!( format!( "odd numbers not allowed: a == {}", a )); //! } else { //! ret!( a ); //! } //! } //! //! // accepts non-zero numbers; rejects zeros and report an error of `&'static str` //! #[cex] //! fn check_nonzero( b: u32 ) -> Result!( u32 throws &'static str ) { //! if b == 0 { //! throw!( "zero not allowed: b == 0" ); //! } else { //! ret!( b ) //! } //! } //! //! struct Underflow; //! //! #[cex] //! fn sub( a: u32, b: u32 ) -> Result!( u32 throws String, &'static str, Underflow ) { //! let a = check_even( a )?; //! let b = check_nonzero( b )?; //! ret!( a+b ); //! } //! //! #[cex] //! fn distance( a: u32, b: u32 ) -> Result!( u32 throws String, &'static str ) { //! ret!( sub(a,b).or_else( |err| {#[ty_pat] match err { //! Underflow => ret!( b-a ), //! String(s) => throw!( s ), //! TyPat::<&'static str>(s) => throw!( s ), //! }})) //! } //! //! #[cex] //! fn distance2( a: u32, b: u32 ) -> Result!( u32 throws String, &'static str ) { //! ret!( sub(a,b).or_else( |err| #[ty_pat(gen_throws)] match err { //! Underflow => ret!( b-a ), //! })) //! } //! //! #[cex] //! fn distance3( a: u32, b: u32 ) -> Result!( u32 throws String, &'static str ) { //! ret!( sub(a,b).or_else( |err| #[ty_pat(gen &'static str, String )] match err { //! Underflow => ret!( b-a ), //! })) //! } //! ``` use enumx::export::*; /// Enum exchange to wrap an `Err`. /// /// ```rust /// use enumx::export::*; /// use enumx::predefined::*; /// use cex::*; /// /// let error: Result<(),Enum!(i32,bool)> = 42.error(); /// assert_eq!( error, Err( Enum2::_0(42) )); /// ``` pub trait Error { fn error<T,Dest,Index>( self ) -> Result<T,Dest> where Self: Sized + ExchangeInto<Dest,Index> { Err( self.exchange_into() ) } } impl<Enum> Error for Enum {} /// Enum exchange for `Err` combinator. /// /// ```rust /// /// use enumx::export::*; /// use enumx::predefined::*; /// use cex::*; /// /// let error: Result<(),i32> = Err( 42 ); /// let error: Result<(),Enum!(i32,bool)> = error.map_error(); /// assert_eq!( error, Err( Enum2::_0(42) )); /// ``` pub trait MapError<T,Src> where Self : Into<Result<T,Src>> { fn map_error<Dest,Indices>( self ) -> Result<T,Dest> where Src : Sized + ExchangeInto<Dest,Indices> { self.into().map_err( |src| src.exchange_into() ) } } impl<Res,T,Src> MapError<T,Src> for Res where Res: Into<Result<T,Src>> {} pub mod result; pub use result::*; pub mod log; pub use self::log::*; #[cfg( not( any( feature="log", feature="env_log" )))] pub use cex_derive::cex; #[cfg( not( any( feature="log", feature="env_log" )))] pub use cex_derive::Result; #[cfg( not( any( feature="log", feature="env_log" )))] pub use cex_derive::Throws; #[cfg( all( feature="log", not( feature="env_log" )))] pub use cex_derive::cex_log as cex; #[cfg( all( feature="log", not( feature="env_log" )))] pub use cex_derive::ResultLog as Result; #[cfg( all( feature="log", not( feature="env_log" )))] pub use cex_derive::ThrowsLog as Throws; #[cfg( all( feature="env_log", not( feature="log" )))] pub use cex_derive::cex_env_log as cex; #[cfg( all( feature="env_log", not( feature="log" )))] pub use cex_derive::ResultEnvLog as Result; #[cfg( all( feature="env_log", not( feature="log" )))] pub use cex_derive::ThrowsEnvLog as Throws;