#![warn(missing_docs)] //! A macro which makes errors easy to write //! //! Minimum type is like this: //! //! ```rust //! #[macro_use] extern crate quick_error; //! # fn main() {} //! //! quick_error! { //! #[derive(Debug)] //! pub enum SomeError { //! Variant1 {} //! } //! } //! ``` //! Both ``pub`` and non-public types may be declared, and all meta attributes //! (such as ``#[derive(Debug)]``) are forwarded as is. The `Debug` must be //! implemented (but you may do that yourself if you like). The documentation //! comments ``/// something`` (as well as other meta attrbiutes) on variants //! are allowed. //! //! # Allowed Syntax //! //! You may add arbitrary parameters to any struct variant: //! //! ```rust //! # #[macro_use] extern crate quick_error; //! # fn main() {} //! # //! quick_error! { //! #[derive(Debug)] //! pub enum SomeError { //! /// IO Error //! Io(err: std::io::Error) {} //! /// Utf8 Error //! Utf8(err: std::str::Utf8Error) {} //! } //! } //! ``` //! //! Note unlike in normal Enum declarations you declare names of fields (which //! are omitted from type). How they can be used is outlined below. //! //! Now you might have noticed trailing braces `{}`. They are used to define //! implementations. By default: //! //! * `Error::cause()` returns None (even if type wraps some value) //! * `Display` outputs debug representation //! * No `From` implementations are defined //! //! ```rust //! # #[macro_use] extern crate quick_error; //! # fn main() {} //! # //! quick_error! { //! #[derive(Debug)] //! pub enum SomeError { //! Io(err: std::io::Error) { //! display("{}", err) //! } //! Utf8(err: std::str::Utf8Error) { //! display("utf8 error") //! } //! } //! } //! ``` //! //! To change `cause` method to return some error, add `cause(value)`, for //! example: //! //! ```rust //! # #[macro_use] extern crate quick_error; //! # fn main() {} //! # //! quick_error! { //! #[derive(Debug)] //! pub enum SomeError { //! Io(err: std::io::Error) { //! cause(err) //! } //! Utf8(err: std::str::Utf8Error) { //! display("utf8 error") //! } //! Other(err: Box<std::error::Error>) { //! cause(&**err) //! } //! } //! } //! ``` //! Note you don't need to wrap value in `Some`, its implicit. In case you want //! `None` returned just omit the `cause`. You can't return `None` //! conditionally. //! //! To change how each clause is `Display`ed add `display(pattern,..args)`, //! for example: //! //! ```rust //! # #[macro_use] extern crate quick_error; //! # fn main() {} //! # //! quick_error! { //! #[derive(Debug)] //! pub enum SomeError { //! Io(err: std::io::Error) { //! display("I/O error: {}", err) //! } //! Utf8(err: std::str::Utf8Error) { //! display("Utf8 error, valid up to {}", err.valid_up_to()) //! } //! } //! } //! ``` //! //! If you need a reference to the error when `Display`ing, you can instead use //! `display(x) -> (pattern, ..args)`, where `x` sets the name of the reference. //! //! ```rust //! # #[macro_use] extern crate quick_error; //! # fn main() {} //! # //! use std::error::Error; // put methods like `source()` of this trait into scope //! //! quick_error! { //! #[derive(Debug)] //! pub enum SomeError { //! Io(err: std::io::Error) { //! display(x) -> ("I/O: {}", err) //! } //! Utf8(err: std::str::Utf8Error) { //! display(self_) -> ("UTF-8 error. Valid up to {}", err.valid_up_to()) //! } //! } //! } //! ``` //! //! To convert to the type from any other, use one of the three forms of //! `from` clause. //! //! For example, to convert simple wrapper use bare `from()`: //! //! ```rust //! # #[macro_use] extern crate quick_error; //! # fn main() {} //! # //! quick_error! { //! #[derive(Debug)] //! pub enum SomeError { //! Io(err: std::io::Error) { //! from() //! } //! } //! } //! ``` //! //! This implements ``From<io::Error>``. //! //! To convert to singleton enumeration type (discarding the value), use //! the `from(type)` form: //! //! ```rust //! # #[macro_use] extern crate quick_error; //! # fn main() {} //! # //! quick_error! { //! #[derive(Debug)] //! pub enum SomeError { //! FormatError { //! from(std::fmt::Error) //! } //! } //! } //! ``` //! //! And the most powerful form is `from(var: type) -> (arguments...)`. It //! might be used to convert to type with multiple arguments or for arbitrary //! value conversions: //! //! ```rust //! # #[macro_use] extern crate quick_error; //! # fn main() {} //! # //! quick_error! { //! #[derive(Debug)] //! pub enum SomeError { //! FailedOperation(s: &'static str, errno: i32) { //! from(errno: i32) -> ("os error", errno) //! from(e: std::io::Error) -> ("io error", e.raw_os_error().unwrap()) //! } //! /// Converts from both kinds of utf8 errors //! Utf8(err: std::str::Utf8Error) { //! from() //! from(err: std::string::FromUtf8Error) -> (err.utf8_error()) //! } //! } //! } //! ``` //! # Context //! //! Since quick-error 1.1 we also have a `context` declaration, which is //! similar to (the longest form of) `from`, but allows adding some context to //! the error. We need a longer example to demonstrate this: //! //! ```rust //! # #[macro_use] extern crate quick_error; //! # use std::io; //! # use std::fs::File; //! # use std::path::{Path, PathBuf}; //! # //! use quick_error::ResultExt; //! //! quick_error! { //! #[derive(Debug)] //! pub enum Error { //! File(filename: PathBuf, err: io::Error) { //! context(path: &'a Path, err: io::Error) //! -> (path.to_path_buf(), err) //! } //! } //! } //! //! fn openfile(path: &Path) -> Result<(), Error> { //! try!(File::open(path).context(path)); //! //! // If we didn't have context, the line above would be written as; //! // //! // try!(File::open(path) //! // .map_err(|err| Error::File(path.to_path_buf(), err))); //! //! Ok(()) //! } //! //! # fn main() { //! # openfile(Path::new("/etc/somefile")).ok(); //! # } //! ``` //! //! Each `context(a: A, b: B)` clause implements //! `From<Context<A, B>> for Error`. Which means multiple `context` clauses //! are a subject to the normal coherence rules. Unfortunately, we can't //! provide full support of generics for the context, but you may either use a //! lifetime `'a` for references or `AsRef<Type>` (the latter means `A: //! AsRef<Type>`, and `Type` must be concrete). It's also occasionally useful //! to use a tuple as a type of the first argument. //! //! You also need to `use quick_error::ResultExt` extension trait to get //! working `.context()` method. //! //! More info on context in [this article](http://bit.ly/1PsuxDt). //! //! All forms of `from`, `display`, `cause`, and `context` //! clauses can be combined and put in arbitrary order. Only `from` and //! `context` can be used multiple times in single variant of enumeration. //! Docstrings are also okay. Empty braces can be omitted as of quick_error //! 0.1.3. //! //! # Private Enums //! //! Since quick-error 1.2.0 we have a way to make a private enum that is //! wrapped by public structure: //! //! ```rust //! #[macro_use] extern crate quick_error; //! # fn main() {} //! //! quick_error! { //! #[derive(Debug)] //! pub enum PubError wraps ErrorEnum { //! Variant1 {} //! } //! } //! ``` //! //! This generates data structures like this //! //! ```rust //! //! pub struct PubError(ErrorEnum); //! //! enum ErrorEnum { //! Variant1, //! } //! //! ``` //! //! Which in turn allows you to export just `PubError` in your crate and keep //! actual enumeration private to the crate. This is useful to keep backwards //! compatibility for error types. Currently there is no shorcuts to define //! error constructors for the inner type, but we consider adding some in //! future versions. //! //! It's possible to declare internal enum as public too. //! //!
/// Main macro that does all the work #[macro_export]
macro_rules! quick_error {
/// Generic context type /// /// Used mostly as a transport for `ResultExt::context` method #[derive(Debug)] pubstruct Context<X, E>(pub X, pub E);
/// Result extension trait adding a `context` method pubtrait ResultExt<T, E> { /// The method is use to add context information to current operation /// /// The context data is then used in error constructor to store additional /// information within error. For example, you may add a filename as a /// context for file operation. See crate documentation for the actual /// example. fn context<X>(self, x: X) -> Result<T, Context<X, E>>;
}
#[cfg(test)] #[allow(deprecated)] mod test { use std::num::{ParseFloatError, ParseIntError}; use std::str::Utf8Error; use std::string::FromUtf8Error; use std::error::Error; use std::path::{Path, PathBuf};
usesuper::ResultExt;
quick_error! { #[derive(Debug)] pubenum Bare {
One
Two
}
}
#[test] fn tuple_wrapper_trait_two_fields() { let invalid_utf8: Vec<u8> = vec![0, 159, 146, 150]; let cause = String::from_utf8(invalid_utf8.clone()).unwrap_err().utf8_error(); let err: &Error = &TupleWrapper::FromUtf8Error(cause.clone(), invalid_utf8.clone());
assert_eq!(format!("{}", err), format!("{desc} at index {pos}: {cause}", desc="utf8 error", pos=cause.valid_up_to(), cause=cause));
assert_eq!(format!("{:?}", err), format!("FromUtf8Error({:?}, {:?})", cause, invalid_utf8));
assert_eq!(format!("{:?}", err.cause().unwrap()), format!("{:?}", cause));
}
#[test] fn tuple_wrapper_from() { let cause = "one and a half times pi".parse::<f32>().unwrap_err(); let err = TupleWrapper::ParseFloatError(cause.clone()); let err_from: TupleWrapper = From::from(cause);
assert_eq!(err_from, err);
}
#[test] fn tuple_wrapper_custom_from() { let invalid_utf8: Vec<u8> = vec![0, 159, 146, 150]; let cause = String::from_utf8(invalid_utf8.clone()).unwrap_err(); let err = TupleWrapper::FromUtf8Error(cause.utf8_error().clone(), invalid_utf8); let err_from: TupleWrapper = From::from(cause);
assert_eq!(err_from, err);
}
¤ Diese beiden folgenden Angebotsgruppen bietet das Unternehmen0.33Angebot
(Wie Sie bei der Firma Beratungs- und Dienstleistungen beauftragen können 2026-06-19)
¤
Die Informationen auf dieser Webseite wurden
nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit,
noch Qualität der bereit gestellten Informationen zugesichert.
Bemerkung:
Die farbliche Syntaxdarstellung und die Messung sind noch experimentell.