Skip to main content

tiff/decoder/
ifd.rs

1//! Function for reading TIFF tags
2
3use std::collections::HashMap;
4use std::io::{self, Read, Seek};
5use std::mem;
6use std::str;
7
8use super::stream::{ByteOrder, EndianReader};
9use crate::tags::{IfdPointer, Tag, Type, ValueBuffer};
10use crate::{TiffError, TiffFormatError, TiffResult};
11
12use self::Value::{
13    Ascii, Byte, Double, Float, Ifd, IfdBig, List, Rational, SRational, Short, Signed, SignedBig,
14    SignedByte, SignedShort, Unsigned, UnsignedBig,
15};
16
17#[allow(unused_qualifications)]
18#[derive(Debug, Clone, PartialEq)]
19#[non_exhaustive]
20pub enum Value {
21    Byte(u8),
22    Short(u16),
23    SignedByte(i8),
24    SignedShort(i16),
25    Signed(i32),
26    SignedBig(i64),
27    Unsigned(u32),
28    UnsignedBig(u64),
29    Float(f32),
30    Double(f64),
31    List(Vec<Value>),
32    Rational(u32, u32),
33    #[deprecated(
34        note = "Not implemented in BigTIFF with a standard tag value",
35        since = "0.11.1"
36    )]
37    RationalBig(u64, u64),
38    SRational(i32, i32),
39    #[deprecated(
40        note = "Not implemented in BigTIFF with a standard tag value",
41        since = "0.11.1"
42    )]
43    SRationalBig(i64, i64),
44    Ascii(String),
45    Ifd(u32),
46    IfdBig(u64),
47}
48
49impl Value {
50    pub fn into_u8(self) -> TiffResult<u8> {
51        match self {
52            Byte(val) => Ok(val),
53            _ => Err(TiffError::FormatError(TiffFormatError::InvalidTypeForTag)),
54        }
55    }
56    pub fn into_i8(self) -> TiffResult<i8> {
57        match self {
58            SignedByte(val) => Ok(val),
59            _ => Err(TiffError::FormatError(TiffFormatError::InvalidTypeForTag)),
60        }
61    }
62
63    pub fn into_u16(self) -> TiffResult<u16> {
64        match self {
65            Byte(val) => Ok(val.into()),
66            Short(val) => Ok(val),
67            Unsigned(val) => Ok(u16::try_from(val)?),
68            UnsignedBig(val) => Ok(u16::try_from(val)?),
69            _ => Err(TiffError::FormatError(TiffFormatError::InvalidTypeForTag)),
70        }
71    }
72
73    pub fn into_i16(self) -> TiffResult<i16> {
74        match self {
75            SignedByte(val) => Ok(val.into()),
76            SignedShort(val) => Ok(val),
77            Signed(val) => Ok(i16::try_from(val)?),
78            SignedBig(val) => Ok(i16::try_from(val)?),
79            _ => Err(TiffError::FormatError(TiffFormatError::InvalidTypeForTag)),
80        }
81    }
82
83    pub fn into_u32(self) -> TiffResult<u32> {
84        match self {
85            Byte(val) => Ok(val.into()),
86            Short(val) => Ok(val.into()),
87            Unsigned(val) => Ok(val),
88            UnsignedBig(val) => Ok(u32::try_from(val)?),
89            Ifd(val) => Ok(val),
90            IfdBig(val) => Ok(u32::try_from(val)?),
91            _ => Err(TiffError::FormatError(TiffFormatError::InvalidTypeForTag)),
92        }
93    }
94
95    pub fn into_i32(self) -> TiffResult<i32> {
96        match self {
97            SignedByte(val) => Ok(val.into()),
98            SignedShort(val) => Ok(val.into()),
99            Signed(val) => Ok(val),
100            SignedBig(val) => Ok(i32::try_from(val)?),
101            _ => Err(TiffError::FormatError(TiffFormatError::InvalidTypeForTag)),
102        }
103    }
104
105    pub fn into_u64(self) -> TiffResult<u64> {
106        match self {
107            Byte(val) => Ok(val.into()),
108            Short(val) => Ok(val.into()),
109            Unsigned(val) => Ok(val.into()),
110            UnsignedBig(val) => Ok(val),
111            Ifd(val) => Ok(val.into()),
112            IfdBig(val) => Ok(val),
113            _ => Err(TiffError::FormatError(TiffFormatError::InvalidTypeForTag)),
114        }
115    }
116
117    pub fn into_i64(self) -> TiffResult<i64> {
118        match self {
119            SignedByte(val) => Ok(val.into()),
120            SignedShort(val) => Ok(val.into()),
121            Signed(val) => Ok(val.into()),
122            SignedBig(val) => Ok(val),
123            _ => Err(TiffError::FormatError(TiffFormatError::InvalidTypeForTag)),
124        }
125    }
126
127    pub fn into_f32(self) -> TiffResult<f32> {
128        match self {
129            Float(val) => Ok(val),
130            _ => Err(TiffError::FormatError(TiffFormatError::InvalidTypeForTag)),
131        }
132    }
133
134    pub fn into_f64(self) -> TiffResult<f64> {
135        match self {
136            Double(val) => Ok(val),
137            _ => Err(TiffError::FormatError(TiffFormatError::InvalidTypeForTag)),
138        }
139    }
140
141    /// Turn this value into an `IfdPointer`.
142    ///
143    /// Notice that this does not take an argument, a 64-bit IFD is always allowed. If the
144    /// difference is crucial and you do not want to be permissive you're expected to filter this
145    /// out before.
146    ///
147    /// For compatibility the smaller sized tags should always be allowed i.e. you might use a
148    /// non-bigtiff's directory and its tag types and move it straight to a bigtiff. For instance
149    /// the SubIFD tag is defined as `LONG or IFD`:
150    ///
151    /// <https://web.archive.org/web/20181105221012/https://www.awaresystems.be/imaging/tiff/tifftags/subifds.html>
152    pub fn into_ifd_pointer(self) -> TiffResult<IfdPointer> {
153        match self {
154            Unsigned(val) | Ifd(val) => Ok(IfdPointer(val.into())),
155            IfdBig(val) => Ok(IfdPointer(val)),
156            _ => Err(TiffError::FormatError(TiffFormatError::InvalidTypeForTag)),
157        }
158    }
159
160    pub fn into_string(self) -> TiffResult<String> {
161        match self {
162            Ascii(val) => Ok(val),
163            _ => Err(TiffError::FormatError(TiffFormatError::InvalidTypeForTag)),
164        }
165    }
166
167    pub fn into_u32_vec(self) -> TiffResult<Vec<u32>> {
168        match self {
169            List(vec) => {
170                let mut new_vec = Vec::with_capacity(vec.len());
171                for v in vec {
172                    new_vec.push(v.into_u32()?)
173                }
174                Ok(new_vec)
175            }
176            Byte(val) => Ok(vec![val.into()]),
177            Short(val) => Ok(vec![val.into()]),
178            Unsigned(val) => Ok(vec![val]),
179            UnsignedBig(val) => Ok(vec![u32::try_from(val)?]),
180            Rational(numerator, denominator) => Ok(vec![numerator, denominator]),
181            #[expect(deprecated)]
182            Value::RationalBig(numerator, denominator) => {
183                Ok(vec![u32::try_from(numerator)?, u32::try_from(denominator)?])
184            }
185            Ifd(val) => Ok(vec![val]),
186            IfdBig(val) => Ok(vec![u32::try_from(val)?]),
187            Ascii(val) => Ok(val.chars().map(u32::from).collect()),
188            _ => Err(TiffError::FormatError(TiffFormatError::InvalidTypeForTag)),
189        }
190    }
191
192    pub fn into_u8_vec(self) -> TiffResult<Vec<u8>> {
193        match self {
194            List(vec) => {
195                let mut new_vec = Vec::with_capacity(vec.len());
196                for v in vec {
197                    new_vec.push(v.into_u8()?)
198                }
199                Ok(new_vec)
200            }
201            Byte(val) => Ok(vec![val]),
202
203            _ => Err(TiffError::FormatError(TiffFormatError::InvalidTypeForTag)),
204        }
205    }
206
207    pub fn into_u16_vec(self) -> TiffResult<Vec<u16>> {
208        match self {
209            List(vec) => {
210                let mut new_vec = Vec::with_capacity(vec.len());
211                for v in vec {
212                    new_vec.push(v.into_u16()?)
213                }
214                Ok(new_vec)
215            }
216            Byte(val) => Ok(vec![val.into()]),
217            Short(val) => Ok(vec![val]),
218            _ => Err(TiffError::FormatError(TiffFormatError::InvalidTypeForTag)),
219        }
220    }
221
222    pub fn into_i32_vec(self) -> TiffResult<Vec<i32>> {
223        match self {
224            List(vec) => {
225                let mut new_vec = Vec::with_capacity(vec.len());
226                for v in vec {
227                    match v {
228                        SRational(numerator, denominator) => {
229                            new_vec.push(numerator);
230                            new_vec.push(denominator);
231                        }
232                        #[expect(deprecated)]
233                        Value::SRationalBig(numerator, denominator) => {
234                            new_vec.push(i32::try_from(numerator)?);
235                            new_vec.push(i32::try_from(denominator)?);
236                        }
237                        _ => new_vec.push(v.into_i32()?),
238                    }
239                }
240                Ok(new_vec)
241            }
242            SignedByte(val) => Ok(vec![val.into()]),
243            SignedShort(val) => Ok(vec![val.into()]),
244            Signed(val) => Ok(vec![val]),
245            SignedBig(val) => Ok(vec![i32::try_from(val)?]),
246            SRational(numerator, denominator) => Ok(vec![numerator, denominator]),
247            #[expect(deprecated)]
248            Value::SRationalBig(numerator, denominator) => {
249                Ok(vec![i32::try_from(numerator)?, i32::try_from(denominator)?])
250            }
251            _ => Err(TiffError::FormatError(TiffFormatError::InvalidTypeForTag)),
252        }
253    }
254
255    pub fn into_f32_vec(self) -> TiffResult<Vec<f32>> {
256        match self {
257            List(vec) => {
258                let mut new_vec = Vec::with_capacity(vec.len());
259                for v in vec {
260                    new_vec.push(v.into_f32()?)
261                }
262                Ok(new_vec)
263            }
264            Float(val) => Ok(vec![val]),
265            _ => Err(TiffError::FormatError(TiffFormatError::InvalidTypeForTag)),
266        }
267    }
268
269    pub fn into_f64_vec(self) -> TiffResult<Vec<f64>> {
270        match self {
271            List(vec) => {
272                let mut new_vec = Vec::with_capacity(vec.len());
273                for v in vec {
274                    new_vec.push(v.into_f64()?)
275                }
276                Ok(new_vec)
277            }
278            Double(val) => Ok(vec![val]),
279            _ => Err(TiffError::FormatError(TiffFormatError::InvalidTypeForTag)),
280        }
281    }
282
283    pub fn into_u64_vec(self) -> TiffResult<Vec<u64>> {
284        match self {
285            List(vec) => {
286                let mut new_vec = Vec::with_capacity(vec.len());
287                for v in vec {
288                    new_vec.push(v.into_u64()?)
289                }
290                Ok(new_vec)
291            }
292            Byte(val) => Ok(vec![val.into()]),
293            Short(val) => Ok(vec![val.into()]),
294            Unsigned(val) => Ok(vec![val.into()]),
295            UnsignedBig(val) => Ok(vec![val]),
296            Rational(numerator, denominator) => Ok(vec![numerator.into(), denominator.into()]),
297            #[expect(deprecated)]
298            Value::RationalBig(numerator, denominator) => Ok(vec![numerator, denominator]),
299            Ifd(val) => Ok(vec![val.into()]),
300            IfdBig(val) => Ok(vec![val]),
301            Ascii(val) => Ok(val.chars().map(u32::from).map(u64::from).collect()),
302            _ => Err(TiffError::FormatError(TiffFormatError::InvalidTypeForTag)),
303        }
304    }
305
306    pub fn into_i64_vec(self) -> TiffResult<Vec<i64>> {
307        match self {
308            List(vec) => {
309                let mut new_vec = Vec::with_capacity(vec.len());
310                for v in vec {
311                    match v {
312                        SRational(numerator, denominator) => {
313                            new_vec.push(numerator.into());
314                            new_vec.push(denominator.into());
315                        }
316                        #[expect(deprecated)]
317                        Value::SRationalBig(numerator, denominator) => {
318                            new_vec.push(numerator);
319                            new_vec.push(denominator);
320                        }
321                        _ => new_vec.push(v.into_i64()?),
322                    }
323                }
324                Ok(new_vec)
325            }
326            SignedByte(val) => Ok(vec![val.into()]),
327            SignedShort(val) => Ok(vec![val.into()]),
328            Signed(val) => Ok(vec![val.into()]),
329            SignedBig(val) => Ok(vec![val]),
330            SRational(numerator, denominator) => Ok(vec![numerator.into(), denominator.into()]),
331            #[expect(deprecated)]
332            Value::SRationalBig(numerator, denominator) => Ok(vec![numerator, denominator]),
333            _ => Err(TiffError::FormatError(TiffFormatError::InvalidTypeForTag)),
334        }
335    }
336
337    pub fn into_ifd_vec(self) -> TiffResult<Vec<IfdPointer>> {
338        let vec = match self {
339            Unsigned(val) | Ifd(val) => return Ok(vec![IfdPointer(val.into())]),
340            IfdBig(val) => return Ok(vec![IfdPointer(val)]),
341            List(vec) => vec,
342            _ => return Err(TiffError::FormatError(TiffFormatError::InvalidTypeForTag)),
343        };
344
345        vec.into_iter().map(Self::into_ifd_pointer).collect()
346    }
347}
348
349/// A combination of type, count, and offset.
350///
351/// In a TIFF the data offset portion of an entry is used for inline data in case the length of the
352/// encoded value does not exceed the size of the offset field. Since the size of the offset field
353/// depends on the file kind (4 bytes for standard TIFF, 8 bytes for BigTIFF) the interpretation of
354/// this struct is only complete in combination with file metadata.
355#[derive(Clone)]
356pub struct Entry {
357    type_: Type,
358    count: u64,
359    offset: [u8; 8],
360}
361
362impl ::std::fmt::Debug for Entry {
363    fn fmt(&self, fmt: &mut ::std::fmt::Formatter) -> Result<(), ::std::fmt::Error> {
364        fmt.write_str(&format!(
365            "Entry {{ type_: {:?}, count: {:?}, offset: {:?} }}",
366            self.type_, self.count, &self.offset
367        ))
368    }
369}
370
371impl Entry {
372    /// Create a new entry fit to be added to a standard TIFF IFD.
373    pub fn new(type_: Type, count: u32, offset: [u8; 4]) -> Entry {
374        let mut entry_off = [0u8; 8];
375        entry_off[..4].copy_from_slice(&offset);
376        Entry::new_u64(type_, count.into(), entry_off)
377    }
378
379    /// Create a new entry with data for a Big TIFF IFD.
380    pub fn new_u64(type_: Type, count: u64, offset: [u8; 8]) -> Entry {
381        Entry {
382            type_,
383            count,
384            offset,
385        }
386    }
387
388    pub fn field_type(&self) -> Type {
389        self.type_
390    }
391
392    pub fn count(&self) -> u64 {
393        self.count
394    }
395
396    pub(crate) fn offset(&self) -> &[u8] {
397        &self.offset
398    }
399
400    /// Returns a mem_reader for the offset/value field
401    pub(crate) fn offset_field_reader(
402        &self,
403        byte_order: ByteOrder,
404    ) -> EndianReader<io::Cursor<Vec<u8>>> {
405        EndianReader::new(io::Cursor::new(self.offset.to_vec()), byte_order)
406    }
407
408    pub(crate) fn val<R: Read + Seek>(
409        &self,
410        limits: &super::Limits,
411        bigtiff: bool,
412        reader: &mut EndianReader<R>,
413    ) -> TiffResult<Value> {
414        // Case 1: there are no values so we can return immediately.
415        if self.count == 0 {
416            return Ok(List(Vec::new()));
417        }
418
419        let bo = reader.byte_order;
420        let value_bytes = self.type_.value_bytes(self.count)?;
421
422        // Case 2: there is one value.
423        if self.count == 1 {
424            // 2a: the value is 5-8 bytes and we're in BigTiff mode.
425            if bigtiff && value_bytes > 4 && value_bytes <= 8 {
426                return Ok(match self.type_ {
427                    Type::LONG8 => UnsignedBig(self.offset_field_reader(bo).read_u64()?),
428                    Type::SLONG8 => SignedBig(self.offset_field_reader(bo).read_i64()?),
429                    Type::DOUBLE => Double(self.offset_field_reader(bo).read_f64()?),
430                    Type::RATIONAL => {
431                        let mut r = self.offset_field_reader(bo);
432                        Rational(r.read_u32()?, r.read_u32()?)
433                    }
434                    Type::SRATIONAL => {
435                        let mut r = self.offset_field_reader(bo);
436                        SRational(r.read_i32()?, r.read_i32()?)
437                    }
438                    Type::IFD8 => IfdBig(self.offset_field_reader(bo).read_u64()?),
439                    Type::BYTE
440                    | Type::SBYTE
441                    | Type::ASCII
442                    | Type::UNDEFINED
443                    | Type::SHORT
444                    | Type::SSHORT
445                    | Type::LONG
446                    | Type::SLONG
447                    | Type::FLOAT
448                    | Type::IFD => unreachable!(),
449                });
450            }
451
452            // 2b: the value is at most 4 bytes or doesn't fit in the offset field.
453            return Ok(match self.type_ {
454                Type::BYTE => Byte(self.offset[0]),
455                Type::SBYTE => SignedByte(self.offset[0] as i8),
456                Type::UNDEFINED => Byte(self.offset[0]),
457                Type::SHORT => Short(self.offset_field_reader(bo).read_u16()?),
458                Type::SSHORT => SignedShort(self.offset_field_reader(bo).read_i16()?),
459                Type::LONG => Unsigned(self.offset_field_reader(bo).read_u32()?),
460                Type::SLONG => Signed(self.offset_field_reader(bo).read_i32()?),
461                Type::FLOAT => Float(self.offset_field_reader(bo).read_f32()?),
462                Type::ASCII => {
463                    if self.offset[0] == 0 {
464                        Ascii("".to_string())
465                    } else {
466                        return Err(TiffError::FormatError(TiffFormatError::InvalidTag));
467                    }
468                }
469                Type::LONG8 => {
470                    reader.goto_offset(self.offset_field_reader(bo).read_u32()?.into())?;
471                    UnsignedBig(reader.read_u64()?)
472                }
473                Type::SLONG8 => {
474                    reader.goto_offset(self.offset_field_reader(bo).read_u32()?.into())?;
475                    SignedBig(reader.read_i64()?)
476                }
477                Type::DOUBLE => {
478                    reader.goto_offset(self.offset_field_reader(bo).read_u32()?.into())?;
479                    Double(reader.read_f64()?)
480                }
481                Type::RATIONAL => {
482                    reader.goto_offset(self.offset_field_reader(bo).read_u32()?.into())?;
483                    Rational(reader.read_u32()?, reader.read_u32()?)
484                }
485                Type::SRATIONAL => {
486                    reader.goto_offset(self.offset_field_reader(bo).read_u32()?.into())?;
487                    SRational(reader.read_i32()?, reader.read_i32()?)
488                }
489                Type::IFD => Ifd(self.offset_field_reader(bo).read_u32()?),
490                Type::IFD8 => {
491                    reader.goto_offset(self.offset_field_reader(bo).read_u32()?.into())?;
492                    IfdBig(reader.read_u64()?)
493                }
494            });
495        }
496
497        // Case 3: There is more than one value, but it fits in the offset field.
498        if value_bytes <= 4 || bigtiff && value_bytes <= 8 {
499            match self.type_ {
500                Type::BYTE => return offset_to_bytes(self.count as usize, self),
501                Type::SBYTE => return offset_to_sbytes(self.count as usize, self),
502                Type::ASCII => {
503                    let mut buf = vec![0; self.count as usize];
504                    buf.copy_from_slice(&self.offset[..self.count as usize]);
505                    if buf.is_ascii() && buf.ends_with(&[0]) {
506                        let v = str::from_utf8(&buf)?;
507                        let v = v.trim_matches(char::from(0));
508                        return Ok(Ascii(v.into()));
509                    } else {
510                        return Err(TiffError::FormatError(TiffFormatError::InvalidTag));
511                    }
512                }
513                Type::UNDEFINED => {
514                    return Ok(List(
515                        self.offset[0..self.count as usize]
516                            .iter()
517                            .map(|&b| Byte(b))
518                            .collect(),
519                    ));
520                }
521                Type::SHORT => {
522                    let mut r = self.offset_field_reader(bo);
523                    let mut v = Vec::new();
524                    for _ in 0..self.count {
525                        v.push(Short(r.read_u16()?));
526                    }
527                    return Ok(List(v));
528                }
529                Type::SSHORT => {
530                    let mut r = self.offset_field_reader(bo);
531                    let mut v = Vec::new();
532                    for _ in 0..self.count {
533                        v.push(SignedShort(r.read_i16()?));
534                    }
535                    return Ok(List(v));
536                }
537                Type::LONG => {
538                    let mut r = self.offset_field_reader(bo);
539                    let mut v = Vec::new();
540                    for _ in 0..self.count {
541                        v.push(Unsigned(r.read_u32()?));
542                    }
543                    return Ok(List(v));
544                }
545                Type::SLONG => {
546                    let mut r = self.offset_field_reader(bo);
547                    let mut v = Vec::new();
548                    for _ in 0..self.count {
549                        v.push(Signed(r.read_i32()?));
550                    }
551                    return Ok(List(v));
552                }
553                Type::FLOAT => {
554                    let mut r = self.offset_field_reader(bo);
555                    let mut v = Vec::new();
556                    for _ in 0..self.count {
557                        v.push(Float(r.read_f32()?));
558                    }
559                    return Ok(List(v));
560                }
561                Type::IFD => {
562                    let mut r = self.offset_field_reader(bo);
563                    let mut v = Vec::new();
564                    for _ in 0..self.count {
565                        v.push(Ifd(r.read_u32()?));
566                    }
567                    return Ok(List(v));
568                }
569                Type::LONG8
570                | Type::SLONG8
571                | Type::RATIONAL
572                | Type::SRATIONAL
573                | Type::DOUBLE
574                | Type::IFD8 => {
575                    unreachable!()
576                }
577            }
578        }
579
580        // Case 4: there is more than one value, and it doesn't fit in the offset field.
581        let mut v;
582        self.set_reader_offset_relative(bigtiff, reader, 0)?;
583
584        match self.type_ {
585            Type::BYTE | Type::UNDEFINED => {
586                v = Self::vec_with_capacity(self.count, limits)?;
587                self.decode_values(self.count, self.type_, reader, |bytes| {
588                    v.extend(bytes.iter().copied().map(Byte))
589                })
590            }
591            Type::SBYTE => {
592                v = Self::vec_with_capacity(self.count, limits)?;
593                self.decode_values(self.count, self.type_, reader, |bytes| {
594                    v.extend(bytes.iter().copied().map(|v| SignedByte(v as i8)))
595                })
596            }
597            Type::SHORT => {
598                v = Self::vec_with_capacity(self.count, limits)?;
599                self.decode_values(self.count, self.type_, reader, |bytes| {
600                    v.extend(
601                        bytes
602                            .chunks_exact(2)
603                            .map(|ch| Short(u16::from_ne_bytes(ch.try_into().unwrap()))),
604                    )
605                })
606            }
607            Type::SSHORT => {
608                v = Self::vec_with_capacity(self.count, limits)?;
609                self.decode_values(self.count, self.type_, reader, |bytes| {
610                    v.extend(
611                        bytes
612                            .chunks_exact(2)
613                            .map(|ch| SignedShort(i16::from_ne_bytes(ch.try_into().unwrap()))),
614                    )
615                })
616            }
617            Type::LONG => {
618                v = Self::vec_with_capacity(self.count, limits)?;
619                self.decode_values(self.count, self.type_, reader, |bytes| {
620                    v.extend(
621                        bytes
622                            .chunks_exact(4)
623                            .map(|ch| Unsigned(u32::from_ne_bytes(ch.try_into().unwrap()))),
624                    )
625                })
626            }
627            Type::SLONG => {
628                v = Self::vec_with_capacity(self.count, limits)?;
629                self.decode_values(self.count, self.type_, reader, |bytes| {
630                    v.extend(
631                        bytes
632                            .chunks_exact(4)
633                            .map(|ch| Signed(i32::from_ne_bytes(ch.try_into().unwrap()))),
634                    )
635                })
636            }
637            Type::FLOAT => {
638                v = Self::vec_with_capacity(self.count, limits)?;
639                self.decode_values(self.count, self.type_, reader, |bytes| {
640                    v.extend(
641                        bytes
642                            .chunks_exact(4)
643                            .map(|ch| Float(f32::from_ne_bytes(ch.try_into().unwrap()))),
644                    )
645                })
646            }
647            Type::DOUBLE => {
648                v = Self::vec_with_capacity(self.count, limits)?;
649                self.decode_values(self.count, self.type_, reader, |bytes| {
650                    v.extend(
651                        bytes
652                            .chunks_exact(8)
653                            .map(|ch| Double(f64::from_ne_bytes(ch.try_into().unwrap()))),
654                    )
655                })
656            }
657            Type::RATIONAL => {
658                v = Self::vec_with_capacity(self.count, limits)?;
659                self.decode_values(self.count, self.type_, reader, |bytes| {
660                    v.extend(bytes.chunks_exact(8).map(|ch| {
661                        Rational(
662                            u32::from_ne_bytes(ch[..4].try_into().unwrap()),
663                            u32::from_ne_bytes(ch[4..].try_into().unwrap()),
664                        )
665                    }))
666                })
667            }
668            Type::SRATIONAL => {
669                v = Self::vec_with_capacity(self.count, limits)?;
670                self.decode_values(self.count, self.type_, reader, |bytes| {
671                    v.extend(bytes.chunks_exact(8).map(|ch| {
672                        SRational(
673                            i32::from_ne_bytes(ch[..4].try_into().unwrap()),
674                            i32::from_ne_bytes(ch[4..].try_into().unwrap()),
675                        )
676                    }))
677                })
678            }
679            Type::LONG8 => {
680                v = Self::vec_with_capacity(self.count, limits)?;
681                self.decode_values(self.count, self.type_, reader, |bytes| {
682                    v.extend(
683                        bytes
684                            .chunks_exact(8)
685                            .map(|ch| UnsignedBig(u64::from_ne_bytes(ch.try_into().unwrap()))),
686                    )
687                })
688            }
689            Type::SLONG8 => {
690                v = Self::vec_with_capacity(self.count, limits)?;
691                self.decode_values(self.count, self.type_, reader, |bytes| {
692                    v.extend(
693                        bytes
694                            .chunks_exact(8)
695                            .map(|ch| SignedBig(i64::from_ne_bytes(ch.try_into().unwrap()))),
696                    )
697                })
698            }
699            Type::IFD => {
700                v = Self::vec_with_capacity(self.count, limits)?;
701                self.decode_values(self.count, self.type_, reader, |bytes| {
702                    v.extend(
703                        bytes
704                            .chunks_exact(4)
705                            .map(|ch| Ifd(u32::from_ne_bytes(ch.try_into().unwrap()))),
706                    )
707                })
708            }
709            Type::IFD8 => {
710                v = Self::vec_with_capacity(self.count, limits)?;
711                self.decode_values(self.count, self.type_, reader, |bytes| {
712                    v.extend(
713                        bytes
714                            .chunks_exact(8)
715                            .map(|ch| IfdBig(u64::from_ne_bytes(ch.try_into().unwrap()))),
716                    )
717                })
718            }
719            Type::ASCII => {
720                let n = usize::try_from(self.count)?;
721
722                if n > limits.decoding_buffer_size {
723                    return Err(dbg!(TiffError::LimitsExceeded));
724                }
725
726                let mut out = vec![0; n];
727                reader.inner().read_exact(&mut out)?;
728                // Strings may be null-terminated, so we trim anything downstream of the null byte
729                if let Some(first) = out.iter().position(|&b| b == 0) {
730                    out.truncate(first);
731                }
732
733                return Ok(Ascii(String::from_utf8(out)?));
734            }
735        }?;
736
737        Ok(List(v))
738    }
739
740    pub(crate) fn buffered_value<R: Read + Seek>(
741        &self,
742        buf: &mut ValueBuffer,
743        limits: &super::Limits,
744        bigtiff: bool,
745        reader: &mut EndianReader<R>,
746    ) -> TiffResult<()> {
747        if self.count == 0 {
748            buf.assume_type(self.type_, 0, reader.byte_order);
749            return Ok(());
750        }
751
752        let value_bytes = self.buffer_with_capacity(buf, limits)?;
753
754        // Case 1: the value fits in the offset field.
755        if value_bytes <= 4 || bigtiff && value_bytes <= 8 {
756            let src = &self.offset[..value_bytes];
757            buf.raw_bytes_mut()[..value_bytes].copy_from_slice(src);
758            buf.assume_type(self.type_, self.count, reader.byte_order);
759
760            return Ok(());
761        }
762
763        // Case 2: the value is stored in the reader at an offset.
764        self.set_reader_offset_relative(bigtiff, reader, 0)?;
765
766        // In case of an error we set the type and endianess.
767        buf.assume_type(self.type_, 0, reader.byte_order);
768        let target = &mut buf.raw_bytes_mut()[..value_bytes];
769        // FIXME: if the read fails we have already grown to full size, which is not great.
770        reader.inner().read_exact(target)?;
771        buf.assume_type(self.type_, self.count, reader.byte_order);
772
773        Ok(())
774    }
775
776    pub(crate) fn raw_value_at<R: Read + Seek>(
777        &self,
778        buf: &mut [u8],
779        bigtiff: bool,
780        reader: &mut EndianReader<R>,
781        at: u64,
782    ) -> TiffResult<usize> {
783        if self.count == 0 {
784            return Ok(0);
785        }
786
787        // We have no limits to handle, we do not allocate.
788        let value_bytes = self.type_.value_bytes(self.count)?;
789
790        // No bytes to fill into the buffer.
791        if at >= value_bytes {
792            return Ok(0);
793        }
794
795        // Case 1: the value fits in the offset field.
796        if value_bytes <= 4 || bigtiff && value_bytes <= 8 {
797            // `at < value_bytes` and `value_bytes <= 8` so casting is mathematical
798            let src = &self.offset[..value_bytes as usize][at as usize..];
799            let len = src.len().min(buf.len());
800            buf[..len].copy_from_slice(&src[..len]);
801            return Ok(value_bytes as usize);
802        }
803
804        // Case 2: the value is stored in the reader at an offset. We will find the offset
805        // encoded in the entry, apply the relative start position and seek there.
806        self.set_reader_offset_relative(bigtiff, reader, at)?;
807
808        let remainder = value_bytes - at;
809        let len = usize::try_from(remainder)
810            .unwrap_or(usize::MAX)
811            .min(buf.len());
812
813        let target = &mut buf[..len];
814        reader.inner().read_exact(target)?;
815
816        // Design note: in a previous draft we would consume the rest of the bytes of this value
817        // here (into a stack buffer if need be) to verify the stream itself. But in the end we
818        // have `Seek` so we better verify this by seeking over the rest of the bytes, finding if
819        // the stream continues that far. Even that is maybe bad if we wanted to provide a
820        // async-adaptor that `WouldBlock` errors to fill back a read window then the seek is
821        // poison to that, too.
822
823        // So a really simple choice: The caller is responsible for handling the fact that this did
824        // not verify the whole value. Attempt a 1-byte read at the end of the value instead?
825        Ok(len)
826    }
827
828    // Returns `Ok(bytes)` if our value's bytes through type and count fit into `usize` and are
829    // within the limits. Extends the buffer to that many bytes.
830    fn buffer_with_capacity(
831        &self,
832        buf: &mut ValueBuffer,
833        limits: &super::Limits,
834    ) -> TiffResult<usize> {
835        let bytes = self.type_.value_bytes(self.count())?;
836
837        let allowed_length = usize::try_from(bytes)
838            .ok()
839            .filter(|&n| n <= limits.decoding_buffer_size)
840            .ok_or(TiffError::LimitsExceeded)?;
841
842        buf.prepare_length(allowed_length);
843
844        Ok(allowed_length)
845    }
846
847    fn vec_with_capacity(
848        value_count: u64,
849        limits: &super::Limits,
850    ) -> Result<Vec<Value>, TiffError> {
851        let value_count = usize::try_from(value_count)?;
852
853        if value_count > limits.decoding_buffer_size / mem::size_of::<Value>() {
854            return Err(TiffError::LimitsExceeded);
855        }
856
857        Ok(Vec::with_capacity(value_count))
858    }
859
860    /// Seek to an offset within a value stored in the offset defined by this entry.
861    fn set_reader_offset_relative<R>(
862        &self,
863        bigtiff: bool,
864        reader: &mut EndianReader<R>,
865        at: u64,
866    ) -> TiffResult<()>
867    where
868        R: Read + Seek,
869    {
870        let bo = reader.byte_order;
871
872        let offset = if bigtiff {
873            self.offset_field_reader(bo).read_u64()?
874        } else {
875            self.offset_field_reader(bo).read_u32()?.into()
876        };
877
878        // FIXME: `at` should be within `self.type_.value_bytes(self.count)` and that itself should
879        // be within the bounds of the stream. But we do not check this eagerly so this below will
880        // fail sometimes differently for exotic streams, depending on the method by which we read
881        // (at once or through multiple raw into-byte-slice reads).
882        let offset = offset.checked_add(at).ok_or(TiffError::FormatError(
883            TiffFormatError::InconsistentSizesEncountered,
884        ))?;
885
886        reader.goto_offset(offset)?;
887
888        Ok(())
889    }
890
891    #[inline]
892    fn decode_values<R, F>(
893        &self,
894        value_count: u64,
895        type_: Type,
896        reader: &mut EndianReader<R>,
897        mut collect: F,
898    ) -> TiffResult<()>
899    where
900        R: Read + Seek,
901        F: FnMut(&[u8]),
902    {
903        let mut total_bytes = type_.value_bytes(value_count)?;
904        let mut buffer = [0u8; 512];
905
906        let buf_unit = usize::from(type_.byte_len());
907        let mul_of_ty = buffer.len() / buf_unit * buf_unit;
908
909        let cls = type_.endian_bytes();
910        let native = ByteOrder::native();
911
912        while total_bytes > 0 {
913            // `now <= mul_of_ty < 512` so casting is mathematical
914            let now = total_bytes.min(mul_of_ty as u64);
915            total_bytes -= now;
916
917            let buffer = &mut buffer[..now as usize];
918            reader.inner().read_exact(buffer)?;
919
920            reader.byte_order.convert_endian_bytes(cls, buffer, native);
921            collect(buffer);
922        }
923
924        Ok(())
925    }
926}
927
928/// Extracts a list of BYTE tags stored in an offset
929#[inline]
930fn offset_to_bytes(n: usize, entry: &Entry) -> TiffResult<Value> {
931    Ok(List(
932        entry.offset[0..n]
933            .iter()
934            .map(|&e| Unsigned(u32::from(e)))
935            .collect(),
936    ))
937}
938
939/// Extracts a list of SBYTE tags stored in an offset
940#[inline]
941fn offset_to_sbytes(n: usize, entry: &Entry) -> TiffResult<Value> {
942    Ok(List(
943        entry.offset[0..n]
944            .iter()
945            .map(|&e| Signed(i32::from(e as i8)))
946            .collect(),
947    ))
948}
949
950/// Type representing an Image File Directory
951#[doc(hidden)]
952#[deprecated = "Use struct `tiff::Directory` instead which contains all fields relevant to an Image File Directory, including the offset to the next directory"]
953pub type Directory = HashMap<Tag, Entry>;