use std::path::PathBuf;
use irontide_core::FilePriority;
use irontide_session::TorrentInfo;
#[derive(Debug, Clone, PartialEq, Eq)]
pub struct FlatFileEntry {
pub path: PathBuf,
pub size: u64,
pub progress: u64,
pub priority: FilePriority,
}
#[must_use]
pub fn build_flat(
info: &TorrentInfo,
progress: &[u64],
priorities: &[FilePriority],
) -> Vec<FlatFileEntry> {
info.files
.iter()
.enumerate()
.map(|(i, entry)| FlatFileEntry {
path: entry.path.clone(),
size: entry.length,
progress: progress.get(i).copied().unwrap_or(0),
priority: priorities.get(i).copied().unwrap_or(FilePriority::Normal),
})
.collect()
}
#[cfg(test)]
mod tests {
use super::*;
use irontide_core::Id20;
use irontide_session::FileInfo;
fn info(files: Vec<(&str, u64)>) -> TorrentInfo {
TorrentInfo {
info_hash: Id20([0u8; 20]),
name: "test".into(),
total_length: files.iter().map(|(_, n)| *n).sum(),
piece_length: 16_384,
num_pieces: 1,
files: files
.into_iter()
.map(|(p, n)| FileInfo {
path: PathBuf::from(p),
length: n,
})
.collect(),
private: false,
}
}
#[test]
fn build_flat_empty_info() {
let i = info(vec![]);
let out = build_flat(&i, &[], &[]);
assert!(out.is_empty());
}
#[test]
fn build_flat_single_file() {
let i = info(vec![("a.bin", 1000)]);
let out = build_flat(&i, &[500], &[FilePriority::High]);
assert_eq!(out.len(), 1);
assert_eq!(out[0].path, PathBuf::from("a.bin"));
assert_eq!(out[0].size, 1000);
assert_eq!(out[0].progress, 500);
assert_eq!(out[0].priority, FilePriority::High);
}
#[test]
fn build_flat_nested_files_preserve_paths() {
let i = info(vec![
("readme.txt", 100),
("video/intro.mp4", 50_000),
("video/extras/bts.mkv", 80_000),
]);
let out = build_flat(
&i,
&[100, 25_000, 0],
&[FilePriority::Normal, FilePriority::High, FilePriority::Skip],
);
assert_eq!(out.len(), 3);
assert_eq!(out[0].path, PathBuf::from("readme.txt"));
assert_eq!(out[1].path, PathBuf::from("video/intro.mp4"));
assert_eq!(out[2].path, PathBuf::from("video/extras/bts.mkv"));
}
#[test]
fn build_flat_priority_progress_aligned_by_index() {
let i = info(vec![("a", 10), ("b", 20), ("c", 30)]);
let out = build_flat(
&i,
&[1, 2, 3],
&[FilePriority::Skip, FilePriority::Low, FilePriority::High],
);
assert_eq!(out[0].progress, 1);
assert_eq!(out[0].priority, FilePriority::Skip);
assert_eq!(out[1].progress, 2);
assert_eq!(out[1].priority, FilePriority::Low);
assert_eq!(out[2].progress, 3);
assert_eq!(out[2].priority, FilePriority::High);
}
#[test]
fn build_flat_length_mismatch_saturates_to_defaults() {
let i = info(vec![("a", 10), ("b", 20), ("c", 30)]);
let out = build_flat(&i, &[1, 2], &[FilePriority::High]);
assert_eq!(out.len(), 3);
assert_eq!(out[0].progress, 1);
assert_eq!(out[0].priority, FilePriority::High);
assert_eq!(out[1].progress, 2);
assert_eq!(out[1].priority, FilePriority::Normal);
assert_eq!(out[2].progress, 0);
assert_eq!(out[2].priority, FilePriority::Normal);
}
}