2 个版本
0.1.1 | 2023 年 4 月 19 日 |
---|---|
0.1.0 | 2023 年 4 月 16 日 |
#679 in 文件系统
50KB
762 行
FTLDat-rs
Rust 实现的 FTLDat - 一个用于解包和重新打包 .dat 文件的简单库,该文件由游戏《Into the Breach》和《Faster than Light》(直到版本 1.6.1)使用。
此库还支持 FTL 版本 1.6.1 之后使用的 PKG 格式。
使用说明
打开包相当简单
use ftldat::Package;
let package = Package::from_path_dat("path/to/file.dat");
// Can now query the package's contents, list or iterate...
println!("Number of entries: {}", &package.entry_count());
println!("Does the package contain a file at path 'test.txt'? {}", &package.entry_exists("test.txt"));
// List paths of all files within the package
let inner_paths = package.inner_paths();
for entry in package.iter() {
// Do something with each entry
}
底层文件是内存映射的,仅在首次创建 package
实例或获取条目内容时读取。
可以修改包以添加、替换或删除条目
use ftldat::{Package, PackageEntry};
let mut package = Package::from_path_dat("path/to/file.dat");
// `add_entry` will only add the entry if the package does NOT already contain an entry at the specified
// path (test.txt). Otherwise, an error is returned.
package.add_entry(PackageEntry::from_string("test.txt", "My text file's content."));
// `put_entry` will overwrite the entry at the specified path (test2.txt) with the provided entry.
package.put_entry(PackageEntry::from_string("test2.txt", "Lorem ipsum dolor sit amet"));
// Remove individual entry
package.remove_entry("test.txt");
// Remove all entries
package.clear();
条目可以通过几种方式创建
// Directly from a string, mostly useful for testing (functionally the same as in-memory byte array)
let entry = PackageEntry::from_string("file.txt", "Lorem ipsum dolor sit amet");
// From a file on disk
let entry = PackageEntry::from_file("file.png", "path/to/file.png");
// From an in-memory byte array
let content = [0, 1, 2, 3];
PackageEntry::from_byte_array("file.bin", content.into());
// From a memory-mapped file
let mmap = ... // Reference to the memory map
let mmap_rc = Rc::new(mmap);
let offset = ... // Offset to the beginning of the entry's content within the memory-mapped file
let length = ... // Number of bytes that make up the entry's content
let entry = PackageEntry::from_memory_mapped_file(
"file.wav",
mmap_rc.clone(),
offset,
length
);
可以将包写回文件
use ftldat::Package;
let package = Package::from_path_dat("path/to/file.dat");
// `write_to_path_*` does not consume the `package`, allowing for multiple writes, but only allows writing
// to files other than the file from which the package was originally loaded.
package.to_path_dat("path/to/other/file.dat");
// `write_into_path_*` consumes the `package`, but releases file system resources and allows overwriting
// the file from which the package was originally loaded.
package.write_into_path_dat(package, "path/to/file.dat");
也可以提取包的内容
use ftldat::Package;
let package = Package::from_path_dat("path/to/file.dat");
package.extract("destination/directory/");
许可证
该项目根据 GPLv3 许可证授权,因为其部分内容最初受到 Slipstream Mod Manager 实现的启发
改进区域
鉴于这个项目是我熟悉 Rust 的方式,肯定有很多改进的空间。以下是一些无序的建议
- 错误处理。尝试使用流行的错误处理 crate
thiserror
,但对此不太自信。 - 字符串的所有权,我只是使用了堆分配的 Strings 并四处复制它们
- 函数命名,遵循 Rust 正确的约定(
from
、into
等) - 将结构体序列化为字节的处理可能更好(尽管我喜欢将内存和磁盘上的表示分开)
依赖关系
~0.5–1MB
~22K SLoC