///|
priv enum PlannedInstruction {
PlannedAdd(target_offset~ : Int, size~ : Int)
PlannedRun(byte~ : Byte, size~ : Int)
PlannedCopy(address~ : Int, size~ : Int)
}
///|
priv struct WindowPlan {
target_offset : Int
target_size : Int
source_size : Int
source_position : Int
instructions : Array[PlannedInstruction]
}
///|
fn basic_window_plan(target_offset : Int, target_size : Int) -> WindowPlan {
let instructions : Array[PlannedInstruction] = []
if target_size > 0 {
instructions.push(PlannedAdd(target_offset~, size=target_size))
}
{
target_offset,
target_size,
source_size: 0,
source_position: 0,
instructions,
}
}
///|
fn flush_pending_add(
instructions : Array[PlannedInstruction],
target_offset : Int,
literal_start : Int,
literal_end : Int,
) -> Unit {
if literal_start >= 0 && literal_end > literal_start {
instructions.push(
PlannedAdd(
target_offset=target_offset + literal_start,
size=literal_end - literal_start,
),
)
}
}
///|
fn index_consumed_target(finder : MatchFinder, start : Int, size : Int) -> Unit {
for position = start; position < start + size; position = position + 1 {
finder.insert_target(position)
}
}
///|
fn matched_window_plan(
source : Bytes,
target : Bytes,
target_offset : Int,
target_size : Int,
options : EncodeOptions,
) -> WindowPlan raise VcdiffError {
let instructions : Array[PlannedInstruction] = []
let finder = MatchFinder::new(source, target, target_offset, target_size)
let mut position = 0
let mut literal_start = -1
while position < target_size {
let absolute = target_offset + position
let run = run_length(target, absolute, target_offset + target_size)
if run >= options.run_threshold {
flush_pending_add(instructions, target_offset, literal_start, position)
literal_start = -1
instructions.push(PlannedRun(byte=target[absolute], size=run))
index_consumed_target(finder, position, run)
position += run
} else {
let best = finder.find_best(
position,
options.minimum_match,
options.max_candidate_chain,
options.enable_target_matches,
)
if best.size > 0 {
flush_pending_add(instructions, target_offset, literal_start, position)
literal_start = -1
instructions.push(PlannedCopy(address=best.address, size=best.size))
index_consumed_target(finder, position, best.size)
position += best.size
} else {
if literal_start < 0 {
literal_start = position
}
finder.insert_target(position)
position += 1
}
}
}
flush_pending_add(instructions, target_offset, literal_start, target_size)
{
target_offset,
target_size,
source_size: source.length(),
source_position: 0,
instructions,
}
}
///|
fn plan_windows(
source : Bytes,
target : Bytes,
options : EncodeOptions,
) -> Array[WindowPlan] raise VcdiffError {
let plans : Array[WindowPlan] = []
let mut offset = 0
while offset < target.length() {
let remaining = target.length() - offset
let size = if remaining < options.window_size {
remaining
} else {
options.window_size
}
if source.length() == 0 &&
!options.enable_target_matches &&
options.run_threshold > size {
plans.push(basic_window_plan(offset, size))
} else {
plans.push(matched_window_plan(source, target, offset, size, options))
}
offset += size
}
plans
}
///|
fn plan_output_size(plan : WindowPlan) -> Int {
let mut output_size = 0
for instruction in plan.instructions {
match instruction {
PlannedAdd(size~, ..) | PlannedRun(size~, ..) | PlannedCopy(size~, ..) =>
output_size += size
}
}
output_size
}