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