use std::collections::VecDeque;
use super::prelude::*;
#[derive(Debug, DataSize, Clone, Object, ObjectWrite, DeepClone)]
pub enum Counter {
#[pdf(name = "D")]
Arabic,
#[pdf(name = "r")]
RomanUpper,
#[pdf(name = "R")]
RomanLower,
#[pdf(name = "a")]
AlphaUpper,
#[pdf(name = "A")]
AlphaLower,
}
#[derive(Debug, DataSize)]
pub enum NameTreeNode<T> {
Intermediate(Vec<Ref<NameTree<T>>>),
Leaf(Vec<(PdfString, T)>),
}
#[derive(Debug, DataSize)]
pub struct NameTree<T> {
pub limits: Option<(PdfString, PdfString)>,
pub node: NameTreeNode<T>,
}
impl<T: Object + DataSize> NameTree<T> {
pub fn walk(&self, r: &impl Resolve, callback: &mut dyn FnMut(&PdfString, &T)) -> Result<()> {
match self.node {
NameTreeNode::Leaf(ref items) => {
for (name, val) in items {
callback(name, val);
}
}
NameTreeNode::Intermediate(ref items) => {
for &tree_ref in items {
let tree = r.get(tree_ref)?;
tree.walk(r, callback)?;
}
}
}
Ok(())
}
}
impl<T: Object> Object for NameTree<T> {
fn from_primitive(p: Primitive, resolve: &impl Resolve) -> Result<Self> {
let mut dict = t!(p.resolve(resolve)?.into_dictionary());
let limits = match dict.remove("Limits") {
Some(limits) => {
let limits = limits.resolve(resolve)?.into_array()?;
if limits.len() != 2 {
bail!("Error reading NameTree: 'Limits' is not of length 2");
}
let min = limits[0].clone().into_string()?;
let max = limits[1].clone().into_string()?;
Some((min, max))
}
None => None,
};
let kids = dict.remove("Kids");
let names = dict.remove("Names");
Ok(match (kids, names) {
(Some(kids), _) => {
let kids = t!(kids
.resolve(resolve)?
.into_array()?
.iter()
.map(|kid| Ref::<NameTree<T>>::from_primitive(kid.clone(), resolve))
.collect::<Result<Vec<_>>>());
NameTree {
limits,
node: NameTreeNode::Intermediate(kids),
}
}
(None, Some(names)) => {
let names = names.resolve(resolve)?.into_array()?;
let mut new_names = Vec::new();
for pair in names.chunks_exact(2) {
let name = pair[0].clone().resolve(resolve)?.into_string()?;
let value = t!(T::from_primitive(pair[1].clone(), resolve));
new_names.push((name, value));
}
NameTree {
limits,
node: NameTreeNode::Leaf(new_names),
}
}
(None, None) => {
warn!("Neither Kids nor Names present in NameTree node.");
NameTree {
limits,
node: NameTreeNode::Intermediate(vec![]),
}
}
})
}
}
impl<T: ObjectWrite> ObjectWrite for NameTree<T> {
fn to_primitive(&self, update: &mut impl Updater) -> Result<Primitive> {
let mut dict = Dictionary::new();
if let Some(ref limits) = self.limits {
dict.insert("Limits", limits.to_primitive(update)?);
}
match self.node {
NameTreeNode::Intermediate(ref kids) => {
dict.insert("Kids", kids.to_primitive(update)?);
}
NameTreeNode::Leaf(ref children) => {
let mut list = Vec::with_capacity(children.len() * 2);
for (key, val) in children {
list.push(Primitive::String(key.clone()));
let val = val.to_primitive(update)?;
match val {
Primitive::Null | Primitive::Name(_) | Primitive::Number(_) | Primitive::Boolean(_) => {
list.push(val);
}
_ => {
list.push(Primitive::Reference(update.create(val)?.inner));
}
}
}
dict.insert("Names", list);
}
}
Ok(dict.into())
}
}
impl<T> NameTree<T> {
pub fn build_flat(mut entries: Vec<(PdfString, T)>) -> Self {
entries.sort_unstable_by(|a, b| a.0.data.as_slice().cmp(b.0.data.as_slice()));
let node = NameTreeNode::Leaf(entries);
NameTree { limits: None, node }
}
pub fn build_tree(mut entries: Vec<(PdfString, T)>) -> Result<Self> {
const IDEAL_LEVEL_SIZE: f32 = 17.;
let len = entries.len();
if len < 20 {
return Ok(Self::build_flat(entries));
}
let levels = (len as f32).log2() / IDEAL_LEVEL_SIZE.log2();
let root_levels_ln2 = levels.fract();
let root_levels = IDEAL_LEVEL_SIZE.powf(root_levels_ln2).ceil() as usize;
entries.sort_unstable_by(|a, b| a.0.data.as_slice().cmp(b.0.data.as_slice()));
let mut entries = VecDeque::from(entries);
unimplemented!()
}
}