///|
pub(all) struct VerificationScope {
complete : Bool
selected_files : Array[Int32]
required_files : Array[Int32]
}
///|
priv struct VerifyPlan {
scope : VerificationScope
selected : Array[Bool]
v1_pieces : Array[Bool]
}
///|
fn marked_indices(mask : Array[Bool]) -> Array[Int32] {
let indices : Array[Int32] = []
for i, marked in mask {
if marked {
indices.push(i)
}
}
indices
}
///|
fn plan_verification(
parsed : ParsedTorrent,
requested : Array[Int32]?,
) -> VerifyPlan raise CrateError {
let selected = Array::make(parsed.summary.files.length(), false)
match requested {
None => selected.fill(true)
Some(indices) => {
if indices.is_empty() {
reject("selection", "select at least one file")
}
for index in indices {
if index < 0 || index >= selected.length() {
reject("selection", "file index is outside inspected file list")
}
selected[index] = true
}
}
}
let v1_pieces = Array::make(parsed.pieces.length() / 20, false)
let piece = parsed.summary.piece_length.to_int64()
let indices = marked_indices(selected)
let complete = indices.length() == selected.length()
let mut cursor = 0L
if complete {
v1_pieces.fill(true)
} else if parsed.summary.mode != V2 {
for entry in parsed.entries {
if !entry.padding && entry.length > 0L && selected[entry.source] {
let first = (cursor / piece).to_int()
let end = ((cursor + entry.length - 1L) / piece).to_int() + 1
for p in first.. 0L {
let first = (cursor / piece).to_int()
let end = ((cursor + entry.length - 1L) / piece).to_int() + 1
for p in first.. VerificationScope raise CrateError {
plan_verification(parse_torrent(torrent), selected_files).scope
}