///|
priv struct PdfClassicReadPlan {
xrefs : Array[@reader.PdfClassicXRefEntry]
xref_stream_refs : Array[(Int, Int)]
trailer : @syntax.PdfObject
}
///|
fn pdf_read_reader_revision_target(
revision : Int?,
) -> Int? raise @core.PdfError {
match revision {
Some(value) if value < 1 => raise BadRevision
_ => revision
}
}
///|
fn pdf_reader_revision_reads_section(
revision : Int?,
current_revision : Int,
) -> Bool {
match revision {
Some(target) => target <= current_revision
None => true
}
}
///|
fn pdf_reader_revision_selects_trailer(
revision : Int?,
current_revision : Int,
depth : Int,
) -> Bool {
match revision {
Some(target) => target == current_revision
None => depth == 0
}
}
///|
fn pdf_reader_classic_read_plan(
cursor : @core.ByteCursor,
xref_position : Int,
revision : Int?,
) -> PdfClassicReadPlan raise @core.PdfError {
let xrefs : Array[@reader.PdfClassicXRefEntry] = []
let xref_seen = @core.pdf_number_set([])
let mut trailer = @syntax.PdfDictionary([])
let xref_stream_refs : Array[(Int, Int)] = []
let mut current_xref = xref_position
let mut done = false
let mut depth = 0
while !done {
if depth >= 1024 {
raise XRefExpected
}
cursor.seek_absolute(current_xref)
let section = pdf_cursor_read_xref_section(cursor)
let current_revision = depth + 1
let read_section = pdf_reader_revision_reads_section(
revision, current_revision,
)
if read_section {
@reader.pdf_classic_xrefs_add_newer_first_with_seen(
xrefs,
xref_seen,
section.entries,
)
match section.stream_object_number {
Some(number) => xref_stream_refs.push((number, current_xref))
None => ()
}
}
let current_trailer = section.trailer
if pdf_reader_revision_selects_trailer(revision, current_revision, depth) {
trailer = current_trailer
}
if read_section {
match @reader.pdf_trailer_xref_stream_position(current_trailer) {
Some(xref_stream_position) => {
cursor.seek_absolute(xref_stream_position)
let stream_section = pdf_cursor_read_xref_stream_section(cursor)
@reader.pdf_classic_xrefs_add_newer_first_with_seen(
xrefs,
xref_seen,
stream_section.entries,
)
guard stream_section.stream_object_number is Some(stream_number) else {
raise XRefEntryExpected
}
xref_stream_refs.push((stream_number, xref_stream_position))
}
None => ()
}
}
match @reader.pdf_trailer_prev_position(current_trailer) {
Some(previous) => current_xref = previous
None => if read_section { done = true } else { raise BadRevision }
}
depth += 1
}
{ xrefs, xref_stream_refs, trailer, }
}