pdf_lib_rs/core/objects/
pdf_array.rs1use std::fmt;
2use crate::core::syntax::CharCodes;
3use super::pdf_object::{PdfObject, PdfObjectTrait};
4
5#[derive(Debug, Clone)]
7pub struct PdfArray {
8 array: Vec<PdfObject>,
9}
10
11impl PdfArray {
12 pub fn new() -> Self {
13 PdfArray { array: Vec::new() }
14 }
15
16 pub fn size(&self) -> usize {
17 self.array.len()
18 }
19
20 pub fn push(&mut self, object: PdfObject) {
21 self.array.push(object);
22 }
23
24 pub fn insert(&mut self, index: usize, object: PdfObject) {
25 self.array.insert(index, object);
26 }
27
28 pub fn remove(&mut self, index: usize) -> PdfObject {
29 self.array.remove(index)
30 }
31
32 pub fn get(&self, index: usize) -> Option<&PdfObject> {
33 self.array.get(index)
34 }
35
36 pub fn set(&mut self, index: usize, object: PdfObject) {
37 self.array[index] = object;
38 }
39
40 pub fn as_slice(&self) -> &[PdfObject] {
41 &self.array
42 }
43}
44
45impl Default for PdfArray {
46 fn default() -> Self {
47 Self::new()
48 }
49}
50
51impl PartialEq for PdfArray {
52 fn eq(&self, _other: &Self) -> bool {
53 false
55 }
56}
57
58impl fmt::Display for PdfArray {
59 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
60 write!(f, "[ ")?;
61 for item in &self.array {
62 write!(f, "{} ", item)?;
63 }
64 write!(f, "]")
65 }
66}
67
68impl PdfObjectTrait for PdfArray {
69 fn size_in_bytes(&self) -> usize {
70 let mut size = 3; for item in &self.array {
73 size += item.size_in_bytes() + 1; }
75 size
76 }
77
78 fn copy_bytes_into(&self, buffer: &mut [u8], offset: usize) -> usize {
79 let initial_offset = offset;
80 let mut off = offset;
81
82 buffer[off] = CharCodes::LeftSquareBracket;
83 off += 1;
84 buffer[off] = CharCodes::Space;
85 off += 1;
86
87 for item in &self.array {
88 off += item.copy_bytes_into(buffer, off);
89 buffer[off] = CharCodes::Space;
90 off += 1;
91 }
92
93 buffer[off] = CharCodes::RightSquareBracket;
94 off += 1;
95
96 off - initial_offset
97 }
98}
99
100#[cfg(test)]
101mod tests {
102 use super::*;
103 use crate::core::objects::{PdfNumber, PdfName};
104
105 #[test]
106 fn can_push_and_get() {
107 let mut arr = PdfArray::new();
108 arr.push(PdfObject::Number(PdfNumber::of(42.0)));
109 arr.push(PdfObject::Name(PdfName::of("Foo")));
110 assert_eq!(arr.size(), 2);
111 }
112
113 #[test]
114 fn can_be_converted_to_string() {
115 let mut arr = PdfArray::new();
116 arr.push(PdfObject::Number(PdfNumber::of(1.0)));
117 arr.push(PdfObject::Number(PdfNumber::of(2.0)));
118 assert_eq!(arr.to_string(), "[ 1 2 ]");
119 }
120
121 #[test]
122 fn can_insert_and_remove() {
123 let mut arr = PdfArray::new();
124 arr.push(PdfObject::Number(PdfNumber::of(1.0)));
125 arr.push(PdfObject::Number(PdfNumber::of(3.0)));
126 arr.insert(1, PdfObject::Number(PdfNumber::of(2.0)));
127 assert_eq!(arr.size(), 3);
128 assert_eq!(arr.to_string(), "[ 1 2 3 ]");
129
130 arr.remove(1);
131 assert_eq!(arr.to_string(), "[ 1 3 ]");
132 }
133
134 #[test]
135 fn can_provide_size_in_bytes() {
136 let arr = PdfArray::new();
137 assert_eq!(arr.size_in_bytes(), 3); let mut arr2 = PdfArray::new();
140 arr2.push(PdfObject::Number(PdfNumber::of(1.0)));
141 assert_eq!(arr2.size_in_bytes(), 5);
143 }
144
145 #[test]
146 fn can_be_serialized() {
147 let mut arr = PdfArray::new();
148 arr.push(PdfObject::Number(PdfNumber::of(1.0)));
149 arr.push(PdfObject::Number(PdfNumber::of(2.0)));
150 let size = arr.size_in_bytes();
151 let mut buffer = vec![0u8; size];
152 arr.copy_bytes_into(&mut buffer, 0);
153 assert_eq!(buffer, b"[ 1 2 ]");
154 }
155}