Expand description
§Throw!
Throw is a new experimental rust error handling library, meant to assist and build on existing error handling systems.
Throw exports two structs, throw::ErrorPoint
and throw::Error
. throw::Error
stores a
single original_error
variable which it is created from, and then a list of ErrorPoint
s
which starts out with the original point of creation with throw!()
, and is added to every
time you propagate the error upwards with up!()
.
Throw does not replace existing error handling systems. The throw::Error
type has a type
parameter E
which represents an internal error type stored. throw::Error
just wraps your
error type and stores ErrorPoints alongside it.
Throw helps you better keep track of your errors. Instead of seeing a generic “No such file or directory” message, you get a stack trace of functions which propagated the error as well.
Instead of:
IO Error: failed to lookup address information: Name or service not known
Get:
Error: IO Error: failed to lookup address information: Name or service not known
at 79:17 in zaldinar::startup (src/startup.rs)
at 104:4 in zaldinar::startup (src/startup.rs)
at 28:17 in zaldinar_irclib (/home/daboross/Projects/Rust/zaldinar/zaldinar-irclib/src/lib.rs)
§Using throw!
The main way you use throw is through two macros, throw!()
and up!()
. throw!()
is used
when you have a regular (non-throw) result coming from some library function that you want to
propagate upwards in case of an error. up!()
is used when you have an error which was
created using throw!()
in a sub-function which you want to add an error point to and
propagate upwards.
Here’s an example of throw in action:
#[macro_use]
extern crate throw;
use std::io::prelude::*;
use std::io;
use std::fs::File;
fn read_log() -> Result<String, throw::Error<io::Error>> {
let mut file = throw!(File::open("some_file.log"));
let mut buf = String::new();
throw!(file.read_to_string(&mut buf));
Ok((buf))
}
fn do_things() -> Result<(), throw::Error<io::Error>> {
let log_contents = up!(read_log());
println!("Log contents: {}", log_contents);
Ok(())
}
fn main() {
let result = do_things();
if let Err(e) = result {
panic!("{}", e);
}
}
This simple program behaves exactly as if Result<_, io::Error>
directly when it functions
correctly. When the program encounters is when throw really shines. This will result in an
error message:
Error: No such file or directory (os error 2)
at 16:23 in main (src/main.rs)
at 9:19 in main (src/main.rs)
These stack traces are stored inside throw::Error, and are recorded automatically when
throw!()
or up!()
returns an Err value.
In each at
line, the 16:23
represents line_num:column_num
, the main
represents the
module path (for example my_program::sub_module
), and src/main.rs
represents the path of
the file in which throw!()
was used in.
Throwing directly from a function is also supported, using throw_new!()
:
fn possibly_fails() -> Result<(), throw::Error<&'static str>> {
if true {
// throw_new!() will always return directly
throw_new!("oops");
}
Ok(())
}
fn main() {
possibly_fails().unwrap()
}
called `Result::unwrap()` on an `Err` value: Error: "oops"
at 6:8 in main (src/main.rs)
throw_new!()
differs from throw!()
in that it takes a parameter directly to pass to a
throw::Error
, rather than a Result<>
to match on. throw_new!()
will always return
directly from the function.
§no_std
Throw offers support for no_std
, with the caveat that a dependency on alloc
is still
required for Vec
support. (throw
uses a Vec to store error points within an error.)
To use this feature, depend on throw
with default-features = false
:
[dependencies]
throw = { version = "0.1", default-features = "false" }
§Key/value pairs
Throw supports adding key/value pairs to errors to provide additional context information.
In order to use this, simply add any number of "key_name" => value,
arguments to any of
the macros throw exports. value
can be any integer type, float type, an &'static str
,
or an owned string.
fn possibly_fails(process_this: &str) -> Result<(), throw::Error<&'static str>> {
if true {
throw_new!("oops", "processing" => process_this.to_owned());
}
Ok(())
}
fn main() {
possibly_fails("hello").unwrap()
}
Results in:
thread 'main' panicked at 'called `Result::unwrap()` on an `Err` value: Error: "oops"
processing: hello
at 6:9 in rust_out (src/lib.rs)', libcore/result.rs:945:5
§Serde support
To have serde::{Serialize, Deserialize}
implemented on Throw types, depend on throw with
features = ["serde-1-std"]
or features = ["serde-1"]
for no-std environments.
Macros§
Structs§
- Error
- Represents an error. Stores an original error of type E, and any number of ErrorPoints at which the error was propagated.
- Error
Point - Represents a location at which an error was thrown via throw!()
- KvPair
- represent a key-value pair
Enums§
- Throw
Context Values - Types allowed to be value in the context vector
Type Aliases§
- Result
- Result alias for a result containing a throw::Error.