///|
/// Coalesced complement of verified reusable target blocks. Fresh snapshot.
pub fn SeedPlan::missing_ranges(self : SeedPlan) -> Array[ByteRange] {
target_gaps(self.spec.length, self.records.iter().map(r => r.target))
}
///|
fn target_gaps(length : Int64, ranges : Iter[ByteRange]) -> Array[ByteRange] {
let gaps = []
let mut cursor = 0L
for range in ranges {
if cursor < range.start {
gaps.push({ start: cursor, end: range.start, })
}
cursor = range.end
}
if cursor < length {
gaps.push({ start: cursor, end: length, })
}
gaps
}
///|
/// Logical bytes not found in this seed, excluding HTTP overhead and retries.
pub fn SeedPlan::download_bytes(self : SeedPlan) -> Int64 {
self.spec.length - self.reused_bytes
}
///|
/// Deterministic MFLPLAN1 report. A preview is a snapshot, not write authority.
pub fn SeedPlan::to_json(self : SeedPlan) -> Json {
Json::array([
Json::string("MFLPLAN1"),
Json::string(self.spec.length.to_string()),
Json::string(self.scanned_bytes.to_string()),
Json::string(self.reused_bytes.to_string()),
Json::string(self.download_bytes().to_string()),
Json::array(
self.records.map(r => {
Json::array([
Json::string(r.source.start.to_string()),
Json::string(r.source.end.to_string()),
Json::string(r.target.start.to_string()),
Json::string(r.target.end.to_string()),
])
}),
),
Json::array(
self
.missing_ranges()
.map(r => {
Json::array([
Json::string(r.start.to_string()),
Json::string(r.end.to_string()),
])
}),
),
])
}