Skip to content

Commit

Permalink
Merge pull request #189 from ANSSI-FR/reader-send
Browse files Browse the repository at this point in the history
When "send" feature is enabled, make Readers `Send` too
  • Loading branch information
commial committed Jan 22, 2024
2 parents 6a5ce37 + be5d279 commit defb19f
Show file tree
Hide file tree
Showing 7 changed files with 38 additions and 14 deletions.
4 changes: 3 additions & 1 deletion 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};
Expand All @@ -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<W1: InnerWriterTrait, R: Read + Seek, S: BuildHasher>(
pub fn linear_extract<W1: InnerWriterTrait, R: InnerReaderTrait, S: BuildHasher>(
archive: &mut ArchiveReader<R>,
export: &mut HashMap<&String, W1, S>,
) -> Result<(), Error> {
Expand Down
4 changes: 3 additions & 1 deletion mla/src/layers/compress.rs
Expand Up @@ -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
Expand Down Expand Up @@ -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<Box<dyn 'a + LayerReader<'a, R>>> {
Some(self.state.into_inner())
}
Expand Down
4 changes: 3 additions & 1 deletion mla/src/layers/encrypt.rs
Expand Up @@ -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;
Expand Down Expand Up @@ -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<Box<dyn 'a + LayerReader<'a, R>>> {
Some(self.inner)
}
Expand Down
12 changes: 7 additions & 5 deletions mla/src/layers/raw.rs
Expand Up @@ -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)
Expand Down Expand Up @@ -49,13 +51,13 @@ impl<W: InnerWriterTrait> Write for RawLayerWriter<W> {
// ---------- Reader ----------

/// Dummy layer, standing for the last layer (wrapping I/O)
pub struct RawLayerReader<R: Read + Seek> {
pub struct RawLayerReader<R: InnerReaderTrait> {
inner: R,
// Offset to use in position
offset_pos: u64,
}

impl<R: Read + Seek> RawLayerReader<R> {
impl<R: InnerReaderTrait> RawLayerReader<R> {
pub fn new(inner: R) -> Self {
Self {
inner,
Expand All @@ -70,7 +72,7 @@ impl<R: Read + Seek> RawLayerReader<R> {
}
}

impl<'a, R: Read + Seek> LayerReader<'a, R> for RawLayerReader<R> {
impl<'a, R: InnerReaderTrait> LayerReader<'a, R> for RawLayerReader<R> {
fn into_inner(self) -> Option<Box<dyn 'a + LayerReader<'a, R>>> {
None
}
Expand All @@ -85,7 +87,7 @@ impl<'a, R: Read + Seek> LayerReader<'a, R> for RawLayerReader<R> {
}
}

impl<R: Read + Seek> Seek for RawLayerReader<R> {
impl<R: InnerReaderTrait> Seek for RawLayerReader<R> {
/// Offer a position relatively to `self.offset_pos`
fn seek(&mut self, ask_pos: SeekFrom) -> io::Result<u64> {
match ask_pos {
Expand Down Expand Up @@ -115,7 +117,7 @@ impl<R: Read + Seek> Seek for RawLayerReader<R> {
}
}

impl<R: Read + Seek> Read for RawLayerReader<R> {
impl<R: InnerReaderTrait> Read for RawLayerReader<R> {
/// Wrapper on inner
fn read(&mut self, into: &mut [u8]) -> io::Result<usize> {
self.inner.read(into)
Expand Down
18 changes: 16 additions & 2 deletions mla/src/layers/traits.rs
Expand Up @@ -3,7 +3,7 @@ use std::io::{Read, Seek, Write};

// Here, feature `send` is used to force `Send` on Box<dyn> 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
Expand Down Expand Up @@ -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<T: Read + Seek> InnerReaderTrait for T {}

#[cfg(feature = "send")]
pub trait InnerReaderTrait: Read + Seek + Send {}
#[cfg(feature = "send")]
impl<T: Read + Seek + Send> 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<Box<dyn 'a + LayerReader<'a, R>>>;

Expand Down
6 changes: 4 additions & 2 deletions mla/src/lib.rs
Expand Up @@ -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;
Expand Down Expand Up @@ -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
Expand All @@ -858,7 +859,7 @@ pub struct ArchiveReader<'a, R: 'a + Read + Seek> {
metadata: Option<ArchiveFooter>,
}

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<Self, Error> {
// Make sure we read the archive header from the start
src.rewind()?;
Expand Down Expand Up @@ -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<File>: Send);
static_assertions::assert_impl_all!(ArchiveReader<File>: Send);
}
}
4 changes: 2 additions & 2 deletions mlar/src/main.rs
Expand Up @@ -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,
Expand Down Expand Up @@ -921,7 +921,7 @@ impl ArchiveInfoReader {
mut config: ArchiveReaderConfig,
) -> Result<Self, MlarError>
where
R: 'a + Read + Seek,
R: 'a + InnerReaderTrait,
{
// Make sure we read the archive header from the start
src.rewind()?;
Expand Down

0 comments on commit defb19f

Please sign in to comment.