#![no_std] //! A `no_std` library to simpify chaining methods when you are returning a [`Result`]. It is a //! trivial library which sould be compatible with all environments. //! //! This is specially noticeable when using crates like [`anyhow`](https://crates.io/crates/anyhow) //! which provide a "catch all" error type, so you need to convert all errors you recieve. //! //! It is also helpful when you have many custom errors constructed with //! [`thiserror`](https://crates.io/crates/thiserror) or //! [`justerror`](https://crates.io/crates/justerror), or use many libraries with different error //! types. //! //! # Usage //! //! Import the traits and you can benefit from it immediately: //! //! ```rust //! use err_into::MapInto; //! use err_into::ErrorInto; //! use err_into::ResultInto; //! //! // ... //! //! let _: Option = Some(0u8).map_into(); //! let _: Result = Ok(0u8).map_into(); //! let _: Result<(), i32> = Err(0u8).err_into(); //! let _: Result = (if false { Ok(0u8) } else { Err(0i8) }).res_into(); //! ``` //! //! ## Motivating example //! //! This is slightly contrived because I don't want to depend on any libraries but showcases where //! `err_into` excels: //! //! ```rust //! use err_into::ErrorInto; //! //! fn process(val: u16) -> Result { //! if val > 255 { //! Err((val >> 8) as u8) //! } else { //! Ok(val as _) //! } //! } //! //! fn long_chain() -> Result { //! (0u16..16u16).map(|x| x * x * x * x) //! .filter(|x| x % 2 == 0) //! .map(process) //! .next() //! .unwrap_or(Err(0)) //! .err_into() //! } //! //! fn long_chain_no_err_into() -> Result { //! // May be confusing //! (0u16..16u16).map(|x| x * x * x * x) //! .filter(|x| x % 2 == 0) //! .map(process) //! .next() //! .unwrap_or(Err(0)) //! .map_err(Into::into) //! } //! //! fn long_chain_no_map_err() -> Result { //! // Please don't do this //! Ok((0u16..16u16).map(|x| x * x * x * x) //! .filter(|x| x % 2 == 0) //! .map(process) //! .next() //! .unwrap_or(Err(0))?) //! } //! ``` /// Maps an error using [`Into::into`] /// /// Short version of `Result::map_err(self, Into::into)` that simplifies operation chains like /// /// ```rust /// use err_into::ErrorInto; /// /// fn get_data() -> Result<(), u8> { /// Err(0u8) /// } /// /// fn handle_data_question_mark() -> Result<(), i32> { /// // Can't be split into multiple lines /// Ok(get_data()?) /// } /// /// fn handle_data_map_err() -> Result<(), i32> { /// // Slightly harder to read /// get_data().map_err(Into::into) /// } /// /// fn handle_data_err_into() -> Result<(), i32> { /// get_data().err_into() /// } /// /// assert_eq!(handle_data_err_into(), handle_data_question_mark()); /// assert_eq!(handle_data_err_into(), handle_data_map_err()); /// ``` pub trait ErrorInto { fn err_into(self) -> Result; } /// Maps both the Value and the Error of a [`Result`] using [`Into::into`] /// /// Shorthand for `result.map(Into::into).map_err(Into::into)` /// /// ```rust /// use err_into::ResultInto; /// /// let res: Result = Ok(0); /// let _: Result = res.res_into(); /// ``` pub trait ResultInto { fn res_into(self) -> Result; } /// Maps a value using [`Into::into`] /// /// Shorthand for `Option::map(self, Into::into)` and `Result::map(self, Into::into)` /// /// ```rust /// use err_into::MapInto; /// /// let value = Some(0u8); /// let map_into: Option = value.map_into(); /// let map_into_std: Option = value.map(Into::into); /// assert_eq!(map_into, map_into_std); /// /// let result = Ok(0u8); /// let map_into: Result = result.map_into(); /// let map_into_std: Result = result.map(Into::into); /// assert_eq!(map_into, map_into_std); /// ``` pub trait MapInto { fn map_into(self) -> T; } impl ErrorInto for Result where F: Into, { fn err_into(self) -> Result { self.map_err(Into::into) } } impl ResultInto for Result where F: Into, U: Into, { fn res_into(self) -> Result { self.map(Into::into).map_err(Into::into) } } impl MapInto> for Result where T: Into, { fn map_into(self) -> Result { self.map(Into::into) } } impl MapInto> for Option where T: Into, { fn map_into(self) -> Option { self.map(Into::into) } }