1pub use std::backtrace::Backtrace;
2use std::ops::Deref;
3
4pub use anyhow::{
5 anyhow,
6 bail,
7 ensure,
8};
9pub use paste::paste;
10pub use regex::{
11 Regex,
12 RegexBuilder,
13};
14pub use thiserror::Error;
15
16pub type EmptyResult = anyhow::Result<()>;
17
18pub const BUILD_DIR: &str = "/.build/";
19pub const RUSTC_DIR: &str = "/rustc/";
20pub const GLIBC: &str = "glibc";
21
22#[derive(Debug, Error)]
28#[error(transparent)]
29pub struct AnyhowError(#[from] anyhow::Error);
30
31impl Deref for AnyhowError {
32 type Target = anyhow::Error;
33
34 fn deref(&self) -> &Self::Target {
35 &self.0
36 }
37}
38
39#[macro_export]
42macro_rules! err_impl {
43 (@hidden $errtype:ident, $item:ident, String) => {
44 paste! {
45 pub(crate) fn [<$item:snake>](in_: &str) -> anyhow::Error {
46 anyhow!{$errtype::$item(in_.into())}
47 }
48 }
49 };
50
51 (@hidden $errtype:ident, $item:ident, $($dtype:tt)::+) => {
52 paste! {
53 pub(crate) fn [<$item:snake>](in_: &$($dtype)::+) -> anyhow::Error {
54 anyhow!{$errtype::$item(in_.clone())}
55 }
56 }
57 };
58
59 ($errtype:ident,
60 $(#[$errinfo:meta] $item:ident($($dtype:tt)::+),)+
61 ) => {
62 #[derive(Debug, Error)]
63 pub(crate) enum $errtype {
64 $(#[$errinfo] $item($($dtype)::+)),+
65 }
66
67 impl $errtype {
68 $(err_impl! {@hidden $errtype, $item, $($dtype)::+})+
69 }
70 };
71}
72
73#[macro_export]
84macro_rules! skerr {
85 (@hidden $err:ident, $msg:literal, $($args:expr),*) => {
86 let bt = $err.backtrace().to_string();
87 let re = RegexBuilder::new(r"^\s+\d+(?s:.*?)(\s+at\s+.*:\d+)$")
88 .multi_line(true)
89 .build()
90 .unwrap();
91 let mut skipped_frames = 0;
92 let mut filtered_bt = re.find_iter(&bt).fold(String::new(), |mut acc, frame| {
93 let frame = frame.as_str();
94 if frame.contains(BUILD_DIR) || frame.contains(RUSTC_DIR) || frame.contains (GLIBC) {
95 skipped_frames += 1;
96 } else if !frame.is_empty() {
97 if skipped_frames == 1 {
98 acc += &format!(" -- <skipped 1 frame> --\n");
99 } else if skipped_frames > 1 {
100 acc += &format!(" -- <skipped {skipped_frames} frames> --\n");
101 }
102 acc += &format!("{frame}\n");
103 skipped_frames = 0;
104 }
105 acc
106 });
107
108 if skipped_frames == 1 {
109 filtered_bt += &format!(" -- <skipped 1 frame> --");
110 } else if skipped_frames > 1 {
111 filtered_bt += &format!(" -- <skipped {skipped_frames} frames> --");
112 }
113 error!(concat!($msg, "\n\n{}\n\nPartial Stack Trace:\n\n{}\n\n") $(, $args)*, $err, filtered_bt);
114 };
115
116 ($err:ident, $msg:literal) => {
117 skerr! {@hidden $err, $msg, };
118 };
119
120 ($err:ident, $msg:literal, $($args:expr),*) => {
121 skerr! {@hidden $err, $msg, $($args),*};
122 };
123}
124
125pub use {
126 err_impl,
127 skerr,
128};