Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

bigerror 0.9.x #17

Merged
merged 8 commits into from
Oct 15, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
36 changes: 20 additions & 16 deletions Cargo.toml
Original file line number Diff line number Diff line change
@@ -1,21 +1,25 @@
[package]
name = "bigerror"
version = "0.8.2"
[workspace]
members = [
"bigerror", "bigerror_derive",
]
resolver = "2"

[workspace.package]
version = "0.9.0"
edition = "2021"
description = "handle big errors ¯\\_(ツ)_/¯"
license = "MIT"
documentation = "https://docs.rs/bigerror"
repository = "https://github.com/knox-networks/bigerror"

[features]
default = ["std"]
std = ["error-stack/std", "error-stack/anyhow"]
spantrace = ["error-stack/spantrace"]
eyre = ["error-stack/eyre"]
serde = ["error-stack/serde"]
hooks = ["error-stack/hooks"]

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

[dependencies]
error-stack = "0.4.1"
thiserror = "1"
[workspace.dependencies]
derive_more = { version = "1", features = ["display"] }
tracing = "0.1"
proc-macro2 = "1.0.74"
quote = "1.0.35"
error-stack = "0.5"
syn = "2.0.46"
bigerror-derive = { path = "./bigerror_derive", version = "0.1.0" }

[workspace.lints.clippy]
unexpected_cfgs = "allow"
24 changes: 24 additions & 0 deletions bigerror/Cargo.toml
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
[package]
name = "bigerror"
version.workspace = true
edition.workspace = true
description.workspace = true
license.workspace = true
documentation.workspace = true
repository.workspace = true

[features]
default = ["std"]
std = ["error-stack/std", "error-stack/anyhow"]
spantrace = ["error-stack/spantrace"]
eyre = ["error-stack/eyre"]
serde = ["error-stack/serde"]
hooks = ["error-stack/hooks"]


[dependencies]
error-stack.workspace = true
tracing.workspace = true
bigerror-derive.workspace = true
derive_more.workspace = true

40 changes: 18 additions & 22 deletions src/attachment.rs → bigerror/src/attachment.rs
Original file line number Diff line number Diff line change
@@ -1,11 +1,7 @@
use std::{fmt, time::Duration};

use tracing::error;

use derive_more as dm;
pub use error_stack::{self, Context, Report, ResultExt};
pub use thiserror;

use crate::reportable;

pub trait Display: fmt::Display + fmt::Debug + Send + Sync + 'static {}

Expand All @@ -32,7 +28,7 @@ impl<A: Debug> fmt::Display for Dbg<A> {
}

// simple key-value pair attachment
#[derive(Debug, PartialEq)]
#[derive(Debug, PartialEq, Eq)]
pub struct KeyValue<K, V>(pub K, pub V);

impl<K: fmt::Display, V: fmt::Display> fmt::Display for KeyValue<K, V> {
Expand All @@ -42,7 +38,7 @@ impl<K: fmt::Display, V: fmt::Display> fmt::Display for KeyValue<K, V> {
}

impl<K: Display, V: Debug> KeyValue<K, Dbg<V>> {
pub fn dbg(key: K, value: V) -> Self {
pub const fn dbg(key: K, value: V) -> Self {
Self(key, Dbg(value))
}
}
Expand Down Expand Up @@ -76,13 +72,13 @@ impl<Id: Display, S: Display> fmt::Display for Field<Id, S> {
}

impl<Id: Display, S: Display> Field<Id, S> {
pub fn new(key: Id, status: S) -> Self {
pub const fn new(key: Id, status: S) -> Self {
Self { id: key, status }
}
}
/// wrapper attachment that is used to refer to the type of an object
/// rather than the value
#[derive(PartialEq)]
#[derive(PartialEq, Eq)]
pub struct Type(&'static str);

impl Type {
Expand Down Expand Up @@ -116,30 +112,29 @@ macro_rules! ty {
};
}

#[derive(Debug, thiserror::Error)]
#[error("already present")]
#[derive(Debug, dm::Display)]
#[display("already present")]
pub struct AlreadyPresent;
reportable!(AlreadyPresent);

#[derive(Debug, thiserror::Error)]
#[error("missing")]
#[derive(Debug, dm::Display)]
#[display("missing")]
pub struct Missing;

#[derive(Debug, thiserror::Error)]
#[error("unsupported")]
#[derive(Debug, dm::Display)]
#[display("unsupported")]
pub struct Unsupported;

#[derive(Debug, thiserror::Error)]
#[error("invalid")]
#[derive(Debug, dm::Display)]
#[display("invalid")]
pub struct Invalid;

#[derive(Debug, thiserror::Error)]
#[derive(Debug)]
pub struct Expectation<E, A> {
pub expected: E,
pub actual: A,
}

#[derive(Debug, thiserror::Error)]
#[derive(Debug)]
pub struct FromTo<F, T>(pub F, pub T);

#[allow(dead_code)]
Expand Down Expand Up @@ -243,6 +238,7 @@ pub fn hms_string(duration: Duration) -> String {
hms
}

#[must_use]
pub fn simple_type_name<T: ?Sized>() -> &'static str {
let full_type = std::any::type_name::<T>();
// Option<T>, [T], Vec<T>
Expand All @@ -256,8 +252,8 @@ pub fn simple_type_name<T: ?Sized>() -> &'static str {
// that the underlying `A` is being
// used as an index key for getter methods in a collection
// such as `HashMap` keys and `Vec` indices
#[derive(Debug, thiserror::Error)]
#[error("idx [{0}: {}]", simple_type_name::<I>())]
#[derive(Debug, dm::Display)]
#[display("idx [{0}: {}]", simple_type_name::<I>())]
pub struct Index<I: fmt::Display>(pub I);

#[cfg(test)]
Expand Down
121 changes: 46 additions & 75 deletions src/context.rs → bigerror/src/context.rs
Original file line number Diff line number Diff line change
@@ -1,26 +1,21 @@
use derive_more as dm;
use std::{path::Path, time::Duration};

use error_stack::Context;

use crate::{
attachment::{self, simple_type_name, Display, FromTo, Unsupported},
ty, AttachExt, Index, Report, Reportable,
ty, AttachExt, Index, Report, ThinContext,
};

use crate::{attachment::DisplayDuration, reportable, Field};
use crate::{attachment::DisplayDuration, Field};

/// Used to enacpsulate opaque `dyn std::error::Error` types
#[derive(Debug, thiserror::Error)]
#[error("{0}")]
pub struct BoxError(Box<dyn std::error::Error + 'static + Send + Sync>);
/// Used to enacpsulate opaque `dyn core::error::Error` types
#[derive(Debug, dm::Display)]
#[display("{_0}")]
pub struct BoxError(Box<dyn core::error::Error + 'static + Send + Sync>);
impl ::core::error::Error for BoxError {}

/// this is a [`BoxError`] that satistifes [`core::error::Error`]
/// using [`core::fmt::Debug`] and [`core::fmt::Display`]
#[derive(Debug, thiserror::Error)]
#[error("{0}")]
pub struct BoxCoreError(Box<dyn CoreError>);
#[derive(Debug, thiserror::Error)]
#[error("DecodeError")]
/// Represents errors emitted during while processing bytes into an object.
/// * byte types can can be represented by objects such as `&[u8]`, `bytes::Bytes`, and `Vec<u8>`
/// * used by codecs/serializers/deserializers
Expand All @@ -30,99 +25,86 @@ pub struct BoxCoreError(Box<dyn CoreError>);
/// * <https://docs.rs/tonic/latest/tonic/codec/trait.Encoder.html>
/// * <https://docs.rs/rkyv/latest/rkyv/ser/serializers/type.AllocSerializer.html>
/// * <https://docs.rs/serde/latest/serde/trait.Serializer.html>
#[derive(ThinContext)]
#[bigerror(crate)]
pub struct DecodeError;
reportable!(DecodeError);

/// Emitted while turning an object into bytes.
/// See [`DecodeError`] for more details.
#[derive(Debug, thiserror::Error)]
#[error("EncodeError")]
#[derive(ThinContext)]
#[bigerror(crate)]
pub struct EncodeError;
reportable!(EncodeError);

/// Emitted during an authorization/verification check
#[derive(Debug, thiserror::Error)]
#[error("AuthError")]
#[derive(ThinContext)]
#[bigerror(crate)]
pub struct AuthError;
reportable!(AuthError);

#[derive(Debug, thiserror::Error)]
#[error("NetworkError")]
#[derive(ThinContext)]
#[bigerror(crate)]
pub struct NetworkError;
reportable!(NetworkError);

/// Emitted while processing a string (UTF-8 or otherwise).
/// Usually associated with the [`std::str::FromStr`] trait and the `.parse::<SomeT>()` method
#[derive(Debug, thiserror::Error)]
#[error("ParseError")]
#[derive(ThinContext)]
#[bigerror(crate)]
pub struct ParseError;
reportable!(ParseError);

/// Represents the conversion of an `Option::<T>::None` into a [`Report`]
#[derive(Debug, thiserror::Error)]
#[error("NotFound")]
#[derive(ThinContext)]
#[bigerror(crate)]
pub struct NotFound;
reportable!(NotFound);

#[derive(Debug, thiserror::Error)]
#[error("DbError")]
#[derive(ThinContext)]
#[bigerror(crate)]
pub struct DbError;
reportable!(DbError);

/// An error that is related to filesystem operations such as those in [`std::fs`]
#[derive(Debug, thiserror::Error)]
#[error("FsError")]
#[derive(ThinContext)]
#[bigerror(crate)]
pub struct FsError;
reportable!(FsError);

/// Emitted during the startup/provisioning phase of a program
#[derive(Debug, thiserror::Error)]
#[error("SetupError")]
#[derive(ThinContext)]
#[bigerror(crate)]
pub struct SetupError;
reportable!(SetupError);

/// Emitted during transformations between [non scalar](https://en.wikipedia.org/w/index.php?title=Scalar_processor&useskin=vector#Scalar_data_type)
/// objects (such as structs, enums, and unions).
#[derive(Debug, thiserror::Error)]
#[error("ConversionError")]
#[derive(ThinContext)]
#[bigerror(crate)]
pub struct ConversionError;
reportable!(ConversionError);

#[derive(Debug, thiserror::Error)]
#[error("InvalidInput")]
#[derive(ThinContext)]
#[bigerror(crate)]
pub struct InvalidInput;
reportable!(InvalidInput);

#[derive(Debug, thiserror::Error)]
#[error("InvalidStatus")]
#[derive(ThinContext)]
#[bigerror(crate)]
pub struct InvalidStatus;
reportable!(InvalidStatus);

#[derive(Debug, thiserror::Error)]
#[error("InvalidState")]
#[derive(ThinContext)]
#[bigerror(crate)]
pub struct InvalidState;
reportable!(InvalidState);

/// Emitted during runtime, indicates problems with input/default settings
#[derive(Debug, thiserror::Error)]
#[error("ConfigError")]
#[derive(ThinContext)]
#[bigerror(crate)]
pub struct ConfigError;
reportable!(ConfigError);

/// Typically emitted by a `build.rs` failure
#[derive(Debug, thiserror::Error)]
#[error("BuildError")]
#[derive(ThinContext)]
#[bigerror(crate)]
pub struct BuildError;
reportable!(BuildError);

#[derive(Debug, thiserror::Error)]
#[error("{}", Field::new("timeout", DisplayDuration(*.0)))]
#[derive(Debug, dm::Display)]
#[display("{}", Field::new("timeout", DisplayDuration(self.0)))]
pub struct Timeout(pub Duration);
impl ::core::error::Error for Timeout {}

#[derive(Debug, thiserror::Error)]
#[error("AssertionError")]
#[derive(ThinContext)]
#[bigerror(crate)]
pub struct AssertionError;
reportable!(AssertionError);

pub trait CoreError: core::fmt::Debug + core::fmt::Display + Send + Sync + 'static {}

Expand All @@ -132,24 +114,13 @@ impl BoxError {
#[track_caller]
pub fn new<E>(err: E) -> Report<Self>
where
E: std::error::Error + 'static + Send + Sync,
E: core::error::Error + 'static + Send + Sync,
{
Report::new(Self(Box::new(err)))
}

#[track_caller]
pub fn from(err: Box<dyn std::error::Error + 'static + Send + Sync>) -> Report<Self> {
Report::new(Self(err))
}
}
impl BoxCoreError {
#[track_caller]
pub fn new<E: CoreError>(err: E) -> Report<Self> {
Report::new(Self(Box::new(err)))
}

#[track_caller]
pub fn from(err: Box<dyn CoreError>) -> Report<Self> {
pub fn from(err: Box<dyn core::error::Error + 'static + Send + Sync>) -> Report<Self> {
Report::new(Self(err))
}
}
Expand Down Expand Up @@ -191,7 +162,7 @@ impl NotFound {
}

pub fn with_index<T, K: Display>(key: K) -> Report<Self> {
Self::with_kv(Index(key), ty!(T))
Self::attach_kv(Index(key), ty!(T))
}
}

Expand Down
Loading