Skip to content

Commit

Permalink
Replace failure dependency with thiserror/anyhow
Browse files Browse the repository at this point in the history
The failure crate appears to be deprecated these days and has drawbacks
including incompatibilities with std::error::Error. For users, it might
be inconvenient to have to deal with error types that don’t implement
std::error::Error.

For this reason, this replaces the failure crate entirely. In the
library part, thiserror is used instead, which also makes the generation
of the error type short and convenient (even taking care of the From
implementations), without exposing any thiserror specifics to the user.

In the example, anyhow now takes care of printing nicely formatted error
messages, including error causes and (if provided with RUST_BACKTRACE=1)
an error backtrace.
  • Loading branch information
pluehne committed Jan 17, 2021
1 parent 4465de5 commit 99f1f18
Show file tree
Hide file tree
Showing 4 changed files with 28 additions and 77 deletions.
2 changes: 2 additions & 0 deletions Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -16,9 +16,11 @@ semver = "0.9"
serde = { version = "1.0", features = ["derive"] }
serde_json = "1.0"
serde_yaml = "0.8"
thiserror = "1.0"
url = "1.7"
url_serde = "0.2"

[dev-dependencies]
anyhow = "1.0"
pretty_assertions = "0.5"
serde_test = "1.0.117"
50 changes: 12 additions & 38 deletions examples/printer.rs
Original file line number Diff line number Diff line change
@@ -1,43 +1,17 @@
use failure::Fail;
use std::{io::Write, process::exit};
use anyhow::Result;

fn main() {
fn main() -> Result<()> {
if let Some(path) = std::env::args().nth(1) {
match openapi::from_path(path) {
Ok(spec) => {
/*for (path, op) in spec.paths {
println!("{}", path);
println!("{:#?}", op);
}
for (name, definition) in spec.definitions {
println!("{}", name);
println!("{:#?}", definition);
}*/
println!("{}", openapi::to_json(&spec).unwrap());
}
Err(e) => {
let stderr = &mut ::std::io::stderr();
let errmsg = "Error writing to stderr";

writeln!(stderr, "error: {}", e).expect(errmsg);
for cause in Fail::iter_chain(&e) {
writeln!(
stderr,
"caused by: {} {}",
cause.name().unwrap_or("Error"),
cause
)
.expect(errmsg);
}

// The backtrace is not always generated. Try to run this example
// with `RUST_BACKTRACE=1`.
if let Some(backtrace) = e.cause().and_then(|cause| cause.backtrace()) {
writeln!(stderr, "backtrace: {:?}", backtrace).expect(errmsg);
}

exit(1);
}
let spec = openapi::from_path(path)?;
/*for (path, op) in spec.paths {
println!("{}", path);
println!("{:#?}", op);
}
for (name, definition) in spec.definitions {
println!("{}", name);
println!("{:#?}", definition);
}*/
println!("{}", openapi::to_json(&spec)?);
}
Ok(())
}
46 changes: 11 additions & 35 deletions src/error.rs
Original file line number Diff line number Diff line change
@@ -1,46 +1,22 @@
//! Error types

use failure::Fail;
use semver::{SemVerError, Version};
use serde_json::Error as JsonError;
use serde_yaml::Error as YamlError;
use std::io::Error as IoError;
use thiserror::Error;

/// errors that openapi functions may return
#[derive(Fail, Debug)]
#[derive(Error, Debug)]
pub enum Error {
#[fail(display = "{}", _0)]
Io(IoError),
#[fail(display = "{}", _0)]
Yaml(YamlError),
#[fail(display = "{}", _0)]
Serialize(JsonError),
#[fail(display = "{}", _0)]
SemVerError(SemVerError),
#[fail(display = "Unsupported spec file version ({})", _0)]
#[error("I/O error")]
Io(#[from] IoError),
#[error("YAML serialization or deserialization error")]
Yaml(#[from] YamlError),
#[error("JSON serialization error")]
Serialize(#[from] JsonError),
#[error("Semantic Versioning parsing error")]
SemVerError(#[from] SemVerError),
#[error("Unsupported spec file version ({0})")]
UnsupportedSpecFileVersion(Version),
}

impl From<IoError> for Error {
fn from(e: IoError) -> Self {
Error::Io(e)
}
}

impl From<YamlError> for Error {
fn from(e: YamlError) -> Self {
Error::Yaml(e)
}
}

impl From<JsonError> for Error {
fn from(e: JsonError) -> Self {
Error::Serialize(e)
}
}

impl From<SemVerError> for Error {
fn from(e: SemVerError) -> Self {
Error::SemVerError(e)
}
}
7 changes: 3 additions & 4 deletions src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -20,10 +20,9 @@
//!
//! # Errors
//!
//! Operations typically result in a `openapi::Result` Type which is an alias
//! for Rust's
//! built-in Result with the Err Type fixed to the
//! [openapi::errors::Error](errors/struct.Error.html) enum type.
//! Operations typically result in a [`Result`] type, an alias for
//! [`std::result::Result`] with the `Err` type fixed to [`Error`],
//! which implements [`std::error::Error`].
//!
use serde::{Deserialize, Serialize};
use std::{fs::File, io::Read, path::Path, result::Result as StdResult};
Expand Down

0 comments on commit 99f1f18

Please sign in to comment.