1#[allow(missing_docs)]
34pub mod ops;
35
36use crate::content::ops::TypedInstruction;
37use crate::object;
38use crate::object::dict::InlineImageDict;
39use crate::object::name::{Name, skip_name_like};
40use crate::object::{Array, Null, Number, Object, Stream};
41use crate::reader::Reader;
42use crate::reader::{Readable, ReaderContext, ReaderExt, Skippable};
43use crate::trivia::is_white_space_character;
44use crate::util::find_needle;
45use core::array;
46use core::fmt::{Debug, Display, Formatter};
47use core::ops::Deref;
48use smallvec::SmallVec;
49
50const OPERANDS_THRESHOLD: usize = 10;
54
55impl Debug for Operator<'_> {
56 fn fmt(&self, f: &mut Formatter<'_>) -> core::fmt::Result {
57 write!(f, "{}", self.0.as_str())
58 }
59}
60
61impl Display for Operator<'_> {
62 fn fmt(&self, f: &mut Formatter<'_>) -> core::fmt::Result {
63 write!(f, "{}", self.0.as_str())
64 }
65}
66
67#[derive(Clone, PartialEq)]
69pub struct Operator<'a>(Name<'a>);
70
71impl Deref for Operator<'_> {
72 type Target = [u8];
73
74 fn deref(&self) -> &Self::Target {
75 self.0.as_ref()
76 }
77}
78
79impl Skippable for Operator<'_> {
80 fn skip(r: &mut Reader<'_>, _: bool) -> Option<()> {
81 skip_name_like(r, false).map(|_| ())
82 }
83}
84
85impl<'a> Readable<'a> for Operator<'a> {
86 fn read(r: &mut Reader<'a>, _: &ReaderContext<'a>) -> Option<Self> {
87 let start = r.offset();
88 skip_name_like(r, false)?;
89 let end = r.offset();
90 let data = r.range(start..end)?;
91
92 if data.is_empty() {
93 return None;
94 }
95
96 Some(Self(Name::new(data)?))
97 }
98}
99
100#[derive(Debug, Clone)]
102pub struct UntypedIter<'a> {
103 reader: Reader<'a>,
104 stack: Stack<'a>,
105 operator: Option<Operator<'a>>,
106}
107
108impl<'a> UntypedIter<'a> {
109 pub fn new(data: &'a [u8]) -> Self {
111 Self {
112 reader: Reader::new(data),
113 stack: Stack::new(),
114 operator: None,
115 }
116 }
117
118 pub fn empty() -> Self {
120 Self {
121 reader: Reader::new(&[]),
122 stack: Stack::new(),
123 operator: None,
124 }
125 }
126
127 #[allow(clippy::should_implement_trait)]
129 pub fn next(&mut self) -> Option<Instruction<'_, 'a>> {
130 self.stack.clear();
131 self.operator = None;
132
133 self.reader.skip_white_spaces_and_comments();
134
135 while !self.reader.at_end() {
136 if matches!(
138 self.reader.peek_byte()?,
139 b'/' | b'.' | b'+' | b'-' | b'0'..=b'9' | b'[' | b'<' | b'('
140 ) {
141 if let Some(object) = self.reader.read_without_context::<Object<'_>>() {
149 self.stack.push(object)?;
150 } else if self.reader.read_without_context::<Operator<'_>>().is_some() {
151 self.stack.clear();
152 } else {
153 return None;
154 }
155 } else {
156 let operator = match self.reader.read_without_context::<Operator<'_>>() {
157 Some(o) => o,
158 None => {
159 warn!("failed to read operator in content stream");
160
161 self.reader.jump_to_end();
162 return None;
163 }
164 };
165
166 if operator.as_ref() == b"BI" {
168 let inline_dict = self.reader.read_without_context::<InlineImageDict<'_>>()?;
170 let dict = inline_dict.get_dict().clone();
171
172 self.reader.read_white_space()?;
174
175 let stream_data = self.reader.tail()?;
176 let start_offset = self.reader.offset();
177
178 'outer: while let Some(pos) = find_needle(self.reader.tail()?, b"EI") {
179 self.reader.read_bytes(pos)?;
180
181 if self.reader.peek_bytes(2) == Some(b"EI") {
182 if self
184 .reader
185 .peek_bytes(3)
186 .is_some_and(|b| !is_white_space_character(b[2]))
187 {
188 self.reader.read_bytes(3)?;
189
190 continue;
191 }
192
193 let end_offset = self.reader.offset() - start_offset;
194 let image_data = &stream_data[..end_offset];
195
196 let stream = Stream::new(image_data, dict.clone());
197
198 let tail = &self.reader.tail()?[2..];
205 let mut find_reader = Reader::new(tail);
206
207 while !find_reader.at_end() {
208 let remaining = find_reader.tail()?;
209 let next_ei = find_needle(remaining, b"EI");
210 let next_bi = find_needle(remaining, b"BI");
211
212 let (next_pos, is_ei) = match (next_ei, next_bi) {
213 (Some(ei), Some(bi)) if ei <= bi => (ei, true),
214 (Some(_), Some(bi)) => (bi, false),
215 (Some(ei), None) => (ei, true),
216 (None, Some(bi)) => (bi, false),
217 (None, None) => break,
218 };
219
220 find_reader.read_bytes(next_pos)?;
221
222 if is_ei {
223 let analyze_data = &tail[..find_reader.offset()];
224
225 if analyze_data.iter().any(|c| !c.is_ascii()) {
228 self.reader.read_bytes(2)?;
229 continue 'outer;
230 }
231
232 let mut iter = TypedIter::new(tail);
241 let mut found = false;
242 let mut counter = 0;
243
244 while let Some(op) = iter.next() {
245 if counter >= 20 {
251 found = true;
252 break;
253 }
254
255 if matches!(
256 op,
257 TypedInstruction::NextLineAndShowText(_)
258 | TypedInstruction::ShowText(_)
259 | TypedInstruction::ShowTexts(_)
260 | TypedInstruction::ShowTextWithParameters(_)
261 ) {
262 found = true;
265 break;
266 }
267
268 counter += 1;
269 }
270
271 if !found {
272 self.reader.read_bytes(2)?;
275 continue 'outer;
276 }
277 } else {
278 let mut cloned = find_reader.clone();
281 cloned.read_bytes(2)?;
282 if cloned
283 .read_without_context::<InlineImageDict<'_>>()
284 .is_some()
285 {
286 break;
287 }
288 }
289
290 find_reader.read_byte()?;
291 }
292
293 self.stack.push(Object::Stream(stream))?;
294
295 self.reader.read_bytes(2)?;
296 self.reader.skip_white_spaces();
297
298 break;
299 }
300 }
301 }
302
303 self.operator = Some(operator);
304 return Some(Instruction {
305 operands: &self.stack,
306 operator: self.operator.as_ref().unwrap(),
307 });
308 }
309
310 self.reader.skip_white_spaces_and_comments();
311 }
312
313 None
314 }
315}
316
317#[derive(Clone)]
320pub struct TypedIter<'a> {
321 untyped: UntypedIter<'a>,
322}
323
324impl<'a> TypedIter<'a> {
325 pub fn new(data: &'a [u8]) -> Self {
327 Self {
328 untyped: UntypedIter::new(data),
329 }
330 }
331
332 pub(crate) fn from_untyped(untyped: UntypedIter<'a>) -> Self {
333 Self { untyped }
334 }
335
336 #[allow(clippy::should_implement_trait)]
338 pub fn next(&mut self) -> Option<TypedInstruction<'_, 'a>> {
339 let op = self.untyped.next()?;
340 match TypedInstruction::dispatch(&op) {
342 Some(op) => Some(op),
343 None => {
348 if [
349 &b"m"[..],
350 &b"l"[..],
351 &b"c"[..],
352 &b"v"[..],
353 &b"y"[..],
354 &b"h"[..],
355 &b"re"[..],
356 ]
357 .contains(&op.operator.0.deref())
358 {
359 None
360 } else {
361 Some(TypedInstruction::Fallback(op.operator))
362 }
363 }
364 }
365 }
366}
367
368#[derive(Debug)]
370pub struct Instruction<'b, 'a> {
371 pub operands: &'b Stack<'a>,
373 pub operator: &'b Operator<'a>,
375}
376
377impl<'b, 'a> Instruction<'b, 'a> {
378 pub fn operands(&self) -> OperandIterator<'b, 'a> {
380 OperandIterator::new(self.operands)
381 }
382}
383
384pub struct Stack<'a> {
386 data: [Object<'a>; OPERANDS_THRESHOLD],
389 len: usize,
390}
391
392impl<'a> Default for Stack<'a> {
393 fn default() -> Self {
394 Self::new()
395 }
396}
397
398impl<'a> Stack<'a> {
399 pub fn new() -> Self {
401 Self {
402 data: array::from_fn(|_| Object::Null(Null)),
403 len: 0,
404 }
405 }
406
407 fn push(&mut self, operand: Object<'a>) -> Option<()> {
408 if self.len >= OPERANDS_THRESHOLD {
409 return None;
410 }
411
412 self.data[self.len] = operand;
413 self.len += 1;
414 Some(())
415 }
416
417 fn clear(&mut self) {
418 self.len = 0;
419 }
420
421 fn len(&self) -> usize {
422 self.len
423 }
424
425 fn as_slice(&self) -> &[Object<'a>] {
426 &self.data[..self.len]
427 }
428
429 fn get<'b, T>(&'b self, index: usize) -> Option<T>
430 where
431 T: Operand<'b, 'a>,
432 {
433 self.as_slice().get(index).and_then(T::from_object)
434 }
435
436 fn get_all<'b, T>(&'b self) -> Option<SmallVec<[T; OPERANDS_THRESHOLD]>>
437 where
438 T: Operand<'b, 'a>,
439 {
440 let mut operands = SmallVec::new();
441
442 for op in self.as_slice() {
443 let converted = T::from_object(op)?;
444 operands.push(converted);
445 }
446
447 Some(operands)
448 }
449}
450
451impl Debug for Stack<'_> {
452 fn fmt(&self, f: &mut Formatter<'_>) -> core::fmt::Result {
453 f.debug_list().entries(self.as_slice()).finish()
454 }
455}
456
457impl Clone for Stack<'_> {
458 fn clone(&self) -> Self {
459 let mut stack = Self::new();
460 for item in self.as_slice() {
461 stack.push(item.clone()).unwrap();
462 }
463 stack
464 }
465}
466
467impl PartialEq for Stack<'_> {
468 fn eq(&self, other: &Self) -> bool {
469 self.as_slice() == other.as_slice()
470 }
471}
472
473trait Operand<'b, 'a>: Sized {
474 fn from_object(object: &'b Object<'a>) -> Option<Self>;
475}
476
477impl<'b, 'a> Operand<'b, 'a> for Number {
478 fn from_object(object: &'b Object<'a>) -> Option<Self> {
479 match object {
480 Object::Number(n) => Some(*n),
481 _ => None,
482 }
483 }
484}
485
486impl<'b, 'a> Operand<'b, 'a> for &'b object::String<'a> {
487 fn from_object(object: &'b Object<'a>) -> Option<Self> {
488 match object {
489 Object::String(s) => Some(s),
490 _ => None,
491 }
492 }
493}
494
495impl<'b, 'a> Operand<'b, 'a> for &'b Name<'a> {
496 fn from_object(object: &'b Object<'a>) -> Option<Self> {
497 match object {
498 Object::Name(n) => Some(n),
499 _ => None,
500 }
501 }
502}
503
504impl<'b, 'a> Operand<'b, 'a> for &'b Array<'a> {
505 fn from_object(object: &'b Object<'a>) -> Option<Self> {
506 match object {
507 Object::Array(a) => Some(a),
508 _ => None,
509 }
510 }
511}
512
513impl<'b, 'a> Operand<'b, 'a> for &'b Stream<'a> {
514 fn from_object(object: &'b Object<'a>) -> Option<Self> {
515 match object {
516 Object::Stream(s) => Some(s),
517 _ => None,
518 }
519 }
520}
521
522impl<'b, 'a> Operand<'b, 'a> for &'b Object<'a> {
523 fn from_object(object: &'b Object<'a>) -> Option<Self> {
524 Some(object)
525 }
526}
527
528pub struct OperandIterator<'b, 'a> {
530 stack: &'b Stack<'a>,
531 cur_index: usize,
532}
533
534impl<'b, 'a> OperandIterator<'b, 'a> {
535 fn new(stack: &'b Stack<'a>) -> Self {
536 Self {
537 stack,
538 cur_index: 0,
539 }
540 }
541}
542
543impl<'b, 'a> Iterator for OperandIterator<'b, 'a> {
544 type Item = &'b Object<'a>;
545
546 fn next(&mut self) -> Option<Self::Item> {
547 if let Some(item) = self.stack.as_slice().get(self.cur_index) {
548 self.cur_index += 1;
549
550 Some(item)
551 } else {
552 None
553 }
554 }
555}
556
557pub(crate) trait OperatorTrait<'b, 'a>: Sized {
558 const OPERATOR: &'static str;
559
560 fn from_stack(stack: &'b Stack<'a>) -> Option<Self>;
561}
562
563mod macros {
564 macro_rules! display_op {
565 ($t:ident $(<$($l:lifetime),+>)?;) => {
566 impl$(<$($l),+>)? core::fmt::Display for $t$(<$($l),+>)? {
567 fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
568 f.write_str(stringify!($t))
569 }
570 }
571 };
572 ($t:ident $(<$($l:lifetime),+>)?; $first:tt $(, $field:tt)*) => {
573 impl$(<$($l),+>)? core::fmt::Display for $t$(<$($l),+>)? {
574 fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
575 f.write_str(concat!(stringify!($t), "("))?;
576 core::fmt::Display::fmt(&self.$first, f)?;
577 $(
578 f.write_str(" ")?;
579 core::fmt::Display::fmt(&self.$field, f)?;
580 )*
581 f.write_str(")")
582 }
583 }
584 };
585 }
586
587 macro_rules! display_variadic_op {
588 ($t:ident $(<$($l:lifetime),+>)?) => {
589 impl$(<$($l),+>)? core::fmt::Display for $t$(<$($l),+>)? {
590 fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
591 f.write_str(stringify!($t))?;
592 if let Some((first, rest)) = self.0.split_first() {
593 f.write_str("(")?;
594 core::fmt::Display::fmt(first, f)?;
595 for value in rest {
596 f.write_str(" ")?;
597 core::fmt::Display::fmt(value, f)?;
598 }
599 f.write_str(")")?;
600 }
601 Ok(())
602 }
603 }
604 };
605 }
606
607 macro_rules! op_impl {
608 ($t:ident $(<$($l:lifetime),+>)?, $e:expr, $n:expr, |$stack:ident : $stack_ty:ty| $body:block) => {
609 impl<'b, 'a> OperatorTrait<'b, 'a> for $t$(<$($l),+>)? {
610 const OPERATOR: &'static str = $e;
611
612 #[inline(always)]
613 fn from_stack($stack: $stack_ty) -> Option<Self> {
614 $body.or_else(|| {
615 warn!("failed to convert operands for operator {}", Self::OPERATOR);
616
617 None
618 })
619 }
620 }
621
622 impl<'b, 'a> From<$t$(<$($l),+>)?> for TypedInstruction<'b, 'a> {
623 fn from(value: $t$(<$($l),+>)?) -> Self {
624 TypedInstruction::$t(value)
625 }
626 }
627
628 impl<'b, 'a> TryFrom<TypedInstruction<'b, 'a>> for $t$(<$($l),+>)? {
629 type Error = ();
630
631 fn try_from(value: TypedInstruction<'b, 'a>) -> core::result::Result<Self, Self::Error> {
632 match value {
633 TypedInstruction::$t(e) => Ok(e),
634 _ => Err(())
635 }
636 }
637 }
638 };
639 }
640
641 macro_rules! op0 {
647 ($t:ident $(<$($l:lifetime),+>)?, $e:expr) => {
648 crate::content::macros::display_op!($t$(<$($l),+>)?;);
649 crate::content::macros::op_impl!($t$(<$($l),+>)?, $e, 0, |_stack: &'b Stack<'a>| {
650 Some(Self)
651 });
652 }
653 }
654
655 macro_rules! op1 {
656 ($t:ident $(<$($l:lifetime),+>)?, $e:expr) => {
657 crate::content::macros::display_op!($t$(<$($l),+>)?; 0);
658 crate::content::macros::op_impl!($t$(<$($l),+>)?, $e, 1, |stack: &'b Stack<'a>| {
659 let shift = stack.len().saturating_sub(1);
660 Some(Self(stack.get(0 + shift)?))
661 });
662 }
663 }
664
665 macro_rules! op_all {
666 ($t:ident $(<$($l:lifetime),+>)?, $e:expr) => {
667 crate::content::macros::display_variadic_op!($t$(<$($l),+>)?);
668 crate::content::macros::op_impl!($t$(<$($l),+>)?, $e, u8::MAX as usize, |stack: &'b Stack<'a>| {
669 Some(Self(stack.get_all()?))
670 });
671 }
672 }
673
674 macro_rules! op2 {
675 ($t:ident $(<$($l:lifetime),+>)?, $e:expr) => {
676 crate::content::macros::display_op!($t$(<$($l),+>)?; 0, 1);
677 crate::content::macros::op_impl!($t$(<$($l),+>)?, $e, 2, |stack: &'b Stack<'a>| {
678 let shift = stack.len().saturating_sub(2);
679 Some(Self(stack.get(0 + shift)?, stack.get(1 + shift)?))
680 });
681 }
682 }
683
684 macro_rules! op3 {
685 ($t:ident $(<$($l:lifetime),+>)?, $e:expr) => {
686 crate::content::macros::display_op!($t$(<$($l),+>)?; 0, 1, 2);
687 crate::content::macros::op_impl!($t$(<$($l),+>)?, $e, 3, |stack: &'b Stack<'a>| {
688 let shift = stack.len().saturating_sub(3);
689 Some(Self(stack.get(0 + shift)?, stack.get(1 + shift)?,
690 stack.get(2 + shift)?))
691 });
692 }
693 }
694
695 macro_rules! op4 {
696 ($t:ident $(<$($l:lifetime),+>)?, $e:expr) => {
697 crate::content::macros::display_op!($t$(<$($l),+>)?; 0, 1, 2, 3);
698 crate::content::macros::op_impl!($t$(<$($l),+>)?, $e, 4, |stack: &'b Stack<'a>| {
699 let shift = stack.len().saturating_sub(4);
700 Some(Self(stack.get(0 + shift)?, stack.get(1 + shift)?,
701 stack.get(2 + shift)?, stack.get(3 + shift)?))
702 });
703 }
704 }
705
706 macro_rules! op6 {
707 ($t:ident $(<$($l:lifetime),+>)?, $e:expr) => {
708 crate::content::macros::display_op!($t$(<$($l),+>)?; 0, 1, 2, 3, 4, 5);
709 crate::content::macros::op_impl!($t$(<$($l),+>)?, $e, 6, |stack: &'b Stack<'a>| {
710 let shift = stack.len().saturating_sub(6);
711 Some(Self(stack.get(0 + shift)?, stack.get(1 + shift)?,
712 stack.get(2 + shift)?, stack.get(3 + shift)?,
713 stack.get(4 + shift)?, stack.get(5 + shift)?))
714 });
715 }
716 }
717
718 pub(crate) use display_op;
719 pub(crate) use display_variadic_op;
720 pub(crate) use op_all;
721 pub(crate) use op_impl;
722 pub(crate) use op0;
723 pub(crate) use op1;
724 pub(crate) use op2;
725 pub(crate) use op3;
726 pub(crate) use op4;
727 pub(crate) use op6;
728}