use crate::EncryptableKind;
use std::error::Error;
use std::fmt;
use std::io;
use std::string::FromUtf8Error;
#[derive(Debug)]
pub enum EnconError {
Encrypt(EncryptError),
Decrypt(DecryptError),
ApplyIntent {
target_kind: EncryptableKind,
source: Box<dyn Error + Send>,
},
DecryptAll {
good_keys: Vec<String>,
bad_keys: Vec<String>,
source: Box<dyn Error + Send>,
},
MapToJson(MapToJsonError),
}
impl EnconError {
pub(crate) fn apply_intent(self, target_kind: EncryptableKind) -> Self {
EnconError::ApplyIntent {
target_kind,
source: Box::new(self),
}
}
}
impl From<EncryptError> for EnconError {
fn from(source: EncryptError) -> Self {
Self::Encrypt(source)
}
}
impl From<DecryptError> for EnconError {
fn from(source: DecryptError) -> Self {
Self::Decrypt(source)
}
}
impl fmt::Display for EnconError {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
match self {
Self::Encrypt(_) => write!(f, "An error ocurred while encrypting"),
Self::Decrypt(_) => write!(f, "An error ocurred while decrypting"),
Self::ApplyIntent { target_kind, .. } => {
write!(f, "Failed to transition the field to {}", target_kind)
}
Self::DecryptAll {
good_keys,
bad_keys,
..
} => {
if bad_keys.is_empty() {
write!(
f,
"Unexpected case where decrypt-all failed, but no failed keys were found."
)
} else if good_keys.is_empty() {
write!(f, "Decrypt-all failed for all keys: {:?}.", bad_keys)
} else {
write!(
f,
"Decrypt-all failed for some keys. Good: {:?}. Bad: {:?}",
good_keys, bad_keys
)
}
}
Self::MapToJson(ref err) => match err {
MapToJsonError::ApplyRequired => write!(
f,
"Converting the Map to JSON failed due to unapplied intents"
),
_ => write!(
f,
"Converting the Map to JSON failed for a reason other than unapplied intents"
),
},
}
}
}
impl Error for EnconError {
fn source(&self) -> Option<&(dyn Error + 'static)> {
match self {
Self::Encrypt(source) => Some(&*source),
Self::Decrypt(source) => Some(&*source),
Self::ApplyIntent { source, .. } => Some(source.as_ref()),
Self::DecryptAll { source, .. } => Some(source.as_ref()),
Self::MapToJson(source) => Some(&*source),
}
}
}
#[derive(Debug)]
pub enum EncryptError {
Init,
EncryptChunk,
Write { source: io::Error },
Serialize { source: serde_json::Error },
}
impl EncryptError {
pub(crate) fn write(source: io::Error) -> Self {
Self::Write { source }
}
pub(crate) fn serialize(source: serde_json::Error) -> Self {
Self::Serialize { source }
}
}
impl fmt::Display for EncryptError {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
write!(
f,
"{}",
match self {
Self::Init => "Unable to initialize the encryption",
Self::EncryptChunk => "Unable to encrypt a chunk",
Self::Write { .. } => "An underlying IO error ocurred during encryption",
Self::Serialize { .. } => "Failed to serialize the value to JSON",
}
)
}
}
impl Error for EncryptError {
fn source(&self) -> Option<&(dyn Error + 'static)> {
match self {
Self::Write { source } => Some(&*source),
Self::Serialize { source } => Some(&*source),
_ => None,
}
}
}
#[derive(Debug)]
pub enum DecryptError {
InputTooShort,
DeriveKey,
Init,
LikelyWrongPassword,
Write { source: io::Error },
Deserialize { source: serde_json::Error },
Utf8 { source: FromUtf8Error },
}
impl DecryptError {
pub(crate) fn write(source: io::Error) -> Self {
Self::Write { source }
}
pub(crate) fn deserialize(source: serde_json::Error) -> Self {
Self::Deserialize { source }
}
pub(crate) fn utf8(source: FromUtf8Error) -> Self {
Self::Utf8 { source }
}
}
impl fmt::Display for DecryptError {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
write!(
f,
"{}",
match self {
Self::InputTooShort => "The provided input is too short to decrypt",
Self::DeriveKey => "Unable to derive a decryption key from the provided password",
Self::Init => "Unable to initialize the decryption",
Self::LikelyWrongPassword => "Unable to decrypt, likely due to an invalid password",
Self::Write { .. } => "An underlying IO error ocurred during decryption",
Self::Deserialize { .. } =>
"Failed to deserialize the encrypted value (invalid JSON)",
Self::Utf8 { .. } => "The decrypted data produced invalid UTF8 bytes",
}
)
}
}
impl Error for DecryptError {
fn source(&self) -> Option<&(dyn Error + 'static)> {
match self {
Self::Write { source } => Some(&*source),
Self::Deserialize { source } => Some(&*source),
Self::Utf8 { source } => Some(&*source),
_ => None,
}
}
}
#[derive(Debug)]
pub enum MapToJsonError {
ApplyRequired,
Serde(serde_json::Error),
}
impl fmt::Display for MapToJsonError {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
match self {
Self::ApplyRequired => write!(
f,
"You must apply all intents before converting a Map to JSON"
),
Self::Serde(_) => write!(f, "A serialization error ocurred"),
}
}
}
impl Error for MapToJsonError {
fn source(&self) -> Option<&(dyn Error + 'static)> {
match self {
Self::Serde(source) => Some(&*source),
Self::ApplyRequired => None,
}
}
}