1use std::fmt::{Debug, Formatter};
2use crate::error::*;
3use crate::object::*;
4use crate as pdf;
5use datasize::DataSize;
6
7#[derive(Copy, Clone, Debug)]
12pub enum XRef {
13 Free {
15 next_obj_nr: ObjNr,
16 gen_nr: GenNr
17 },
18
19 Raw {
21 pos: usize,
22 gen_nr: GenNr
23 },
24 Stream {
26 stream_id: ObjNr,
27 index: usize,
28 },
29
30 Promised,
31
32 Invalid
33}
34
35impl XRef {
36 pub fn get_gen_nr(&self) -> GenNr {
37 match *self {
38 XRef::Free {gen_nr, ..}
39 | XRef::Raw {gen_nr, ..} => gen_nr,
40 XRef::Stream { .. } => 0, _ => panic!()
42 }
43 }
44}
45
46
47#[derive(Clone)]
49pub struct XRefTable {
50 entries: Vec<XRef>
53}
54
55
56impl XRefTable {
57 pub fn new(num_objects: ObjNr) -> XRefTable {
58 let mut entries = Vec::new();
59 entries.resize(num_objects as usize, XRef::Invalid);
60 entries.push(XRef::Free { next_obj_nr: 0, gen_nr: 0xffff });
61 XRefTable {
62 entries,
63 }
64 }
65
66 pub fn iter(&self) -> impl Iterator<Item=u32> + '_ {
67 self.entries.iter().enumerate()
68 .filter(|(_, xref)| matches!(xref, XRef::Raw { .. } | XRef::Stream { .. } ))
69 .map(|(i, _)| i as u32)
70 }
71
72 pub fn get(&self, id: ObjNr) -> Result<XRef> {
73 match self.entries.get(id as usize) {
74 Some(&entry) => Ok(entry),
75 None => Err(PdfError::UnspecifiedXRefEntry {id}),
76 }
77 }
78 pub fn set(&mut self, id: ObjNr, r: XRef) {
79 self.entries[id as usize] = r;
80 }
81 pub fn len(&self) -> usize {
82 self.entries.len()
83 }
84 pub fn is_empty(&self) -> bool {
85 self.entries.is_empty()
86 }
87 pub fn push(&mut self, new_entry: XRef) {
88 self.entries.push(new_entry);
89 }
90 pub fn num_entries(&self) -> usize {
91 self.entries.len()
92 }
93 pub fn max_field_widths(&self) -> (u64, u64) {
94 let mut max_a = 0;
95 let mut max_b = 0;
96 for &e in &self.entries {
97 let (a, b) = match e {
98 XRef::Raw { pos, gen_nr } => (pos as u64, gen_nr),
99 XRef::Free { next_obj_nr, gen_nr } => (next_obj_nr, gen_nr),
100 XRef::Stream { stream_id, index } => (stream_id, index as u64),
101 _ => continue
102 };
103 max_a = max_a.max(a);
104 max_b = max_b.max(b);
105 }
106 (max_a, max_b)
107 }
108
109 pub fn add_entries_from(&mut self, section: XRefSection) -> Result<()> {
110 for (i, &entry) in section.entries() {
111 if let Some(dst) = self.entries.get_mut(i) {
112 let should_be_updated = match *dst {
114 XRef::Raw { gen_nr: gen, .. } | XRef::Free { gen_nr: gen, .. }
115 => entry.get_gen_nr() > gen,
116 XRef::Stream { .. } | XRef::Invalid
117 => true,
118 x => bail!("found {:?}", x)
119 };
120 if should_be_updated {
121 *dst = entry;
122 }
123 }
124 }
125 Ok(())
126 }
127
128 pub fn write_stream(&self, size: usize) -> Result<Stream<XRefInfo>> {
129 let (max_a, max_b) = self.max_field_widths();
130 let a_w = byte_len(max_a);
131 let b_w = byte_len(max_b);
132
133 let mut data = Vec::with_capacity((1 + a_w + b_w) * size);
134 for &x in self.entries.iter().take(size) {
135 let (t, a, b) = match x {
136 XRef::Free { next_obj_nr, gen_nr } => (0, next_obj_nr, gen_nr),
137 XRef::Raw { pos, gen_nr } => (1, pos as u64, gen_nr),
138 XRef::Stream { stream_id, index } => (2, stream_id, index as u64),
139 XRef::Invalid | XRef::Promised => (0, 0, 0),
141 };
142 data.push(t);
143 data.extend_from_slice(&a.to_be_bytes()[8 - a_w ..]);
144 data.extend_from_slice(&b.to_be_bytes()[8 - b_w ..]);
145 }
146 let info = XRefInfo {
147 size: size as u32,
148 index: vec![0, size as u32],
149 prev: None,
150 w: vec![1, a_w, b_w],
151 };
152
153 Ok(Stream::new(info, data))
154 }
155}
156
157fn byte_len(n: u64) -> usize {
158 (64 + 8 - 1 - n.leading_zeros()) as usize / 8 + (n == 0) as usize
159}
160
161impl Debug for XRefTable {
162 fn fmt(&self, f: &mut Formatter) -> std::fmt::Result {
163 for (i, entry) in self.entries.iter().enumerate() {
164 match *entry {
165 XRef::Free {next_obj_nr, gen_nr} => {
166 writeln!(f, "{:4}: {:010} {:05} f", i, next_obj_nr, gen_nr)?
167 },
168 XRef::Raw {pos, gen_nr} => {
169 writeln!(f, "{:4}: {:010} {:05} n", i, pos, gen_nr)?
170 },
171 XRef::Stream {stream_id, index} => {
172 writeln!(f, "{:4}: in stream {}, index {}", i, stream_id, index)?
173 },
174 XRef::Promised => {
175 writeln!(f, "{:4}: Promised?", i)?
176 },
177 XRef::Invalid => {
178 writeln!(f, "{:4}: Invalid!", i)?
179 }
180 }
181 }
182 Ok(())
183 }
184}
185
186#[derive(Debug)]
188pub struct XRefSection {
189 pub first_id: u32,
190 pub entries: Vec<XRef>,
191}
192
193
194impl XRefSection {
195 pub fn new(first_id: u32) -> XRefSection {
196 XRefSection {
197 first_id,
198 entries: Vec::new(),
199 }
200 }
201 pub fn add_free_entry(&mut self, next_obj_nr: ObjNr, gen_nr: GenNr) {
202 self.entries.push(XRef::Free{next_obj_nr, gen_nr});
203 }
204 pub fn add_inuse_entry(&mut self, pos: usize, gen_nr: GenNr) {
205 self.entries.push(XRef::Raw{pos, gen_nr});
206 }
207 pub fn entries(&self) -> impl Iterator<Item=(usize, &XRef)> {
208 self.entries.iter().enumerate().map(move |(i, e)| (i + self.first_id as usize, e))
209 }
210}
211
212
213#[derive(Object, ObjectWrite, Debug, DataSize)]
214#[pdf(Type = "XRef")]
215pub struct XRefInfo {
216 #[pdf(key = "Size")]
218 pub size: u32,
219
220 #[pdf(key = "Index", default = "vec![0, size]")]
222 pub index: Vec<u32>,
225
226 #[pdf(key = "Prev")]
227 prev: Option<i32>,
228
229 #[pdf(key = "W")]
230 pub w: Vec<usize>,
231}
232
233