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(slice: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(slice: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(slice: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(slice: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(slice: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(slice: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(slice: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(slice: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(slice: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(slice: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(slice: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: &[u8] = bytecast::u32_as_ne_bytes(slice:from_ref(&self.n));
394 let second_dword: &[u8] = bytecast::u32_as_ne_bytes(slice: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: &[u8] = bytecast::i32_as_ne_bytes(slice:from_ref(&self.n));
417 let second_dword: &[u8] = bytecast::i32_as_ne_bytes(slice: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}
524