use builder pattern

This commit is contained in:
spuds 2023-09-20 19:42:48 +01:00
parent 564c4f6a45
commit e2edd97d6e
No known key found for this signature in database
GPG key ID: 0B6CA6068E827C8F
4 changed files with 47 additions and 131 deletions

View file

@ -20,6 +20,7 @@ zstd = { version = "0.12", optional = true }
thiserror = "1.0"
sha1 = { workspace = true }
strum = { workspace = true }
once_cell = "1.18"
[dev-dependencies]
base64 = { workspace = true }

View file

@ -307,7 +307,6 @@ impl Entry {
compression: &[Compression],
#[allow(unused)] key: &super::Key,
buf: &mut W,
#[allow(unused)] oodle: super::Oodle,
) -> Result<(), super::Error> {
reader.seek(io::SeekFrom::Start(self.offset))?;
Entry::read(reader, version)?;
@ -377,7 +376,7 @@ impl Entry {
}
#[cfg(feature = "oodle")]
Some(Compression::Oodle) => unsafe {
let super::Oodle::Some(oodle) = oodle else {
let Some(ref oodle) = super::OODLE else {
return Err(super::Error::OodleFailed);
};
let mut decompressed = vec![0; self.uncompressed as usize];

View file

@ -10,7 +10,10 @@ pub use {error::*, pak::*};
pub const MAGIC: u32 = 0x5A6F12E1;
#[cfg(feature = "oodle")]
pub type DECOMPRESS = unsafe extern "C" fn(
static mut OODLE: Option<once_cell::sync::Lazy<Decompress>> = None;
#[cfg(feature = "oodle")]
pub type Decompress = unsafe extern "C" fn(
compBuf: *mut u8,
compBufSize: usize,
rawBuf: *mut u8,
@ -155,7 +158,7 @@ impl From<aes::Aes256> for Key {
#[cfg(feature = "oodle")]
pub(crate) enum Oodle<'func> {
Some(&'func DECOMPRESS),
Some(&'func Decompress),
None,
}

View file

@ -4,6 +4,46 @@ use byteorder::{ReadBytesExt, WriteBytesExt, LE};
use std::collections::BTreeMap;
use std::io::{self, Read, Seek, Write};
#[derive(Debug)]
pub struct PakBuilder {
key: super::Key,
}
impl PakBuilder {
pub fn new() -> Self {
Self {
key: super::Key::None,
}
}
#[cfg(feature = "encryption")]
pub fn key(&mut self, key: aes::Aes256) {
self.key = super::Key::Some(key)
}
#[cfg(feature = "oodle")]
pub fn oodle(&mut self, oodle: fn() -> super::Decompress) {
unsafe { super::OODLE = Some(once_cell::sync::Lazy::new(oodle)) }
}
pub fn reader<R: Read + Seek>(self, reader: &mut R) -> Result<PakReader, super::Error> {
PakReader::new_any_inner(reader, self.key)
}
pub fn reader_with_version<R: Read + Seek>(
self,
reader: &mut R,
version: super::Version,
) -> Result<PakReader, super::Error> {
PakReader::new_inner(reader, version, self.key)
}
pub fn writer<W: Write + Seek>(
self,
writer: W,
version: super::Version,
mount_point: String,
path_hash_seed: Option<u64>,
) -> PakWriter<W> {
PakWriter::new_inner(writer, self.key, version, mount_point, path_hash_seed)
}
}
#[derive(Debug)]
pub struct PakReader {
pak: Pak,
@ -83,29 +123,6 @@ fn decrypt(key: &super::Key, bytes: &mut [u8]) -> Result<(), super::Error> {
}
impl PakReader {
pub fn new_any<R: Read + Seek>(reader: &mut R) -> Result<Self, super::Error> {
Self::new_any_inner(reader, super::Key::None)
}
#[cfg(feature = "encryption")]
pub fn new_any_with_key<R: Read + Seek>(
reader: &mut R,
key: aes::Aes256,
) -> Result<Self, super::Error> {
Self::new_any_inner(reader, key.into())
}
#[cfg(feature = "encryption")]
pub fn new_any_with_optional_key<R: Read + Seek>(
reader: &mut R,
key: Option<aes::Aes256>,
) -> Result<Self, super::Error> {
match key {
Some(key) => Self::new_any_with_key(reader, key),
None => Self::new_any(reader),
}
}
fn new_any_inner<R: Read + Seek>(
reader: &mut R,
key: super::Key,
@ -122,34 +139,6 @@ impl PakReader {
Err(super::Error::UnsupportedOrEncrypted(log))
}
pub fn new<R: Read + Seek>(
reader: &mut R,
version: super::Version,
) -> Result<Self, super::Error> {
Self::new_inner(reader, version, super::Key::None)
}
#[cfg(feature = "encryption")]
pub fn new_with_key<R: Read + Seek>(
reader: &mut R,
version: super::Version,
key: aes::Aes256,
) -> Result<Self, super::Error> {
Self::new_inner(reader, version, key.into())
}
#[cfg(feature = "encryption")]
pub fn new_with_optional_key<R: Read + Seek>(
reader: &mut R,
version: super::Version,
key: Option<aes::Aes256>,
) -> Result<Self, super::Error> {
match key {
Some(key) => Self::new_with_key(reader, version, key),
None => Self::new(reader, version),
}
}
fn new_inner<R: Read + Seek>(
reader: &mut R,
version: super::Version,
@ -180,18 +169,6 @@ impl PakReader {
Ok(data)
}
#[cfg(feature = "oodle")]
pub fn get_with_oodle<R: Read + Seek>(
&self,
path: &str,
reader: &mut R,
oodle: &super::DECOMPRESS,
) -> Result<Vec<u8>, super::Error> {
let mut data = Vec::new();
self.read_file_with_oodle(path, reader, &mut data, oodle)?;
Ok(data)
}
pub fn read_file<R: Read + Seek, W: Write>(
&self,
path: &str,
@ -205,28 +182,6 @@ impl PakReader {
&self.pak.compression,
&self.key,
writer,
super::Oodle::None,
),
None => Err(super::Error::MissingEntry(path.to_owned())),
}
}
#[cfg(feature = "oodle")]
pub fn read_file_with_oodle<R: Read + Seek, W: Write>(
&self,
path: &str,
reader: &mut R,
writer: &mut W,
oodle: &super::DECOMPRESS,
) -> Result<(), super::Error> {
match self.pak.index.entries().get(path) {
Some(entry) => entry.read_file(
reader,
self.pak.version,
&self.pak.compression,
&self.key,
writer,
super::Oodle::Some(oodle),
),
None => Err(super::Error::MissingEntry(path.to_owned())),
}
@ -250,48 +205,6 @@ impl PakReader {
}
impl<W: Write + Seek> PakWriter<W> {
pub fn new(
writer: W,
version: Version,
mount_point: String,
path_hash_seed: Option<u64>,
) -> Self {
PakWriter {
pak: Pak::new(version, mount_point, path_hash_seed),
writer,
key: super::Key::None,
}
}
#[cfg(feature = "encryption")]
pub fn new_with_key(
writer: W,
key: aes::Aes256,
version: Version,
mount_point: String,
path_hash_seed: Option<u64>,
) -> Self {
PakWriter {
pak: Pak::new(version, mount_point, path_hash_seed),
writer,
key: key.into(),
}
}
#[cfg(feature = "encryption")]
pub fn new_with_optional_key(
writer: W,
key: Option<aes::Aes256>,
version: Version,
mount_point: String,
path_hash_seed: Option<u64>,
) -> Self {
match key {
Some(key) => Self::new_with_key(writer, key, version, mount_point, path_hash_seed),
None => Self::new(writer, version, mount_point, path_hash_seed),
}
}
fn new_inner(
writer: W,
key: super::Key,