1use crate::object::ObjectIdentifier;
2use crate::object::Stream;
3use crate::reader::ReaderContext;
4use crate::sync::FxHashMap;
5use crate::sync::{Arc, Mutex, MutexExt};
6use crate::util::SegmentList;
7use crate::xref::ObjectStream;
8use alloc::vec::Vec;
9use core::fmt::{Debug, Formatter};
10
11#[derive(Clone)]
13pub struct PdfData {
14 #[cfg(feature = "std")]
15 inner: Arc<dyn AsRef<[u8]> + Send + Sync>,
16 #[cfg(not(feature = "std"))]
17 inner: Arc<dyn AsRef<[u8]>>,
18}
19
20impl Debug for PdfData {
21 fn fmt(&self, f: &mut Formatter<'_>) -> core::fmt::Result {
22 write!(f, "PdfData {{ ... }}")
23 }
24}
25
26impl AsRef<[u8]> for PdfData {
27 fn as_ref(&self) -> &[u8] {
28 (*self.inner).as_ref()
29 }
30}
31
32#[cfg(feature = "std")]
33impl<T: AsRef<[u8]> + Send + Sync + 'static> From<Arc<T>> for PdfData {
34 fn from(data: Arc<T>) -> Self {
35 Self { inner: data }
36 }
37}
38
39#[cfg(not(feature = "std"))]
40impl<T: AsRef<[u8]> + 'static> From<Arc<T>> for PdfData {
41 fn from(data: Arc<T>) -> Self {
42 Self { inner: data }
43 }
44}
45
46impl From<Vec<u8>> for PdfData {
47 fn from(data: Vec<u8>) -> Self {
48 Self {
49 inner: Arc::new(data),
50 }
51 }
52}
53
54pub(crate) struct Data {
66 data: PdfData,
67 object_streams: SegmentList<ObjectStream, 32>,
69 map: Mutex<FxHashMap<ObjectIdentifier, usize>>,
70}
71
72impl Debug for Data {
73 fn fmt(&self, f: &mut Formatter<'_>) -> core::fmt::Result {
74 write!(f, "Data {{ ... }}")
75 }
76}
77
78impl Data {
79 pub(crate) fn new(data: PdfData) -> Self {
81 Self {
82 data,
83 object_streams: SegmentList::new(),
84 map: Mutex::new(FxHashMap::default()),
85 }
86 }
87
88 pub(crate) fn get(&self) -> &PdfData {
90 &self.data
91 }
92
93 pub(crate) fn object_stream(
95 &self,
96 id: ObjectIdentifier,
97 ctx: &ReaderContext<'_>,
98 ) -> Option<&ObjectStream> {
99 if let Some(&idx) = self.map.get().get(&id) {
100 return self.object_streams.get(idx);
101 }
102
103 let stream = ctx.xref().get_with::<Stream<'_>>(id, ctx)?;
105 let object_stream = ObjectStream::new(&stream)?;
106
107 let mut locked = self.map.get();
108 if let Some(&idx) = locked.get(&id) {
109 return self.object_streams.get(idx);
110 }
111
112 let idx = locked.len();
113 let object_stream = self.object_streams.get_or_init(idx, || object_stream);
114 locked.insert(id, idx);
115
116 Some(object_stream)
117 }
118}