use lopdf::{Dictionary, Document, Object};
pub fn deref<'a>(doc: &'a Document, obj: &'a Object) -> &'a Object {
match obj {
Object::Reference(id) => doc.get_object(*id).unwrap_or(obj),
o => o,
}
}
pub fn as_dict<'a>(doc: &'a Document, obj: &'a Object) -> Option<&'a Dictionary> {
match deref(doc, obj) {
Object::Dictionary(d) => Some(d),
Object::Stream(s) => Some(&s.dict),
_ => None,
}
}
pub fn as_stream<'a>(doc: &'a Document, obj: &'a Object) -> Option<&'a lopdf::Stream> {
match deref(doc, obj) {
Object::Stream(s) => Some(s),
_ => None,
}
}
pub fn num(o: &Object) -> Option<f64> {
match o {
Object::Integer(i) => Some(*i as f64),
Object::Real(r) => Some(f64::from(*r)),
_ => None,
}
}
pub fn nums(doc: &Document, o: &Object) -> Option<Vec<f64>> {
match deref(doc, o) {
Object::Array(a) => Some(a.iter().filter_map(|x| num(deref(doc, x))).collect()),
_ => None,
}
}
pub fn name(o: &Object) -> Option<&[u8]> {
match o {
Object::Name(n) => Some(n),
_ => None,
}
}
pub fn get<'a>(doc: &'a Document, dict: &'a Dictionary, key: &[u8]) -> Option<&'a Object> {
dict.get(key).ok().map(|o| deref(doc, o))
}
pub fn get2<'a>(
doc: &'a Document,
dict: &'a Dictionary,
key: &[u8],
alt: &[u8],
) -> Option<&'a Object> {
get(doc, dict, key).or_else(|| get(doc, dict, alt))
}
pub fn get_int2(doc: &Document, d: &Dictionary, key: &[u8], alt: &[u8]) -> Option<i64> {
get_int(doc, d, key).or_else(|| get_int(doc, d, alt))
}
pub fn get_bool2(doc: &Document, d: &Dictionary, key: &[u8], alt: &[u8]) -> Option<bool> {
get_bool(doc, d, key).or_else(|| get_bool(doc, d, alt))
}
pub fn get_num(doc: &Document, dict: &Dictionary, key: &[u8]) -> Option<f64> {
get(doc, dict, key).and_then(num)
}
pub fn get_int(doc: &Document, dict: &Dictionary, key: &[u8]) -> Option<i64> {
get(doc, dict, key).and_then(|o| match o {
Object::Integer(i) => Some(*i),
Object::Real(r) => Some(*r as i64),
_ => None,
})
}
pub fn get_bool(doc: &Document, dict: &Dictionary, key: &[u8]) -> Option<bool> {
get(doc, dict, key).and_then(|o| match o {
Object::Boolean(b) => Some(*b),
Object::Integer(i) => Some(*i != 0),
_ => None,
})
}
pub fn get_name<'a>(doc: &'a Document, dict: &'a Dictionary, key: &[u8]) -> Option<&'a [u8]> {
get(doc, dict, key).and_then(name)
}
pub fn get_dict<'a>(doc: &'a Document, dict: &'a Dictionary, key: &[u8]) -> Option<&'a Dictionary> {
dict.get(key).ok().and_then(|o| as_dict(doc, o))
}
pub fn resource<'a>(
doc: &'a Document,
res: Option<&'a Dictionary>,
kind: &[u8],
name: &[u8],
) -> Option<&'a Object> {
res?.get(kind)
.ok()
.and_then(|o| as_dict(doc, o))
.and_then(|d| d.get(name).ok())
}
pub fn stream_data(s: &lopdf::Stream) -> Option<Vec<u8>> {
s.decompressed_content().ok()
}