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.
videl/src/error/wrap.rs

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
}
})
}
}