Initial Commit
This commit is contained in:
commit
4cb572f64c
2
.gitignore
vendored
Normal file
2
.gitignore
vendored
Normal file
@ -0,0 +1,2 @@
|
|||||||
|
/target
|
||||||
|
/Cargo.lock
|
19
Cargo.toml
Normal file
19
Cargo.toml
Normal file
@ -0,0 +1,19 @@
|
|||||||
|
[package]
|
||||||
|
name = "ctxerr"
|
||||||
|
version = "0.2.0"
|
||||||
|
authors = ["Andrey Tkachenko <andrey@aidev.ru>"]
|
||||||
|
repository = "https://github.com/andreytkachenko/ctxerr.git"
|
||||||
|
keywords = ["error", "handling", "thiserror", "context", "backtrace"]
|
||||||
|
categories = ["error-handling"]
|
||||||
|
description = "Tiny wrapper on thiserror embedding backtrace and location"
|
||||||
|
license = "MIT OR Apache-2.0"
|
||||||
|
exclude = [".gitignore", ".cargo/config", ".github/**", "codecov.yml"]
|
||||||
|
edition = "2021"
|
||||||
|
resolver = "2"
|
||||||
|
|
||||||
|
[workspace]
|
||||||
|
members = ["derive"]
|
||||||
|
|
||||||
|
[dependencies]
|
||||||
|
ctxerr_derive = {version = "0.3.0", path = "derive"}
|
||||||
|
thiserror = "1.0.39"
|
19
derive/Cargo.toml
Normal file
19
derive/Cargo.toml
Normal file
@ -0,0 +1,19 @@
|
|||||||
|
[package]
|
||||||
|
name = "ctxerr_derive"
|
||||||
|
version = "0.3.0"
|
||||||
|
authors = ["Andrey Tkachenko <andrey@aidev.ru>"]
|
||||||
|
repository = "https://github.com/andreytkachenko/ctxerr.git"
|
||||||
|
keywords = ["error", "handling", "thiserror", "context", "backtrace"]
|
||||||
|
categories = ["error-handling"]
|
||||||
|
description = "Tiny wrapper on thiserror embedding backtrace and location"
|
||||||
|
license = "MIT OR Apache-2.0"
|
||||||
|
exclude = [".gitignore", ".cargo/config", ".github/**", "codecov.yml"]
|
||||||
|
edition = "2021"
|
||||||
|
|
||||||
|
[lib]
|
||||||
|
proc-macro = true
|
||||||
|
|
||||||
|
[dependencies]
|
||||||
|
proc-macro2 = "1"
|
||||||
|
quote = "1"
|
||||||
|
syn = {version = "1", features = ["full"]}
|
76
derive/src/lib.rs
Normal file
76
derive/src/lib.rs
Normal file
@ -0,0 +1,76 @@
|
|||||||
|
#![recursion_limit = "128"]
|
||||||
|
extern crate proc_macro;
|
||||||
|
extern crate proc_macro2;
|
||||||
|
use proc_macro2::Ident;
|
||||||
|
use syn::DeriveInput;
|
||||||
|
|
||||||
|
use quote::quote;
|
||||||
|
|
||||||
|
#[proc_macro_attribute]
|
||||||
|
pub fn ctxerr(
|
||||||
|
_metadata: proc_macro::TokenStream,
|
||||||
|
input: proc_macro::TokenStream,
|
||||||
|
) -> proc_macro::TokenStream {
|
||||||
|
let ast: DeriveInput = syn::parse(input).unwrap();
|
||||||
|
let name = ast.ident.to_string();
|
||||||
|
if !name.ends_with("Kind") {
|
||||||
|
panic!("Ttypename should ends with `Kind`!");
|
||||||
|
}
|
||||||
|
|
||||||
|
let name_ident = &ast.ident;
|
||||||
|
let base_name = Ident::new(&name[0..name.len() - 4], ast.ident.span());
|
||||||
|
let tokens = quote! {
|
||||||
|
#[derive(Debug, ctxerr::thiserror::Error)]
|
||||||
|
#ast
|
||||||
|
|
||||||
|
#[derive(ctxerr::thiserror::Error)]
|
||||||
|
pub struct #base_name {
|
||||||
|
kind: #name_ident,
|
||||||
|
backtrace: Option<std::backtrace::Backtrace>,
|
||||||
|
location: Option<&'static core::panic::Location<'static>>,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl std::fmt::Debug for #base_name {
|
||||||
|
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
|
||||||
|
writeln!(f, "{:?}: {}", self.kind, self.kind)?;
|
||||||
|
if let Some(b) = &self.backtrace {
|
||||||
|
writeln!(f, "backtrace: \n{}", b)?;
|
||||||
|
}
|
||||||
|
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl std::fmt::Display for #base_name {
|
||||||
|
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
|
||||||
|
write!(f, "{:?}: {}", self.kind, self.kind)?;
|
||||||
|
if let Some(loc) = self.location {
|
||||||
|
writeln!(f, " file: {}:{}:{}", loc.file(), loc.line(), loc.column())?;
|
||||||
|
} else {
|
||||||
|
writeln!(f)?;
|
||||||
|
}
|
||||||
|
|
||||||
|
if let Some(b) = &self.backtrace {
|
||||||
|
writeln!(f, "backtrace: \n{}", b)?;
|
||||||
|
}
|
||||||
|
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<T: Into<ErrorKind>> From<T> for #base_name {
|
||||||
|
#[track_caller]
|
||||||
|
fn from(val: T) -> Self {
|
||||||
|
let b = std::backtrace::Backtrace::capture();
|
||||||
|
Self{
|
||||||
|
kind: val.into(),
|
||||||
|
backtrace: Some(std::backtrace::Backtrace::capture()),
|
||||||
|
location: Some(core::panic::Location::caller()),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
};
|
||||||
|
|
||||||
|
tokens.into()
|
||||||
|
}
|
22
examples/demo.rs
Normal file
22
examples/demo.rs
Normal file
@ -0,0 +1,22 @@
|
|||||||
|
use ctxerr_derive::ctxerr;
|
||||||
|
|
||||||
|
#[ctxerr]
|
||||||
|
pub enum ErrorKind {
|
||||||
|
#[error("Some error {0}")]
|
||||||
|
Error1(#[from] std::io::Error),
|
||||||
|
}
|
||||||
|
|
||||||
|
fn operation() -> Result<(), std::io::Error> {
|
||||||
|
std::fs::File::open("")?;
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
|
||||||
|
fn test() -> Result<(), Error> {
|
||||||
|
Ok(operation()?)
|
||||||
|
}
|
||||||
|
|
||||||
|
fn main() {
|
||||||
|
if let Err(err) = test() {
|
||||||
|
println!("{}", err);
|
||||||
|
}
|
||||||
|
}
|
2
src/lib.rs
Normal file
2
src/lib.rs
Normal file
@ -0,0 +1,2 @@
|
|||||||
|
pub use ctxerr_derive::*;
|
||||||
|
pub use thiserror;
|
Loading…
Reference in New Issue
Block a user