use crate::prelude::*;
use core::fmt;
pub type Result<T> = core::result::Result<T, Error>;
#[derive(Debug, thiserror::Error)]
#[non_exhaustive]
pub enum Error {
#[cfg(feature = "std")]
#[error("i/o error: {0}")]
Io(#[from] std::io::Error),
#[cfg(feature = "json")]
#[error("json error: {0}")]
Json(#[from] serde_json::Error),
#[error("utf-8 error: {0}")]
Utf8(#[from] core::str::Utf8Error),
#[error("cannot decode {key}: {message}")]
Decode {
key: String,
message: String,
},
#[error("cannot encode {key}: {message}")]
Encode {
key: String,
message: String,
},
#[error("missing key: did not find {wanted:?} in {available:?}")]
MissingKey {
wanted: Vec<String>,
available: Vec<String>,
},
#[error("duplicate key {key} in sample {sample_key}")]
DuplicateKey {
key: String,
sample_key: String,
},
#[error("refused in secure mode: {0}")]
Security(String),
#[error("subprocess failed: {0}")]
Subprocess(String),
#[error("malformed input: {0}")]
Format(String),
#[error("unsupported: {0}")]
Unsupported(String),
#[error("invalid value: {0}")]
Value(String),
#[error("empty: {0}")]
Empty(String),
#[error("{context}: {source}")]
Context {
context: String,
#[source]
source: Box<Error>,
},
}
impl Error {
pub fn format(message: impl fmt::Display) -> Self {
Error::Format(message.to_string())
}
pub fn value(message: impl fmt::Display) -> Self {
Error::Value(message.to_string())
}
pub fn unsupported(message: impl fmt::Display) -> Self {
Error::Unsupported(message.to_string())
}
pub fn decode(key: impl Into<String>, message: impl fmt::Display) -> Self {
Error::Decode { key: key.into(), message: message.to_string() }
}
pub fn encode(key: impl Into<String>, message: impl fmt::Display) -> Self {
Error::Encode { key: key.into(), message: message.to_string() }
}
pub fn context(self, context: impl fmt::Display) -> Self {
Error::Context { context: context.to_string(), source: Box::new(self) }
}
}
pub trait ResultExt<T> {
fn with_context<C: fmt::Display>(self, f: impl FnOnce() -> C) -> Result<T>;
}
impl<T, E: Into<Error>> ResultExt<T> for core::result::Result<T, E> {
fn with_context<C: fmt::Display>(self, f: impl FnOnce() -> C) -> Result<T> {
self.map_err(|e| e.into().context(f()))
}
}