rust_unreal_unpak/pak/
pak_file.rs1use std::path::Path;
2
3use thiserror::Error;
4use tokio::{fs::File, io::AsyncReadExt};
5
6use super::pak_reader::{PakReader, PakReaderError};
7use std::collections::HashMap;
8use crate::pak::pak_reader::PakEntry;
9
10#[derive(Error, Debug)]
11pub enum PakError {
12 #[error("Error opening or reading file: {0}")]
13 FileError(#[from] std::io::Error),
14 #[error("Error parsing the pak file: {0}")]
15 ReaderError(#[from] PakReaderError),
16}
17
18#[derive(Debug)]
19pub struct PakInfo {
20 pub encryption_index_guid: Vec<u8>,
21 pub is_encrypted: bool,
22 pub magic: u32,
23 pub version: i32,
24 pub sub_version: i32,
25 pub index_offset: i64,
26 pub index_size: i64,
27 pub index_hash: Vec<u8>,
28 pub index_frozen: u8,
29 pub compression_methods: Vec<String>
30}
31
32#[derive(Debug)]
33pub struct PakCompressionBlock {
34 pub compression_start: i64,
35 pub compression_end: i64
36}
37
38#[derive(Debug)]
39pub struct PakFile {
40 pub info: PakInfo,
41 pub mount_point: String,
42 pub file_indexes: HashMap<String, PakEntry>,
43 reader: PakReader
44}
45
46impl PakFile {
47 pub async fn from_path(path: &Path) -> Result<Self, PakError> {
49 match File::open(path).await {
50 Ok(file) => Self::from_file(file).await,
51 Err(err) => Err(PakError::FileError(err)),
52 }
53 }
54
55 pub async fn from_file(mut file: File) -> Result<Self, PakError> {
57 let mut buffer = Vec::new();
58 match file.read_to_end(&mut buffer).await {
59 Ok(_) => Self::from_memory(buffer).await,
60 Err(e) => Err(PakError::FileError(e)),
61 }
62 }
63
64 pub async fn from_memory(buffer: Vec<u8>) -> Result<Self, PakError> {
66 let mut reader = PakReader::new(buffer);
67
68 let pak_info = reader.get_pak_info().await?;
69 let (mount_point, indexes) = reader.get_pak_entries(&pak_info).await?;
70
71 Ok(Self {
72 info: pak_info,
73 mount_point: mount_point,
74 file_indexes: indexes,
75 reader: reader
76 })
77 }
78
79 pub async fn get_entry_data<T: Into<String>>(&mut self, index: T) -> Result<Option<Vec<u8>>, PakError> {
80 let entry = self.file_indexes.get(&index.into());
81 if let Some(pak_entry) = entry {
82 Ok(Some(self.reader.get_pak_entry_data(pak_entry).await?))
83 } else {
84 Ok(None)
85 }
86 }
87
88}