mirror of https://github.com/zkat/miette.git
fix: support no-std environments
This commit is contained in:
parent
df7bcfa17d
commit
243ea534e8
11
Cargo.toml
11
Cargo.toml
|
|
@ -13,9 +13,11 @@ rust-version = "1.82.0"
|
|||
exclude = ["images/", "tests/", "miette-derive/"]
|
||||
|
||||
[dependencies]
|
||||
thiserror = "2.0.11"
|
||||
miette-derive = { path = "miette-derive", version = "=7.6.0", optional = true }
|
||||
unicode-width = "0.2.0"
|
||||
unicode-width = { version = "0.2.0", default-features = false }
|
||||
cfg-if = "1.0.0"
|
||||
spin = { version = "0.9", default-features = false, features = ["mutex", "spin_mutex", "lazy"] }
|
||||
|
||||
owo-colors = { version = "4.0.0", optional = true }
|
||||
textwrap = { version = "0.16.0", default-features = false, features = ["unicode-linebreak", "unicode-width"], optional = true }
|
||||
|
|
@ -29,9 +31,11 @@ serde = { version = "1.0.196", features = ["derive"], optional = true }
|
|||
syntect = { version = "5.1.0", optional = true }
|
||||
|
||||
[dev-dependencies]
|
||||
thiserror = "2.0.11"
|
||||
semver = "1.0.21"
|
||||
|
||||
[build-dependencies]
|
||||
rustc_version = "0.2"
|
||||
|
||||
# Eyre devdeps
|
||||
futures = { version = "0.3", default-features = false }
|
||||
indenter = "0.3.3"
|
||||
|
|
@ -45,7 +49,8 @@ serde_json = "1.0.113"
|
|||
strip-ansi-escapes = "0.2.0"
|
||||
|
||||
[features]
|
||||
default = ["derive"]
|
||||
default = ["derive", "std"]
|
||||
std = ["thiserror/std", "fancy-no-syscall"]
|
||||
derive = ["dep:miette-derive"]
|
||||
no-format-args-capture = []
|
||||
fancy-base = [
|
||||
|
|
|
|||
|
|
@ -56,13 +56,13 @@ impl Code {
|
|||
let code = &code.as_ref()?.0;
|
||||
Some(match fields {
|
||||
syn::Fields::Named(_) => {
|
||||
quote! { Self::#ident { .. } => std::option::Option::Some(std::boxed::Box::new(#code)), }
|
||||
quote! { Self::#ident { .. } => Option::Some(alloc::boxed::Box::new(#code)), }
|
||||
}
|
||||
syn::Fields::Unnamed(_) => {
|
||||
quote! { Self::#ident(..) => std::option::Option::Some(std::boxed::Box::new(#code)), }
|
||||
quote! { Self::#ident(..) => Option::Some(alloc::boxed::Box::new(#code)), }
|
||||
}
|
||||
syn::Fields::Unit => {
|
||||
quote! { Self::#ident => std::option::Option::Some(std::boxed::Box::new(#code)), }
|
||||
quote! { Self::#ident => Option::Some(alloc::boxed::Box::new(#code)), }
|
||||
}
|
||||
})
|
||||
},
|
||||
|
|
@ -72,8 +72,8 @@ impl Code {
|
|||
pub(crate) fn gen_struct(&self) -> Option<TokenStream> {
|
||||
let code = &self.0;
|
||||
Some(quote! {
|
||||
fn code(&self) -> std::option::Option<std::boxed::Box<dyn std::fmt::Display + '_>> {
|
||||
std::option::Option::Some(std::boxed::Box::new(#code))
|
||||
fn code(&self) -> Option<alloc::boxed::Box<dyn core::fmt::Display + '_>> {
|
||||
Some(alloc::boxed::Box::new(#code))
|
||||
}
|
||||
})
|
||||
}
|
||||
|
|
|
|||
|
|
@ -59,7 +59,7 @@ impl DiagnosticSource {
|
|||
};
|
||||
quote! {
|
||||
Self::#ident #display_pat => {
|
||||
std::option::Option::Some(std::borrow::Borrow::borrow(#rel))
|
||||
Some(alloc::borrow::Borrow::borrow(#rel))
|
||||
}
|
||||
}
|
||||
})
|
||||
|
|
@ -70,8 +70,8 @@ impl DiagnosticSource {
|
|||
pub(crate) fn gen_struct(&self) -> Option<TokenStream> {
|
||||
let rel = &self.0;
|
||||
Some(quote! {
|
||||
fn diagnostic_source<'a>(&'a self) -> std::option::Option<&'a dyn miette::Diagnostic> {
|
||||
std::option::Option::Some(std::borrow::Borrow::borrow(&self.#rel))
|
||||
fn diagnostic_source<'a>(&'a self) -> Option<&'a dyn miette::Diagnostic> {
|
||||
Some(alloc::borrow::Borrow::borrow(&self.#rel))
|
||||
}
|
||||
})
|
||||
}
|
||||
|
|
|
|||
|
|
@ -58,34 +58,34 @@ impl WhichFn {
|
|||
pub fn signature(&self) -> TokenStream {
|
||||
match self {
|
||||
Self::Code => quote! {
|
||||
fn code(& self) -> std::option::Option<std::boxed::Box<dyn std::fmt::Display + '_>>
|
||||
fn code(& self) -> Option<alloc::boxed::Box<dyn core::fmt::Display + '_>>
|
||||
},
|
||||
Self::Help => quote! {
|
||||
fn help(& self) -> std::option::Option<std::boxed::Box<dyn std::fmt::Display + '_>>
|
||||
fn help(& self) -> Option<alloc::boxed::Box<dyn core::fmt::Display + '_>>
|
||||
},
|
||||
Self::Url => quote! {
|
||||
fn url(& self) -> std::option::Option<std::boxed::Box<dyn std::fmt::Display + '_>>
|
||||
fn url(& self) -> Option<alloc::boxed::Box<dyn core::fmt::Display + '_>>
|
||||
},
|
||||
Self::Severity => quote! {
|
||||
fn severity(&self) -> std::option::Option<miette::Severity>
|
||||
fn severity(&self) -> Option<miette::Severity>
|
||||
},
|
||||
Self::Related => quote! {
|
||||
fn related(&self) -> std::option::Option<std::boxed::Box<dyn std::iter::Iterator<Item = &dyn miette::Diagnostic> + '_>>
|
||||
fn related(&self) -> Option<alloc::boxed::Box<dyn Iterator<Item = &dyn miette::Diagnostic> + '_>>
|
||||
},
|
||||
Self::Labels => quote! {
|
||||
fn labels(&self) -> std::option::Option<std::boxed::Box<dyn std::iter::Iterator<Item = miette::LabeledSpan> + '_>>
|
||||
fn labels(&self) -> Option<alloc::boxed::Box<dyn Iterator<Item = miette::LabeledSpan> + '_>>
|
||||
},
|
||||
Self::SourceCode => quote! {
|
||||
fn source_code(&self) -> std::option::Option<&dyn miette::SourceCode>
|
||||
fn source_code(&self) -> Option<&dyn miette::SourceCode>
|
||||
},
|
||||
Self::DiagnosticSource => quote! {
|
||||
fn diagnostic_source(&self) -> std::option::Option<&dyn miette::Diagnostic>
|
||||
fn diagnostic_source(&self) -> Option<&dyn miette::Diagnostic>
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
pub fn catchall_arm(&self) -> TokenStream {
|
||||
quote! { _ => std::option::Option::None }
|
||||
quote! { _ => Option::None }
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -94,7 +94,7 @@ impl Help {
|
|||
Help::Display(display) => {
|
||||
let (fmt, args) = display.expand_shorthand_cloned(&display_members);
|
||||
Some(quote! {
|
||||
Self::#ident #display_pat => std::option::Option::Some(std::boxed::Box::new(format!(#fmt #args))),
|
||||
Self::#ident #display_pat => Option::Some(alloc::boxed::Box::new(format!(#fmt #args))),
|
||||
})
|
||||
}
|
||||
Help::Field(member, ty) => {
|
||||
|
|
@ -108,7 +108,7 @@ impl Help {
|
|||
Some(quote! {
|
||||
Self::#ident #display_pat => {
|
||||
use miette::macro_helpers::ToOption;
|
||||
miette::macro_helpers::OptionalWrapper::<#ty>::new().to_option(&#help).as_ref().map(|#var| -> std::boxed::Box<dyn std::fmt::Display + '_> { std::boxed::Box::new(format!("{}", #var)) })
|
||||
miette::macro_helpers::OptionalWrapper::<#ty>::new().to_option(&#help).as_ref().map(|#var| -> alloc::boxed::Box<dyn core::fmt::Display + '_> { alloc::boxed::Box::new(format!("{}", #var)) })
|
||||
},
|
||||
})
|
||||
}
|
||||
|
|
@ -123,21 +123,21 @@ impl Help {
|
|||
Help::Display(display) => {
|
||||
let (fmt, args) = display.expand_shorthand_cloned(&display_members);
|
||||
Some(quote! {
|
||||
fn help(&self) -> std::option::Option<std::boxed::Box<dyn std::fmt::Display + '_>> {
|
||||
fn help(&self) -> Option<alloc::boxed::Box<dyn core::fmt::Display + '_>> {
|
||||
#[allow(unused_variables, deprecated)]
|
||||
let Self #display_pat = self;
|
||||
std::option::Option::Some(std::boxed::Box::new(format!(#fmt #args)))
|
||||
Option::Some(alloc::boxed::Box::new(format!(#fmt #args)))
|
||||
}
|
||||
})
|
||||
}
|
||||
Help::Field(member, ty) => {
|
||||
let var = quote! { __miette_internal_var };
|
||||
Some(quote! {
|
||||
fn help(&self) -> std::option::Option<std::boxed::Box<dyn std::fmt::Display + '_>> {
|
||||
fn help(&self) -> Option<alloc::boxed::Box<dyn core::fmt::Display + '_>> {
|
||||
#[allow(unused_variables, deprecated)]
|
||||
let Self #display_pat = self;
|
||||
use miette::macro_helpers::ToOption;
|
||||
miette::macro_helpers::OptionalWrapper::<#ty>::new().to_option(&self.#member).as_ref().map(|#var| -> std::boxed::Box<dyn std::fmt::Display + '_> { std::boxed::Box::new(format!("{}", #var)) })
|
||||
miette::macro_helpers::OptionalWrapper::<#ty>::new().to_option(&self.#member).as_ref().map(|#var| -> alloc::boxed::Box<dyn core::fmt::Display + '_> { alloc::boxed::Box::new(format!("{}", #var)) })
|
||||
}
|
||||
})
|
||||
}
|
||||
|
|
|
|||
|
|
@ -175,9 +175,9 @@ impl Labels {
|
|||
let var = quote! { __miette_internal_var };
|
||||
let display = if let Some(display) = label {
|
||||
let (fmt, args) = display.expand_shorthand_cloned(&display_members);
|
||||
quote! { std::option::Option::Some(format!(#fmt #args)) }
|
||||
quote! { Option::Some(format!(#fmt #args)) }
|
||||
} else {
|
||||
quote! { std::option::Option::None }
|
||||
quote! { Option::None }
|
||||
};
|
||||
let ctor = if *lbl_ty == LabelType::Primary {
|
||||
quote! { miette::LabeledSpan::new_primary_with_span }
|
||||
|
|
@ -205,9 +205,9 @@ impl Labels {
|
|||
}
|
||||
let display = if let Some(display) = label {
|
||||
let (fmt, args) = display.expand_shorthand_cloned(&display_members);
|
||||
quote! { std::option::Option::Some(format!(#fmt #args)) }
|
||||
quote! { Option::Some(format!(#fmt #args)) }
|
||||
} else {
|
||||
quote! { std::option::Option::None }
|
||||
quote! { Option::None }
|
||||
};
|
||||
Some(quote! {
|
||||
.chain({
|
||||
|
|
@ -226,7 +226,7 @@ impl Labels {
|
|||
|
||||
Some(quote! {
|
||||
#[allow(unused_variables)]
|
||||
fn labels(&self) -> std::option::Option<std::boxed::Box<dyn std::iter::Iterator<Item = miette::LabeledSpan> + '_>> {
|
||||
fn labels(&self) -> Option<alloc::boxed::Box<dyn Iterator<Item = miette::LabeledSpan> + '_>> {
|
||||
use miette::macro_helpers::ToOption;
|
||||
let Self #display_pat = self;
|
||||
|
||||
|
|
@ -236,7 +236,7 @@ impl Labels {
|
|||
.into_iter()
|
||||
#(#collections_chain)*;
|
||||
|
||||
std::option::Option::Some(Box::new(labels_iter.filter(Option::is_some).map(Option::unwrap)))
|
||||
Option::Some(alloc::boxed::Box::new(labels_iter.filter(Option::is_some).map(Option::unwrap)))
|
||||
}
|
||||
})
|
||||
}
|
||||
|
|
@ -322,7 +322,7 @@ impl Labels {
|
|||
]
|
||||
.into_iter()
|
||||
#(#collections_chain)*;
|
||||
std::option::Option::Some(std::boxed::Box::new(labels_iter.filter(Option::is_some).map(Option::unwrap)))
|
||||
Option::Some(alloc::boxed::Box::new(labels_iter.filter(Option::is_some).map(Option::unwrap)))
|
||||
}
|
||||
}),
|
||||
}
|
||||
|
|
|
|||
|
|
@ -55,7 +55,7 @@ impl Related {
|
|||
};
|
||||
quote! {
|
||||
Self::#ident #display_pat => {
|
||||
std::option::Option::Some(std::boxed::Box::new(
|
||||
Option::Some(alloc::boxed::Box::new(
|
||||
#rel.iter().map(|x| -> &(dyn miette::Diagnostic) { &*x })
|
||||
))
|
||||
}
|
||||
|
|
@ -68,9 +68,9 @@ impl Related {
|
|||
pub(crate) fn gen_struct(&self) -> Option<TokenStream> {
|
||||
let rel = &self.0;
|
||||
Some(quote! {
|
||||
fn related<'a>(&'a self) -> std::option::Option<std::boxed::Box<dyn std::iter::Iterator<Item = &'a dyn miette::Diagnostic> + 'a>> {
|
||||
use ::core::borrow::Borrow;
|
||||
std::option::Option::Some(std::boxed::Box::new(
|
||||
fn related<'a>(&'a self) -> Option<alloc::boxed::Box<dyn Iterator<Item = &'a dyn miette::Diagnostic> + 'a>> {
|
||||
use alloc::borrow::Borrow;
|
||||
Option::Some(alloc::boxed::Box::new(
|
||||
self.#rel.iter().map(|x| -> &(dyn miette::Diagnostic) { &*x.borrow() })
|
||||
))
|
||||
}
|
||||
|
|
|
|||
|
|
@ -72,7 +72,7 @@ impl Severity {
|
|||
syn::Fields::Unit => quote! {},
|
||||
};
|
||||
Some(
|
||||
quote! { Self::#ident #fields => std::option::Option::Some(miette::Severity::#severity), },
|
||||
quote! { Self::#ident #fields => Option::Some(miette::Severity::#severity), },
|
||||
)
|
||||
},
|
||||
)
|
||||
|
|
|
|||
|
|
@ -74,7 +74,7 @@ impl SourceCode {
|
|||
|
||||
Some(quote! {
|
||||
#[allow(unused_variables)]
|
||||
fn source_code(&self) -> std::option::Option<&dyn miette::SourceCode> {
|
||||
fn source_code(&self) -> Option<&dyn miette::SourceCode> {
|
||||
let Self #display_pat = self;
|
||||
#ret
|
||||
}
|
||||
|
|
@ -101,7 +101,7 @@ impl SourceCode {
|
|||
}
|
||||
} else {
|
||||
quote! {
|
||||
std::option::Option::Some(#field)
|
||||
Option::Some(#field)
|
||||
}
|
||||
};
|
||||
match &fields {
|
||||
|
|
|
|||
|
|
@ -96,7 +96,7 @@ impl Url {
|
|||
}
|
||||
};
|
||||
Some(quote! {
|
||||
Self::#ident #pat => std::option::Option::Some(std::boxed::Box::new(format!(#fmt #args))),
|
||||
Self::#ident #pat => Option::Some(alloc::boxed::Box::new(format!(#fmt #args))),
|
||||
})
|
||||
},
|
||||
)
|
||||
|
|
@ -129,10 +129,10 @@ impl Url {
|
|||
}
|
||||
};
|
||||
Some(quote! {
|
||||
fn url(&self) -> std::option::Option<std::boxed::Box<dyn std::fmt::Display + '_>> {
|
||||
fn url(&self) -> Option<alloc::boxed::Box<dyn core::fmt::Display + '_>> {
|
||||
#[allow(unused_variables, deprecated)]
|
||||
let Self #pat = self;
|
||||
std::option::Option::Some(std::boxed::Box::new(format!(#fmt #args)))
|
||||
Option::Some(alloc::boxed::Box::new(format!(#fmt #args)))
|
||||
}
|
||||
})
|
||||
}
|
||||
|
|
|
|||
|
|
@ -3,8 +3,13 @@ Iterate over error `.source()` chains.
|
|||
|
||||
NOTE: This module is taken wholesale from <https://crates.io/crates/eyre>.
|
||||
*/
|
||||
extern crate alloc;
|
||||
|
||||
#[cfg(feature = "std")]
|
||||
use std::error::Error as StdError;
|
||||
use std::vec;
|
||||
#[cfg(not(feature = "std"))]
|
||||
use crate::StdError;
|
||||
use alloc::vec::{self, Vec};
|
||||
|
||||
use ChainState::*;
|
||||
|
||||
|
|
|
|||
|
|
@ -2,7 +2,10 @@
|
|||
Iterate over error `.diagnostic_source()` chains.
|
||||
*/
|
||||
|
||||
extern crate alloc;
|
||||
|
||||
use crate::protocol::Diagnostic;
|
||||
use alloc::string::ToString;
|
||||
|
||||
/// Iterator of a chain of cause errors.
|
||||
#[derive(Clone, Default)]
|
||||
|
|
@ -18,7 +21,7 @@ impl<'a> DiagnosticChain<'a> {
|
|||
}
|
||||
}
|
||||
|
||||
pub(crate) fn from_stderror(head: &'a (dyn std::error::Error + 'static)) -> Self {
|
||||
pub(crate) fn from_stderror(head: &'a (dyn crate::StdError + 'static)) -> Self {
|
||||
DiagnosticChain {
|
||||
state: Some(ErrorKind::StdError(head)),
|
||||
}
|
||||
|
|
@ -59,7 +62,7 @@ impl ExactSizeIterator for DiagnosticChain<'_> {
|
|||
#[derive(Clone)]
|
||||
pub(crate) enum ErrorKind<'a> {
|
||||
Diagnostic(&'a dyn Diagnostic),
|
||||
StdError(&'a (dyn std::error::Error + 'static)),
|
||||
StdError(&'a (dyn crate::StdError + 'static)),
|
||||
}
|
||||
|
||||
impl<'a> ErrorKind<'a> {
|
||||
|
|
@ -74,8 +77,8 @@ impl<'a> ErrorKind<'a> {
|
|||
}
|
||||
}
|
||||
|
||||
impl std::fmt::Debug for ErrorKind<'_> {
|
||||
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
|
||||
impl core::fmt::Debug for ErrorKind<'_> {
|
||||
fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
|
||||
match self {
|
||||
ErrorKind::Diagnostic(d) => d.fmt(f),
|
||||
ErrorKind::StdError(e) => e.fmt(f),
|
||||
|
|
@ -83,8 +86,8 @@ impl std::fmt::Debug for ErrorKind<'_> {
|
|||
}
|
||||
}
|
||||
|
||||
impl std::fmt::Display for ErrorKind<'_> {
|
||||
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
|
||||
impl core::fmt::Display for ErrorKind<'_> {
|
||||
fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
|
||||
match self {
|
||||
ErrorKind::Diagnostic(d) => d.fmt(f),
|
||||
ErrorKind::StdError(e) => e.fmt(f),
|
||||
|
|
|
|||
|
|
@ -1,10 +1,14 @@
|
|||
/*!
|
||||
Default trait implementations for [`Diagnostic`].
|
||||
*/
|
||||
extern crate alloc;
|
||||
|
||||
use std::{convert::Infallible, fmt::Display};
|
||||
use core::{convert::Infallible, fmt::Display};
|
||||
use alloc::boxed::Box;
|
||||
|
||||
use crate::{Diagnostic, LabeledSpan, Severity, SourceCode};
|
||||
use crate::{Diagnostic, LabeledSpan, Severity, SourceCode, StdError};
|
||||
|
||||
impl StdError for Infallible {}
|
||||
|
||||
impl Diagnostic for Infallible {
|
||||
fn code<'a>(&'a self) -> Option<Box<dyn Display + 'a>> {
|
||||
|
|
|
|||
43
src/error.rs
43
src/error.rs
|
|
@ -1,8 +1,13 @@
|
|||
use std::{
|
||||
error::Error,
|
||||
fmt::{self, Display},
|
||||
io,
|
||||
};
|
||||
extern crate alloc;
|
||||
|
||||
#[cfg(feature = "std")]
|
||||
use std::io;
|
||||
#[cfg(feature = "std")]
|
||||
use std::error::Error;
|
||||
#[cfg(not(feature = "std"))]
|
||||
use crate::StdError as Error;
|
||||
use core::fmt::{self, Display};
|
||||
use alloc::boxed::Box;
|
||||
|
||||
use crate::Diagnostic;
|
||||
|
||||
|
|
@ -11,8 +16,9 @@ Error enum for miette. Used by certain operations in the protocol.
|
|||
*/
|
||||
#[derive(Debug)]
|
||||
pub enum MietteError {
|
||||
/// Wrapper around [`std::io::Error`]. This is returned when something went
|
||||
/// Wrapper around [`io::Error`]. This is returned when something went
|
||||
/// wrong while reading a [`SourceCode`](crate::SourceCode).
|
||||
#[cfg(feature = "std")]
|
||||
IoError(io::Error),
|
||||
|
||||
/// Returned when a [`SourceSpan`](crate::SourceSpan) extends beyond the
|
||||
|
|
@ -23,6 +29,7 @@ pub enum MietteError {
|
|||
impl Display for MietteError {
|
||||
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
||||
match self {
|
||||
#[cfg(feature = "std")]
|
||||
MietteError::IoError(error) => write!(f, "{error}"),
|
||||
MietteError::OutOfBounds => {
|
||||
write!(f, "The given offset is outside the bounds of its Source")
|
||||
|
|
@ -34,12 +41,14 @@ impl Display for MietteError {
|
|||
impl Error for MietteError {
|
||||
fn source(&self) -> Option<&(dyn Error + 'static)> {
|
||||
match self {
|
||||
#[cfg(feature = "std")]
|
||||
MietteError::IoError(error) => error.source(),
|
||||
MietteError::OutOfBounds => None,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(feature = "std")]
|
||||
impl From<io::Error> for MietteError {
|
||||
fn from(value: io::Error) -> Self {
|
||||
Self::IoError(value)
|
||||
|
|
@ -49,6 +58,7 @@ impl From<io::Error> for MietteError {
|
|||
impl Diagnostic for MietteError {
|
||||
fn code<'a>(&'a self) -> Option<Box<dyn fmt::Display + 'a>> {
|
||||
match self {
|
||||
#[cfg(feature = "std")]
|
||||
MietteError::IoError(_) => Some(Box::new("miette::io_error")),
|
||||
MietteError::OutOfBounds => Some(Box::new("miette::span_out_of_bounds")),
|
||||
}
|
||||
|
|
@ -56,6 +66,7 @@ impl Diagnostic for MietteError {
|
|||
|
||||
fn help<'a>(&'a self) -> Option<Box<dyn fmt::Display + 'a>> {
|
||||
match self {
|
||||
#[cfg(feature = "std")]
|
||||
MietteError::IoError(_) => None,
|
||||
MietteError::OutOfBounds => Some(Box::new(
|
||||
"Double-check your spans. Do you have an off-by-one error?",
|
||||
|
|
@ -66,10 +77,11 @@ impl Diagnostic for MietteError {
|
|||
fn url<'a>(&'a self) -> Option<Box<dyn fmt::Display + 'a>> {
|
||||
let crate_version = env!("CARGO_PKG_VERSION");
|
||||
let variant = match self {
|
||||
#[cfg(feature = "std")]
|
||||
MietteError::IoError(_) => "#variant.IoError",
|
||||
MietteError::OutOfBounds => "#variant.OutOfBounds",
|
||||
};
|
||||
Some(Box::new(format!(
|
||||
Some(Box::new(alloc::format!(
|
||||
"https://docs.rs/miette/{}/miette/enum.MietteError.html{}",
|
||||
crate_version, variant,
|
||||
)))
|
||||
|
|
@ -78,12 +90,18 @@ impl Diagnostic for MietteError {
|
|||
|
||||
#[cfg(test)]
|
||||
pub(crate) mod tests {
|
||||
use std::{error::Error, io::ErrorKind};
|
||||
#[cfg(feature = "std")]
|
||||
use std::io::ErrorKind;
|
||||
#[cfg(not(feature = "std"))]
|
||||
use crate::StdError as Error;
|
||||
|
||||
use super::*;
|
||||
|
||||
#[derive(Debug)]
|
||||
#[cfg(feature = "std")]
|
||||
pub(crate) struct TestError(pub(crate) io::Error);
|
||||
#[cfg(not(feature = "std"))]
|
||||
pub(crate) struct TestError(pub(crate) &'static str);
|
||||
|
||||
impl Display for TestError {
|
||||
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
||||
|
|
@ -91,12 +109,21 @@ pub(crate) mod tests {
|
|||
}
|
||||
}
|
||||
|
||||
#[cfg(feature = "std")]
|
||||
impl Error for TestError {
|
||||
fn source(&self) -> Option<&(dyn Error + 'static)> {
|
||||
Some(&self.0)
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(not(feature = "std"))]
|
||||
impl Error for TestError {
|
||||
fn source(&self) -> Option<&(dyn Error + 'static)> {
|
||||
None
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(feature = "std")]
|
||||
#[test]
|
||||
fn io_error() {
|
||||
let inner_error = io::Error::new(ErrorKind::Other, "halt and catch fire");
|
||||
|
|
|
|||
|
|
@ -1,8 +1,15 @@
|
|||
extern crate alloc;
|
||||
|
||||
use super::error::{ContextError, ErrorImpl};
|
||||
use super::{Report, WrapErr};
|
||||
use core::fmt::{self, Debug, Display, Write};
|
||||
use core::convert::Infallible;
|
||||
|
||||
#[cfg(feature = "std")]
|
||||
use std::error::Error as StdError;
|
||||
#[cfg(not(feature = "std"))]
|
||||
use crate::StdError as StdError;
|
||||
use alloc::boxed::Box;
|
||||
|
||||
use crate::{Diagnostic, LabeledSpan};
|
||||
|
||||
|
|
@ -38,7 +45,7 @@ mod ext {
|
|||
}
|
||||
}
|
||||
|
||||
impl<T> WrapErr<T, std::convert::Infallible> for Option<T> {
|
||||
impl<T> WrapErr<T, Infallible> for Option<T> {
|
||||
fn wrap_err<D>(self, msg: D) -> Result<T, Report>
|
||||
where
|
||||
D: Display + Send + Sync + 'static,
|
||||
|
|
|
|||
|
|
@ -1,8 +1,14 @@
|
|||
extern crate alloc;
|
||||
|
||||
use core::any::TypeId;
|
||||
use core::fmt::{self, Debug, Display};
|
||||
use core::mem::ManuallyDrop;
|
||||
use core::ptr::{self, NonNull};
|
||||
#[cfg(feature = "std")]
|
||||
use std::error::Error as StdError;
|
||||
#[cfg(not(feature = "std"))]
|
||||
use crate::StdError as StdError;
|
||||
use alloc::boxed::Box;
|
||||
|
||||
use super::ptr::{Mut, Own, Ref};
|
||||
use super::Report;
|
||||
|
|
@ -429,7 +435,7 @@ impl Report {
|
|||
/// Construct a [`Report`] directly from an error-like type
|
||||
pub fn from_err<E>(err: E) -> Self
|
||||
where
|
||||
E: std::error::Error + Send + Sync + 'static,
|
||||
E: StdError + Send + Sync + 'static,
|
||||
{
|
||||
super::DiagnosticError(Box::new(err)).into()
|
||||
}
|
||||
|
|
@ -816,8 +822,16 @@ impl AsRef<dyn StdError> for Report {
|
|||
}
|
||||
}
|
||||
|
||||
#[cfg(feature = "std")]
|
||||
impl std::borrow::Borrow<dyn Diagnostic> for Report {
|
||||
fn borrow(&self) -> &(dyn Diagnostic + 'static) {
|
||||
self.as_ref()
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(not(feature = "std"))]
|
||||
impl core::borrow::Borrow<dyn Diagnostic> for Report {
|
||||
fn borrow(&self) -> &(dyn Diagnostic + 'static) {
|
||||
self.as_ref()
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,14 +1,21 @@
|
|||
use std::{error::Error, fmt::Display};
|
||||
extern crate alloc;
|
||||
|
||||
#[cfg(feature = "std")]
|
||||
use std::error::Error;
|
||||
#[cfg(not(feature = "std"))]
|
||||
use crate::StdError as Error;
|
||||
use core::fmt::Display;
|
||||
use alloc::boxed::Box;
|
||||
|
||||
use crate::{Diagnostic, Report};
|
||||
|
||||
/// Convenience [`Diagnostic`] that can be used as an "anonymous" wrapper for
|
||||
/// Errors. This is intended to be paired with [`IntoDiagnostic`].
|
||||
#[derive(Debug)]
|
||||
pub(crate) struct DiagnosticError(pub(crate) Box<dyn std::error::Error + Send + Sync + 'static>);
|
||||
pub(crate) struct DiagnosticError(pub(crate) Box<dyn Error + Send + Sync + 'static>);
|
||||
|
||||
impl Display for DiagnosticError {
|
||||
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
|
||||
impl core::fmt::Display for DiagnosticError {
|
||||
fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
|
||||
let msg = &self.0;
|
||||
write!(f, "{msg}")
|
||||
}
|
||||
|
|
@ -38,20 +45,31 @@ pub trait IntoDiagnostic<T, E> {
|
|||
fn into_diagnostic(self) -> Result<T, Report>;
|
||||
}
|
||||
|
||||
#[cfg(feature = "std")]
|
||||
impl<T, E: std::error::Error + Send + Sync + 'static> IntoDiagnostic<T, E> for Result<T, E> {
|
||||
fn into_diagnostic(self) -> Result<T, Report> {
|
||||
self.map_err(|e| DiagnosticError(Box::new(e)).into())
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(not(feature = "std"))]
|
||||
impl<T, E: Error + Send + Sync + 'static> IntoDiagnostic<T, E> for Result<T, E> {
|
||||
fn into_diagnostic(self) -> Result<T, Report> {
|
||||
self.map_err(|e| DiagnosticError(Box::new(e)).into())
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
#[cfg(feature = "std")]
|
||||
use std::io::{self, ErrorKind};
|
||||
|
||||
use super::*;
|
||||
|
||||
#[cfg(feature = "std")]
|
||||
use crate::error::tests::TestError;
|
||||
|
||||
#[cfg(feature = "std")]
|
||||
#[test]
|
||||
fn diagnostic_error() {
|
||||
let inner_error = io::Error::new(ErrorKind::Other, "halt and catch fire");
|
||||
|
|
|
|||
|
|
@ -45,11 +45,17 @@
|
|||
// let error = $msg;
|
||||
// (&error).miette_kind().new(error)
|
||||
|
||||
#[cfg(not(feature = "std"))]
|
||||
extern crate alloc;
|
||||
|
||||
use super::Report;
|
||||
use core::fmt::{Debug, Display};
|
||||
|
||||
use crate::Diagnostic;
|
||||
|
||||
#[cfg(not(feature = "std"))]
|
||||
use alloc::boxed::Box;
|
||||
|
||||
pub struct Adhoc;
|
||||
|
||||
pub trait AdhocKind: Sized {
|
||||
|
|
|
|||
|
|
@ -4,10 +4,16 @@
|
|||
clippy::new_ret_no_self,
|
||||
clippy::wrong_self_convention
|
||||
)]
|
||||
use core::fmt::Display;
|
||||
extern crate alloc;
|
||||
|
||||
use core::fmt::Display;
|
||||
use alloc::boxed::Box;
|
||||
|
||||
#[cfg(feature = "std")]
|
||||
use std::error::Error as StdError;
|
||||
use std::sync::OnceLock;
|
||||
#[cfg(not(feature = "std"))]
|
||||
use crate::StdError as StdError;
|
||||
use spin::Once;
|
||||
|
||||
#[allow(unreachable_pub)]
|
||||
pub use into_diagnostic::*;
|
||||
|
|
@ -61,7 +67,11 @@ unsafe impl Send for Report {}
|
|||
pub type ErrorHook =
|
||||
Box<dyn Fn(&(dyn Diagnostic + 'static)) -> Box<dyn ReportHandler> + Sync + Send + 'static>;
|
||||
|
||||
static HOOK: OnceLock<ErrorHook> = OnceLock::new();
|
||||
static HOOK: Once<ErrorHook> = Once::new();
|
||||
|
||||
fn default_hook() -> ErrorHook {
|
||||
Box::new(get_default_printer)
|
||||
}
|
||||
|
||||
/// Error indicating that [`set_hook()`] was unable to install the provided
|
||||
/// [`ErrorHook`].
|
||||
|
|
@ -81,18 +91,23 @@ impl Diagnostic for InstallError {}
|
|||
Set the error hook.
|
||||
*/
|
||||
pub fn set_hook(hook: ErrorHook) -> Result<(), InstallError> {
|
||||
HOOK.set(hook).map_err(|_| InstallError)
|
||||
HOOK.call_once(|| hook);
|
||||
Ok(())
|
||||
}
|
||||
|
||||
#[cfg_attr(track_caller, track_caller)]
|
||||
#[cfg_attr(not(track_caller), allow(unused_mut))]
|
||||
fn capture_handler(error: &(dyn Diagnostic + 'static)) -> Box<dyn ReportHandler> {
|
||||
let hook = HOOK.get_or_init(|| Box::new(get_default_printer)).as_ref();
|
||||
static DEFAULT: Once<ErrorHook> = Once::new();
|
||||
let hook = HOOK.get().unwrap_or_else(|| {
|
||||
DEFAULT.call_once(|| default_hook());
|
||||
DEFAULT.get().unwrap()
|
||||
});
|
||||
|
||||
#[cfg(track_caller)]
|
||||
{
|
||||
let mut handler = hook(error);
|
||||
handler.track_caller(std::panic::Location::caller());
|
||||
handler.track_caller(core::panic::Location::caller());
|
||||
handler
|
||||
}
|
||||
#[cfg(not(track_caller))]
|
||||
|
|
@ -193,7 +208,7 @@ pub trait ReportHandler: core::any::Any + Send + Sync {
|
|||
|
||||
/// Store the location of the caller who constructed this error report
|
||||
#[allow(unused_variables)]
|
||||
fn track_caller(&mut self, location: &'static std::panic::Location<'static>) {}
|
||||
fn track_caller(&mut self, location: &'static core::panic::Location<'static>) {}
|
||||
}
|
||||
|
||||
/// type alias for `Result<T, Report>`
|
||||
|
|
|
|||
|
|
@ -1,4 +1,8 @@
|
|||
use std::{marker::PhantomData, ptr::NonNull};
|
||||
extern crate alloc;
|
||||
|
||||
use core::marker::PhantomData;
|
||||
use core::ptr::NonNull;
|
||||
use alloc::boxed::Box;
|
||||
|
||||
#[repr(transparent)]
|
||||
/// A raw pointer that owns its pointee
|
||||
|
|
|
|||
|
|
@ -1,6 +1,14 @@
|
|||
extern crate alloc;
|
||||
|
||||
use core::fmt::{self, Debug, Display};
|
||||
|
||||
#[cfg(feature = "std")]
|
||||
use std::error::Error as StdError;
|
||||
#[cfg(not(feature = "std"))]
|
||||
use crate::StdError as StdError;
|
||||
use alloc::boxed::Box;
|
||||
use alloc::string::String;
|
||||
use alloc::vec::Vec;
|
||||
|
||||
use crate::{Diagnostic, LabeledSpan, Report, SourceCode};
|
||||
|
||||
|
|
@ -107,16 +115,6 @@ impl StdError for BoxedError {
|
|||
fn source(&self) -> Option<&(dyn StdError + 'static)> {
|
||||
self.0.source()
|
||||
}
|
||||
|
||||
fn description(&self) -> &str {
|
||||
#[allow(deprecated)]
|
||||
self.0.description()
|
||||
}
|
||||
|
||||
fn cause(&self) -> Option<&dyn StdError> {
|
||||
#[allow(deprecated)]
|
||||
self.0.cause()
|
||||
}
|
||||
}
|
||||
|
||||
pub(crate) struct WithSourceCode<E, C> {
|
||||
|
|
|
|||
|
|
@ -8,7 +8,7 @@ use crate::ReportHandler;
|
|||
use crate::ThemeCharacters;
|
||||
use crate::ThemeStyles;
|
||||
use cfg_if::cfg_if;
|
||||
use std::fmt;
|
||||
use core::fmt;
|
||||
|
||||
/// Settings to control the color format used for graphical rendering.
|
||||
#[derive(Copy, Clone, Debug, Eq, PartialEq, Default)]
|
||||
|
|
|
|||
|
|
@ -1,4 +1,7 @@
|
|||
use std::fmt;
|
||||
extern crate alloc;
|
||||
|
||||
use core::fmt;
|
||||
use alloc::vec::Vec;
|
||||
|
||||
use crate::{protocol::Diagnostic, ReportHandler};
|
||||
|
||||
|
|
@ -34,25 +37,25 @@ impl DebugReportHandler {
|
|||
diagnostic: &dyn Diagnostic,
|
||||
) -> fmt::Result {
|
||||
let mut diag = f.debug_struct("Diagnostic");
|
||||
diag.field("message", &format!("{}", diagnostic));
|
||||
diag.field("message", &alloc::format!("{}", diagnostic));
|
||||
if let Some(code) = diagnostic.code() {
|
||||
diag.field("code", &code.to_string());
|
||||
diag.field("code", &alloc::format!("{}", code));
|
||||
}
|
||||
if let Some(severity) = diagnostic.severity() {
|
||||
diag.field("severity", &format!("{:?}", severity));
|
||||
diag.field("severity", &alloc::format!("{:?}", severity));
|
||||
}
|
||||
if let Some(url) = diagnostic.url() {
|
||||
diag.field("url", &url.to_string());
|
||||
diag.field("url", &alloc::format!("{}", url));
|
||||
}
|
||||
if let Some(help) = diagnostic.help() {
|
||||
diag.field("help", &help.to_string());
|
||||
diag.field("help", &alloc::format!("{}", help));
|
||||
}
|
||||
if let Some(labels) = diagnostic.labels() {
|
||||
let labels: Vec<_> = labels.collect();
|
||||
diag.field("labels", &format!("{:?}", labels));
|
||||
diag.field("labels", &alloc::format!("{:?}", labels));
|
||||
}
|
||||
if let Some(cause) = diagnostic.diagnostic_source() {
|
||||
diag.field("caused by", &format!("{:?}", cause));
|
||||
diag.field("caused by", &alloc::format!("{:?}", cause));
|
||||
}
|
||||
diag.finish()?;
|
||||
writeln!(f)?;
|
||||
|
|
|
|||
|
|
@ -1,4 +1,7 @@
|
|||
use std::fmt::{self, Write};
|
||||
extern crate alloc;
|
||||
|
||||
use core::fmt::{self, Write};
|
||||
use alloc::string::ToString;
|
||||
|
||||
use crate::{
|
||||
diagnostic_chain::DiagnosticChain, protocol::Diagnostic, ReportHandler, Severity, SourceCode,
|
||||
|
|
|
|||
|
|
@ -1,10 +1,15 @@
|
|||
use std::fmt;
|
||||
extern crate alloc;
|
||||
|
||||
use core::fmt;
|
||||
|
||||
use unicode_width::{UnicodeWidthChar, UnicodeWidthStr};
|
||||
|
||||
use crate::diagnostic_chain::DiagnosticChain;
|
||||
use crate::protocol::{Diagnostic, Severity};
|
||||
use crate::{LabeledSpan, MietteError, ReportHandler, SourceCode, SourceSpan, SpanContents};
|
||||
use alloc::string::String;
|
||||
use alloc::vec::Vec;
|
||||
use alloc::boxed::Box;
|
||||
|
||||
/**
|
||||
[`ReportHandler`] that renders plain text and avoids extraneous graphics.
|
||||
|
|
@ -290,7 +295,7 @@ impl NarratableReportHandler {
|
|||
let context_data = source
|
||||
.read_span(context_span, self.context_lines, self.context_lines)
|
||||
.map_err(|_| fmt::Error)?;
|
||||
let context = std::str::from_utf8(context_data.data()).expect("Bad utf8 detected");
|
||||
let context = core::str::from_utf8(context_data.data()).expect("Bad utf8 detected");
|
||||
let mut line = context_data.line();
|
||||
let mut column = context_data.column();
|
||||
let mut offset = context_data.span().offset();
|
||||
|
|
|
|||
19
src/lib.rs
19
src/lib.rs
|
|
@ -1,3 +1,5 @@
|
|||
#![no_std]
|
||||
|
||||
#![deny(missing_docs, missing_debug_implementations, nonstandard_style)]
|
||||
#![warn(unreachable_pub, rust_2018_idioms)]
|
||||
#![allow(unexpected_cfgs)]
|
||||
|
|
@ -815,6 +817,23 @@
|
|||
//! and some from [`thiserror`](https://github.com/dtolnay/thiserror), also
|
||||
//! under the Apache License. Some code is taken from
|
||||
//! [`ariadne`](https://github.com/zesterer/ariadne), which is MIT licensed.
|
||||
#[cfg(feature = "std")]
|
||||
extern crate std;
|
||||
|
||||
#[cfg(feature = "std")]
|
||||
pub use std::error::Error as StdError;
|
||||
|
||||
#[cfg(not(feature = "std"))]
|
||||
/// Compatibility trait for error handling in no_std environments.
|
||||
/// This trait provides a subset of `std::error::Error` functionality
|
||||
/// suitable for no_std environments.
|
||||
pub trait StdError: core::fmt::Debug + core::fmt::Display {
|
||||
/// Returns the lower-level source of this error, if any.
|
||||
fn source(&self) -> Option<&(dyn StdError + 'static)> {
|
||||
None
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(feature = "derive")]
|
||||
pub use miette_derive::*;
|
||||
|
||||
|
|
|
|||
|
|
@ -51,6 +51,7 @@ impl ToLabeledSpan<LabeledSpan> for ToLabelSpanWrapper {
|
|||
span
|
||||
}
|
||||
}
|
||||
#[cfg(not(feature = "std"))]
|
||||
impl<T> ToLabeledSpan<T> for ToLabelSpanWrapper
|
||||
where
|
||||
T: Into<SourceSpan>,
|
||||
|
|
|
|||
|
|
@ -1,7 +1,14 @@
|
|||
use std::{
|
||||
error::Error,
|
||||
fmt::{Debug, Display},
|
||||
};
|
||||
extern crate alloc;
|
||||
|
||||
use core::fmt::{Debug, Display};
|
||||
#[cfg(feature = "std")]
|
||||
use std::error::Error;
|
||||
#[cfg(not(feature = "std"))]
|
||||
use crate::StdError as Error;
|
||||
use alloc::string::String;
|
||||
use alloc::vec::{self, Vec};
|
||||
use alloc::format;
|
||||
use alloc::boxed::Box;
|
||||
|
||||
#[cfg(feature = "serde")]
|
||||
use serde::{Deserialize, Serialize};
|
||||
|
|
@ -39,7 +46,7 @@ pub struct MietteDiagnostic {
|
|||
}
|
||||
|
||||
impl Display for MietteDiagnostic {
|
||||
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
|
||||
fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
|
||||
write!(f, "{}", &self.message)
|
||||
}
|
||||
}
|
||||
|
|
@ -183,7 +190,7 @@ impl MietteDiagnostic {
|
|||
/// assert_eq!(diag.labels, Some(vec![label]));
|
||||
/// ```
|
||||
pub fn with_label(mut self, label: impl Into<LabeledSpan>) -> Self {
|
||||
self.labels = Some(vec![label.into()]);
|
||||
self.labels = Some(Vec::from([label.into()]));
|
||||
self
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -10,8 +10,14 @@ pub struct NamedSource<S: SourceCode + 'static> {
|
|||
language: Option<String>,
|
||||
}
|
||||
|
||||
impl<S: SourceCode> std::fmt::Debug for NamedSource<S> {
|
||||
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
|
||||
extern crate alloc;
|
||||
|
||||
use alloc::string::String;
|
||||
use alloc::string::ToString;
|
||||
use alloc::boxed::Box;
|
||||
|
||||
impl<S: SourceCode> core::fmt::Debug for NamedSource<S> {
|
||||
fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
|
||||
f.debug_struct("NamedSource")
|
||||
.field("name", &self.name)
|
||||
.field("source", &"<redacted>")
|
||||
|
|
|
|||
|
|
@ -3,11 +3,15 @@ This module defines the core of the miette protocol: a series of types and
|
|||
traits that you can implement to get access to miette's (and related library's)
|
||||
full reporting and such features.
|
||||
*/
|
||||
use std::{
|
||||
fmt::{self, Display},
|
||||
fs,
|
||||
panic::Location,
|
||||
};
|
||||
extern crate alloc;
|
||||
|
||||
use core::fmt::{self, Display};
|
||||
#[cfg(feature = "std")]
|
||||
use std::fs;
|
||||
use core::panic::Location;
|
||||
use core::ops;
|
||||
use alloc::boxed::Box;
|
||||
use alloc::string::String;
|
||||
|
||||
#[cfg(feature = "serde")]
|
||||
use serde::{Deserialize, Serialize};
|
||||
|
|
@ -17,7 +21,7 @@ use crate::{DiagnosticError, MietteError};
|
|||
/// Adds rich metadata to your Error that can be used by
|
||||
/// [`Report`](crate::Report) to print really nice and human-friendly error
|
||||
/// messages.
|
||||
pub trait Diagnostic: std::error::Error {
|
||||
pub trait Diagnostic: crate::StdError {
|
||||
/// Unique diagnostic code that can be used to look up more information
|
||||
/// about this `Diagnostic`. Ideally also globally unique, and documented
|
||||
/// in the toplevel crate's documentation for easy searching. Rust path
|
||||
|
|
@ -72,14 +76,10 @@ pub trait Diagnostic: std::error::Error {
|
|||
macro_rules! box_error_impls {
|
||||
($($box_type:ty),*) => {
|
||||
$(
|
||||
impl std::error::Error for $box_type {
|
||||
fn source(&self) -> Option<&(dyn std::error::Error + 'static)> {
|
||||
impl crate::StdError for $box_type {
|
||||
fn source(&self) -> Option<&(dyn crate::StdError + 'static)> {
|
||||
(**self).source()
|
||||
}
|
||||
|
||||
fn cause(&self) -> Option<&dyn std::error::Error> {
|
||||
self.source()
|
||||
}
|
||||
}
|
||||
)*
|
||||
}
|
||||
|
|
@ -94,7 +94,7 @@ box_error_impls! {
|
|||
macro_rules! box_borrow_impls {
|
||||
($($box_type:ty),*) => {
|
||||
$(
|
||||
impl std::borrow::Borrow<dyn Diagnostic> for $box_type {
|
||||
impl core::borrow::Borrow<dyn Diagnostic> for $box_type {
|
||||
fn borrow(&self) -> &(dyn Diagnostic + 'static) {
|
||||
self.as_ref()
|
||||
}
|
||||
|
|
@ -152,7 +152,10 @@ impl From<String> for Box<dyn Diagnostic + Send + Sync> {
|
|||
fn from(s: String) -> Self {
|
||||
struct StringError(String);
|
||||
|
||||
#[cfg(feature = "std")]
|
||||
impl std::error::Error for StringError {}
|
||||
#[cfg(not(feature = "std"))]
|
||||
impl crate::StdError for StringError {}
|
||||
impl Diagnostic for StringError {}
|
||||
|
||||
impl Display for StringError {
|
||||
|
|
@ -172,6 +175,7 @@ impl From<String> for Box<dyn Diagnostic + Send + Sync> {
|
|||
}
|
||||
}
|
||||
|
||||
#[cfg(feature = "std")]
|
||||
impl From<Box<dyn std::error::Error + Send + Sync>> for Box<dyn Diagnostic + Send + Sync> {
|
||||
fn from(s: Box<dyn std::error::Error + Send + Sync>) -> Self {
|
||||
Box::new(DiagnosticError(s))
|
||||
|
|
@ -594,8 +598,8 @@ impl From<(SourceOffset, usize)> for SourceSpan {
|
|||
}
|
||||
}
|
||||
|
||||
impl From<std::ops::Range<ByteOffset>> for SourceSpan {
|
||||
fn from(range: std::ops::Range<ByteOffset>) -> Self {
|
||||
impl From<ops::Range<ByteOffset>> for SourceSpan {
|
||||
fn from(range: ops::Range<ByteOffset>) -> Self {
|
||||
Self {
|
||||
offset: range.start.into(),
|
||||
length: range.len(),
|
||||
|
|
@ -603,12 +607,12 @@ impl From<std::ops::Range<ByteOffset>> for SourceSpan {
|
|||
}
|
||||
}
|
||||
|
||||
impl From<std::ops::RangeInclusive<ByteOffset>> for SourceSpan {
|
||||
impl From<ops::RangeInclusive<ByteOffset>> for SourceSpan {
|
||||
/// # Panics
|
||||
///
|
||||
/// Panics if the total length of the inclusive range would overflow a
|
||||
/// `usize`. This will only occur with the range `0..=usize::MAX`.
|
||||
fn from(range: std::ops::RangeInclusive<ByteOffset>) -> Self {
|
||||
fn from(range: ops::RangeInclusive<ByteOffset>) -> Self {
|
||||
let (start, end) = range.clone().into_inner();
|
||||
Self {
|
||||
offset: start.into(),
|
||||
|
|
@ -715,6 +719,7 @@ impl SourceOffset {
|
|||
/// you're shipping binaries for your application, you'll want to ignore
|
||||
/// the Err case or otherwise report it.
|
||||
#[track_caller]
|
||||
#[cfg(feature = "std")]
|
||||
pub fn from_current_location() -> Result<(String, Self), MietteError> {
|
||||
let loc = Location::caller();
|
||||
Ok((
|
||||
|
|
@ -723,6 +728,15 @@ impl SourceOffset {
|
|||
.map(|txt| Self::from_location(txt, loc.line() as usize, loc.column() as usize))?,
|
||||
))
|
||||
}
|
||||
|
||||
/// Returns both the filename that was given and the offset of the caller
|
||||
/// as a [`SourceOffset`].
|
||||
///
|
||||
/// In no_std environments, this is not supported and will return an error.
|
||||
#[cfg(not(feature = "std"))]
|
||||
pub fn from_current_location() -> Result<(String, Self), MietteError> {
|
||||
Err(MietteError::OutOfBounds)
|
||||
}
|
||||
}
|
||||
|
||||
impl From<ByteOffset> for SourceOffset {
|
||||
|
|
|
|||
|
|
@ -1,7 +1,16 @@
|
|||
/*!
|
||||
Default trait implementations for [`SourceCode`].
|
||||
*/
|
||||
use std::{borrow::Cow, collections::VecDeque, fmt::Debug, sync::Arc};
|
||||
extern crate alloc;
|
||||
|
||||
use core::fmt::Debug;
|
||||
use alloc::borrow::Cow;
|
||||
use alloc::borrow::ToOwned;
|
||||
use alloc::collections::VecDeque;
|
||||
use alloc::sync::Arc;
|
||||
use alloc::string::String;
|
||||
use alloc::vec::Vec;
|
||||
use alloc::boxed::Box;
|
||||
|
||||
use crate::{MietteError, MietteSpanContents, SourceCode, SourceSpan, SpanContents};
|
||||
|
||||
|
|
@ -205,7 +214,7 @@ mod tests {
|
|||
fn basic() -> Result<(), MietteError> {
|
||||
let src = String::from("foo\n");
|
||||
let contents = src.read_span(&(0, 4).into(), 0, 0)?;
|
||||
assert_eq!("foo\n", std::str::from_utf8(contents.data()).unwrap());
|
||||
assert_eq!("foo\n", core::str::from_utf8(contents.data()).unwrap());
|
||||
assert_eq!(0, contents.line());
|
||||
assert_eq!(0, contents.column());
|
||||
Ok(())
|
||||
|
|
@ -215,7 +224,7 @@ mod tests {
|
|||
fn shifted() -> Result<(), MietteError> {
|
||||
let src = String::from("foobar");
|
||||
let contents = src.read_span(&(3, 3).into(), 1, 1)?;
|
||||
assert_eq!("foobar", std::str::from_utf8(contents.data()).unwrap());
|
||||
assert_eq!("foobar", core::str::from_utf8(contents.data()).unwrap());
|
||||
assert_eq!(0, contents.line());
|
||||
assert_eq!(0, contents.column());
|
||||
Ok(())
|
||||
|
|
@ -225,7 +234,7 @@ mod tests {
|
|||
fn middle() -> Result<(), MietteError> {
|
||||
let src = String::from("foo\nbar\nbaz\n");
|
||||
let contents = src.read_span(&(4, 4).into(), 0, 0)?;
|
||||
assert_eq!("bar\n", std::str::from_utf8(contents.data()).unwrap());
|
||||
assert_eq!("bar\n", core::str::from_utf8(contents.data()).unwrap());
|
||||
assert_eq!(1, contents.line());
|
||||
assert_eq!(0, contents.column());
|
||||
Ok(())
|
||||
|
|
@ -235,7 +244,7 @@ mod tests {
|
|||
fn middle_of_line() -> Result<(), MietteError> {
|
||||
let src = String::from("foo\nbarbar\nbaz\n");
|
||||
let contents = src.read_span(&(7, 4).into(), 0, 0)?;
|
||||
assert_eq!("bar\n", std::str::from_utf8(contents.data()).unwrap());
|
||||
assert_eq!("bar\n", core::str::from_utf8(contents.data()).unwrap());
|
||||
assert_eq!(1, contents.line());
|
||||
assert_eq!(3, contents.column());
|
||||
Ok(())
|
||||
|
|
@ -245,7 +254,7 @@ mod tests {
|
|||
fn with_crlf() -> Result<(), MietteError> {
|
||||
let src = String::from("foo\r\nbar\r\nbaz\r\n");
|
||||
let contents = src.read_span(&(5, 5).into(), 0, 0)?;
|
||||
assert_eq!("bar\r\n", std::str::from_utf8(contents.data()).unwrap());
|
||||
assert_eq!("bar\r\n", core::str::from_utf8(contents.data()).unwrap());
|
||||
assert_eq!(1, contents.line());
|
||||
assert_eq!(0, contents.column());
|
||||
Ok(())
|
||||
|
|
@ -257,7 +266,7 @@ mod tests {
|
|||
let contents = src.read_span(&(8, 3).into(), 1, 1)?;
|
||||
assert_eq!(
|
||||
"foo\nbar\nbaz\n",
|
||||
std::str::from_utf8(contents.data()).unwrap()
|
||||
core::str::from_utf8(contents.data()).unwrap()
|
||||
);
|
||||
assert_eq!(1, contents.line());
|
||||
assert_eq!(0, contents.column());
|
||||
|
|
@ -270,7 +279,7 @@ mod tests {
|
|||
let contents = src.read_span(&(9, 11).into(), 1, 1)?;
|
||||
assert_eq!(
|
||||
"\nfoo\nbar\nbaz\n\n",
|
||||
std::str::from_utf8(contents.data()).unwrap()
|
||||
core::str::from_utf8(contents.data()).unwrap()
|
||||
);
|
||||
assert_eq!(2, contents.line());
|
||||
assert_eq!(0, contents.column());
|
||||
|
|
@ -285,7 +294,7 @@ mod tests {
|
|||
let contents = src.read_span(&(2, 0).into(), 2, 2)?;
|
||||
assert_eq!(
|
||||
"one\ntwo\n\n",
|
||||
std::str::from_utf8(contents.data()).unwrap()
|
||||
core::str::from_utf8(contents.data()).unwrap()
|
||||
);
|
||||
assert_eq!(0, contents.line());
|
||||
assert_eq!(0, contents.column());
|
||||
|
|
|
|||
Loading…
Reference in New Issue