mirror of
https://github.com/encounter/nod.git
synced 2026-07-10 12:18:48 -07:00
Fix SplitFileReader logic for parts
This commit is contained in:
+82
-11
@@ -28,21 +28,19 @@ fn split_path_1(input: &Path, index: u32) -> PathBuf {
|
||||
let input_str = input.to_str().unwrap_or("[INVALID]");
|
||||
let mut out = input_str.to_string();
|
||||
out.push('.');
|
||||
out.push(char::from_digit(index, 10).unwrap());
|
||||
out.push_str(&index.to_string());
|
||||
PathBuf::from(out)
|
||||
}
|
||||
|
||||
// .part1.iso, .part2.iso, etc.
|
||||
fn split_path_2(input: &Path, index: u32) -> PathBuf {
|
||||
let extension = input.extension().and_then(|s| s.to_str()).unwrap_or("iso");
|
||||
let input_without_ext = input.with_extension("");
|
||||
let input_str = input_without_ext.to_str().unwrap_or("[INVALID]");
|
||||
let mut out = input_str.to_string();
|
||||
out.push_str(".part");
|
||||
out.push(char::from_digit(index, 10).unwrap());
|
||||
out.push('.');
|
||||
out.push_str(extension);
|
||||
PathBuf::from(out)
|
||||
let stem = input.file_stem().and_then(|s| s.to_str()).unwrap_or("[INVALID]");
|
||||
let base_stem = stem
|
||||
.rsplit_once(".part")
|
||||
.filter(|(_, suffix)| !suffix.is_empty() && suffix.chars().all(|c| c.is_ascii_digit()))
|
||||
.map_or(stem, |(base, _)| base);
|
||||
input.with_file_name(format!("{base_stem}.part{index}.{extension}"))
|
||||
}
|
||||
|
||||
// .wbf1, .wbf2, etc.
|
||||
@@ -51,7 +49,7 @@ fn split_path_3(input: &Path, index: u32) -> PathBuf {
|
||||
let mut chars = input_str.chars();
|
||||
chars.next_back();
|
||||
let mut out = chars.as_str().to_string();
|
||||
out.push(char::from_digit(index, 10).unwrap());
|
||||
out.push_str(&index.to_string());
|
||||
PathBuf::from(out)
|
||||
}
|
||||
|
||||
@@ -72,17 +70,23 @@ impl SplitFileReader {
|
||||
}
|
||||
for path_fn in [split_path_1, split_path_2, split_path_3] {
|
||||
let mut index = 1;
|
||||
let mut found_split = false;
|
||||
loop {
|
||||
let path = path_fn(path, index);
|
||||
if path == files[0].inner {
|
||||
index += 1;
|
||||
continue;
|
||||
}
|
||||
if let Ok(metadata) = path.metadata() {
|
||||
files.push(Split { inner: path, begin, size: metadata.len() });
|
||||
begin += metadata.len();
|
||||
index += 1;
|
||||
found_split = true;
|
||||
} else {
|
||||
break;
|
||||
}
|
||||
}
|
||||
if index > 1 {
|
||||
if found_split {
|
||||
break;
|
||||
}
|
||||
}
|
||||
@@ -140,3 +144,70 @@ impl DiscStream for SplitFileReader {
|
||||
|
||||
fn stream_len(&mut self) -> io::Result<u64> { Ok(self.len()) }
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use std::{
|
||||
fs,
|
||||
time::{SystemTime, UNIX_EPOCH},
|
||||
};
|
||||
|
||||
use super::*;
|
||||
|
||||
struct TestDir(PathBuf);
|
||||
|
||||
impl TestDir {
|
||||
fn new() -> Self {
|
||||
let mut path = std::env::temp_dir();
|
||||
let nanos = SystemTime::now().duration_since(UNIX_EPOCH).unwrap().as_nanos();
|
||||
path.push(format!("nod-split-test-{}-{nanos}", std::process::id()));
|
||||
fs::create_dir(&path).unwrap();
|
||||
Self(path)
|
||||
}
|
||||
|
||||
fn path(&self) -> &Path { &self.0 }
|
||||
}
|
||||
|
||||
impl Drop for TestDir {
|
||||
fn drop(&mut self) {
|
||||
let _ = fs::remove_dir_all(&self.0);
|
||||
}
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn part_zero_input_builds_next_part_paths() {
|
||||
let input = Path::new("/tmp/game.part0.iso");
|
||||
|
||||
assert_eq!(split_path_2(input, 1), PathBuf::from("/tmp/game.part1.iso"));
|
||||
assert_eq!(split_path_2(input, 10), PathBuf::from("/tmp/game.part10.iso"));
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn reads_part_zero_sequence_across_multiple_parts() {
|
||||
let dir = TestDir::new();
|
||||
for index in 0..=10 {
|
||||
let path = dir.path().join(format!("game.part{index}.iso"));
|
||||
fs::write(path, [index as u8]).unwrap();
|
||||
}
|
||||
|
||||
let input = dir.path().join("game.part0.iso");
|
||||
let mut reader = SplitFileReader::new(&input).unwrap();
|
||||
let mut buf = [0; 11];
|
||||
reader.read_exact_at(&mut buf, 0).unwrap();
|
||||
|
||||
assert_eq!(reader.len(), 11);
|
||||
assert_eq!(buf, [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10]);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn numbered_input_is_not_added_twice() {
|
||||
let dir = TestDir::new();
|
||||
let input = dir.path().join("game.part1.iso");
|
||||
fs::write(&input, [1]).unwrap();
|
||||
|
||||
let reader = SplitFileReader::new(&input).unwrap();
|
||||
|
||||
assert_eq!(reader.len(), 1);
|
||||
assert_eq!(reader.files.len(), 1);
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user