tiff/encoder/
tiff_value.rs

1use std::{borrow::Cow, io::Write, slice::from_ref};
2
3use crate::{bytecast, tags::Type, TiffError, TiffFormatError, TiffResult};
4
5use super::writer::TiffWriter;
6
7/// Trait for types that can be encoded in a tiff file
8pub trait TiffValue {
9    const BYTE_LEN: u8;
10    const FIELD_TYPE: Type;
11    fn count(&self) -> usize;
12    fn bytes(&self) -> usize {
13        self.count() * usize::from(Self::BYTE_LEN)
14    }
15
16    /// Access this value as an contiguous sequence of bytes.
17    /// If their is no trivial representation, allocate it on the heap.
18    fn data(&self) -> Cow<[u8]>;
19
20    /// Write this value to a TiffWriter.
21    /// While the default implementation will work in all cases, it may require unnecessary allocations.
22    /// The written bytes of any custom implementation MUST be the same as yielded by `self.data()`.
23    fn write<W: Write>(&self, writer: &mut TiffWriter<W>) -> TiffResult<()> {
24        writer.write_bytes(&self.data())?;
25        Ok(())
26    }
27}
28
29impl TiffValue for [u8] {
30    const BYTE_LEN: u8 = 1;
31    const FIELD_TYPE: Type = Type::BYTE;
32
33    fn count(&self) -> usize {
34        self.len()
35    }
36
37    fn data(&self) -> Cow<[u8]> {
38        Cow::Borrowed(self)
39    }
40}
41
42impl TiffValue for [i8] {
43    const BYTE_LEN: u8 = 1;
44    const FIELD_TYPE: Type = Type::SBYTE;
45
46    fn count(&self) -> usize {
47        self.len()
48    }
49
50    fn data(&self) -> Cow<[u8]> {
51        Cow::Borrowed(bytecast::i8_as_ne_bytes(self))
52    }
53}
54
55impl TiffValue for [u16] {
56    const BYTE_LEN: u8 = 2;
57    const FIELD_TYPE: Type = Type::SHORT;
58
59    fn count(&self) -> usize {
60        self.len()
61    }
62
63    fn data(&self) -> Cow<[u8]> {
64        Cow::Borrowed(bytecast::u16_as_ne_bytes(self))
65    }
66}
67
68impl TiffValue for [i16] {
69    const BYTE_LEN: u8 = 2;
70    const FIELD_TYPE: Type = Type::SSHORT;
71
72    fn count(&self) -> usize {
73        self.len()
74    }
75
76    fn data(&self) -> Cow<[u8]> {
77        Cow::Borrowed(bytecast::i16_as_ne_bytes(self))
78    }
79}
80
81impl TiffValue for [u32] {
82    const BYTE_LEN: u8 = 4;
83    const FIELD_TYPE: Type = Type::LONG;
84
85    fn count(&self) -> usize {
86        self.len()
87    }
88
89    fn data(&self) -> Cow<[u8]> {
90        Cow::Borrowed(bytecast::u32_as_ne_bytes(self))
91    }
92}
93
94impl TiffValue for [i32] {
95    const BYTE_LEN: u8 = 4;
96    const FIELD_TYPE: Type = Type::SLONG;
97
98    fn count(&self) -> usize {
99        self.len()
100    }
101
102    fn data(&self) -> Cow<[u8]> {
103        Cow::Borrowed(bytecast::i32_as_ne_bytes(self))
104    }
105}
106
107impl TiffValue for [u64] {
108    const BYTE_LEN: u8 = 8;
109    const FIELD_TYPE: Type = Type::LONG8;
110
111    fn count(&self) -> usize {
112        self.len()
113    }
114
115    fn data(&self) -> Cow<[u8]> {
116        Cow::Borrowed(bytecast::u64_as_ne_bytes(self))
117    }
118}
119
120impl TiffValue for [i64] {
121    const BYTE_LEN: u8 = 8;
122    const FIELD_TYPE: Type = Type::SLONG8;
123
124    fn count(&self) -> usize {
125        self.len()
126    }
127
128    fn data(&self) -> Cow<[u8]> {
129        Cow::Borrowed(bytecast::i64_as_ne_bytes(self))
130    }
131}
132
133impl TiffValue for [f32] {
134    const BYTE_LEN: u8 = 4;
135    const FIELD_TYPE: Type = Type::FLOAT;
136
137    fn count(&self) -> usize {
138        self.len()
139    }
140
141    fn data(&self) -> Cow<[u8]> {
142        // We write using native endian so this should be safe
143        Cow::Borrowed(bytecast::f32_as_ne_bytes(self))
144    }
145}
146
147impl TiffValue for [f64] {
148    const BYTE_LEN: u8 = 8;
149    const FIELD_TYPE: Type = Type::DOUBLE;
150
151    fn count(&self) -> usize {
152        self.len()
153    }
154
155    fn data(&self) -> Cow<[u8]> {
156        // We write using native endian so this should be safe
157        Cow::Borrowed(bytecast::f64_as_ne_bytes(self))
158    }
159}
160
161impl TiffValue for u8 {
162    const BYTE_LEN: u8 = 1;
163    const FIELD_TYPE: Type = Type::BYTE;
164
165    fn count(&self) -> usize {
166        1
167    }
168
169    fn write<W: Write>(&self, writer: &mut TiffWriter<W>) -> TiffResult<()> {
170        writer.write_u8(*self)?;
171        Ok(())
172    }
173
174    fn data(&self) -> Cow<[u8]> {
175        Cow::Borrowed(from_ref(self))
176    }
177}
178
179impl TiffValue for i8 {
180    const BYTE_LEN: u8 = 1;
181    const FIELD_TYPE: Type = Type::SBYTE;
182
183    fn count(&self) -> usize {
184        1
185    }
186
187    fn write<W: Write>(&self, writer: &mut TiffWriter<W>) -> TiffResult<()> {
188        writer.write_i8(*self)?;
189        Ok(())
190    }
191
192    fn data(&self) -> Cow<[u8]> {
193        Cow::Borrowed(bytecast::i8_as_ne_bytes(from_ref(self)))
194    }
195}
196
197impl TiffValue for u16 {
198    const BYTE_LEN: u8 = 2;
199    const FIELD_TYPE: Type = Type::SHORT;
200
201    fn count(&self) -> usize {
202        1
203    }
204
205    fn write<W: Write>(&self, writer: &mut TiffWriter<W>) -> TiffResult<()> {
206        writer.write_u16(*self)?;
207        Ok(())
208    }
209
210    fn data(&self) -> Cow<[u8]> {
211        Cow::Borrowed(bytecast::u16_as_ne_bytes(from_ref(self)))
212    }
213}
214
215impl TiffValue for i16 {
216    const BYTE_LEN: u8 = 2;
217    const FIELD_TYPE: Type = Type::SSHORT;
218
219    fn count(&self) -> usize {
220        1
221    }
222
223    fn write<W: Write>(&self, writer: &mut TiffWriter<W>) -> TiffResult<()> {
224        writer.write_i16(*self)?;
225        Ok(())
226    }
227
228    fn data(&self) -> Cow<[u8]> {
229        Cow::Borrowed(bytecast::i16_as_ne_bytes(from_ref(self)))
230    }
231}
232
233impl TiffValue for u32 {
234    const BYTE_LEN: u8 = 4;
235    const FIELD_TYPE: Type = Type::LONG;
236
237    fn count(&self) -> usize {
238        1
239    }
240
241    fn write<W: Write>(&self, writer: &mut TiffWriter<W>) -> TiffResult<()> {
242        writer.write_u32(*self)?;
243        Ok(())
244    }
245
246    fn data(&self) -> Cow<[u8]> {
247        Cow::Borrowed(bytecast::u32_as_ne_bytes(from_ref(self)))
248    }
249}
250
251impl TiffValue for i32 {
252    const BYTE_LEN: u8 = 4;
253    const FIELD_TYPE: Type = Type::SLONG;
254
255    fn count(&self) -> usize {
256        1
257    }
258
259    fn write<W: Write>(&self, writer: &mut TiffWriter<W>) -> TiffResult<()> {
260        writer.write_i32(*self)?;
261        Ok(())
262    }
263
264    fn data(&self) -> Cow<[u8]> {
265        Cow::Borrowed(bytecast::i32_as_ne_bytes(from_ref(self)))
266    }
267}
268
269impl TiffValue for u64 {
270    const BYTE_LEN: u8 = 8;
271    const FIELD_TYPE: Type = Type::LONG8;
272
273    fn count(&self) -> usize {
274        1
275    }
276
277    fn write<W: Write>(&self, writer: &mut TiffWriter<W>) -> TiffResult<()> {
278        writer.write_u64(*self)?;
279        Ok(())
280    }
281
282    fn data(&self) -> Cow<[u8]> {
283        Cow::Borrowed(bytecast::u64_as_ne_bytes(from_ref(self)))
284    }
285}
286
287impl TiffValue for i64 {
288    const BYTE_LEN: u8 = 8;
289    const FIELD_TYPE: Type = Type::SLONG8;
290
291    fn count(&self) -> usize {
292        1
293    }
294
295    fn write<W: Write>(&self, writer: &mut TiffWriter<W>) -> TiffResult<()> {
296        writer.write_i64(*self)?;
297        Ok(())
298    }
299
300    fn data(&self) -> Cow<[u8]> {
301        Cow::Borrowed(bytecast::i64_as_ne_bytes(from_ref(self)))
302    }
303}
304
305impl TiffValue for f32 {
306    const BYTE_LEN: u8 = 4;
307    const FIELD_TYPE: Type = Type::FLOAT;
308
309    fn count(&self) -> usize {
310        1
311    }
312
313    fn write<W: Write>(&self, writer: &mut TiffWriter<W>) -> TiffResult<()> {
314        writer.write_f32(*self)?;
315        Ok(())
316    }
317
318    fn data(&self) -> Cow<[u8]> {
319        Cow::Borrowed(bytecast::f32_as_ne_bytes(from_ref(self)))
320    }
321}
322
323impl TiffValue for f64 {
324    const BYTE_LEN: u8 = 8;
325    const FIELD_TYPE: Type = Type::DOUBLE;
326
327    fn count(&self) -> usize {
328        1
329    }
330
331    fn write<W: Write>(&self, writer: &mut TiffWriter<W>) -> TiffResult<()> {
332        writer.write_f64(*self)?;
333        Ok(())
334    }
335
336    fn data(&self) -> Cow<[u8]> {
337        Cow::Borrowed(bytecast::f64_as_ne_bytes(from_ref(self)))
338    }
339}
340
341impl TiffValue for Ifd {
342    const BYTE_LEN: u8 = 4;
343    const FIELD_TYPE: Type = Type::IFD;
344
345    fn count(&self) -> usize {
346        1
347    }
348
349    fn write<W: Write>(&self, writer: &mut TiffWriter<W>) -> TiffResult<()> {
350        writer.write_u32(self.0)?;
351        Ok(())
352    }
353
354    fn data(&self) -> Cow<[u8]> {
355        Cow::Borrowed(bytecast::u32_as_ne_bytes(from_ref(&self.0)))
356    }
357}
358
359impl TiffValue for Ifd8 {
360    const BYTE_LEN: u8 = 8;
361    const FIELD_TYPE: Type = Type::IFD8;
362
363    fn count(&self) -> usize {
364        1
365    }
366
367    fn write<W: Write>(&self, writer: &mut TiffWriter<W>) -> TiffResult<()> {
368        writer.write_u64(self.0)?;
369        Ok(())
370    }
371
372    fn data(&self) -> Cow<[u8]> {
373        Cow::Borrowed(bytecast::u64_as_ne_bytes(from_ref(&self.0)))
374    }
375}
376
377impl TiffValue for Rational {
378    const BYTE_LEN: u8 = 8;
379    const FIELD_TYPE: Type = Type::RATIONAL;
380
381    fn count(&self) -> usize {
382        1
383    }
384
385    fn write<W: Write>(&self, writer: &mut TiffWriter<W>) -> TiffResult<()> {
386        writer.write_u32(self.n)?;
387        writer.write_u32(self.d)?;
388        Ok(())
389    }
390
391    fn data(&self) -> Cow<[u8]> {
392        Cow::Owned({
393            let first_dword = bytecast::u32_as_ne_bytes(from_ref(&self.n));
394            let second_dword = bytecast::u32_as_ne_bytes(from_ref(&self.d));
395            [first_dword, second_dword].concat()
396        })
397    }
398}
399
400impl TiffValue for SRational {
401    const BYTE_LEN: u8 = 8;
402    const FIELD_TYPE: Type = Type::SRATIONAL;
403
404    fn count(&self) -> usize {
405        1
406    }
407
408    fn write<W: Write>(&self, writer: &mut TiffWriter<W>) -> TiffResult<()> {
409        writer.write_i32(self.n)?;
410        writer.write_i32(self.d)?;
411        Ok(())
412    }
413
414    fn data(&self) -> Cow<[u8]> {
415        Cow::Owned({
416            let first_dword = bytecast::i32_as_ne_bytes(from_ref(&self.n));
417            let second_dword = bytecast::i32_as_ne_bytes(from_ref(&self.d));
418            [first_dword, second_dword].concat()
419        })
420    }
421}
422
423impl TiffValue for str {
424    const BYTE_LEN: u8 = 1;
425    const FIELD_TYPE: Type = Type::ASCII;
426
427    fn count(&self) -> usize {
428        self.len() + 1
429    }
430
431    fn write<W: Write>(&self, writer: &mut TiffWriter<W>) -> TiffResult<()> {
432        if self.is_ascii() && !self.bytes().any(|b| b == 0) {
433            writer.write_bytes(self.as_bytes())?;
434            writer.write_u8(0)?;
435            Ok(())
436        } else {
437            Err(TiffError::FormatError(TiffFormatError::InvalidTag))
438        }
439    }
440
441    fn data(&self) -> Cow<[u8]> {
442        Cow::Owned({
443            if self.is_ascii() && !self.bytes().any(|b| b == 0) {
444                let bytes: &[u8] = self.as_bytes();
445                [bytes, &[0]].concat()
446            } else {
447                vec![]
448            }
449        })
450    }
451}
452
453impl<'a, T: TiffValue + ?Sized> TiffValue for &'a T {
454    const BYTE_LEN: u8 = T::BYTE_LEN;
455    const FIELD_TYPE: Type = T::FIELD_TYPE;
456
457    fn count(&self) -> usize {
458        (*self).count()
459    }
460
461    fn write<W: Write>(&self, writer: &mut TiffWriter<W>) -> TiffResult<()> {
462        (*self).write(writer)
463    }
464
465    fn data(&self) -> Cow<[u8]> {
466        T::data(self)
467    }
468}
469
470macro_rules! impl_tiff_value_for_contiguous_sequence {
471    ($inner_type:ty; $bytes:expr; $field_type:expr) => {
472        impl $crate::encoder::TiffValue for [$inner_type] {
473            const BYTE_LEN: u8 = $bytes;
474            const FIELD_TYPE: Type = $field_type;
475
476            fn count(&self) -> usize {
477                self.len()
478            }
479
480            fn write<W: Write>(&self, writer: &mut TiffWriter<W>) -> TiffResult<()> {
481                for x in self {
482                    x.write(writer)?;
483                }
484                Ok(())
485            }
486
487            fn data(&self) -> Cow<[u8]> {
488                let mut buf: Vec<u8> = Vec::with_capacity(Self::BYTE_LEN as usize * self.len());
489                for x in self {
490                    buf.extend_from_slice(&x.data());
491                }
492                Cow::Owned(buf)
493            }
494        }
495    };
496}
497
498impl_tiff_value_for_contiguous_sequence!(Ifd; 4; Type::IFD);
499impl_tiff_value_for_contiguous_sequence!(Ifd8; 8; Type::IFD8);
500impl_tiff_value_for_contiguous_sequence!(Rational; 8; Type::RATIONAL);
501impl_tiff_value_for_contiguous_sequence!(SRational; 8; Type::SRATIONAL);
502
503/// Type to represent tiff values of type `IFD`
504#[derive(Clone)]
505pub struct Ifd(pub u32);
506
507/// Type to represent tiff values of type `IFD8`
508#[derive(Clone)]
509pub struct Ifd8(pub u64);
510
511/// Type to represent tiff values of type `RATIONAL`
512#[derive(Clone)]
513pub struct Rational {
514    pub n: u32,
515    pub d: u32,
516}
517
518/// Type to represent tiff values of type `SRATIONAL`
519#[derive(Clone)]
520pub struct SRational {
521    pub n: i32,
522    pub d: i32,
523}