///|
priv struct PdfReconstructedXRefCoverage {
sections : Array[(Int, @core.PdfNumberSet)]
}
///|
fn pdf_reconstructed_trailer_root_numbers(
classic_sections : ArrayView[(Int, PdfXRefSection)],
xref_stream_sections : ArrayView[PdfXRefSection],
) -> @core.PdfNumberSet {
let roots = @core.pdf_number_set([])
for item in classic_sections {
match item.1.trailer.lookup_immediate(pdf_reader_root_name()) {
Some(PdfIndirect(root)) => roots.add(root)
_ => ()
}
}
for section in xref_stream_sections {
match section.trailer.lookup_immediate(pdf_reader_root_name()) {
Some(PdfIndirect(root)) => roots.add(root)
_ => ()
}
}
roots
}
///|
fn pdf_reconstructed_classic_xref_entry_is_verified(
data : BytesView,
entries : ArrayView[PdfClassicXRefEntry],
xref_index : PdfClassicXRefIndex,
xref : PdfClassicXRefEntry,
) -> Bool {
if !xref.in_use {
true
} else {
let cursor = byte_cursor_of_view(data)
try {
cursor.seek_absolute(xref.offset)
let parsed = pdf_cursor_read_first_indirect_object_at_current(
cursor,
entries,
xref_index=Some(xref_index),
)
parsed.number == xref.object_number &&
parsed.generation == xref.generation
} catch {
_ => false
}
}
}
///|
fn pdf_reconstructed_xref_coverage(
data : BytesView,
classic_sections : ArrayView[(Int, PdfXRefSection)],
xref_stream_sections : ArrayView[PdfXRefSection],
) -> PdfReconstructedXRefCoverage {
let covered : Array[(Int, @core.PdfNumberSet)] = Array::new(
capacity=classic_sections.length() + xref_stream_sections.length(),
)
let trailer_roots = pdf_reconstructed_trailer_root_numbers(
classic_sections, xref_stream_sections,
)
for item in classic_sections {
let (offset, section) = item
let numbers = @core.pdf_number_set([])
let xref_index = pdf_classic_xref_index(section.entries)
for xref in section.entries {
if xref.object_number > 0 &&
(xref.in_use || !trailer_roots.contains(xref.object_number)) &&
pdf_reconstructed_classic_xref_entry_is_verified(
data,
section.entries,
xref_index,
xref,
) {
numbers.add(xref.object_number)
}
}
covered.push((offset, numbers))
}
for section in xref_stream_sections {
match section.stream_object_offset {
Some(offset) => {
let numbers = @core.pdf_number_set([])
for xref in section.entries {
if xref.object_number > 0 &&
(xref.in_use || !trailer_roots.contains(xref.object_number)) {
numbers.add(xref.object_number)
}
}
covered.push((offset, numbers))
}
None => ()
}
}
{ sections: covered }
}
///|
fn PdfReconstructedXRefCoverage::contains(
self : PdfReconstructedXRefCoverage,
object_number : Int,
object_offset : Int,
) -> Bool {
for section in self.sections {
let (section_offset, object_numbers) = section
if object_offset <= section_offset && object_numbers.contains(object_number) {
break true
}
} nobreak {
false
}
}