1use crate::object::macros::object;
4use crate::object::r#ref::MaybeRef;
5use crate::object::{FromBytes, Object, ObjectLike};
6use crate::reader::Reader;
7use crate::reader::{Readable, ReaderContext, ReaderExt, Skippable};
8use log::warn;
9use smallvec::SmallVec;
10use std::fmt::{Debug, Formatter};
11use std::marker::PhantomData;
12
13#[derive(Clone)]
15pub struct Array<'a> {
16 data: &'a [u8],
17 ctx: ReaderContext<'a>,
18}
19
20impl PartialEq for Array<'_> {
23 fn eq(&self, other: &Self) -> bool {
24 self.data == other.data
25 }
26}
27
28impl<'a> Array<'a> {
29 pub fn raw_iter(&self) -> ArrayIter<'a> {
31 ArrayIter::new(self.data, &self.ctx)
32 }
33
34 #[allow(
36 private_bounds,
37 reason = "users shouldn't be able to implement `ObjectLike` for custom objects."
38 )]
39 pub fn iter<T>(&self) -> ResolvedArrayIter<'a, T>
40 where
41 T: ObjectLike<'a>,
42 {
43 ResolvedArrayIter::new(self.data, &self.ctx)
44 }
45
46 pub fn flex_iter(&self) -> FlexArrayIter<'a> {
48 FlexArrayIter::new(self.data, &self.ctx)
49 }
50
51 pub fn data(&self) -> &'a [u8] {
53 self.data
54 }
55}
56
57impl Debug for Array<'_> {
58 fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
59 let mut debug_list = f.debug_list();
60
61 self.raw_iter().for_each(|i| {
62 debug_list.entry(&i);
63 });
64
65 Ok(())
66 }
67}
68
69object!(Array<'a>, Array);
70
71impl Skippable for Array<'_> {
72 fn skip(r: &mut Reader<'_>, is_content_stream: bool) -> Option<()> {
73 r.forward_tag(b"[")?;
74
75 loop {
76 r.skip_white_spaces_and_comments();
77
78 if let Some(()) = r.forward_tag(b"]") {
79 return Some(());
80 } else if is_content_stream {
81 r.skip_not_in_content_stream::<Object<'_>>()?;
82 } else {
83 r.skip_not_in_content_stream::<MaybeRef<Object<'_>>>()?;
84 }
85 }
86 }
87}
88
89impl Default for Array<'_> {
90 fn default() -> Self {
91 Self::from_bytes(b"[]").unwrap()
92 }
93}
94
95impl<'a> Readable<'a> for Array<'a> {
96 fn read(r: &mut Reader<'a>, ctx: &ReaderContext<'a>) -> Option<Self> {
97 let bytes = r.skip::<Array<'_>>(ctx.in_content_stream)?;
98
99 Some(Self {
100 data: &bytes[1..bytes.len() - 1],
101 ctx: ctx.clone(),
102 })
103 }
104}
105
106pub struct ArrayIter<'a> {
108 reader: Reader<'a>,
109 ctx: ReaderContext<'a>,
110}
111
112impl<'a> ArrayIter<'a> {
113 fn new(data: &'a [u8], ctx: &ReaderContext<'a>) -> Self {
114 Self {
115 reader: Reader::new(data),
116 ctx: ctx.clone(),
117 }
118 }
119}
120
121impl<'a> Iterator for ArrayIter<'a> {
122 type Item = MaybeRef<Object<'a>>;
123
124 fn next(&mut self) -> Option<Self::Item> {
125 self.reader.skip_white_spaces_and_comments();
126
127 if !self.reader.at_end() {
128 let item = self
130 .reader
131 .read_with_context::<MaybeRef<Object<'_>>>(&self.ctx)
132 .unwrap();
133 return Some(item);
134 }
135
136 None
137 }
138}
139
140pub struct ResolvedArrayIter<'a, T> {
142 flex_iter: FlexArrayIter<'a>,
143 phantom_data: PhantomData<T>,
144}
145
146impl<'a, T> ResolvedArrayIter<'a, T> {
147 fn new(data: &'a [u8], ctx: &ReaderContext<'a>) -> Self {
148 Self {
149 flex_iter: FlexArrayIter::new(data, ctx),
150 phantom_data: PhantomData,
151 }
152 }
153}
154
155impl<'a, T> Iterator for ResolvedArrayIter<'a, T>
156where
157 T: ObjectLike<'a>,
158{
159 type Item = T;
160
161 fn next(&mut self) -> Option<Self::Item> {
162 self.flex_iter.next::<T>()
163 }
164}
165
166pub struct FlexArrayIter<'a> {
168 reader: Reader<'a>,
169 ctx: ReaderContext<'a>,
170}
171
172impl<'a> FlexArrayIter<'a> {
173 fn new(data: &'a [u8], ctx: &ReaderContext<'a>) -> Self {
174 Self {
175 reader: Reader::new(data),
176 ctx: ctx.clone(),
177 }
178 }
179
180 #[allow(
181 private_bounds,
182 reason = "users shouldn't be able to implement `ObjectLike` for custom objects."
183 )]
184 #[allow(clippy::should_implement_trait)]
185 pub fn next<T: ObjectLike<'a>>(&mut self) -> Option<T> {
187 self.reader.skip_white_spaces_and_comments();
188
189 if !self.reader.at_end() {
190 return match self.reader.read_with_context::<MaybeRef<T>>(&self.ctx)? {
191 MaybeRef::Ref(r) => self.ctx.xref.get_with::<T>(r.into(), &self.ctx),
192 MaybeRef::NotRef(i) => Some(i),
193 };
194 }
195
196 None
197 }
198}
199
200impl<'a, T: ObjectLike<'a> + Copy + Default, const C: usize> TryFrom<Array<'a>> for [T; C] {
201 type Error = ();
202
203 fn try_from(value: Array<'a>) -> Result<Self, Self::Error> {
204 let mut iter = value.iter::<T>();
205
206 let mut val = [T::default(); C];
207
208 for i in 0..C {
209 val[i] = iter.next().ok_or(())?;
210 }
211
212 if iter.next().is_some() {
213 warn!("found excess elements in array");
214
215 return Err(());
216 }
217
218 Ok(val)
219 }
220}
221
222impl<'a, T: ObjectLike<'a> + Copy + Default, const C: usize> TryFrom<Object<'a>> for [T; C]
223where
224 [T; C]: TryFrom<Array<'a>, Error = ()>,
225{
226 type Error = ();
227
228 fn try_from(value: Object<'a>) -> Result<Self, Self::Error> {
229 match value {
230 Object::Array(a) => a.try_into(),
231 _ => Err(()),
232 }
233 }
234}
235
236impl<'a, T: ObjectLike<'a> + Copy + Default, const C: usize> Readable<'a> for [T; C] {
237 fn read(r: &mut Reader<'a>, ctx: &ReaderContext<'a>) -> Option<Self> {
238 let array = Array::read(r, ctx)?;
239 array.try_into().ok()
240 }
241}
242
243impl<'a, T: ObjectLike<'a> + Copy + Default, const C: usize> ObjectLike<'a> for [T; C] {}
244
245impl<'a, T: ObjectLike<'a>> TryFrom<Array<'a>> for Vec<T> {
246 type Error = ();
247
248 fn try_from(value: Array<'a>) -> Result<Self, Self::Error> {
249 Ok(value.iter::<T>().collect())
250 }
251}
252
253impl<'a, T: ObjectLike<'a>> TryFrom<Object<'a>> for Vec<T> {
254 type Error = ();
255
256 fn try_from(value: Object<'a>) -> Result<Self, Self::Error> {
257 match value {
258 Object::Array(a) => a.try_into(),
259 _ => Err(()),
260 }
261 }
262}
263
264impl<'a, T: ObjectLike<'a>> Readable<'a> for Vec<T> {
265 fn read(r: &mut Reader<'a>, ctx: &ReaderContext<'a>) -> Option<Self> {
266 let array = Array::read(r, ctx)?;
267 array.try_into().ok()
268 }
269}
270
271impl<'a, T: ObjectLike<'a>> ObjectLike<'a> for Vec<T> {}
272
273impl<'a, U: ObjectLike<'a>, T: ObjectLike<'a> + smallvec::Array<Item = U>> TryFrom<Array<'a>>
274 for SmallVec<T>
275{
276 type Error = ();
277
278 fn try_from(value: Array<'a>) -> Result<Self, Self::Error> {
279 Ok(value.iter::<U>().collect())
280 }
281}
282
283impl<'a, U: ObjectLike<'a>, T: ObjectLike<'a> + smallvec::Array<Item = U>> TryFrom<Object<'a>>
284 for SmallVec<T>
285{
286 type Error = ();
287
288 fn try_from(value: Object<'a>) -> Result<Self, Self::Error> {
289 match value {
290 Object::Array(a) => a.try_into(),
291 _ => Err(()),
292 }
293 }
294}
295
296impl<'a, U: ObjectLike<'a>, T: ObjectLike<'a> + smallvec::Array<Item = U>> Readable<'a>
297 for SmallVec<T>
298{
299 fn read(r: &mut Reader<'a>, ctx: &ReaderContext<'a>) -> Option<Self> {
300 let array = Array::read(r, ctx)?;
301 array.try_into().ok()
302 }
303}
304
305impl<'a, U: ObjectLike<'a>, T: ObjectLike<'a> + smallvec::Array<Item = U>> ObjectLike<'a>
306 for SmallVec<T>
307where
308 U: Clone,
309 U: Debug,
310{
311}
312
313#[cfg(test)]
314mod tests {
315 use crate::object::Array;
316 use crate::object::Object;
317 use crate::object::r#ref::{MaybeRef, ObjRef};
318 use crate::reader::Reader;
319 use crate::reader::{ReaderContext, ReaderExt};
320 use crate::xref::XRef;
321
322 fn array_impl(data: &[u8]) -> Option<Vec<Object<'_>>> {
323 Reader::new(data)
324 .read_with_context::<Array<'_>>(&ReaderContext::new(XRef::dummy(), false))
325 .map(|a| a.iter::<Object<'_>>().collect::<Vec<_>>())
326 }
327
328 fn array_ref_impl(data: &[u8]) -> Option<Vec<MaybeRef<Object<'_>>>> {
329 Reader::new(data)
330 .read_with_context::<Array<'_>>(&ReaderContext::new(XRef::dummy(), false))
331 .map(|a| a.raw_iter().collect::<Vec<_>>())
332 }
333
334 #[test]
335 fn empty_array_1() {
336 let res = array_impl(b"[]").unwrap();
337 assert!(res.is_empty());
338 }
339
340 #[test]
341 fn empty_array_2() {
342 let res = array_impl(b"[ \n]").unwrap();
343 assert!(res.is_empty());
344 }
345
346 #[test]
347 fn array_1() {
348 let res = array_impl(b"[34]").unwrap();
349 assert!(matches!(res[0], Object::Number(_)));
350 }
351
352 #[test]
353 fn array_2() {
354 let res = array_impl(b"[true ]").unwrap();
355 assert!(matches!(res[0], Object::Boolean(_)));
356 }
357
358 #[test]
359 fn array_3() {
360 let res = array_impl(b"[true \n false 34.564]").unwrap();
361 assert!(matches!(res[0], Object::Boolean(_)));
362 assert!(matches!(res[1], Object::Boolean(_)));
363 assert!(matches!(res[2], Object::Number(_)));
364 }
365
366 #[test]
367 fn array_4() {
368 let res = array_impl(b"[(A string.) << /Hi 34.35 >>]").unwrap();
369 assert!(matches!(res[0], Object::String(_)));
370 assert!(matches!(res[1], Object::Dict(_)));
371 }
372
373 #[test]
374 fn array_5() {
375 let res = array_impl(b"[[32] 345.6]").unwrap();
376 assert!(matches!(res[0], Object::Array(_)));
377 assert!(matches!(res[1], Object::Number(_)));
378 }
379
380 #[test]
381 fn array_with_ref() {
382 let res = array_ref_impl(b"[345 34 5 R 34.0]").unwrap();
383 assert!(matches!(res[0], MaybeRef::NotRef(Object::Number(_))));
384 assert!(matches!(
385 res[1],
386 MaybeRef::Ref(ObjRef {
387 obj_number: 34,
388 gen_number: 5
389 })
390 ));
391 assert!(matches!(res[2], MaybeRef::NotRef(Object::Number(_))));
392 }
393
394 #[test]
395 fn array_with_comment() {
396 let res = array_impl(b"[true % A comment \n false]").unwrap();
397 assert!(matches!(res[0], Object::Boolean(_)));
398 assert!(matches!(res[1], Object::Boolean(_)));
399 }
400
401 #[test]
402 fn array_with_trailing() {
403 let res = array_impl(b"[(Hi) /Test]trialing data").unwrap();
404 assert!(matches!(res[0], Object::String(_)));
405 assert!(matches!(res[1], Object::Name(_)));
406 }
407}