justpdf_core/content/
operator.rs1#[derive(Debug, Clone, PartialEq)]
3pub enum Operand {
4 Integer(i64),
5 Real(f64),
6 Bool(bool),
7 Null,
8 Name(Vec<u8>),
9 String(Vec<u8>),
10 Array(Vec<Operand>),
11 Dict(Vec<(Vec<u8>, Operand)>),
12 InlineImage {
14 dict: Vec<(Vec<u8>, Operand)>,
15 data: Vec<u8>,
16 },
17}
18
19impl Operand {
20 pub fn as_i64(&self) -> Option<i64> {
21 match self {
22 Self::Integer(v) => Some(*v),
23 _ => None,
24 }
25 }
26
27 pub fn as_f64(&self) -> Option<f64> {
28 match self {
29 Self::Real(v) => Some(*v),
30 Self::Integer(v) => Some(*v as f64),
31 _ => None,
32 }
33 }
34
35 pub fn as_name(&self) -> Option<&[u8]> {
36 match self {
37 Self::Name(v) => Some(v),
38 _ => None,
39 }
40 }
41
42 pub fn as_str(&self) -> Option<&[u8]> {
43 match self {
44 Self::String(v) => Some(v),
45 _ => None,
46 }
47 }
48
49 pub fn as_array(&self) -> Option<&[Operand]> {
50 match self {
51 Self::Array(v) => Some(v),
52 _ => None,
53 }
54 }
55}
56
57#[derive(Debug, Clone)]
59pub struct ContentOp {
60 pub operator: Vec<u8>,
62 pub operands: Vec<Operand>,
64}
65
66impl ContentOp {
67 pub fn operator_str(&self) -> &str {
69 std::str::from_utf8(&self.operator).unwrap_or("?")
70 }
71}
72
73impl std::fmt::Display for ContentOp {
74 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
75 for (i, op) in self.operands.iter().enumerate() {
76 if i > 0 {
77 write!(f, " ")?;
78 }
79 write!(f, "{}", format_operand(op))?;
80 }
81 if !self.operands.is_empty() {
82 write!(f, " ")?;
83 }
84 write!(f, "{}", self.operator_str())
85 }
86}
87
88fn format_operand(op: &Operand) -> String {
89 match op {
90 Operand::Integer(v) => v.to_string(),
91 Operand::Real(v) => format!("{v}"),
92 Operand::Bool(v) => v.to_string(),
93 Operand::Null => "null".into(),
94 Operand::Name(n) => format!("/{}", std::str::from_utf8(n).unwrap_or("?")),
95 Operand::String(s) => match std::str::from_utf8(s) {
96 Ok(text) => format!("({text})"),
97 Err(_) => {
98 let hex: String = s.iter().map(|b| format!("{b:02X}")).collect();
99 format!("<{hex}>")
100 }
101 },
102 Operand::Array(items) => {
103 let inner: Vec<String> = items.iter().map(format_operand).collect();
104 format!("[{}]", inner.join(" "))
105 }
106 Operand::Dict(entries) => {
107 let inner: Vec<String> = entries
108 .iter()
109 .map(|(k, v)| {
110 format!(
111 "/{} {}",
112 std::str::from_utf8(k).unwrap_or("?"),
113 format_operand(v)
114 )
115 })
116 .collect();
117 format!("<< {} >>", inner.join(" "))
118 }
119 Operand::InlineImage { .. } => "<inline-image>".into(),
120 }
121}