///|
let pdf_metadata_xml_uri : String = "http://www.w3.org/XML/1998/namespace"
///|
let pdf_metadata_xmlns_uri : String = "http://www.w3.org/2000/xmlns/"
///|
fn pdf_metadata_xml_decode_name(
value : BytesView,
) -> String raise @core.PdfError {
@utf8.decode(value) catch {
_ => raise InvalidUTF8
}
}
///|
fn pdf_metadata_xml_is_name_boundary(byte : Byte) -> Bool {
let value = byte.to_int()
value == 9 ||
value == 10 ||
value == 13 ||
value == 32 ||
value == 47 ||
value == 61 ||
value == 62
}
///|
fn pdf_metadata_xml_skip_space(data : BytesView, start : Int) -> Int {
let mut index = start
while index < data.length() && pdf_metadata_is_xml_space(data[index]) {
index += 1
}
index
}
///|
fn pdf_metadata_xml_read_name(
data : BytesView,
start : Int,
) -> (Bytes, Int) raise @core.PdfError {
let mut index = start
while index < data.length() && !pdf_metadata_xml_is_name_boundary(data[index]) {
index += 1
}
guard index > start else { raise BadText }
(data[start:index].to_owned(), index)
}
///|
fn pdf_metadata_xml_uri_lookup(
context : ArrayView[(String, String)],
prefix : String,
) -> String? {
for offset in 0.. @metadata.PdfMetadataXmlName raise @core.PdfError {
let colon = pdf_metadata_find_byte(qname, 0, 58)
if colon >= 0 {
let prefix = pdf_metadata_xml_decode_name(qname[:colon])
let local_name = pdf_metadata_xml_decode_name(qname[colon + 1:])
let uri = if prefix == "xml" {
pdf_metadata_xml_uri
} else if prefix == "xmlns" {
pdf_metadata_xmlns_uri
} else {
match pdf_metadata_xml_uri_lookup(context, prefix) {
Some(uri) => uri
None => raise BadText
}
}
{ uri, local_name, prefix: Some(prefix), }
} else {
let local_name = pdf_metadata_xml_decode_name(qname)
let uri = if is_attribute {
if local_name == "xmlns" {
pdf_metadata_xmlns_uri
} else {
""
}
} else {
match pdf_metadata_xml_uri_lookup(context, "") {
Some(uri) => uri
None => ""
}
}
{ uri, local_name, prefix: None, }
}
}
///|
fn pdf_metadata_xml_parse_raw_attributes(
data : BytesView,
start : Int,
) -> Array[(Bytes, String)] raise @core.PdfError {
let attributes : Array[(Bytes, String)] = []
let mut index = start
while index < data.length() {
index = pdf_metadata_xml_skip_space(data, index)
if index >= data.length() {
break
}
let (name, after_name) = pdf_metadata_xml_read_name(data, index)
index = pdf_metadata_xml_skip_space(data, after_name)
guard index < data.length() && data[index].to_int() == 61 else {
raise BadText
}
index = pdf_metadata_xml_skip_space(data, index + 1)
guard index < data.length() &&
(data[index].to_int() == 34 || data[index].to_int() == 39) else {
raise BadText
}
let quote = data[index].to_int()
let value_start = index + 1
let value_end = pdf_metadata_find_byte(data, value_start, quote)
guard value_end >= 0 else { raise BadText }
let value = match
pdf_metadata_decode_xml_text(data[value_start:value_end]) {
Some(value) => value
None => raise InvalidUTF8
}
attributes.push((name, value))
index = value_end + 1
}
attributes
}
///|
fn pdf_metadata_xml_context_with_attributes(
context : ArrayView[(String, String)],
attributes : ArrayView[(Bytes, String)],
) -> Array[(String, String)] raise @core.PdfError {
let output = context.to_owned()
for attribute in attributes {
let name = attribute.0[:]
if name.length() == 5 && pdf_metadata_view_matches_at(name, 0, b"xmlns") {
output.push(("", attribute.1))
} else if name.length() > 6 &&
pdf_metadata_view_matches_at(name, 0, b"xmlns:") {
output.push((pdf_metadata_xml_decode_name(name[6:]), attribute.1))
}
}
output
}
///|
fn pdf_metadata_xml_tag_from_raw(
name : BytesView,
attributes : ArrayView[(Bytes, String)],
context : ArrayView[(String, String)],
) -> @metadata.PdfMetadataXmlTag raise @core.PdfError {
let resolved_attributes : Array[@metadata.PdfMetadataXmlAttribute] = []
for attribute in attributes {
resolved_attributes.push({
name: pdf_metadata_xml_resolve_name(attribute.0, true, context),
value: attribute.1,
})
}
{
name: pdf_metadata_xml_resolve_name(name, false, context),
attributes: resolved_attributes,
}
}