Skip to content

Commit

Permalink
switch from using eyre prototype to actual eyre (#1)
Browse files Browse the repository at this point in the history
- add ci
- update docs
- set default lints
- bump version for new release
  • Loading branch information
yaahc committed May 18, 2020
1 parent 92577f7 commit 01e30fd
Show file tree
Hide file tree
Showing 4 changed files with 241 additions and 89 deletions.
121 changes: 121 additions & 0 deletions .github/workflows/ci.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,121 @@
on:
push:
branches:
- master
pull_request: {}

name: Continuous integration

jobs:
check:
name: Check
runs-on: ubuntu-latest
strategy:
matrix:
rust:
- stable
steps:
- uses: actions/checkout@v2
- uses: actions-rs/toolchain@v1
with:
toolchain: ${{ matrix.rust }}
override: true
- uses: actions-rs/cargo@v1
with:
command: check

test-features:
name: Test Suite
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v2
- uses: actions-rs/toolchain@v1
with:
toolchain: stable
override: true
- uses: actions-rs/cargo@v1
with:
command: test
- uses: actions-rs/cargo@v1
with:
command: test
args: --all-features
- uses: actions-rs/cargo@v1
with:
command: test
args: --no-default-features

test-versions:
name: Test Suite
runs-on: ubuntu-latest
strategy:
matrix:
rust:
- stable
- beta
- nightly
- 1.39.0
steps:
- uses: actions/checkout@v2
- uses: actions-rs/toolchain@v1
with:
toolchain: ${{ matrix.rust }}
override: true
- uses: actions-rs/cargo@v1
with:
command: test

test-os:
name: Test Suite
runs-on: ${{ matrix.os }}
strategy:
matrix:
os: [ubuntu-latest, windows-latest, macOS-latest]
steps:
- uses: actions/checkout@v2
- uses: actions-rs/toolchain@v1
with:
toolchain: stable
override: true
profile: minimal
- uses: actions-rs/cargo@v1
with:
command: test

fmt:
name: Rustfmt
runs-on: ubuntu-latest
strategy:
matrix:
rust:
- stable
steps:
- uses: actions/checkout@v2
- uses: actions-rs/toolchain@v1
with:
toolchain: ${{ matrix.rust }}
override: true
- run: rustup component add rustfmt
- uses: actions-rs/cargo@v1
with:
command: fmt
args: --all -- --check

clippy:
name: Clippy
runs-on: ubuntu-latest
strategy:
matrix:
rust:
- stable
steps:
- uses: actions/checkout@v1
- uses: actions-rs/toolchain@v1
with:
toolchain: ${{ matrix.rust }}
override: true
- run: rustup component add clippy
- uses: actions-rs/cargo@v1
with:
command: clippy
args: --all-targets --all-features -- -D warnings
11 changes: 4 additions & 7 deletions Cargo.toml
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
[package]
name = "simple-eyre"
version = "0.1.0"
version = "0.2.0"
authors = ["Jane Lusby <jlusby@yaah.dev>"]
edition = "2018"
license = "MIT OR Apache-2.0"
Expand All @@ -10,12 +10,9 @@ homepage = "https://github.com/yaahc/simple-eyre"
documentation = "https://docs.rs/simple-eyre"
keywords = ["error"]
description = """
One of the simplest error types one can build ontop of eyre, including only an
inner error boxed as a trait object and a context with only a Backtrace
One of the simplest error reporters one can build ontop of eyre, defining only an error report
"""

# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html

[dependencies]
eyre-impl = "0.1.0"
thiserror = "1.0.10"
eyre = "0.4.2"
indenter = "0.3.0"
28 changes: 14 additions & 14 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -4,32 +4,33 @@ Simple-Eyre
[![Latest Version](https://img.shields.io/crates/v/simple-eyre.svg)](https://crates.io/crates/simple-eyre)
[![Rust Documentation](https://img.shields.io/badge/api-rustdoc-blue.svg)](https://docs.rs/simple-eyre)

This library provides a custom [`eyre::EyreContext`] type for usage with
[`eyre`] that provides a minimal error report with no additional context.
Essentially the minimal implementation of an error reporter.

```toml
[dependencies]
simple-eyre = "0.1"
eyre = "0.4"
simple-eyre = "0.2"
```

<br>

## Example

```rust
fn eyre::ErrReport;
use eyre::{eyre, WrapErr};
use simple_eyre::Report;

fn main() -> Result<(), Report> {
let e: Report = eyre!("oh no this program is just bad!");

fn find_git_root() -> Result<PathBuf, ErrReport> {
find_dir_in_ancestors(".git")?;
Err(e).wrap_err("usage example successfully experienced a failure")
}
```

<br>

## Details

- This library is meant to be used as a minimal example of how to use
`eyre-impl`. It implements the absolute minimum necessary to function as a
dynamic error wrapper that associates some context with it. In this case the
context is only a Backtrace.

<br>

#### License
Expand All @@ -47,6 +48,5 @@ for inclusion in this crate by you, as defined in the Apache-2.0 license, shall
be dual licensed as above, without any additional terms or conditions.
</sub>




[`eyre::EyreContext`]: https://docs.rs/eyre/*/eyre/trait.EyreContext.html
[`eyre`]: https://docs.rs/eyre
170 changes: 102 additions & 68 deletions src/lib.rs
Original file line number Diff line number Diff line change
@@ -1,82 +1,116 @@
#![feature(backtrace)]
use eyre_impl::{ErrorReporter, Indented};
use std::backtrace::{Backtrace, BacktraceStatus};
use std::fmt::{self, Write as _};

//! This library provides a custom [`eyre::EyreContext`] type for usage with [`eyre`] that provides
//! a minimal error report with no additional context. Essentially the minimal implementation of an
//! error reporter.
//!
//! # Example
//!
//! ```rust,should_panic
//! use eyre::{eyre, WrapErr};
//! use simple_eyre::Report;
//!
//! fn main() -> Result<(), Report> {
//! let e: Report = eyre!("oh no this program is just bad!");
//!
//! Err(e).wrap_err("usage example successfully experienced a failure")
//! }
//! ```
//!
//! [`eyre::EyreContext`]: https://docs.rs/eyre/*/eyre/trait.EyreContext.html
//! [`eyre`]: https://docs.rs/eyre
#![doc(html_root_url = "https://docs.rs/simple-eyre/0.2.0")]
#![warn(
missing_debug_implementations,
missing_docs,
missing_doc_code_examples,
rust_2018_idioms,
unreachable_pub,
bad_style,
const_err,
dead_code,
improper_ctypes,
non_shorthand_field_patterns,
no_mangle_generic_items,
overflowing_literals,
path_statements,
patterns_in_fns_without_body,
private_in_public,
unconditional_recursion,
unused,
unused_allocation,
unused_comparisons,
unused_parens,
while_true
)]
use eyre::Chain;
use eyre::EyreContext;
use indenter::indented;
use std::error::Error;

/// A custom context type for minimal error reporting via `eyre`
#[derive(Debug)]
pub struct BoxError(Box<dyn std::error::Error + Send + Sync + 'static>);

impl std::error::Error for BoxError {
fn source(&self) -> Option<&(dyn std::error::Error + 'static)> {
self.0.source()
}
}

impl fmt::Display for BoxError {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
fmt::Display::fmt(&self.0, f)
}
}

pub struct Context {
backtrace: Backtrace,
}

impl Default for Context {
fn default() -> Self {
Self {
backtrace: Backtrace::capture(),
}
}
}

pub struct ErrReport(ErrorReporter<BoxError, Context>);
pub struct Context;

impl<E> From<E> for ErrReport
where
E: std::error::Error + Send + Sync + 'static,
{
fn from(err: E) -> Self {
ErrReport(ErrorReporter::from(BoxError(Box::new(err))))
impl EyreContext for Context {
#[allow(unused_variables)]
fn default(error: &(dyn Error + 'static)) -> Self {
Self
}
}

impl fmt::Debug for ErrReport {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
let error = &self.0.error;
fn debug(
&self,
error: &(dyn Error + 'static),
f: &mut core::fmt::Formatter<'_>,
) -> core::fmt::Result {
use core::fmt::Write as _;

if f.alternate() {
return fmt::Debug::fmt(error, f);
}

let errors = self.0.chain().rev().enumerate();

writeln!(f)?;

for (n, error) in errors {
write!(Indented::numbered(f, n), "{}", error)?;
writeln!(f)?;
}

let backtrace = &self.0.context.backtrace;
if let BacktraceStatus::Captured = backtrace.status() {
write!(f, "\n\n{}", backtrace)?;
return core::fmt::Debug::fmt(error, f);
}

Ok(())
}
}

impl fmt::Display for ErrReport {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
write!(f, "{}", self.0.error)?;

if f.alternate() {
for cause in self.0.chain().skip(1) {
write!(f, ": {}", cause)?;
write!(f, "{}", error)?;

if let Some(cause) = error.source() {
write!(f, "\n\nCaused by:")?;
let multiple = cause.source().is_some();
for (n, error) in Chain::new(cause).enumerate() {
writeln!(f)?;
if multiple {
write!(indented(f).ind(n), "{}", error)?;
} else {
write!(indented(f), "{}", error)?;
}
}
}

Ok(())
}
}

/// A type alias for `eyre::Report<simple_eyre::Context>`
///
/// # Example
///
/// ```rust
/// use simple_eyre::Report;
///
/// # struct Config;
/// fn try_thing(path: &str) -> Result<Config, Report> {
/// // ...
/// # Ok(Config)
/// }
/// ```
pub type Report = eyre::Report<Context>;

/// A type alias for `Result<T, simple_eyre::Report>`
///
/// # Example
///
///```
/// fn main() -> simple_eyre::Result<()> {
///
/// // ...
///
/// Ok(())
/// }
/// ```
pub type Result<T, E = Report> = core::result::Result<T, E>;

0 comments on commit 01e30fd

Please sign in to comment.