diff options
Diffstat (limited to 'vendor/miette/src/eyreish/macros.rs')
-rw-r--r-- | vendor/miette/src/eyreish/macros.rs | 300 |
1 files changed, 300 insertions, 0 deletions
diff --git a/vendor/miette/src/eyreish/macros.rs b/vendor/miette/src/eyreish/macros.rs new file mode 100644 index 0000000..e13309f --- /dev/null +++ b/vendor/miette/src/eyreish/macros.rs @@ -0,0 +1,300 @@ +/// Return early with an error. +/// +/// This macro is equivalent to `return Err(From::from($err))`. +/// +/// # Example +/// +/// ``` +/// # use miette::{bail, Result}; +/// # +/// # fn has_permission(user: usize, resource: usize) -> bool { +/// # true +/// # } +/// # +/// # fn main() -> Result<()> { +/// # let user = 0; +/// # let resource = 0; +/// # +/// if !has_permission(user, resource) { +#[cfg_attr( + not(feature = "no-format-args-capture"), + doc = r#" bail!("permission denied for accessing {resource}");"# +)] +#[cfg_attr( + feature = "no-format-args-capture", + doc = r#" bail!("permission denied for accessing {}", resource);"# +)] +/// } +/// # Ok(()) +/// # } +/// ``` +/// +/// ``` +/// # use miette::{bail, Result}; +/// # use thiserror::Error; +/// # +/// # const MAX_DEPTH: usize = 1; +/// # +/// #[derive(Error, Debug)] +/// enum ScienceError { +/// #[error("recursion limit exceeded")] +/// RecursionLimitExceeded, +/// # #[error("...")] +/// # More = (stringify! { +/// ... +/// # }, 1).1, +/// } +/// +/// # fn main() -> Result<()> { +/// # let depth = 0; +/// # let err: &'static dyn std::error::Error = &ScienceError::RecursionLimitExceeded; +/// # +/// if depth > MAX_DEPTH { +/// bail!(ScienceError::RecursionLimitExceeded); +/// } +/// # Ok(()) +/// # } +/// ``` +/// +/// ``` +/// use miette::{bail, Result, Severity}; +/// +/// fn divide(x: f64, y: f64) -> Result<f64> { +/// if y.abs() < 1e-3 { +/// bail!( +/// severity = Severity::Warning, +#[cfg_attr( + not(feature = "no-format-args-capture"), + doc = r#" "dividing by value ({y}) close to 0""# +)] +#[cfg_attr( + feature = "no-format-args-capture", + doc = r#" "dividing by value ({}) close to 0", y"# +)] +/// ); +/// } +/// Ok(x / y) +/// } +/// ``` +#[macro_export] +macro_rules! bail { + ($($key:ident = $value:expr,)* $fmt:literal $($arg:tt)*) => { + return $crate::private::Err( + $crate::miette!($($key = $value,)* $fmt $($arg)*) + ); + }; + ($err:expr $(,)?) => { + return $crate::private::Err($crate::miette!($err)); + }; +} + +/// Return early with an error if a condition is not satisfied. +/// +/// This macro is equivalent to `if !$cond { return Err(From::from($err)); }`. +/// +/// Analogously to `assert!`, `ensure!` takes a condition and exits the function +/// if the condition fails. Unlike `assert!`, `ensure!` returns an `Error` +/// rather than panicking. +/// +/// # Example +/// +/// ``` +/// # use miette::{ensure, Result}; +/// # +/// # fn main() -> Result<()> { +/// # let user = 0; +/// # +/// ensure!(user == 0, "only user 0 is allowed"); +/// # Ok(()) +/// # } +/// ``` +/// +/// ``` +/// # use miette::{ensure, Result}; +/// # use thiserror::Error; +/// # +/// # const MAX_DEPTH: usize = 1; +/// # +/// #[derive(Error, Debug)] +/// enum ScienceError { +/// #[error("recursion limit exceeded")] +/// RecursionLimitExceeded, +/// # #[error("...")] +/// # More = (stringify! { +/// ... +/// # }, 1).1, +/// } +/// +/// # fn main() -> Result<()> { +/// # let depth = 0; +/// # +/// ensure!(depth <= MAX_DEPTH, ScienceError::RecursionLimitExceeded); +/// # Ok(()) +/// # } +/// ``` +/// +/// ``` +/// use miette::{ensure, Result, Severity}; +/// +/// fn divide(x: f64, y: f64) -> Result<f64> { +/// ensure!( +/// y.abs() >= 1e-3, +/// severity = Severity::Warning, +#[cfg_attr( + not(feature = "no-format-args-capture"), + doc = r#" "dividing by value ({y}) close to 0""# +)] +#[cfg_attr( + feature = "no-format-args-capture", + doc = r#" "dividing by value ({}) close to 0", y"# +)] +/// ); +/// Ok(x / y) +/// } +/// ``` +#[macro_export] +macro_rules! ensure { + ($cond:expr, $($key:ident = $value:expr,)* $fmt:literal $($arg:tt)*) => { + if !$cond { + return $crate::private::Err( + $crate::miette!($($key = $value,)* $fmt $($arg)*) + ); + } + }; + ($cond:expr, $err:expr $(,)?) => { + if !$cond { + return $crate::private::Err($crate::miette!($err)); + } + }; +} + +/// Construct an ad-hoc [`Report`]. +/// +/// # Examples +/// +/// With string literal and interpolation: +/// ``` +/// # use miette::miette; +/// let x = 1; +/// let y = 2; +#[cfg_attr( + not(feature = "no-format-args-capture"), + doc = r#"let report = miette!("{x} + {} = {z}", y, z = x + y);"# +)] +#[cfg_attr( + feature = "no-format-args-capture", + doc = r#"let report = miette!("{} + {} = {z}", x, y, z = x + y);"# +)] +/// +/// assert_eq!(report.to_string().as_str(), "1 + 2 = 3"); +/// +/// let z = x + y; +#[cfg_attr( + not(feature = "no-format-args-capture"), + doc = r#"let report = miette!("{x} + {y} = {z}");"# +)] +#[cfg_attr( + feature = "no-format-args-capture", + doc = r#"let report = miette!("{} + {} = {}", x, y, z);"# +)] +/// assert_eq!(report.to_string().as_str(), "1 + 2 = 3"); +/// ``` +/// +/// With [`diagnostic!`]-like arguments: +/// ``` +/// use miette::{miette, LabeledSpan, Severity}; +/// +/// let source = "(2 + 2".to_string(); +/// let report = miette!( +/// // Those fields are optional +/// severity = Severity::Error, +/// code = "expected::rparen", +/// help = "always close your parens", +/// labels = vec![LabeledSpan::at_offset(6, "here")], +/// url = "https://example.com", +/// // Rest of the arguments are passed to `format!` +/// // to form diagnostic message +/// "expected closing ')'" +/// ) +/// .with_source_code(source); +/// ``` +/// +/// ## `anyhow`/`eyre` Users +/// +/// You can just replace `use`s of the `anyhow!`/`eyre!` macros with `miette!`. +/// +/// [`diagnostic!`]: crate::diagnostic! +/// [`Report`]: crate::Report +#[macro_export] +macro_rules! miette { + ($($key:ident = $value:expr,)* $fmt:literal $($arg:tt)*) => { + $crate::Report::from( + $crate::diagnostic!($($key = $value,)* $fmt $($arg)*) + ) + }; + ($err:expr $(,)?) => ({ + use $crate::private::kind::*; + let error = $err; + (&error).miette_kind().new(error) + }); +} + +/// Construct a [`MietteDiagnostic`] in more user-friendly way. +/// +/// # Examples +/// ``` +/// use miette::{diagnostic, LabeledSpan, Severity}; +/// +/// let source = "(2 + 2".to_string(); +/// let diag = diagnostic!( +/// // Those fields are optional +/// severity = Severity::Error, +/// code = "expected::rparen", +/// help = "always close your parens", +/// labels = vec![LabeledSpan::at_offset(6, "here")], +/// url = "https://example.com", +/// // Rest of the arguments are passed to `format!` +/// // to form diagnostic message +/// "expected closing ')'", +/// ); +/// ``` +/// Diagnostic without any fields: +/// ``` +/// # use miette::diagnostic; +/// let x = 1; +/// let y = 2; +/// +#[cfg_attr( + not(feature = "no-format-args-capture"), + doc = r#" let diag = diagnostic!("{x} + {} = {z}", y, z = x + y);"# +)] +#[cfg_attr( + feature = "no-format-args-capture", + doc = r#" let diag = diagnostic!("{} + {} = {z}", x, y, z = x + y);"# +)] +/// assert_eq!(diag.message, "1 + 2 = 3"); +/// +/// let z = x + y; +#[cfg_attr( + not(feature = "no-format-args-capture"), + doc = r#"let diag = diagnostic!("{x} + {y} = {z}");"# +)] +#[cfg_attr( + feature = "no-format-args-capture", + doc = r#"let diag = diagnostic!("{} + {} = {}", x, y, z);"# +)] +/// assert_eq!(diag.message, "1 + 2 = 3"); +/// ``` +/// +/// [`MietteDiagnostic`]: crate::MietteDiagnostic +#[macro_export] +macro_rules! diagnostic { + ($fmt:literal $($arg:tt)*) => {{ + $crate::MietteDiagnostic::new(format!($fmt $($arg)*)) + }}; + ($($key:ident = $value:expr,)+ $fmt:literal $($arg:tt)*) => {{ + let mut diag = $crate::MietteDiagnostic::new(format!($fmt $($arg)*)); + $(diag.$key = Some($value.into());)* + diag + }}; +} |