sett 0.4.0

Rust port of sett (data compression, encryption and transfer tool).
Documentation
//! Tooling for the management of passwords and other secrets

/// In-memory encrypted secret.
///
/// The secret is encrypted in memory and decrypted only when needed.
#[derive(Clone)]
pub struct Secret(sequoia_openpgp::crypto::Password);

impl std::fmt::Debug for Secret {
    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
        write!(f, "{:?}", self.0)
    }
}
impl Secret {
    pub(crate) fn as_inner(&self) -> &sequoia_openpgp::crypto::Password {
        &self.0
    }

    /// Returns a non-encrypted, plain text copy of the secret.
    pub(crate) fn reveal(
        &self,
        description: &'static str,
    ) -> Result<String, SecretCorruptionError> {
        self.0
            .map(|s| std::str::from_utf8(s.as_ref()).map(<_ as ToString>::to_string))
            .map_err(|source_error| SecretCorruptionError {
                secret_description: description,
                source: source_error,
            })
    }
}

impl From<String> for Secret {
    fn from(s: String) -> Self {
        Self(sequoia_openpgp::crypto::Password::from(s))
    }
}

impl From<&str> for Secret {
    fn from(s: &str) -> Self {
        Self(sequoia_openpgp::crypto::Password::from(s))
    }
}

impl From<Vec<u8>> for Secret {
    fn from(v: Vec<u8>) -> Self {
        Self(sequoia_openpgp::crypto::Password::from(v))
    }
}

impl From<&[u8]> for Secret {
    fn from(v: &[u8]) -> Self {
        Self(sequoia_openpgp::crypto::Password::from(v))
    }
}

/// Error occurring when decoding a [`Secret`].
#[derive(Debug)]
pub struct SecretCorruptionError {
    /// Description of secret (e.g. "S3 secret key", "S3 access key", ...).
    pub secret_description: &'static str,
    /// Lower level cause of the error.
    pub source: std::str::Utf8Error,
}

impl std::fmt::Display for SecretCorruptionError {
    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
        write!(f, "{} conversion to utf-8 failed", self.secret_description)
    }
}
impl std::error::Error for SecretCorruptionError {
    fn source(&self) -> Option<&(dyn std::error::Error + 'static)> {
        Some(&self.source)
    }
}