mirror of
https://github.com/xavo95/repak.git
synced 2025-01-18 10:54:38 +00:00
use builder pattern
This commit is contained in:
parent
564c4f6a45
commit
e2edd97d6e
4 changed files with 47 additions and 131 deletions
|
@ -20,6 +20,7 @@ zstd = { version = "0.12", optional = true }
|
||||||
thiserror = "1.0"
|
thiserror = "1.0"
|
||||||
sha1 = { workspace = true }
|
sha1 = { workspace = true }
|
||||||
strum = { workspace = true }
|
strum = { workspace = true }
|
||||||
|
once_cell = "1.18"
|
||||||
|
|
||||||
[dev-dependencies]
|
[dev-dependencies]
|
||||||
base64 = { workspace = true }
|
base64 = { workspace = true }
|
||||||
|
|
|
@ -307,7 +307,6 @@ impl Entry {
|
||||||
compression: &[Compression],
|
compression: &[Compression],
|
||||||
#[allow(unused)] key: &super::Key,
|
#[allow(unused)] key: &super::Key,
|
||||||
buf: &mut W,
|
buf: &mut W,
|
||||||
#[allow(unused)] oodle: super::Oodle,
|
|
||||||
) -> Result<(), super::Error> {
|
) -> Result<(), super::Error> {
|
||||||
reader.seek(io::SeekFrom::Start(self.offset))?;
|
reader.seek(io::SeekFrom::Start(self.offset))?;
|
||||||
Entry::read(reader, version)?;
|
Entry::read(reader, version)?;
|
||||||
|
@ -377,7 +376,7 @@ impl Entry {
|
||||||
}
|
}
|
||||||
#[cfg(feature = "oodle")]
|
#[cfg(feature = "oodle")]
|
||||||
Some(Compression::Oodle) => unsafe {
|
Some(Compression::Oodle) => unsafe {
|
||||||
let super::Oodle::Some(oodle) = oodle else {
|
let Some(ref oodle) = super::OODLE else {
|
||||||
return Err(super::Error::OodleFailed);
|
return Err(super::Error::OodleFailed);
|
||||||
};
|
};
|
||||||
let mut decompressed = vec![0; self.uncompressed as usize];
|
let mut decompressed = vec![0; self.uncompressed as usize];
|
||||||
|
|
|
@ -10,7 +10,10 @@ pub use {error::*, pak::*};
|
||||||
pub const MAGIC: u32 = 0x5A6F12E1;
|
pub const MAGIC: u32 = 0x5A6F12E1;
|
||||||
|
|
||||||
#[cfg(feature = "oodle")]
|
#[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,
|
compBuf: *mut u8,
|
||||||
compBufSize: usize,
|
compBufSize: usize,
|
||||||
rawBuf: *mut u8,
|
rawBuf: *mut u8,
|
||||||
|
@ -155,7 +158,7 @@ impl From<aes::Aes256> for Key {
|
||||||
|
|
||||||
#[cfg(feature = "oodle")]
|
#[cfg(feature = "oodle")]
|
||||||
pub(crate) enum Oodle<'func> {
|
pub(crate) enum Oodle<'func> {
|
||||||
Some(&'func DECOMPRESS),
|
Some(&'func Decompress),
|
||||||
None,
|
None,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
167
repak/src/pak.rs
167
repak/src/pak.rs
|
@ -4,6 +4,46 @@ use byteorder::{ReadBytesExt, WriteBytesExt, LE};
|
||||||
use std::collections::BTreeMap;
|
use std::collections::BTreeMap;
|
||||||
use std::io::{self, Read, Seek, Write};
|
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)]
|
#[derive(Debug)]
|
||||||
pub struct PakReader {
|
pub struct PakReader {
|
||||||
pak: Pak,
|
pak: Pak,
|
||||||
|
@ -83,29 +123,6 @@ fn decrypt(key: &super::Key, bytes: &mut [u8]) -> Result<(), super::Error> {
|
||||||
}
|
}
|
||||||
|
|
||||||
impl PakReader {
|
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>(
|
fn new_any_inner<R: Read + Seek>(
|
||||||
reader: &mut R,
|
reader: &mut R,
|
||||||
key: super::Key,
|
key: super::Key,
|
||||||
|
@ -122,34 +139,6 @@ impl PakReader {
|
||||||
Err(super::Error::UnsupportedOrEncrypted(log))
|
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>(
|
fn new_inner<R: Read + Seek>(
|
||||||
reader: &mut R,
|
reader: &mut R,
|
||||||
version: super::Version,
|
version: super::Version,
|
||||||
|
@ -180,18 +169,6 @@ impl PakReader {
|
||||||
Ok(data)
|
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>(
|
pub fn read_file<R: Read + Seek, W: Write>(
|
||||||
&self,
|
&self,
|
||||||
path: &str,
|
path: &str,
|
||||||
|
@ -205,28 +182,6 @@ impl PakReader {
|
||||||
&self.pak.compression,
|
&self.pak.compression,
|
||||||
&self.key,
|
&self.key,
|
||||||
writer,
|
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())),
|
None => Err(super::Error::MissingEntry(path.to_owned())),
|
||||||
}
|
}
|
||||||
|
@ -250,48 +205,6 @@ impl PakReader {
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<W: Write + Seek> PakWriter<W> {
|
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(
|
fn new_inner(
|
||||||
writer: W,
|
writer: W,
|
||||||
key: super::Key,
|
key: super::Key,
|
||||||
|
|
Loading…
Reference in a new issue