sett 0.3.0

Rust port of sett (data compression, encryption and transfer tool).
Documentation
//! Destination types for data packages.

use std::path::{Path, PathBuf};

/// Destination type for data packages.
#[derive(Debug)]
pub enum Destination {
    /// A location in the local filesystem.
    Local(Local),
    /// Standard output
    Stdout,
    /// A location on a remote SFTP server.
    Sftp(Sftp),
    /// A location on a remote S3 compatible object store.
    S3(S3),
}

impl From<Local> for Destination {
    fn from(opts: Local) -> Self {
        Destination::Local(opts)
    }
}

impl From<Sftp> for Destination {
    fn from(sftp: Sftp) -> Self {
        Destination::Sftp(sftp)
    }
}

impl From<S3> for Destination {
    fn from(s3: S3) -> Self {
        Destination::S3(s3)
    }
}

#[derive(Debug, Clone)]
/// Local destination.
pub struct Local {
    /// Path to the directory where the data package will be stored.
    pub(crate) path: PathBuf,
    /// Name of the encrypted data package.
    pub(crate) name: Option<String>,
}

impl Local {
    /// Creates a new local destination.
    ///
    /// `path` must be a directory. If `name` is `None`, a package name will be generated.
    /// If `name` is `Some`, it will be used as the package name.
    pub fn new(path: impl Into<PathBuf>, name: Option<impl Into<String>>) -> anyhow::Result<Self> {
        Ok(Self {
            path: path.into().canonicalize()?,
            name: name.map(Into::into),
        })
    }

    pub(crate) fn package_name(
        &self,
        timestamp: &chrono::DateTime<chrono::Utc>,
        prefix: Option<&str>,
    ) -> String {
        self.name.as_ref().map_or_else(
            || crate::package::generate_package_name(timestamp, prefix),
            Into::into,
        )
    }
}

/// S3 destination.
#[derive(Debug)]
pub struct S3 {
    client: crate::remote::s3::Client,
    bucket: String,
}

impl S3 {
    /// Creates a new S3 destination.
    pub fn new(client: crate::remote::s3::Client, bucket: impl Into<String>) -> Self {
        Self {
            client,
            bucket: bucket.into(),
        }
    }

    /// Returns the S3 client.
    pub fn client(&self) -> &crate::remote::s3::Client {
        &self.client
    }

    /// Returns the bucket name.
    pub fn bucket(&self) -> &str {
        &self.bucket
    }
}

/// SFTP destination.
#[derive(Debug)]
pub struct Sftp {
    client: crate::remote::sftp::Client,
    /// Path on the remote SFTP host where encrypted files will be stored.
    base_path: PathBuf,
}

impl Sftp {
    /// Creates a new SFTP destination.
    pub fn new(client: crate::remote::sftp::Client, base_path: impl Into<PathBuf>) -> Self {
        Self {
            client,
            base_path: base_path.into(),
        }
    }

    /// Returns the SFTP client.
    pub fn client(&self) -> &crate::remote::sftp::Client {
        &self.client
    }

    /// Returns the base path.
    pub fn base_path(&self) -> &Path {
        &self.base_path
    }
}