caff-archive 0.1.0

a library for manipulating CAFF archives
Documentation
use super::Metadata;
use crate::prelude::*;

#[derive(derivative::Derivative, Clone, PartialEq, Eq, PartialOrd, Ord, Hash)]
#[derivative(Debug)]
pub struct Body {
  pub metadata: Vec<Metadata>,
  #[derivative(Debug = "ignore")]
  pub data: Vec<Vec<u8>>,
  pub trailing: Vec<u8>,
}

impl Body {
  pub fn read<R: Read + Seek>(reader: &mut R, key: Key) -> Result<Self> {
    let total_file_entries = reader.read_encrypted_u32::<BigEndian>(key)?;

    let mut metadata = Vec::new();

    for _ in 0..total_file_entries {
      let file_info = Metadata::read(reader, key)?;
      metadata.push(file_info);
    }

    let mut data = Vec::new();
    for metadata in metadata.iter() {
      let mut bytes = Vec::with_capacity(metadata.file_size.try_into()?);

      if metadata.is_obfuscated {
        for _ in 0..metadata.file_size {
          bytes.push(reader.read_encrypted_u8(key)?)
        }
      } else {
        for _ in 0..metadata.file_size {
          bytes.push(reader.read_u8()?)
        }
      }

      data.push(bytes);
    }

    let mut trailing = Vec::new();
    reader.read_to_end(&mut trailing)?;

    Ok(Self { metadata, data, trailing })
  }

  pub fn write<W: Write + Seek>(&self, writer: &mut W, key: Key) -> Result<()> {
    for metadata in &self.metadata {
      metadata.write(writer, key)?;
    }

    for data in &self.data {
      for byte in data {
        writer.write_encrypted_u8(*byte, key)?;
      }
    }

    writer.write_all(&self.trailing)?;

    Ok(())
  }
}