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