You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
118 lines
3.3 KiB
118 lines
3.3 KiB
//! Wrapping errors
|
|
use super::*;
|
|
use std::result::Result;
|
|
|
|
/// Convenienve constant for `map_msg`, used so you don't need to keep going `Option::<!>::None`.
|
|
pub const NO_MESSAGE: Option<!> = None;
|
|
|
|
/// Traits for assigning messages and context to any error that can be transformed into `ErrorKind`.
|
|
pub trait Assign<T>: Sized
|
|
{
|
|
/// Wrap an error with a context message deferred
|
|
fn wrap_err_with<F,D>(self, with: F) -> Result<T, Error>
|
|
where D: fmt::Display + Send + Sync + 'static,
|
|
F: FnOnce() -> ContextMessage<D>;
|
|
/// Wrap an error with a context message
|
|
#[inline] fn wrap_err<D>(self, with: ContextMessage<D>) -> Result<T, Error>
|
|
where D: fmt::Display + Send + Sync + 'static
|
|
{
|
|
self.wrap_err_with(|| with)
|
|
}
|
|
/// Wrap an error with a message and no context
|
|
#[inline] fn wrap_err_no_context<D>(self, with: D) -> Result<T, Error>
|
|
where D: fmt::Display + Send + Sync + 'static
|
|
{
|
|
self.wrap_err(ContextMessage::new(Default::default(), with))
|
|
}
|
|
/// Wrap an error with a message and no context deferred
|
|
#[inline] fn wrap_err_with_no_context<F, D>(self, with: F) -> Result<T, Error>
|
|
where D: fmt::Display + Send + Sync + 'static,
|
|
F: FnOnce() -> D
|
|
{
|
|
self.wrap_err_with(|| ContextMessage::new(Default::default(), with()))
|
|
}
|
|
}
|
|
|
|
impl<T> Assign<T> for Result<T,Error>
|
|
{
|
|
fn wrap_err_with<F,D>(self, with: F) -> Result<T, Error>
|
|
where D: fmt::Display + Send + Sync + 'static,
|
|
F: FnOnce() -> ContextMessage<D>
|
|
{
|
|
self.map_err(|e| {
|
|
let val = with();
|
|
Error::new(ErrorKind::Wrap(e), val.1, val.0)
|
|
})
|
|
}
|
|
}
|
|
impl<T,E> Assign<T> for Result<T,E>
|
|
where E: Into<ErrorKind>
|
|
{
|
|
fn wrap_err_with<F,D>(self, with: F) -> Result<T, Error>
|
|
where D: fmt::Display + Send + Sync + 'static,
|
|
F: FnOnce() -> ContextMessage<D>
|
|
{
|
|
self.map_err(|e| {
|
|
let val = with();
|
|
Error::new(e.into(), val.1, val.0)
|
|
})
|
|
}
|
|
}
|
|
|
|
/// Error mapping extensions
|
|
pub trait WrapErr<T>: Sized
|
|
{
|
|
|
|
/// Map the error kind
|
|
fn map_kind_with<F: FnOnce(ErrorKind) -> ErrorKind>(self, kind: F) -> Result<T,Error>;
|
|
/// Map the error kind impeatively
|
|
#[inline] fn map_kind(self, kind: ErrorKind) -> Result<T, Error>
|
|
{
|
|
self.map_kind_with(|_| kind)
|
|
}
|
|
|
|
/// Map the error message
|
|
fn map_msg_with<M, F: FnOnce(Option<Cow<'static, str>>) -> Option<M>>(self, msg: F) -> Result<T, Error>
|
|
where M: fmt::Display + Send + Sync + 'static;
|
|
/// Map the error message
|
|
#[inline] fn map_msg<M>(self, msg: M) -> Result<T, Error>
|
|
where M: fmt::Display + Send + Sync + 'static
|
|
{
|
|
self.map_msg_with(|_| Some(msg))
|
|
}
|
|
|
|
#[inline] fn map_msg_remove(self) -> Result<T, Error>
|
|
{
|
|
self.map_msg_with(|_| NO_MESSAGE)
|
|
}
|
|
}
|
|
|
|
impl<T> WrapErr<T> for Result<T,Error>
|
|
{
|
|
fn map_kind_with<F: FnOnce(ErrorKind) -> ErrorKind>(self, kind: F) -> Result<T,Error>
|
|
{
|
|
self.map_err(|err| {
|
|
Error {
|
|
internal: box kind(*err.internal),
|
|
..err
|
|
}
|
|
})
|
|
}
|
|
|
|
fn map_msg_with<M, F: FnOnce(Option<Cow<'static, str>>) -> Option<M>>(self, msg: F) -> Result<T, Error>
|
|
where M: fmt::Display + Send + Sync + 'static
|
|
{
|
|
self.map_err(|err| {
|
|
let msg = msg(err.message.into_string());
|
|
|
|
Error {
|
|
message: match msg {
|
|
Some(msg) => Message::from_other(msg),
|
|
None => Message::None,
|
|
},
|
|
..err
|
|
}
|
|
})
|
|
}
|
|
}
|