feat: new 7z output parser

This commit is contained in:
DecDuck
2025-12-18 17:36:47 +11:00
parent e37e3f620b
commit d7f9faf602
7 changed files with 54 additions and 33 deletions
+1 -1
View File
@@ -219,7 +219,7 @@ dependencies = [
[[package]]
name = "droplet-rs"
version = "0.11.1"
version = "0.11.2"
dependencies = [
"anyhow",
"async-trait",
+2 -2
View File
@@ -2,7 +2,7 @@
edition = "2021"
authors = ["Drop-OSS"]
name = "droplet-rs"
version = "0.11.1"
version = "0.11.2"
license = "AGPL-3.0-only"
description = "Droplet is a `napi.rs` Rust/Node.js package full of high-performance and low-level utils for Drop"
@@ -11,7 +11,7 @@ hex = "0.4.3"
time = "0.3.41"
ring = "0.17.14"
dyn-clone = "1.0.20"
tokio = { version = "^1.48.0", features = ["process", "fs", "io-util", "sync", "macros", "rt-multi-thread"] }
tokio = { version = "^1.48.0", features = ["process", "fs", "io-util", "rt", "rt-multi-thread", "macros", "sync"] }
anyhow = "1.0.100"
async-trait = "0.1.89"
serde = { version = "1.0.228", features = ["derive"] }
+4 -1
View File
@@ -4,4 +4,7 @@
pub mod file_utils;
pub mod ssl;
pub mod versions;
pub mod manifest;
pub mod manifest;
#[cfg(test)]
pub mod tests;
+2
View File
@@ -29,6 +29,7 @@ pub struct FileEntry {
pub struct ChunkData {
files: Vec<FileEntry>,
checksum: String,
//iv: [u8; 16]
}
#[derive(Serialize)]
@@ -155,6 +156,7 @@ pub async fn generate_manifest_rusty<T: Fn(String), V: Fn(f32)>(
let mut chunk_data = ChunkData {
files: Vec::new(),
checksum: String::new(),
//iv:
};
let mut chunk_length = 0;
+11
View File
@@ -0,0 +1,11 @@
use std::path::PathBuf;
use crate::versions::create_backend_constructor;
#[tokio::test]
pub async fn test_7z_list() {
let zip_path = "/home/decduck/Dev/droplet/assets/TheGame.zip";
let mut backend = create_backend_constructor(&PathBuf::from(zip_path)).unwrap()().unwrap();
let files = backend.list_files().await.unwrap();
tokio::fs::write("./test.txt", format!("{:?}", files)).await.unwrap();
}
+33 -29
View File
@@ -15,6 +15,7 @@ use tokio::{
io::{AsyncReadExt as _, AsyncSeekExt as _, BufReader},
process::Command,
};
use x509_parser::nom::InputIter;
use crate::versions::types::{MinimumFileObject, VersionBackend, VersionFile};
@@ -148,7 +149,7 @@ impl ZipVersionBackend {
impl VersionBackend for ZipVersionBackend {
async fn list_files(&mut self) -> anyhow::Result<Vec<VersionFile>> {
let mut list_command = Command::new("7z");
list_command.args(vec!["l", "-ba", &self.path]);
list_command.args(vec!["l", &self.path]);
let result = list_command.output().await?;
if !result.status.success() {
return Err(anyhow!(
@@ -157,35 +158,38 @@ impl VersionBackend for ZipVersionBackend {
));
}
let raw_result = String::from_utf8(result.stdout)?;
let files = raw_result
.split("\n")
.filter(|v| !v.is_empty())
.map(|v| v.split(" ").filter(|v| !v.is_empty()));
let mut results = Vec::new();
let mut lines = raw_result.split("\n").skip(11);
for file in files {
let values = file.collect::<Vec<&str>>();
let mut iter = values.iter();
let (date, time, attrs, size, compress, name) = (
iter.next().expect("failed to read date"),
iter.next().expect("failed to read time"),
iter.next().expect("failed to read attrs"),
iter.next().expect("failed to read size"),
iter.next().expect("failed to read compress"),
iter.collect::<Vec<&&str>>(),
);
if attrs.starts_with("D") {
continue;
}
results.push(VersionFile {
relative_filename: name
.into_iter().copied()
.fold(String::new(), |a, b| a + b + " ")
.trim_end()
.to_owned(),
permission: 0o744, // owner r/w/x, everyone else, read
size: size.parse().unwrap(),
});
let mut column_lines = lines
.find(|v| v.starts_with('-'))
.ok_or(anyhow!("invalid 7z output"))?
.chars();
let file_lines = lines.take_while(|v| !v.starts_with("-"));
/*
Date Time Attr Size Compressed Name
------------------- ----- ------------ ------------ ------------------------
*/
let datetime_pos = 0usize;
let attrs_pos = datetime_pos + column_lines.position(|v| v == ' ').unwrap() + 1;
let size_pos = attrs_pos + column_lines.position(|v| v == ' ').unwrap() + 1;
let compressed_size_pos = size_pos + column_lines.position(|v| v == ' ').unwrap() + 1;
let name_pos = compressed_size_pos + column_lines.position(|v| v == ' ').unwrap() + 1;
let mut results = Vec::new();
for file in file_lines {
let name = file[name_pos..].trim();
let size = file[size_pos..compressed_size_pos].trim();
let size = str::parse::<u64>(size)?;
let version_file = VersionFile {
relative_filename: name.to_string(),
permission: 0o744,
size: size,
};
results.push(version_file);
}
Ok(results)
+1
View File
@@ -0,0 +1 @@
[VersionFile { relative_filename: "setup.exe", permission: 484, size: 1024000000 }, VersionFile { relative_filename: "test file.txt", permission: 484, size: 12 }]