use folio_cos::PdfObject;
use indexmap::IndexMap;
#[derive(Debug, Clone, Default)]
pub struct DocInfo {
dict: IndexMap<Vec<u8>, PdfObject>,
}
impl DocInfo {
pub(crate) fn from_dict(dict: IndexMap<Vec<u8>, PdfObject>) -> Self {
Self { dict }
}
fn get_text(&self, key: &[u8]) -> Option<String> {
self.dict.get(key).and_then(|obj| match obj {
PdfObject::Str(s) => Some(decode_pdf_text(s)),
_ => None,
})
}
pub fn title(&self) -> Option<String> {
self.get_text(b"Title")
}
pub fn author(&self) -> Option<String> {
self.get_text(b"Author")
}
pub fn subject(&self) -> Option<String> {
self.get_text(b"Subject")
}
pub fn keywords(&self) -> Option<String> {
self.get_text(b"Keywords")
}
pub fn creator(&self) -> Option<String> {
self.get_text(b"Creator")
}
pub fn producer(&self) -> Option<String> {
self.get_text(b"Producer")
}
pub fn creation_date(&self) -> Option<String> {
self.get_text(b"CreationDate")
}
pub fn mod_date(&self) -> Option<String> {
self.get_text(b"ModDate")
}
}
fn decode_pdf_text(data: &[u8]) -> String {
if data.len() >= 2 && data[0] == 0xFE && data[1] == 0xFF {
let mut chars = Vec::new();
let mut i = 2;
while i + 1 < data.len() {
let code = ((data[i] as u16) << 8) | (data[i + 1] as u16);
chars.push(code);
i += 2;
}
String::from_utf16_lossy(&chars)
} else if data.len() >= 3 && data[0] == 0xEF && data[1] == 0xBB && data[2] == 0xBF {
String::from_utf8_lossy(&data[3..]).into_owned()
} else {
String::from_utf8_lossy(data).into_owned()
}
}