mirror of
https://github.com/lifegpc/msg-tool.git
synced 2026-06-18 17:04:50 +08:00
131 lines
3.4 KiB
Rust
131 lines
3.4 KiB
Rust
use super::consts::*;
|
|
use super::crypt::Crypt;
|
|
use crate::scripts::base::{AnyDebug, ReadSeek};
|
|
use std::ops::{Deref, DerefMut};
|
|
use std::sync::{Arc, Mutex};
|
|
|
|
/// Represents a single data segment for a file.
|
|
/// A file can be split into multiple segments, which can be compressed independently.
|
|
#[derive(Debug, Clone, PartialEq, Eq, PartialOrd, Ord)]
|
|
pub struct Segment {
|
|
pub is_compressed: bool,
|
|
/// The offset of the segment's data within the archive file.
|
|
pub start: u64,
|
|
/// The offset of this segment within the original, uncompressed file.
|
|
pub offset_in_file: u64,
|
|
/// The size of the segment after decompression.
|
|
pub original_size: u64,
|
|
/// The size of the segment in the archive (potentially compressed).
|
|
pub archived_size: u64,
|
|
}
|
|
|
|
/// Represents a single file entry within the XP3 archive.
|
|
#[derive(Debug, Clone, PartialEq, Eq, PartialOrd, Ord)]
|
|
pub struct ArchiveItem {
|
|
pub name: String,
|
|
pub file_hash: u32,
|
|
pub original_size: u64,
|
|
pub archived_size: u64,
|
|
pub segments: Vec<Segment>,
|
|
}
|
|
|
|
#[derive(Debug, Clone)]
|
|
#[allow(unused)]
|
|
pub struct Xp3Entry {
|
|
pub name: String,
|
|
pub flags: u32,
|
|
pub file_hash: u32,
|
|
pub original_size: u64,
|
|
pub archived_size: u64,
|
|
pub timestamp: Option<u64>,
|
|
pub segments: Vec<Segment>,
|
|
pub extras: Vec<ExtraProp>,
|
|
pub extra: Option<Arc<Box<dyn AnyDebug + Send + Sync>>>,
|
|
}
|
|
|
|
impl Xp3Entry {
|
|
pub fn is_encrypted(&self) -> bool {
|
|
self.flags != 0
|
|
}
|
|
}
|
|
|
|
#[derive(Debug, Clone, PartialEq, Eq, PartialOrd, Ord)]
|
|
pub struct ExtraProp {
|
|
pub tag: PropTag,
|
|
pub data: Vec<u8>,
|
|
}
|
|
|
|
#[derive(Clone, PartialEq, Eq, PartialOrd, Ord)]
|
|
pub struct PropTag {
|
|
tag: [u8; 4],
|
|
}
|
|
|
|
impl std::fmt::Debug for PropTag {
|
|
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
|
|
write!(f, "{:?}", bytes::Bytes::copy_from_slice(&self.tag))
|
|
}
|
|
}
|
|
|
|
impl Deref for PropTag {
|
|
type Target = [u8; 4];
|
|
|
|
fn deref(&self) -> &Self::Target {
|
|
&self.tag
|
|
}
|
|
}
|
|
|
|
impl DerefMut for PropTag {
|
|
fn deref_mut(&mut self) -> &mut Self::Target {
|
|
&mut self.tag
|
|
}
|
|
}
|
|
|
|
impl From<[u8; 4]> for PropTag {
|
|
fn from(value: [u8; 4]) -> Self {
|
|
PropTag { tag: value }
|
|
}
|
|
}
|
|
|
|
impl PartialEq<&[u8; 4]> for PropTag {
|
|
fn eq(&self, other: &&[u8; 4]) -> bool {
|
|
&self.tag == *other
|
|
}
|
|
}
|
|
|
|
impl PartialEq<String> for PropTag {
|
|
fn eq(&self, other: &String) -> bool {
|
|
self.tag == other.as_bytes()
|
|
}
|
|
}
|
|
|
|
impl PartialEq<&str> for PropTag {
|
|
fn eq(&self, other: &&str) -> bool {
|
|
self.tag == other.as_bytes()
|
|
}
|
|
}
|
|
|
|
impl ExtraProp {
|
|
pub fn is_filename_hash(&self) -> bool {
|
|
self.tag == CHUNK_HNFN
|
|
|| self.tag == CHUNK_SMIL
|
|
|| self.tag == CHUNK_ELIF
|
|
|| self.tag == CHUNK_YUZU
|
|
}
|
|
}
|
|
|
|
/// Represents the entire XP3 archive
|
|
#[derive(Debug)]
|
|
#[allow(dead_code)]
|
|
pub struct Xp3Archive<'a> {
|
|
pub inner: Arc<Mutex<Box<dyn ReadSeek + Send + Sync + 'a>>>,
|
|
pub crypt: Arc<Box<dyn Crypt + Send + Sync>>,
|
|
/// The offset which the archive file start. If the archive is embedded in another file (such as exe), this is the offset of the archive data within the larger file.
|
|
pub base_offset: u64,
|
|
/// The offset which index start. Releatived to whole file not just xp3 archive.
|
|
pub index_offset: u64,
|
|
/// Minor version
|
|
pub minor_version: u32,
|
|
pub entries: Vec<Xp3Entry>,
|
|
pub extras: Vec<ExtraProp>,
|
|
}
|