///|
fn pdf_cursor_input_next_hex_byte(cursor : @core.ByteCursor) -> Int {
let mut result = @core.pdf_no_more
let mut done = false
while !done {
let value = cursor.input_byte()
if value == @core.pdf_no_more || @core.pdf_is_not_whitespace_byte(value) {
result = value
done = true
}
}
result
}
///|
fn pdf_cursor_hex_string_output_capacity(cursor : @core.ByteCursor) -> Int {
let mut index = cursor.absolute_position()
let mut digits = 0
let mut done = false
while index < cursor.length() && !done {
let value = cursor.byte_int_at_absolute(index)
index += 1
if value == 62 {
done = true
} else if @core.pdf_is_not_whitespace_byte(value) {
digits += 1
}
}
(digits + 1) / 2
}
///|
/// Lex a PDF hexadecimal string.
///
/// The opening `<` must not be a dictionary delimiter `<<`. White space inside
/// the hex string is ignored, odd trailing nibbles are padded in the PDF way,
/// and invalid hex digits raise `@core.PdfError::InvalidHexEscape`.
pub fn pdf_cursor_lex_hex_string(
cursor : @core.ByteCursor,
) -> PdfLexeme raise @core.PdfError {
let position = cursor.absolute_position()
if cursor.peek_byte() != 60 || cursor.byte_int_at_absolute(position + 1) == 60 {
LexNone
} else {
cursor.nudge()
let bytes = Array::make(
pdf_cursor_hex_string_output_capacity(cursor),
b'\x00',
)
let mut position = 0
let mut done = false
while !done {
let high = pdf_cursor_input_next_hex_byte(cursor)
if high == @core.pdf_no_more || high == 62 {
done = true
} else {
let low = pdf_cursor_input_next_hex_byte(cursor)
if low == @core.pdf_no_more {
done = true
} else {
match (pdf_hex_value(high), low) {
(Some(high), 62) => {
position = pdf_lexeme_write_byte_at(
bytes,
position,
(high * 16).to_byte(),
)
done = true
}
(Some(high), low) =>
match pdf_hex_value(low) {
Some(low) =>
position = pdf_lexeme_write_byte_at(
bytes,
position,
(high * 16 + low).to_byte(),
)
None => raise InvalidHexEscape
}
_ => raise InvalidHexEscape
}
}
}
}
LexString(Bytes::from_array(bytes[:position]))
}
}