///|
fn pdf_util_cpdfjson_integer_field(
object : @syntax.PdfObject,
key : @core.PdfName,
) -> Int raise @core.PdfError {
match object.lookup_immediate(key) {
Some(PdfInteger(value)) => value
_ => raise BadText
}
}
///|
fn pdf_util_cpdfjson_check_stream_data(
params : @syntax.PdfObject,
) -> Unit raise @core.PdfError {
match params.lookup_immediate(pdf_util_cpdfjson_stream_data_included_key()) {
Some(PdfBoolean(false)) => raise BadText
_ => ()
}
}
///|
fn pdf_util_cpdfjson_root_number(
trailer : @syntax.PdfObject,
) -> Int raise @core.PdfError {
match trailer {
PdfDictionary(_) =>
match trailer.lookup_immediate(pdf_util_cpdfjson_root_key()) {
Some(PdfIndirect(number)) => number
_ => raise RootExpected
}
_ => raise RootExpected
}
}
///|
fn pdf_util_cpdfjson_item_number(json : Json) -> Int raise @core.PdfError {
match json {
Number(value, repr=_) => pdf_util_json_integral_number(value)
_ => raise BadText
}
}
///|
fn pdf_util_cpdfjson_read_item(
json : Json,
params : Ref[@syntax.PdfObject],
trailer : Ref[@syntax.PdfObject],
objects : Array[(Int, @syntax.PdfObject)],
) -> Unit raise @core.PdfError {
match json {
Array([number_json, object_json]) => {
let number = pdf_util_cpdfjson_item_number(number_json)
match number {
-1 => params.val = pdf_object_of_json(object_json)
0 => trailer.val = pdf_object_of_json(object_json)
value if value < 0 => ()
value => objects.push((value, pdf_object_of_json(object_json)))
}
}
_ => raise BadText
}
}
///|
/// Convert a CPDFJSON top-level array into an in-memory PDF document.
///
/// This ports cpdf's `pdf_of_json` document-input path. Object `-1` supplies
/// CPDFJSON parameters, object `0` supplies the trailer dictionary, positive
/// object numbers populate the document object table, and other negative
/// object numbers are ignored. `/CPDFJSONstreamdataincluded false` is rejected
/// because the stream bytes needed for reconstruction are not present.
pub fn pdf_document_of_json(json : Json) -> PdfDocument raise @core.PdfError {
let items = match json {
Array(values) => values
_ => raise BadText
}
let params = Ref::{ val: @syntax.PdfObject::PdfNull, }
let trailer = Ref::{ val: @syntax.PdfObject::PdfNull, }
let objects : Array[(Int, @syntax.PdfObject)] = Array(capacity=items.length())
for item in items {
pdf_util_cpdfjson_read_item(item, params, trailer, objects)
}
pdf_util_cpdfjson_check_stream_data(params.val)
let major = pdf_util_cpdfjson_integer_field(
params.val,
pdf_util_cpdfjson_major_version_key(),
)
let minor = pdf_util_cpdfjson_integer_field(
params.val,
pdf_util_cpdfjson_minor_version_key(),
)
let root = pdf_util_cpdfjson_root_number(trailer.val)
let document = pdf_document_empty()
document.set_version(major, minor)
document.set_root(root)
document.set_trailer_dict(trailer.val)
for entry in objects {
document.load_object_given_number(entry.0, entry.1)
}
document
}
///|
/// Read a CPDFJSON document from UTF-8 JSON bytes.
///
/// This is the in-memory byte-input counterpart of cpdf's
/// `Cpdfjson.of_input`.
pub fn pdf_document_of_json_blob(
data : BytesView,
) -> PdfDocument raise @core.PdfError {
let text = @utf8.decode(data) catch { _ => raise BadText }
let json = @json.parse(text) catch { _ => raise BadText }
pdf_document_of_json(json)
}