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
//! # How to create opaque error types for public APIs //! //! While creating error types on top of Rust enums allows for great //! flexibility inside your code, that same flexibility may not be //! desired in a public API. Public enums also expose their variants //! and the variant's fields, allowing consumers to rely on those //! details. //! //! The most conservative approach is to create an *opaque* error type //! that only implements a handful of traits. This can be done by //! deriving `Snafu` for a newtype struct that contains another SNAFU //! error: //! //! ```rust //! # use snafu::Snafu; //! #[derive(Debug, Snafu)] //! pub struct Error(InnerError); //! //! // That's all it takes! The rest is demonstration of how to use it. //! //! pub fn login(id: i32) -> Result<(), Error> { //! validate_user(id)?; //! is_user_locked(id)?; //! Ok(()) //! } //! //! #[derive(Debug, Snafu)] //! enum InnerError { //! #[snafu(display("User ID {} is invalid", user_id))] //! InvalidUser { user_id: i32 }, //! #[snafu(display("User ID {} is locked", user_id))] //! UserLocked { user_id: i32 }, //! } //! //! fn validate_user(user_id: i32) -> Result<(), InnerError> { //! InvalidUser { user_id }.fail() //! } //! //! fn is_user_locked(user_id: i32) -> Result<(), InnerError> { //! UserLocked { user_id }.fail() //! } //! ``` //! //! ## Delegated traits //! //! - [`Error`][] //! - [`Display`][] //! - [`ErrorCompat`][] //! //! [`Error`]: std::error::Error //! [`Display`]: std::fmt::Display //! [`ErrorCompat`]: crate::ErrorCompat //! //! ## `From` //! //! The `From` trait is also implemented to convert the inner type into //! the opaque type. This makes converting from internal errors to public //! errors very easy.