pdf/
xref.rs

1use std::fmt::{Debug, Formatter};
2use crate::error::*;
3use crate::object::*;
4use crate as pdf;
5use datasize::DataSize;
6
7///////////////////////////
8// Cross-reference table //
9///////////////////////////
10
11#[derive(Copy, Clone, Debug)]
12pub enum XRef {
13    /// Not currently used.
14    Free {
15        next_obj_nr: ObjNr,
16        gen_nr: GenNr
17    },
18
19    /// In use.
20    Raw {
21        pos: usize,
22        gen_nr: GenNr
23    },
24    /// In use and compressed inside an Object Stream
25    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, // TODO I think these always have gen nr 0?
41            _ => panic!()
42        }
43    }
44}
45
46
47/// Runtime lookup table of all objects
48#[derive(Clone)]
49pub struct XRefTable {
50    // None means that it's not specified, and should result in an error if used
51    // Thought: None could also mean Free?
52    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                // Early return if the entry we have has larger or equal generation number
113                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                x => bail!("invalid xref entry: {:?}", x)
140            };
141            data.push(t);
142            data.extend_from_slice(&a.to_be_bytes()[8 - a_w ..]);
143            data.extend_from_slice(&b.to_be_bytes()[8 - b_w ..]);
144        }
145        let info = XRefInfo {
146            size: size as u32,
147            index: vec![0, size as u32],
148            prev: None,
149            w: vec![1, a_w, b_w],
150        };
151        
152        Ok(Stream::new(info, data))
153    }
154}
155
156fn byte_len(n: u64) -> usize {
157    (64 + 8 - 1 - n.leading_zeros()) as usize / 8 + (n == 0) as usize
158}
159
160impl Debug for XRefTable {
161    fn fmt(&self, f: &mut Formatter) -> std::fmt::Result {
162        for (i, entry) in self.entries.iter().enumerate() {
163            match *entry {
164                XRef::Free {next_obj_nr, gen_nr} => {
165                    writeln!(f, "{:4}: {:010} {:05} f", i, next_obj_nr, gen_nr)?
166                },
167                XRef::Raw {pos, gen_nr} => {
168                    writeln!(f, "{:4}: {:010} {:05} n", i, pos, gen_nr)?
169                },
170                XRef::Stream {stream_id, index} => {
171                    writeln!(f, "{:4}: in stream {}, index {}", i, stream_id, index)?
172                },
173                XRef::Promised => {
174                    writeln!(f, "{:4}: Promised?", i)?
175                },
176                XRef::Invalid => {
177                    writeln!(f, "{:4}: Invalid!", i)?
178                }
179            }
180        }
181        Ok(())
182    }
183}
184
185/// As found in PDF files
186#[derive(Debug)]
187pub struct XRefSection {
188    pub first_id: u32,
189    pub entries: Vec<XRef>,
190}
191
192
193impl XRefSection {
194    pub fn new(first_id: u32) -> XRefSection {
195        XRefSection {
196            first_id,
197            entries: Vec::new(),
198        }
199    }
200    pub fn add_free_entry(&mut self, next_obj_nr: ObjNr, gen_nr: GenNr) {
201        self.entries.push(XRef::Free{next_obj_nr, gen_nr});
202    }
203    pub fn add_inuse_entry(&mut self, pos: usize, gen_nr: GenNr) {
204        self.entries.push(XRef::Raw{pos, gen_nr});
205    }
206    pub fn entries(&self) -> impl Iterator<Item=(usize, &XRef)> {
207        self.entries.iter().enumerate().map(move |(i, e)| (i + self.first_id as usize, e))
208    }
209}
210
211
212#[derive(Object, ObjectWrite, Debug, DataSize)]
213#[pdf(Type = "XRef")]
214pub struct XRefInfo {
215    // XRefStream fields
216    #[pdf(key = "Size")]
217    pub size: u32,
218
219    //
220    #[pdf(key = "Index", default = "vec![0, size]")]
221    /// Array of pairs of integers for each subsection, (first object number, number of entries).
222    /// Default value (assumed when None): `(0, self.size)`.
223    pub index: Vec<u32>,
224
225    #[pdf(key = "Prev")]
226    prev: Option<i32>,
227
228    #[pdf(key = "W")]
229    pub w: Vec<usize>,
230}
231
232// read_xref_table
233// read_xref_stream
234// read_xref_and_trailer_at