use std::fmt;
use std::ops::{Index, IndexMut};
use super::PdfObject;
#[derive(Debug, Clone, PartialEq, Default)]
pub struct PdfArray(Vec<PdfObject>);
impl PdfArray {
pub fn new() -> Self {
PdfArray(Vec::new())
}
pub fn with_capacity(capacity: usize) -> Self {
PdfArray(Vec::with_capacity(capacity))
}
pub fn from_vec(objects: Vec<PdfObject>) -> Self {
PdfArray(objects)
}
pub fn len(&self) -> usize {
self.0.len()
}
pub fn is_empty(&self) -> bool {
self.0.is_empty()
}
pub fn push<T: Into<PdfObject>>(&mut self, object: T) {
self.0.push(object.into());
}
pub fn get(&self, index: usize) -> Option<&PdfObject> {
self.0.get(index)
}
pub fn get_mut(&mut self, index: usize) -> Option<&mut PdfObject> {
self.0.get_mut(index)
}
pub fn iter(&self) -> impl Iterator<Item = &PdfObject> {
self.0.iter()
}
pub fn iter_mut(&mut self) -> impl Iterator<Item = &mut PdfObject> {
self.0.iter_mut()
}
pub fn into_vec(self) -> Vec<PdfObject> {
self.0
}
pub fn as_slice(&self) -> &[PdfObject] {
&self.0
}
pub fn get_integer(&self, index: usize) -> Option<i64> {
self.get(index).and_then(|v| v.as_integer())
}
pub fn get_real(&self, index: usize) -> Option<f64> {
self.get(index).and_then(|v| v.as_real())
}
pub fn get_name(&self, index: usize) -> Option<&super::PdfName> {
self.get(index).and_then(|v| v.as_name())
}
pub fn get_reference(&self, index: usize) -> Option<super::PdfRef> {
self.get(index).and_then(|v| v.as_reference())
}
pub fn get_dict(&self, index: usize) -> Option<&super::PdfDict> {
self.get(index).and_then(|v| v.as_dict())
}
pub fn get_array(&self, index: usize) -> Option<&PdfArray> {
self.get(index).and_then(|v| v.as_array())
}
}
impl Index<usize> for PdfArray {
type Output = PdfObject;
fn index(&self, index: usize) -> &Self::Output {
&self.0[index]
}
}
impl IndexMut<usize> for PdfArray {
fn index_mut(&mut self, index: usize) -> &mut Self::Output {
&mut self.0[index]
}
}
impl fmt::Display for PdfArray {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
write!(f, "[")?;
for (i, obj) in self.0.iter().enumerate() {
if i > 0 {
write!(f, " ")?;
}
write!(f, "{}", obj)?;
}
write!(f, "]")
}
}
impl<T: Into<PdfObject>> FromIterator<T> for PdfArray {
fn from_iter<I: IntoIterator<Item = T>>(iter: I) -> Self {
PdfArray(iter.into_iter().map(Into::into).collect())
}
}
impl IntoIterator for PdfArray {
type Item = PdfObject;
type IntoIter = std::vec::IntoIter<PdfObject>;
fn into_iter(self) -> Self::IntoIter {
self.0.into_iter()
}
}
impl<'a> IntoIterator for &'a PdfArray {
type Item = &'a PdfObject;
type IntoIter = std::slice::Iter<'a, PdfObject>;
fn into_iter(self) -> Self::IntoIter {
self.0.iter()
}
}
impl From<Vec<PdfObject>> for PdfArray {
fn from(v: Vec<PdfObject>) -> Self {
PdfArray(v)
}
}
#[macro_export]
macro_rules! pdf_array {
() => {
$crate::objects::PdfArray::new()
};
($($x:expr),+ $(,)?) => {{
let mut array = $crate::objects::PdfArray::new();
$(array.push($x);)+
array
}};
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn test_array_creation() {
let arr = PdfArray::new();
assert!(arr.is_empty());
assert_eq!(arr.len(), 0);
}
#[test]
fn test_array_push() {
let mut arr = PdfArray::new();
arr.push(PdfObject::Integer(1));
arr.push(PdfObject::Integer(2));
arr.push(PdfObject::Integer(3));
assert_eq!(arr.len(), 3);
assert_eq!(arr[0], PdfObject::Integer(1));
}
#[test]
fn test_array_display() {
let mut arr = PdfArray::new();
arr.push(PdfObject::Integer(1));
arr.push(PdfObject::Integer(2));
arr.push(PdfObject::Integer(3));
assert_eq!(format!("{}", arr), "[1 2 3]");
}
#[test]
fn test_array_display_empty() {
let arr = PdfArray::new();
assert_eq!(format!("{}", arr), "[]");
}
#[test]
fn test_array_iteration() {
let arr: PdfArray = vec![
PdfObject::Integer(1),
PdfObject::Integer(2),
PdfObject::Integer(3),
]
.into();
let sum: i64 = arr.iter().filter_map(|o| o.as_integer()).sum();
assert_eq!(sum, 6);
}
}