use std::path::PathBuf;
#[non_exhaustive]
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub enum CompressionMethod {
None,
Zlib,
Lz4,
}
impl CompressionMethod {
#[must_use]
pub fn from_flags(flags: u8) -> Self {
match flags & 0x0F {
0 => CompressionMethod::None,
1 => CompressionMethod::Zlib,
2 => CompressionMethod::Lz4,
_ => CompressionMethod::None, }
}
#[must_use]
pub fn as_str(&self) -> &'static str {
match self {
CompressionMethod::None => "none",
CompressionMethod::Zlib => "zlib",
CompressionMethod::Lz4 => "lz4",
}
}
#[must_use]
pub fn to_flags(self) -> u8 {
match self {
CompressionMethod::None => 0,
CompressionMethod::Zlib => 1,
CompressionMethod::Lz4 => 2,
}
}
}
#[derive(Debug, Clone)]
pub(crate) struct LspkHeader {
#[allow(dead_code)]
pub magic: [u8; 4],
pub version: u32,
pub footer_offset: u64,
}
#[derive(Debug, Clone)]
pub(crate) struct LspkFooter {
pub num_files: u32,
pub table_size_compressed: u32,
}
#[non_exhaustive]
#[derive(Debug, Clone)]
pub struct FileTableEntry {
pub path: PathBuf,
pub offset: u64,
pub size_compressed: u32,
pub size_decompressed: u32,
pub compression: CompressionMethod,
#[allow(dead_code)]
pub flags: u8,
pub archive_part: u8,
}
#[non_exhaustive]
#[derive(Debug, Clone)]
pub struct PakFile {
pub path: PathBuf,
pub data: Vec<u8>,
}
#[non_exhaustive]
#[derive(Debug)]
pub struct PakContents {
pub files: Vec<PakFile>,
pub errors: Vec<(PathBuf, String)>,
pub version: u32,
}
impl PakContents {
#[must_use]
pub fn new(version: u32) -> Self {
Self {
files: Vec::new(),
errors: Vec::new(),
version,
}
}
#[must_use]
pub fn is_complete(&self) -> bool {
self.errors.is_empty()
}
#[must_use]
pub fn total_files(&self) -> usize {
self.files.len() + self.errors.len()
}
}
#[non_exhaustive]
#[derive(Debug, Clone)]
pub struct PakProgress {
pub phase: PakPhase,
pub current: usize,
pub total: usize,
pub current_file: Option<String>,
}
impl PakProgress {
#[must_use]
pub fn new(phase: PakPhase, current: usize, total: usize) -> Self {
Self {
phase,
current,
total,
current_file: None,
}
}
#[must_use]
pub fn with_file(
phase: PakPhase,
current: usize,
total: usize,
file: impl Into<String>,
) -> Self {
Self {
phase,
current,
total,
current_file: Some(file.into()),
}
}
#[must_use]
pub fn percentage(&self) -> f32 {
if self.total == 0 {
1.0
} else {
self.current as f32 / self.total as f32
}
}
}
#[non_exhaustive]
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub enum PakPhase {
ReadingHeader,
ReadingTable,
DecompressingFiles,
ScanningFiles,
CompressingFiles,
WritingTable,
WritingFiles,
Complete,
}
impl PakPhase {
#[must_use]
pub fn as_str(self) -> &'static str {
match self {
Self::ReadingHeader => "Reading header",
Self::ReadingTable => "Reading file table",
Self::DecompressingFiles => "Decompressing files",
Self::ScanningFiles => "Scanning files",
Self::CompressingFiles => "Compressing files",
Self::WritingTable => "Writing file table",
Self::WritingFiles => "Writing files",
Self::Complete => "Complete",
}
}
}