tiff_encoder/ifd/
values.rs1use std::io;
20
21use crate::ifd::types::{TiffType, IFD, LONG};
22use crate::ifd::{AllocatedIfdChain, IfdChain};
23use crate::write::{Cursor, Datablock, EndianFile};
24
25pub trait FieldValues: private::Sealed {
45 #[doc(hidden)]
47 fn count(&self) -> u32;
48 #[doc(hidden)]
52 fn size(&self) -> u32;
53 #[doc(hidden)]
56 fn allocate(self: Box<Self>, c: &mut Cursor) -> Box<AllocatedFieldValues>;
57}
58
59#[doc(hidden)]
61pub trait AllocatedFieldValues {
62 fn count(&self) -> u32;
64 fn size(&self) -> u32;
68 fn position(&self) -> Option<u32>;
72 fn type_id(&self) -> u16;
74 fn write_to(self: Box<Self>, file: &mut EndianFile) -> io::Result<()>;
77}
78
79mod private {
83 pub trait Sealed {}
84 impl<T: super::Datablock> Sealed for super::Offsets<T> {}
85 impl<T: super::TiffType> Sealed for super::TiffTypeValues<T> {}
86 impl Sealed for super::OffsetsToIfds {}
87}
88
89pub struct Offsets<T: Datablock> {
99 pub data: Vec<T>,
100}
101impl<T: Datablock + 'static> Offsets<T> {
102 pub fn new(datablocks: Vec<T>) -> Self {
106 Offsets { data: datablocks }
107 }
108
109 pub fn single(datablock: T) -> Self {
113 Offsets::new(vec![datablock])
114 }
115}
116impl<T: Datablock + 'static> FieldValues for Offsets<T> {
117 #[doc(hidden)]
118 fn count(&self) -> u32 {
119 self.data.len() as u32
120 }
121
122 #[doc(hidden)]
123 fn size(&self) -> u32 {
124 LONG::size() * self.count()
125 }
126
127 #[doc(hidden)]
128 fn allocate(self: Box<Self>, c: &mut Cursor) -> Box<AllocatedFieldValues> {
129 let position = Some(c.allocated_bytes());
130 if self.data.len() == 1 {
131 let offsets = Vec::new();
134 let block_size = self.data.get(0).unwrap().size(); c.allocate(if block_size % 2 == 0 {
140 block_size
141 } else {
142 block_size + 1
143 });
144
145 Box::new(AllocatedOffsets {
146 position,
147 offsets,
148 data: self.data,
149 })
150 } else {
151 c.allocate(self.size());
152 let mut offsets = Vec::with_capacity(self.data.len());
153
154 for block in self.data.iter() {
155 offsets.push(LONG(c.allocated_bytes()));
156 c.allocate(if block.size() % 2 == 0 {
157 block.size()
158 } else {
159 block.size() + 1
160 });
161 }
162
163 Box::new(AllocatedOffsets {
164 position,
165 offsets,
166 data: self.data,
167 })
168 }
169 }
170}
171
172struct AllocatedOffsets<T: Datablock> {
174 position: Option<u32>,
175 offsets: Vec<LONG>,
176 data: Vec<T>,
177}
178impl<T: Datablock> AllocatedFieldValues for AllocatedOffsets<T> {
179 fn count(&self) -> u32 {
180 self.data.len() as u32
181 }
182
183 fn size(&self) -> u32 {
184 LONG::size() * self.count()
185 }
186
187 fn position(&self) -> Option<u32> {
188 self.position
189 }
190
191 fn type_id(&self) -> u16 {
192 LONG::id()
193 }
194
195 fn write_to(self: Box<Self>, file: &mut EndianFile) -> io::Result<()> {
196 let unboxed = *self;
197 let Self { data, offsets, .. } = unboxed;
198 for offset in offsets {
199 offset.write_to(file)?;
200 }
201 for block in data {
202 let file_initial = file.written_bytes();
203 let block_size = block.size();
204 block.write_to(file)?;
205 let written_size = file.written_bytes() - file_initial;
206 if written_size % 2 == 1 {
210 file.write_arbitrary_byte()?
211 }
212 if written_size != block_size {
213 panic!(
214 "The number of bytes allocated by the Datablock ({}) is different from the number of bytes written to the file ({}).",
215 block_size, written_size
216 )
217 }
218 }
219
220 Ok(())
221 }
222}
223
224#[derive(Debug, PartialEq)]
228pub struct TiffTypeValues<T: TiffType> {
229 values: Vec<T>,
230}
231impl<T: TiffType + 'static> TiffTypeValues<T> {
232 pub fn new(values: Vec<T>) -> Self {
237 if values.len() == 0 {
238 panic!("Cannot create an empty instance of TiffTypeValues")
239 }
240 TiffTypeValues { values }
241 }
242}
243impl<T: TiffType + 'static> FieldValues for TiffTypeValues<T> {
244 #[doc(hidden)]
245 fn count(&self) -> u32 {
246 self.values.len() as u32
247 }
248
249 #[doc(hidden)]
250 fn size(&self) -> u32 {
251 T::size() * self.count()
252 }
253
254 #[doc(hidden)]
255 fn allocate(self: Box<Self>, c: &mut Cursor) -> Box<AllocatedFieldValues> {
256 let position = if self.size() <= 4 {
257 None
258 } else {
259 let size = self.size() + self.size() % 2;
262 let pos = c.allocated_bytes();
263 c.allocate(size);
264 Some(pos)
265 };
266
267 Box::new(AllocatedTiffTypeValues {
268 position,
269 values: self.values,
270 })
271 }
272}
273
274struct AllocatedTiffTypeValues<T: TiffType> {
276 position: Option<u32>,
277 values: Vec<T>,
278}
279impl<T: TiffType> AllocatedFieldValues for AllocatedTiffTypeValues<T> {
280 fn count(&self) -> u32 {
281 self.values.len() as u32
282 }
283
284 fn size(&self) -> u32 {
285 T::size() * self.count()
286 }
287
288 fn position(&self) -> Option<u32> {
289 self.position
290 }
291
292 fn type_id(&self) -> u16 {
293 T::id()
294 }
295
296 fn write_to(self: Box<Self>, file: &mut EndianFile) -> io::Result<()> {
297 let size = self.size();
298 for value in self.values {
299 let file_initial = file.written_bytes();
300 value.write_to(file)?;
301 let written_size = file.written_bytes() - file_initial;
302 if written_size != T::size() {
303 panic!(
304 "The size indicated ({}) is different from the number of bytes the type has written to the file ({}).",
305 T::size(), written_size
306 )
307 }
308 }
309
310 if size % 2 == 1 && size > 4 {
311 file.write_arbitrary_byte()?;
312 }
313 Ok(())
314 }
315}
316
317pub struct OffsetsToIfds {
333 pub data: Vec<IfdChain>,
334}
335impl OffsetsToIfds {
336 pub fn new(ifds: Vec<IfdChain>) -> Self {
340 OffsetsToIfds { data: ifds }
341 }
342}
343impl FieldValues for OffsetsToIfds {
344 #[doc(hidden)]
345 fn count(&self) -> u32 {
346 self.data.len() as u32
347 }
348
349 #[doc(hidden)]
350 fn size(&self) -> u32 {
351 IFD::size() * self.count()
352 }
353
354 #[doc(hidden)]
355 fn allocate(self: Box<Self>, c: &mut Cursor) -> Box<AllocatedFieldValues> {
356 let position = Some(c.allocated_bytes());
357 if self.data.len() == 1 {
358 let offsets = Vec::new();
361 let ifd = self.data.into_iter().next().unwrap(); let allocated_data = vec![ifd.allocate(c)];
363
364 Box::new(AllocatedOffsetsToIfds {
365 position,
366 offsets,
367 data: allocated_data,
368 })
369 } else {
370 c.allocate(self.size());
371 let mut offsets = Vec::with_capacity(self.data.len());
372 let mut allocated_data = Vec::with_capacity(self.data.len());
373
374 for ifd in self.data {
375 offsets.push(IFD(c.allocated_bytes()));
376 allocated_data.push(ifd.allocate(c));
377 }
378
379 Box::new(AllocatedOffsetsToIfds {
380 position,
381 offsets,
382 data: allocated_data,
383 })
384 }
385 }
386}
387
388struct AllocatedOffsetsToIfds {
390 position: Option<u32>,
391 offsets: Vec<IFD>,
392 data: Vec<AllocatedIfdChain>,
393}
394impl AllocatedFieldValues for AllocatedOffsetsToIfds {
395 fn count(&self) -> u32 {
396 self.data.len() as u32
397 }
398
399 fn size(&self) -> u32 {
400 IFD::size() * self.count()
401 }
402
403 fn position(&self) -> Option<u32> {
404 self.position
405 }
406
407 fn type_id(&self) -> u16 {
408 IFD::id()
409 }
410
411 fn write_to(self: Box<Self>, file: &mut EndianFile) -> io::Result<()> {
412 let unboxed = *self;
413 let Self { data, offsets, .. } = unboxed;
414 for offset in offsets {
415 offset.write_to(file)?;
416 }
417 for ifd in data.into_iter() {
418 ifd.write_to(file)?;
419 }
420
421 Ok(())
422 }
423}