Add `ErrorContext` extension trait to attach additional context to `Error`
This commit is contained in:
parent
a0d37fd182
commit
8d80321738
49
src/error.rs
49
src/error.rs
|
@ -7,6 +7,8 @@ use std::str::Utf8Error;
|
||||||
use std::string::String as StdString;
|
use std::string::String as StdString;
|
||||||
use std::sync::Arc;
|
use std::sync::Arc;
|
||||||
|
|
||||||
|
use crate::private::Sealed;
|
||||||
|
|
||||||
/// Error type returned by `mlua` methods.
|
/// Error type returned by `mlua` methods.
|
||||||
#[derive(Debug, Clone)]
|
#[derive(Debug, Clone)]
|
||||||
#[non_exhaustive]
|
#[non_exhaustive]
|
||||||
|
@ -190,6 +192,11 @@ pub enum Error {
|
||||||
/// error. The Rust code that originally invoked the Lua code then receives a `CallbackError`,
|
/// error. The Rust code that originally invoked the Lua code then receives a `CallbackError`,
|
||||||
/// from which the original error (and a stack traceback) can be recovered.
|
/// from which the original error (and a stack traceback) can be recovered.
|
||||||
ExternalError(Arc<dyn StdError + Send + Sync>),
|
ExternalError(Arc<dyn StdError + Send + Sync>),
|
||||||
|
/// An error with additional context.
|
||||||
|
WithContext {
|
||||||
|
context: StdString,
|
||||||
|
cause: Arc<Error>,
|
||||||
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
/// A specialized `Result` type used by `mlua`'s API.
|
/// A specialized `Result` type used by `mlua`'s API.
|
||||||
|
@ -306,6 +313,10 @@ impl fmt::Display for Error {
|
||||||
write!(fmt, "deserialize error: {err}")
|
write!(fmt, "deserialize error: {err}")
|
||||||
},
|
},
|
||||||
Error::ExternalError(ref err) => write!(fmt, "{err}"),
|
Error::ExternalError(ref err) => write!(fmt, "{err}"),
|
||||||
|
Error::WithContext { ref context, ref cause } => {
|
||||||
|
writeln!(fmt, "{context}")?;
|
||||||
|
write!(fmt, "{cause}")
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -374,6 +385,44 @@ where
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Provides the `context` method for [`Error`] and `Result<T, Error>`.
|
||||||
|
pub trait ErrorContext: Sealed {
|
||||||
|
fn context<C: fmt::Display>(self, context: C) -> Self;
|
||||||
|
fn with_context<C: fmt::Display>(self, f: impl FnOnce(&Error) -> C) -> Self;
|
||||||
|
}
|
||||||
|
|
||||||
|
impl ErrorContext for Error {
|
||||||
|
fn context<C: fmt::Display>(self, context: C) -> Self {
|
||||||
|
Error::WithContext {
|
||||||
|
context: context.to_string(),
|
||||||
|
cause: Arc::new(self),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn with_context<C: fmt::Display>(self, f: impl FnOnce(&Error) -> C) -> Self {
|
||||||
|
Error::WithContext {
|
||||||
|
context: f(&self).to_string(),
|
||||||
|
cause: Arc::new(self),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<T> ErrorContext for StdResult<T, Error> {
|
||||||
|
fn context<C: fmt::Display>(self, context: C) -> Self {
|
||||||
|
self.map_err(|err| Error::WithContext {
|
||||||
|
context: context.to_string(),
|
||||||
|
cause: Arc::new(err),
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
fn with_context<C: fmt::Display>(self, f: impl FnOnce(&Error) -> C) -> Self {
|
||||||
|
self.map_err(|err| Error::WithContext {
|
||||||
|
context: f(&err).to_string(),
|
||||||
|
cause: Arc::new(err),
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
impl std::convert::From<AddrParseError> for Error {
|
impl std::convert::From<AddrParseError> for Error {
|
||||||
fn from(err: AddrParseError) -> Self {
|
fn from(err: AddrParseError) -> Self {
|
||||||
Error::external(err)
|
Error::external(err)
|
||||||
|
|
11
src/lib.rs
11
src/lib.rs
|
@ -108,7 +108,7 @@ pub mod prelude;
|
||||||
pub use crate::{ffi::lua_CFunction, ffi::lua_State};
|
pub use crate::{ffi::lua_CFunction, ffi::lua_State};
|
||||||
|
|
||||||
pub use crate::chunk::{AsChunk, Chunk, ChunkMode};
|
pub use crate::chunk::{AsChunk, Chunk, ChunkMode};
|
||||||
pub use crate::error::{Error, ExternalError, ExternalResult, Result};
|
pub use crate::error::{Error, ErrorContext, ExternalError, ExternalResult, Result};
|
||||||
pub use crate::function::{Function, FunctionInfo};
|
pub use crate::function::{Function, FunctionInfo};
|
||||||
pub use crate::hook::{Debug, DebugEvent, DebugNames, DebugSource, DebugStack};
|
pub use crate::hook::{Debug, DebugEvent, DebugNames, DebugSource, DebugStack};
|
||||||
pub use crate::lua::{GCMode, Lua, LuaOptions};
|
pub use crate::lua::{GCMode, Lua, LuaOptions};
|
||||||
|
@ -232,3 +232,12 @@ pub use mlua_derive::chunk;
|
||||||
#[cfg(any(feature = "module", docsrs))]
|
#[cfg(any(feature = "module", docsrs))]
|
||||||
#[cfg_attr(docsrs, doc(cfg(feature = "module")))]
|
#[cfg_attr(docsrs, doc(cfg(feature = "module")))]
|
||||||
pub use mlua_derive::lua_module;
|
pub use mlua_derive::lua_module;
|
||||||
|
|
||||||
|
pub(crate) mod private {
|
||||||
|
use super::*;
|
||||||
|
|
||||||
|
pub trait Sealed {}
|
||||||
|
|
||||||
|
impl Sealed for Error {}
|
||||||
|
impl<T> Sealed for std::result::Result<T, Error> {}
|
||||||
|
}
|
||||||
|
|
|
@ -3,10 +3,10 @@
|
||||||
#[doc(no_inline)]
|
#[doc(no_inline)]
|
||||||
pub use crate::{
|
pub use crate::{
|
||||||
AnyUserData as LuaAnyUserData, AnyUserDataExt as LuaAnyUserDataExt, Chunk as LuaChunk,
|
AnyUserData as LuaAnyUserData, AnyUserDataExt as LuaAnyUserDataExt, Chunk as LuaChunk,
|
||||||
Error as LuaError, ExternalError as LuaExternalError, ExternalResult as LuaExternalResult,
|
Error as LuaError, ErrorContext as LuaErrorContext, ExternalError as LuaExternalError,
|
||||||
FromLua, FromLuaMulti, Function as LuaFunction, FunctionInfo as LuaFunctionInfo,
|
ExternalResult as LuaExternalResult, FromLua, FromLuaMulti, Function as LuaFunction,
|
||||||
GCMode as LuaGCMode, Integer as LuaInteger, IntoLua, IntoLuaMulti,
|
FunctionInfo as LuaFunctionInfo, GCMode as LuaGCMode, Integer as LuaInteger, IntoLua,
|
||||||
LightUserData as LuaLightUserData, Lua, LuaOptions, MetaMethod as LuaMetaMethod,
|
IntoLuaMulti, LightUserData as LuaLightUserData, Lua, LuaOptions, MetaMethod as LuaMetaMethod,
|
||||||
MultiValue as LuaMultiValue, Nil as LuaNil, Number as LuaNumber, RegistryKey as LuaRegistryKey,
|
MultiValue as LuaMultiValue, Nil as LuaNil, Number as LuaNumber, RegistryKey as LuaRegistryKey,
|
||||||
Result as LuaResult, StdLib as LuaStdLib, String as LuaString, Table as LuaTable,
|
Result as LuaResult, StdLib as LuaStdLib, String as LuaString, Table as LuaTable,
|
||||||
TableExt as LuaTableExt, TablePairs as LuaTablePairs, TableSequence as LuaTableSequence,
|
TableExt as LuaTableExt, TablePairs as LuaTablePairs, TableSequence as LuaTableSequence,
|
||||||
|
|
Loading…
Reference in New Issue