err_tools 0.2.2

Helper traits and functions for building errors in rust
Documentation
Err Tools
=========

A library for simple but precise error handling.

By Matthew Stoodley

Purpose
------

'err tools' provides tools for maintaining an 'error stack' explicitly, and easily in error handling.

It provides Two Concrete Types:

* ErrorAt 
    * An Error with a file and line number
    * The error can be a simple ```&'static str```, or a 'String', or an anyhow::error.
* ErrorTrace
    * A list of 'ErrorAt's that itself implements Error

It also provides a set of macros that attach the *current line* and *current file* to the created error. These had to be macros, otherwise the line_number and file_name would be applied in the wrong place.

* ```err_at(err,?fmt_params...)!``` creates an ErrorAt with *Line* and *File* set correctly.    
    ie: ```option.ok_or(err_at!('No ingredients found'))?```
* ```err_at_res(err,?fmt_params...)``` creates an Err(ErrorAt) result with *Line* and *File* set correctly    
    ie: ```return err_at_res('A new error')```
* ```err_at_map!``` A closure to add location to the given error     
    ie: ```err.map_err(err_at_map!())```
* ```err_wrap!(err,?fmt_params...)``` Wrap the current error with another error, creating a stack trace
    ie : ```err.map_err(err_wrap!('Trying to bake a cake'))?```
    

These keep the error handling 'explicit', but out of the way.

It enables you to create errors detailed traceable errors.

Starting with the macro ```err_at``` you can make an error from a static ```&str``` or a 'format string' or any thing that implements ```[

```rust

#[macro_use]
use err_tools::{*,traceable::*};
fn do_thing()->Result<i32,AtError>{
    err_at_res!("I had {} issues", 20)
}
// The line and file where the macro is called.
let e_line = line!() - 3;
let e_file = file!();

let x = do_thing();
let err = x.err().unwrap();

assert_eq!(e_file,err.loc.file);
assert_eq!(e_line,err.loc.line);
assert_eq!(
    format!("{}:{} - I had 20 issues",e_file,e_line),
    err.to_string()
);

```

However it is designed for building a trace too. 
To build a full call stack history of the error, more info can be easily added at each return.

```rust
#[macro_use]
use err_tools::{*,traceable::*};

fn inner()->Result<i32,AtError>{
    err_at_res!("inner error")
}

fn outer()->Result<i32,TraceError>{
    inner().map_err(err_wrap!("outer error"))
}

let res = outer();
let e = res.err().unwrap();
assert_eq!(2,e.trace().len());

```

AtError implements 'into' TraceError, and the err_wrap! macro takes advantage of this.

It also works from anyhow errors, but with other error types it is better to use the err_at!


Dependencies
------------

* 'anyhow' enables handling all kinds of Errors in the stack.
* 'thiserror' provides some derivations for the display method.



ChangeLog
---------

# v0.2.2

Adds a call to 'into' inside the err_at! macro, so that if you function needs a TraceError or Anyhow::Error, that is automatically covered.

fixes err_at_map macro so that it calls the err_at function not err_at_res,  
meaning it can be used effectively inside err_map.

# v0.2.1

Removes 'op_err' and 'res_err' from OpErr, and ResErr Traits respectively, and move the implementation from the trait to Option and Result, types.  op_err should not have been used directly, now it can't be.

creates a traceable error and macros to fit with it and include the file_name and line_number.