///|
const VCD_MAGIC_1 : Byte = b'\xd6'
///|
const VCD_MAGIC_2 : Byte = b'\xc3'
///|
const VCD_MAGIC_3 : Byte = b'\xc4'
///|
const VCD_VERSION : Byte = b'\x00'
///|
const VCD_DECOMPRESS : Int = 0x01
///|
const VCD_CODETABLE : Int = 0x02
///|
const VCD_SOURCE : Int = 0x01
///|
const VCD_TARGET : Int = 0x02
///|
priv struct ParsedFileHeader {
length : Int
}
///|
priv struct ParsedWindow {
offset : Int
indicator : Int
source_size : Int
source_position : Int
delta_length : Int
target_size : Int
data_offset : Int
instruction_offset : Int
address_offset : Int
data : Bytes
instructions : Bytes
addresses : Bytes
}
///|
priv struct ParsedDelta {
header : ParsedFileHeader
windows : Array[ParsedWindow]
}
///|
fn checked_section_sum(
offset : Int,
first : Int,
second : Int,
third : Int,
) -> Int raise VcdiffError {
if first > MAX_PORTABLE_INT - second {
raise IntegerOverflow(offset~)
}
let partial = first + second
if partial > MAX_PORTABLE_INT - third {
raise IntegerOverflow(offset~)
}
partial + third
}
///|
fn parse_file_header(cursor : ByteCursor) -> ParsedFileHeader raise VcdiffError {
let start = cursor.offset()
let first = cursor.read_byte()
let second = cursor.read_byte()
let third = cursor.read_byte()
if first != VCD_MAGIC_1 || second != VCD_MAGIC_2 || third != VCD_MAGIC_3 {
raise InvalidMagic(offset=start)
}
let version_offset = cursor.offset()
let version = cursor.read_byte()
if version != VCD_VERSION {
raise UnsupportedVersion(offset=version_offset, version=version.to_int())
}
let indicator_offset = cursor.offset()
let indicator = cursor.read_byte().to_int()
if indicator > VCD_DECOMPRESS + VCD_CODETABLE {
raise InvalidHeader(
offset=indicator_offset,
reason="reserved header indicator bits are set",
)
}
if (indicator & VCD_DECOMPRESS) != 0 {
raise UnsupportedFeature(
offset=indicator_offset,
feature="secondary compressor",
)
}
if (indicator & VCD_CODETABLE) != 0 {
raise UnsupportedFeature(
offset=indicator_offset,
feature="custom code table",
)
}
{ length: cursor.offset() - start }
}
///|
fn parse_window(cursor : ByteCursor) -> ParsedWindow raise VcdiffError {
let window_offset = cursor.offset()
let indicator_offset = cursor.offset()
let indicator = cursor.read_byte().to_int()
if indicator > VCD_SOURCE + VCD_TARGET {
raise InvalidWindow(
offset=indicator_offset,
reason="reserved window indicator bits are set",
)
}
if (indicator & VCD_SOURCE) != 0 && (indicator & VCD_TARGET) != 0 {
raise InvalidWindow(
offset=indicator_offset,
reason="VCD_SOURCE and VCD_TARGET cannot both be set",
)
}
let mut source_size = 0
let mut source_position = 0
if indicator != 0 {
source_size = read_varint(cursor)
source_position = read_varint(cursor)
}
let delta_length_offset = cursor.offset()
let delta_length = read_varint(cursor)
let delta = cursor.read_subcursor(delta_length)
let target_size = read_varint(delta)
let delta_indicator_offset = delta.offset()
let delta_indicator = delta.read_byte().to_int()
if delta_indicator != 0 {
if (delta_indicator & 0x07) != 0 {
raise UnsupportedFeature(
offset=delta_indicator_offset,
feature="secondary-compressed window section",
)
}
raise InvalidWindow(
offset=delta_indicator_offset,
reason="reserved delta indicator bits are set",
)
}
let data_length = read_varint(delta)
let instruction_length = read_varint(delta)
let address_length = read_varint(delta)
let section_length = checked_section_sum(
delta.offset(),
data_length,
instruction_length,
address_length,
)
if section_length != delta.remaining() {
raise LengthMismatch(
offset=delta.offset(),
expected=section_length,
actual=delta.remaining(),
)
}
let data_offset = delta.offset()
let data = delta.read_exact(data_length)
let instruction_offset = delta.offset()
let instructions = delta.read_exact(instruction_length)
let address_offset = delta.offset()
let addresses = delta.read_exact(address_length)
if delta.remaining() != 0 {
raise LengthMismatch(
offset=delta.offset(),
expected=delta_length,
actual=delta_length - delta.remaining(),
)
}
if delta_length < 5 {
raise InvalidWindow(
offset=delta_length_offset,
reason="delta encoding is shorter than its mandatory fields",
)
}
{
offset: window_offset,
indicator,
source_size,
source_position,
delta_length,
target_size,
data_offset,
instruction_offset,
address_offset,
data,
instructions,
addresses,
}
}
///|
fn parse_delta(delta : Bytes) -> ParsedDelta raise VcdiffError {
let cursor = ByteCursor::new(delta)
let header = parse_file_header(cursor)
let windows : Array[ParsedWindow] = []
while cursor.remaining() > 0 {
windows.push(parse_window(cursor))
}
{ header, windows }
}
///|
/// Validates the RFC file and window framing without executing instructions.
///
/// The returned value is the number of target windows found.
pub fn validate_structure(delta : Bytes) -> Int raise VcdiffError {
let parsed = parse_delta(delta)
let mut declared_target_bytes = 0
for window in parsed.windows {
if declared_target_bytes > MAX_PORTABLE_INT - window.target_size {
raise IntegerOverflow(offset=window.offset)
}
declared_target_bytes += window.target_size
ignore(window.indicator)
ignore(window.source_size)
ignore(window.source_position)
ignore(window.delta_length)
ignore(window.data_offset)
ignore(window.instruction_offset)
ignore(window.address_offset)
ignore(window.data.length())
ignore(window.instructions.length())
ignore(window.addresses.length())
}
ignore(parsed.header.length)
parsed.windows.length()
}