///|
fn pdf_pagespec_copy_view(
output : Array[Byte],
position : Int,
bytes : BytesView,
) -> Int {
let mut position = position
for byte in bytes {
output[position] = byte
position += 1
}
position
}
///|
fn PdfPageSpecContext::read_page_label_reference(
self : PdfPageSpecContext,
spec : BytesView,
open_index : Int,
) -> (Bytes, Int) raise PdfError {
let mut index = open_index + 1
let mut label_length = 0
let mut closed = false
while index < spec.length() && !closed {
let current = spec[index].to_int()
if current == 93 {
closed = true
index += 1
} else if current == 92 &&
index + 1 < spec.length() &&
(spec[index + 1].to_int() == 91 || spec[index + 1].to_int() == 93) {
label_length += 1
index += 2
} else if current == 91 {
self.bad()
} else {
label_length += 1
index += 1
}
}
if !closed {
self.bad()
}
let output = Array::make(label_length, b'\x00')
let mut position = 0
let mut label_index = open_index + 1
let close_index = index - 1
while label_index < close_index {
let current = spec[label_index].to_int()
if current == 92 &&
label_index + 1 < close_index &&
(
spec[label_index + 1].to_int() == 91 ||
spec[label_index + 1].to_int() == 93
) {
output[position] = spec[label_index + 1]
label_index += 2
} else {
output[position] = spec[label_index]
label_index += 1
}
position += 1
}
(Bytes::from_array(output), index)
}
///|
fn PdfPageSpecContext::page_number_bytes_for_label(
self : PdfPageSpecContext,
label : BytesView,
labels : ArrayView[PdfPageLabel],
) -> Bytes raise PdfError {
let mut found = false
let mut output = Bytes::new(0)
for page_number in 1..<=self.end_page {
let page_label = match
pdf_page_label_text_of_page_number(page_number, labels) {
Some(value) => value
None => Bytes::new(0)
}
if !found && page_label[:] == label {
output = @ascii.encode(page_number.to_string())
found = true
}
}
if found {
output
} else {
self.bad()
Bytes::new(0)
}
}
///|
fn PdfPageSpecContext::resolved_page_labels_length(
self : PdfPageSpecContext,
spec : BytesView,
labels : ArrayView[PdfPageLabel],
) -> Int raise PdfError {
let mut length = 0
let mut index = 0
while index < spec.length() {
let value = spec[index].to_int()
if value == 91 {
let (label, next_index) = self.read_page_label_reference(spec, index)
let page_number = self.page_number_bytes_for_label(label, labels)
length += page_number.length()
index = next_index
} else if value == 92 &&
index + 1 < spec.length() &&
(spec[index + 1].to_int() == 91 || spec[index + 1].to_int() == 93) {
length += 1
index += 2
} else if value == 93 {
self.bad()
} else {
length += 1
index += 1
}
}
length
}
///|
fn PdfPageSpecContext::resolve_page_labels(
self : PdfPageSpecContext,
spec : BytesView,
) -> Bytes raise PdfError {
match self.document {
None => {
for byte in spec {
if byte.to_int() == 91 || byte.to_int() == 93 {
self.bad()
}
}
spec.to_owned()
}
Some(document) => {
let labels = document.read_page_labels()
let output = Array::make(
self.resolved_page_labels_length(spec, labels),
b'\x00',
)
let mut index = 0
let mut position = 0
while index < spec.length() {
let value = spec[index].to_int()
if value == 91 {
let (label, next_index) = self.read_page_label_reference(spec, index)
let page_number = self.page_number_bytes_for_label(label, labels)
position = pdf_pagespec_copy_view(output, position, page_number)
index = next_index
} else if value == 92 &&
index + 1 < spec.length() &&
(spec[index + 1].to_int() == 91 || spec[index + 1].to_int() == 93) {
output[position] = spec[index + 1]
position += 1
index += 2
} else if value == 93 {
self.bad()
} else {
output[position] = spec[index]
position += 1
index += 1
}
}
Bytes::from_array(output)
}
}
}