sett 0.4.0

Rust port of sett (data compression, encryption and transfer tool).
Documentation
//! Abstractions of what a package source must provide to be processable by sett.

use crate::zip::error::HeaderParseError;

/// Trait collection providing everything sett needs to read a package.
pub trait PackageStreamReader: tokio::io::AsyncBufRead + Unpin + Send + Sync {}

impl<T: tokio::io::AsyncBufRead + Unpin + Send + Sync> PackageStreamReader for T {}

/// Conversion to an async reader
pub trait IntoAsyncRead {
    /// Convert an object to an async reader
    fn into_async_reader(self) -> impl PackageStreamReader;
}

/// Intermediate container for 2 variants.
///
/// Used e.g. to propagate 2 error variants to a higher level error enum while
/// at the same time hide the rest of the higher level variants to
/// the implementation using [Either].
pub enum Either<A, B> {
    /// 1st variant
    Either(A),
    /// 2nd variant
    Or(B),
}

impl<B> From<HeaderParseError> for Either<HeaderParseError, B> {
    fn from(value: HeaderParseError) -> Self {
        Self::Either(value)
    }
}

/// Low level abstraction for zipped data sources.
pub trait PackageStream {
    /// Error occurring when interacting with the data source.
    type Error;
    /// This intermediate associated type is used here to avoid a
    /// return-position impl of the [`Self::open_file_header_stream`] method.
    /// If this method would have a return-position impl, the impl would
    /// capture the lifetime of &self and the compiler would require a
    /// 'static lifetime for &self:
    type FileStream: IntoAsyncRead;

    /// Open the central directory to read the ZIP archive TOC.
    ///
    /// This function should return a reader over data containing
    /// the central directory of a ZIP archive and an offset between
    /// the reader and the beginning of the ZIP archive.
    fn open_central_directory_stream(
        &self,
    ) -> impl std::future::Future<Output = Result<(impl std::io::Read + std::io::Seek, u64), Self::Error>>;

    /// Open the actual data at a given offset.
    fn open_file_header_stream(
        &self,
        offset: u64,
        total_size: u64,
    ) -> impl std::future::Future<Output = Result<Self::FileStream, Either<HeaderParseError, Self::Error>>>;

    /// Open package file as raw bytes
    fn open_raw(&self) -> impl std::future::Future<Output = Result<Self::FileStream, Self::Error>>;

    /// Returns the total size of the package stream
    fn size(&self) -> impl std::future::Future<Output = Result<u64, Self::Error>>;

    /// Provided for convenience as dependency injection.
    fn local_header_size<R: tokio::io::AsyncBufRead + Unpin>(
        reader: &mut R,
    ) -> impl std::future::Future<Output = Result<u64, HeaderParseError>> {
        crate::zip::reader::local_header_size(reader)
    }

    /// Returns package name
    fn name(&self) -> String;
}

impl IntoAsyncRead for tokio::io::Take<tokio::io::BufReader<tokio::fs::File>> {
    fn into_async_reader(self) -> impl PackageStreamReader {
        self
    }
}