pmv_encryption_rs 1.0.0

Implementation of PersonalMediaVault encrypted storage model. This library allows to encrypt and decrypt data, and also read ans write files in the same format PersonalMediaVault uses.
Documentation
// Write stream

use std::{
    fs::File,
    io::{self, Seek, Write},
    path::Path,
};

use byteorder::{BigEndian, ByteOrder};

use crate::MultiFilePackWriteError;

/// A stream to write and pack multiple small files
pub struct MultiFilePackWriteStream {
    /// File descriptor
    file: File,

    /// Number of files contained in the file
    file_count: u64,

    /// Index of the current file being written
    current_write_index: u64,

    /// Position of the cursor to write the next file
    current_write_pt: u64,
}

impl MultiFilePackWriteStream {
    /// Creates a new instance of MultiFilePackWriteStream
    /// Creates the file and writes the header
    ///
    /// Parameters:
    ///  - `file_path` - Path to the file to create
    ///  - `file_count` - The number of small files that will be packed
    ///
    /// Return the instance of MultiFilePackWriteStream, or an error.
    pub fn new<P>(file_path: P, file_count: u64) -> Result<MultiFilePackWriteStream, io::Error>
    where
        P: AsRef<Path>,
    {
        let mut file = File::create(file_path)?;

        let mut buf: [u8; 8] = [0; 8];

        // Put file count in file header

        BigEndian::write_u64(&mut buf, file_count);

        file.write_all(&buf)?;

        // Write the initial file index

        let buf_file_index: [u8; 16] = [0; 16];

        for _i in 0..file_count {
            file.write_all(&buf_file_index)?;
        }

        Ok(MultiFilePackWriteStream {
            file,
            file_count,
            current_write_index: 0,
            current_write_pt: 8 + (16 * file_count),
        })
    }

    /// Writes the next file
    ///
    /// Parameters:
    ///  - `data` - File data to write
    ///
    /// May return an error if it fails
    pub fn write_file(&mut self, data: &[u8]) -> Result<(), MultiFilePackWriteError> {
        if self.current_write_index >= self.file_count {
            return Err(MultiFilePackWriteError::ExceededFileCount);
        }

        // Write file index

        let file_size = data.len() as u64;

        let mut buf_file_index: [u8; 16] = [0; 16];

        BigEndian::write_u64(&mut buf_file_index[0..8], self.current_write_pt); // Start pointer
        BigEndian::write_u64(&mut buf_file_index[8..16], file_size); // File length

        self.file
            .seek(io::SeekFrom::Start(8 + self.current_write_index * 16))?;
        self.file.write_all(&buf_file_index)?;

        // Write data

        self.file.seek(io::SeekFrom::Start(self.current_write_pt))?;
        self.file.write_all(data)?;

        // Update pointer

        self.current_write_index += 1;
        self.current_write_pt += file_size;

        Ok(())
    }

    /// Closes the file and drops the stream
    pub fn close(self) {}
}