diff --git a/mla/src/helpers.rs b/mla/src/helpers.rs index d8c4396..99cebfc 100644 --- a/mla/src/helpers.rs +++ b/mla/src/helpers.rs @@ -1,3 +1,5 @@ +use crate::layers::traits::InnerReaderTrait; + use super::layers::traits::InnerWriterTrait; /// Helpers for common operation with MLA Archives use super::{ArchiveFileBlock, ArchiveFileID, ArchiveReader, ArchiveWriter, Error}; @@ -19,7 +21,7 @@ use std::io::{self, Read, Seek, Write}; /// encryption tag). /// Linear extraction avoids these costs by reading once and only once each byte, /// and by reducing the amount of seeks. -pub fn linear_extract( +pub fn linear_extract( archive: &mut ArchiveReader, export: &mut HashMap<&String, W1, S>, ) -> Result<(), Error> { diff --git a/mla/src/layers/compress.rs b/mla/src/layers/compress.rs index 209371b..bd61ed2 100644 --- a/mla/src/layers/compress.rs +++ b/mla/src/layers/compress.rs @@ -15,6 +15,8 @@ use crate::{Error, BINCODE_MAX_DESERIALIZE}; use crate::config::{ArchiveWriterConfig, ConfigResult}; use crate::errors::ConfigError; +use super::traits::InnerReaderTrait; + // ---------- Config ---------- /// A bigger value means a better compression ratio, less indexes to save (in @@ -292,7 +294,7 @@ impl<'a, R: 'a + Read> CompressionLayerReader<'a, R> { } } -impl<'a, R: 'a + Read + Seek> LayerReader<'a, R> for CompressionLayerReader<'a, R> { +impl<'a, R: 'a + InnerReaderTrait> LayerReader<'a, R> for CompressionLayerReader<'a, R> { fn into_inner(self) -> Option>> { Some(self.state.into_inner()) } diff --git a/mla/src/layers/encrypt.rs b/mla/src/layers/encrypt.rs index bbf917b..54767bc 100644 --- a/mla/src/layers/encrypt.rs +++ b/mla/src/layers/encrypt.rs @@ -16,6 +16,8 @@ use x25519_dalek::{PublicKey, StaticSecret}; use serde::{Deserialize, Serialize}; +use super::traits::InnerReaderTrait; + const CIPHER_BUF_SIZE: u64 = 4096; // This is the size of the nonce taken as input const NONCE_SIZE: usize = 8; @@ -342,7 +344,7 @@ impl<'a, R: 'a + Read + Seek> EncryptionLayerReader<'a, R> { } } -impl<'a, R: 'a + Read + Seek> LayerReader<'a, R> for EncryptionLayerReader<'a, R> { +impl<'a, R: 'a + InnerReaderTrait> LayerReader<'a, R> for EncryptionLayerReader<'a, R> { fn into_inner(self) -> Option>> { Some(self.inner) } diff --git a/mla/src/layers/raw.rs b/mla/src/layers/raw.rs index 758faa6..0035097 100644 --- a/mla/src/layers/raw.rs +++ b/mla/src/layers/raw.rs @@ -6,6 +6,8 @@ use crate::layers::traits::{ }; use crate::Error; +use super::traits::InnerReaderTrait; + // ---------- Writer ---------- /// Dummy layer, standing for the last layer (wrapping I/O) @@ -49,13 +51,13 @@ impl Write for RawLayerWriter { // ---------- Reader ---------- /// Dummy layer, standing for the last layer (wrapping I/O) -pub struct RawLayerReader { +pub struct RawLayerReader { inner: R, // Offset to use in position offset_pos: u64, } -impl RawLayerReader { +impl RawLayerReader { pub fn new(inner: R) -> Self { Self { inner, @@ -70,7 +72,7 @@ impl RawLayerReader { } } -impl<'a, R: Read + Seek> LayerReader<'a, R> for RawLayerReader { +impl<'a, R: InnerReaderTrait> LayerReader<'a, R> for RawLayerReader { fn into_inner(self) -> Option>> { None } @@ -85,7 +87,7 @@ impl<'a, R: Read + Seek> LayerReader<'a, R> for RawLayerReader { } } -impl Seek for RawLayerReader { +impl Seek for RawLayerReader { /// Offer a position relatively to `self.offset_pos` fn seek(&mut self, ask_pos: SeekFrom) -> io::Result { match ask_pos { @@ -115,7 +117,7 @@ impl Seek for RawLayerReader { } } -impl Read for RawLayerReader { +impl Read for RawLayerReader { /// Wrapper on inner fn read(&mut self, into: &mut [u8]) -> io::Result { self.inner.read(into) diff --git a/mla/src/layers/traits.rs b/mla/src/layers/traits.rs index 6f310a9..9b1dd06 100644 --- a/mla/src/layers/traits.rs +++ b/mla/src/layers/traits.rs @@ -3,7 +3,7 @@ use std::io::{Read, Seek, Write}; // Here, feature `send` is used to force `Send` on Box type // Indeed, the auto-derivation of Send is not able to automatically propagates it -// As a result, forcing `Send` on the Layers forces it on the initial `W` (writable) type +// As a result, forcing `Send` on the Layers forces it on the initial `W` (writable) and `R` (readable) types // To avoid this restriction when `Send` is not required, a feature is used /// Type alias for Layer Writer inner type @@ -43,8 +43,22 @@ pub trait LayerWriter<'a, W: InnerWriterTrait>: Write { fn finalize(&mut self) -> Result<(), Error>; } +/// Trait alias for Layer Reader readable source +// Type aliases are not yet stable +// See https://github.com/rust-lang/rust/issues/41517 +// -> use a dummy trait instead +#[cfg(not(feature = "send"))] +pub trait InnerReaderTrait: Read + Seek {} +#[cfg(not(feature = "send"))] +impl InnerReaderTrait for T {} + +#[cfg(feature = "send")] +pub trait InnerReaderTrait: Read + Seek + Send {} +#[cfg(feature = "send")] +impl InnerReaderTrait for T {} + /// Trait to be implemented by layer readers -pub trait LayerReader<'a, R: Read + Seek>: Read + Seek { +pub trait LayerReader<'a, R: InnerReaderTrait>: InnerReaderTrait { /// Unwraps the inner reader fn into_inner(self) -> Option>>; diff --git a/mla/src/lib.rs b/mla/src/lib.rs index 423a055..a5c4bdb 100644 --- a/mla/src/lib.rs +++ b/mla/src/lib.rs @@ -6,6 +6,7 @@ use std::io::{Read, Seek, SeekFrom, Write}; extern crate bitflags; use bincode::Options; use byteorder::{LittleEndian, ReadBytesExt, WriteBytesExt}; +use layers::traits::InnerReaderTrait; use serde::{Deserialize, Serialize}; pub mod layers; @@ -847,7 +848,7 @@ pub struct FileInfo { eof_offset: u64, } -pub struct ArchiveReader<'a, R: 'a + Read + Seek> { +pub struct ArchiveReader<'a, R: 'a + InnerReaderTrait> { /// MLA Archive format Reader /// User's reading configuration @@ -858,7 +859,7 @@ pub struct ArchiveReader<'a, R: 'a + Read + Seek> { metadata: Option, } -impl<'b, R: 'b + Read + Seek> ArchiveReader<'b, R> { +impl<'b, R: 'b + InnerReaderTrait> ArchiveReader<'b, R> { pub fn from_config(mut src: R, mut config: ArchiveReaderConfig) -> Result { // Make sure we read the archive header from the start src.rewind()?; @@ -2187,5 +2188,6 @@ pub(crate) mod tests { static_assertions::assert_cfg!(feature = "send"); static_assertions::assert_impl_all!(File: Send); static_assertions::assert_impl_all!(ArchiveWriter: Send); + static_assertions::assert_impl_all!(ArchiveReader: Send); } } diff --git a/mlar/src/main.rs b/mlar/src/main.rs index 5641c8d..cf0d138 100644 --- a/mlar/src/main.rs +++ b/mlar/src/main.rs @@ -12,7 +12,7 @@ use mla::helpers::linear_extract; use mla::layers::compress::CompressionLayerReader; use mla::layers::encrypt::EncryptionLayerReader; use mla::layers::raw::RawLayerReader; -use mla::layers::traits::LayerReader; +use mla::layers::traits::{InnerReaderTrait, LayerReader}; use mla::{ ArchiveFailSafeReader, ArchiveFile, ArchiveFooter, ArchiveHeader, ArchiveReader, ArchiveWriter, Layers, @@ -921,7 +921,7 @@ impl ArchiveInfoReader { mut config: ArchiveReaderConfig, ) -> Result where - R: 'a + Read + Seek, + R: 'a + InnerReaderTrait, { // Make sure we read the archive header from the start src.rewind()?;