1use 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 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#[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 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 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 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 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 if self.count == 1 {
424 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 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 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 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 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 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 self.set_reader_offset_relative(bigtiff, reader, 0)?;
765
766 buf.assume_type(self.type_, 0, reader.byte_order);
768 let target = &mut buf.raw_bytes_mut()[..value_bytes];
769 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 let value_bytes = self.type_.value_bytes(self.count)?;
789
790 if at >= value_bytes {
792 return Ok(0);
793 }
794
795 if value_bytes <= 4 || bigtiff && value_bytes <= 8 {
797 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 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 Ok(len)
826 }
827
828 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 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 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 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#[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#[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#[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>;