mirror of
https://github.com/lifegpc/msg-tool.git
synced 2026-06-06 12:58:45 +08:00
Add ZSTD compress support when pack xp3 archive
This commit is contained in:
@@ -86,7 +86,7 @@ hexen-haus = ["memchr", "utils-str"]
|
||||
hexen-haus-arc = ["hexen-haus"]
|
||||
hexen-haus-img = ["hexen-haus", "image"]
|
||||
kirikiri = ["emote-psb", "fancy-regex", "flate2", "json", "lz4", "utils-escape"]
|
||||
kirikiri-arc = ["kirikiri", "adler", "fastcdc", "flate2", "parse-size", "sha2", "xp3", "utils-threadpool"]
|
||||
kirikiri-arc = ["kirikiri", "adler", "fastcdc", "flate2", "parse-size", "sha2", "xp3", "zstd", "utils-threadpool"]
|
||||
kirikiri-img = ["kirikiri", "image", "libtlg-rs"]
|
||||
silky = []
|
||||
softpal = ["int-enum"]
|
||||
|
||||
@@ -508,9 +508,13 @@ pub struct Arg {
|
||||
/// Disable compressing index in Kirikiri XP3 archive when creating XP3 archive.
|
||||
pub xp3_no_compress_index: bool,
|
||||
#[cfg(feature = "kirikiri-arc")]
|
||||
#[arg(long, global = true, default_value_t = num_cpus::get())]
|
||||
#[arg(long, global = true, default_value_t = num_cpus::get(), visible_alias = "xp3-compress-jobs")]
|
||||
/// Workers count for compress files in Kirikiri XP3 archive when creating in parallel.
|
||||
pub xp3_compress_workers: usize,
|
||||
#[cfg(feature = "kirikiri-arc")]
|
||||
#[arg(long, global = true)]
|
||||
/// Use zstd compression for files in Kirikiri XP3 archive when creating. (Warning: Kirikiri engine don't support this. Hook is required.)
|
||||
pub xp3_zstd: bool,
|
||||
#[command(subcommand)]
|
||||
/// Command
|
||||
pub command: Command,
|
||||
|
||||
@@ -2757,6 +2757,8 @@ fn main() {
|
||||
xp3_compress_index: !arg.xp3_no_compress_index,
|
||||
#[cfg(feature = "kirikiri-arc")]
|
||||
xp3_compress_workers: arg.xp3_compress_workers,
|
||||
#[cfg(feature = "kirikiri-arc")]
|
||||
xp3_zstd: arg.xp3_zstd,
|
||||
});
|
||||
match &arg.command {
|
||||
args::Command::Export { input, output } => {
|
||||
|
||||
@@ -73,6 +73,8 @@ pub struct Xp3ArchiveWriter<T: Write + Seek> {
|
||||
stats: Arc<Stats>,
|
||||
compress_workers: Option<Arc<ThreadPool<Result<()>>>>,
|
||||
processing_segments: Arc<Mutex<HashSet<[u8; 32]>>>,
|
||||
use_zstd: bool,
|
||||
zstd_compression_level: i32,
|
||||
}
|
||||
|
||||
impl Xp3ArchiveWriter<std::io::BufWriter<std::fs::File>> {
|
||||
@@ -113,6 +115,8 @@ impl Xp3ArchiveWriter<std::io::BufWriter<std::fs::File>> {
|
||||
None
|
||||
},
|
||||
processing_segments: Arc::new(Mutex::new(HashSet::new())),
|
||||
use_zstd: config.xp3_zstd,
|
||||
zstd_compression_level: config.zstd_compression_level,
|
||||
})
|
||||
}
|
||||
}
|
||||
@@ -194,6 +198,8 @@ impl<T: Write + Seek + Sync + Send + 'static> Archive for Xp3ArchiveWriter<T> {
|
||||
let zlib_compression_level = self.zlib_compression_level;
|
||||
let workers = self.compress_workers.clone();
|
||||
let processiong_segments = self.processing_segments.clone();
|
||||
let use_zstd = self.use_zstd;
|
||||
let zstd_compression_level = self.zstd_compression_level;
|
||||
self.runner.execute(
|
||||
move |_| {
|
||||
let mut reader = reader;
|
||||
@@ -234,14 +240,23 @@ impl<T: Write + Seek + Sync + Send + 'static> Archive for Xp3ArchiveWriter<T> {
|
||||
workers.execute(
|
||||
move |_| {
|
||||
let data = {
|
||||
let mut e = flate2::write::ZlibEncoder::new(
|
||||
Vec::new(),
|
||||
flate2::Compression::new(
|
||||
zlib_compression_level,
|
||||
),
|
||||
);
|
||||
e.write_all(&seg)?;
|
||||
e.finish()?
|
||||
if use_zstd {
|
||||
let mut e = zstd::stream::Encoder::new(
|
||||
Vec::new(),
|
||||
zstd_compression_level,
|
||||
)?;
|
||||
e.write_all(&seg)?;
|
||||
e.finish()?
|
||||
} else {
|
||||
let mut e = flate2::write::ZlibEncoder::new(
|
||||
Vec::new(),
|
||||
flate2::Compression::new(
|
||||
zlib_compression_level,
|
||||
),
|
||||
);
|
||||
e.write_all(&seg)?;
|
||||
e.finish()?
|
||||
}
|
||||
};
|
||||
let mut file = file.lock_blocking();
|
||||
let start = file.seek(std::io::SeekFrom::End(0))?;
|
||||
@@ -375,11 +390,19 @@ impl<T: Write + Seek + Sync + Send + 'static> Archive for Xp3ArchiveWriter<T> {
|
||||
let start = file.seek(std::io::SeekFrom::End(0))?;
|
||||
let size = {
|
||||
let mut writer = if is_compressed {
|
||||
let e = flate2::write::ZlibEncoder::new(
|
||||
&mut *file,
|
||||
flate2::Compression::new(zlib_compression_level),
|
||||
);
|
||||
Box::new(e) as Box<dyn Write>
|
||||
if use_zstd {
|
||||
let e = zstd::stream::Encoder::new(
|
||||
&mut *file,
|
||||
zstd_compression_level,
|
||||
)?;
|
||||
Box::new(e) as Box<dyn Write>
|
||||
} else {
|
||||
let e = flate2::write::ZlibEncoder::new(
|
||||
&mut *file,
|
||||
flate2::Compression::new(zlib_compression_level),
|
||||
);
|
||||
Box::new(e) as Box<dyn Write>
|
||||
}
|
||||
} else {
|
||||
Box::new(&mut *file) as Box<dyn Write>
|
||||
};
|
||||
@@ -474,12 +497,18 @@ impl<T: Write + Seek + Sync + Send + 'static> Archive for Xp3ArchiveWriter<T> {
|
||||
}
|
||||
let index_data = index_data.into_inner();
|
||||
if self.compress_index {
|
||||
let mut e = flate2::write::ZlibEncoder::new(
|
||||
Vec::new(),
|
||||
flate2::Compression::new(self.zlib_compression_level),
|
||||
);
|
||||
e.write_all(&index_data)?;
|
||||
let compressed_index = e.finish()?;
|
||||
let compressed_index = if self.use_zstd {
|
||||
let mut e = zstd::stream::Encoder::new(Vec::new(), self.zstd_compression_level)?;
|
||||
e.write_all(&index_data)?;
|
||||
e.finish()?
|
||||
} else {
|
||||
let mut e = flate2::write::ZlibEncoder::new(
|
||||
Vec::new(),
|
||||
flate2::Compression::new(self.zlib_compression_level),
|
||||
);
|
||||
e.write_all(&index_data)?;
|
||||
e.finish()?
|
||||
};
|
||||
file.write_u8(TVP_XP3_INDEX_ENCODE_ZLIB)?;
|
||||
file.write_u64(compressed_index.len() as u64)?;
|
||||
file.write_u64(index_data.len() as u64)?;
|
||||
|
||||
@@ -495,6 +495,9 @@ pub struct ExtraConfig {
|
||||
#[default(num_cpus::get())]
|
||||
/// Workers count for compress files in Kirikiri XP3 archive when creating in parallel. Default is CPU cores count.
|
||||
pub xp3_compress_workers: usize,
|
||||
#[cfg(feature = "kirikiri-arc")]
|
||||
/// Use zstd compression for files in Kirikiri XP3 archive when creating. (Warning: Kirikiri engine don't support this. Hook is required.)
|
||||
pub xp3_zstd: bool,
|
||||
}
|
||||
|
||||
#[derive(Clone, Copy, Debug, ValueEnum, PartialEq, Eq, PartialOrd, Ord)]
|
||||
|
||||
Reference in New Issue
Block a user