use std::convert::TryFrom;
use crate::{
error::{ParseError, PdfResult},
objects::{Dictionary, Object, ObjectType, Reference, TypeOrArray},
stream::Stream,
};
pub trait Resolve {
fn lex_object_from_reference(&mut self, reference: Reference) -> PdfResult<Object>;
fn assert_integer(&mut self, obj: Object) -> PdfResult<i32> {
match obj {
Object::Integer(i) => Ok(i),
Object::Reference(r) => {
let obj = self.lex_object_from_reference(r)?;
self.assert_integer(obj)
}
found => Err(ParseError::MismatchedObjectType {
expected: ObjectType::Integer,
found,
}),
}
}
fn assert_unsigned_integer(&mut self, obj: Object) -> PdfResult<u32> {
match obj {
Object::Integer(i) => Ok(u32::try_from(i)?),
Object::Reference(r) => {
let obj = self.lex_object_from_reference(r)?;
self.assert_unsigned_integer(obj)
}
found => Err(ParseError::MismatchedObjectType {
expected: ObjectType::Integer,
found,
}),
}
}
fn assert_number(&mut self, obj: Object) -> PdfResult<f32> {
match obj {
Object::Integer(i) => Ok(i as f32),
Object::Real(i) => Ok(i),
Object::Reference(r) => {
let obj = self.lex_object_from_reference(r)?;
self.assert_number(obj)
}
found => Err(ParseError::MismatchedObjectType {
expected: ObjectType::Real,
found,
}),
}
}
fn assert_dict(&mut self, obj: Object) -> PdfResult<Dictionary> {
match obj {
Object::Dictionary(d) => Ok(d),
Object::Reference(r) => {
let obj = self.lex_object_from_reference(r)?;
self.assert_dict(obj)
}
found => Err(ParseError::MismatchedObjectType {
expected: ObjectType::Dictionary,
found,
}),
}
}
fn assert_name(&mut self, obj: Object) -> PdfResult<String> {
match obj {
Object::Name(n) => Ok(n),
Object::Reference(r) => {
let obj = self.lex_object_from_reference(r)?;
self.assert_name(obj)
}
found => Err(ParseError::MismatchedObjectType {
expected: ObjectType::Name,
found,
}),
}
}
fn assert_string(&mut self, obj: Object) -> PdfResult<String> {
match obj {
Object::String(s) => Ok(s),
Object::Reference(r) => {
let obj = self.lex_object_from_reference(r)?;
self.assert_string(obj)
}
found => Err(ParseError::MismatchedObjectType {
expected: ObjectType::String,
found,
}),
}
}
fn assert_arr(&mut self, obj: Object) -> PdfResult<Vec<Object>> {
match obj {
Object::Array(a) => Ok(a),
Object::Reference(r) => {
let obj = self.lex_object_from_reference(r)?;
self.assert_arr(obj)
}
found => Err(ParseError::MismatchedObjectType {
expected: ObjectType::Array,
found,
}),
}
}
fn assert_bool(&mut self, obj: Object) -> PdfResult<bool> {
match obj {
Object::True => Ok(true),
Object::False => Ok(false),
Object::Reference(r) => {
let obj = self.lex_object_from_reference(r)?;
self.assert_bool(obj)
}
found => Err(ParseError::MismatchedObjectType {
expected: ObjectType::Boolean,
found,
}),
}
}
fn assert_stream(&mut self, obj: Object) -> PdfResult<Stream> {
match obj {
Object::Stream(s) => Ok(s),
Object::Reference(r) => {
let obj = self.lex_object_from_reference(r)?;
self.assert_stream(obj)
}
found => Err(ParseError::MismatchedObjectType {
expected: ObjectType::Stream,
found,
}),
}
}
fn resolve(&mut self, obj: Object) -> PdfResult<Object> {
match obj {
Object::Reference(r) => {
let obj = self.lex_object_from_reference(r)?;
self.resolve(obj)
}
obj => Ok(obj),
}
}
fn assert_or_null<T>(
&mut self,
obj: Object,
convert: impl Fn(&mut Self, Object) -> PdfResult<T>,
) -> PdfResult<Option<T>>
where
Self: Sized,
{
match obj {
Object::Reference(r) => {
let obj = self.lex_object_from_reference(r)?;
self.assert_or_null(obj, convert)
}
Object::Null => Ok(None),
obj => Some(convert(self, obj)).transpose(),
}
}
fn get_type_or_arr<T>(
&mut self,
obj: Object,
convert: impl Fn(&mut Self, Object) -> PdfResult<T>,
) -> PdfResult<TypeOrArray<T>>
where
Self: Sized,
{
let obj = self.resolve(obj)?;
Ok(if let Object::Array(els) = obj {
TypeOrArray::Array(
els.into_iter()
.map(|el| convert(self, el))
.collect::<PdfResult<Vec<T>>>()?,
)
} else {
TypeOrArray::Type(convert(self, obj)?)
})
}
}