1 | //! Function for reading TIFF tags |
2 | |
3 | use std::collections::HashMap; |
4 | use std::convert::{TryFrom, TryInto}; |
5 | use std::io::{self, Read, Seek}; |
6 | use std::mem; |
7 | use std::str; |
8 | |
9 | use super::stream::{ByteOrder, EndianReader, SmartReader}; |
10 | use crate::tags::{Tag, Type}; |
11 | use crate::{TiffError, TiffFormatError, TiffResult}; |
12 | |
13 | use self::Value::{ |
14 | Ascii, Byte, Double, Float, Ifd, IfdBig, List, Rational, RationalBig, SRational, SRationalBig, |
15 | Short, Signed, SignedBig, Unsigned, UnsignedBig, |
16 | }; |
17 | |
18 | #[allow (unused_qualifications)] |
19 | #[derive (Debug, Clone, PartialEq)] |
20 | #[non_exhaustive ] |
21 | pub enum Value { |
22 | Byte(u8), |
23 | Short(u16), |
24 | Signed(i32), |
25 | SignedBig(i64), |
26 | Unsigned(u32), |
27 | UnsignedBig(u64), |
28 | Float(f32), |
29 | Double(f64), |
30 | List(Vec<Value>), |
31 | Rational(u32, u32), |
32 | RationalBig(u64, u64), |
33 | SRational(i32, i32), |
34 | SRationalBig(i64, i64), |
35 | Ascii(String), |
36 | Ifd(u32), |
37 | IfdBig(u64), |
38 | } |
39 | |
40 | impl Value { |
41 | pub fn into_u8(self) -> TiffResult<u8> { |
42 | match self { |
43 | Byte(val) => Ok(val), |
44 | val => Err(TiffError::FormatError(TiffFormatError::ByteExpected(val))), |
45 | } |
46 | } |
47 | |
48 | pub fn into_u16(self) -> TiffResult<u16> { |
49 | match self { |
50 | Short(val) => Ok(val), |
51 | Unsigned(val) => Ok(u16::try_from(val)?), |
52 | UnsignedBig(val) => Ok(u16::try_from(val)?), |
53 | val => Err(TiffError::FormatError( |
54 | TiffFormatError::UnsignedIntegerExpected(val), |
55 | )), |
56 | } |
57 | } |
58 | |
59 | pub fn into_u32(self) -> TiffResult<u32> { |
60 | match self { |
61 | Short(val) => Ok(val.into()), |
62 | Unsigned(val) => Ok(val), |
63 | UnsignedBig(val) => Ok(u32::try_from(val)?), |
64 | Ifd(val) => Ok(val), |
65 | IfdBig(val) => Ok(u32::try_from(val)?), |
66 | val => Err(TiffError::FormatError( |
67 | TiffFormatError::UnsignedIntegerExpected(val), |
68 | )), |
69 | } |
70 | } |
71 | |
72 | pub fn into_i32(self) -> TiffResult<i32> { |
73 | match self { |
74 | Signed(val) => Ok(val), |
75 | SignedBig(val) => Ok(i32::try_from(val)?), |
76 | val => Err(TiffError::FormatError( |
77 | TiffFormatError::SignedIntegerExpected(val), |
78 | )), |
79 | } |
80 | } |
81 | |
82 | pub fn into_u64(self) -> TiffResult<u64> { |
83 | match self { |
84 | Short(val) => Ok(val.into()), |
85 | Unsigned(val) => Ok(val.into()), |
86 | UnsignedBig(val) => Ok(val), |
87 | Ifd(val) => Ok(val.into()), |
88 | IfdBig(val) => Ok(val), |
89 | val => Err(TiffError::FormatError( |
90 | TiffFormatError::UnsignedIntegerExpected(val), |
91 | )), |
92 | } |
93 | } |
94 | |
95 | pub fn into_i64(self) -> TiffResult<i64> { |
96 | match self { |
97 | Signed(val) => Ok(val.into()), |
98 | SignedBig(val) => Ok(val), |
99 | val => Err(TiffError::FormatError( |
100 | TiffFormatError::SignedIntegerExpected(val), |
101 | )), |
102 | } |
103 | } |
104 | |
105 | pub fn into_f32(self) -> TiffResult<f32> { |
106 | match self { |
107 | Float(val) => Ok(val), |
108 | val => Err(TiffError::FormatError( |
109 | TiffFormatError::SignedIntegerExpected(val), |
110 | )), |
111 | } |
112 | } |
113 | |
114 | pub fn into_f64(self) -> TiffResult<f64> { |
115 | match self { |
116 | Double(val) => Ok(val), |
117 | val => Err(TiffError::FormatError( |
118 | TiffFormatError::SignedIntegerExpected(val), |
119 | )), |
120 | } |
121 | } |
122 | |
123 | pub fn into_string(self) -> TiffResult<String> { |
124 | match self { |
125 | Ascii(val) => Ok(val), |
126 | val => Err(TiffError::FormatError( |
127 | TiffFormatError::SignedIntegerExpected(val), |
128 | )), |
129 | } |
130 | } |
131 | |
132 | pub fn into_u32_vec(self) -> TiffResult<Vec<u32>> { |
133 | match self { |
134 | List(vec) => { |
135 | let mut new_vec = Vec::with_capacity(vec.len()); |
136 | for v in vec { |
137 | new_vec.push(v.into_u32()?) |
138 | } |
139 | Ok(new_vec) |
140 | } |
141 | Unsigned(val) => Ok(vec![val]), |
142 | UnsignedBig(val) => Ok(vec![u32::try_from(val)?]), |
143 | Rational(numerator, denominator) => Ok(vec![numerator, denominator]), |
144 | RationalBig(numerator, denominator) => { |
145 | Ok(vec![u32::try_from(numerator)?, u32::try_from(denominator)?]) |
146 | } |
147 | Ifd(val) => Ok(vec![val]), |
148 | IfdBig(val) => Ok(vec![u32::try_from(val)?]), |
149 | Ascii(val) => Ok(val.chars().map(u32::from).collect()), |
150 | val => Err(TiffError::FormatError( |
151 | TiffFormatError::UnsignedIntegerExpected(val), |
152 | )), |
153 | } |
154 | } |
155 | |
156 | pub fn into_u8_vec(self) -> TiffResult<Vec<u8>> { |
157 | match self { |
158 | List(vec) => { |
159 | let mut new_vec = Vec::with_capacity(vec.len()); |
160 | for v in vec { |
161 | new_vec.push(v.into_u8()?) |
162 | } |
163 | Ok(new_vec) |
164 | } |
165 | Byte(val) => Ok(vec![val]), |
166 | |
167 | val => Err(TiffError::FormatError( |
168 | TiffFormatError::UnsignedIntegerExpected(val), |
169 | )), |
170 | } |
171 | } |
172 | |
173 | pub fn into_u16_vec(self) -> TiffResult<Vec<u16>> { |
174 | match self { |
175 | List(vec) => { |
176 | let mut new_vec = Vec::with_capacity(vec.len()); |
177 | for v in vec { |
178 | new_vec.push(v.into_u16()?) |
179 | } |
180 | Ok(new_vec) |
181 | } |
182 | Short(val) => Ok(vec![val]), |
183 | val => Err(TiffError::FormatError( |
184 | TiffFormatError::UnsignedIntegerExpected(val), |
185 | )), |
186 | } |
187 | } |
188 | |
189 | pub fn into_i32_vec(self) -> TiffResult<Vec<i32>> { |
190 | match self { |
191 | List(vec) => { |
192 | let mut new_vec = Vec::with_capacity(vec.len()); |
193 | for v in vec { |
194 | match v { |
195 | SRational(numerator, denominator) => { |
196 | new_vec.push(numerator); |
197 | new_vec.push(denominator); |
198 | } |
199 | SRationalBig(numerator, denominator) => { |
200 | new_vec.push(i32::try_from(numerator)?); |
201 | new_vec.push(i32::try_from(denominator)?); |
202 | } |
203 | _ => new_vec.push(v.into_i32()?), |
204 | } |
205 | } |
206 | Ok(new_vec) |
207 | } |
208 | Signed(val) => Ok(vec![val]), |
209 | SignedBig(val) => Ok(vec![i32::try_from(val)?]), |
210 | SRational(numerator, denominator) => Ok(vec![numerator, denominator]), |
211 | SRationalBig(numerator, denominator) => { |
212 | Ok(vec![i32::try_from(numerator)?, i32::try_from(denominator)?]) |
213 | } |
214 | val => Err(TiffError::FormatError( |
215 | TiffFormatError::SignedIntegerExpected(val), |
216 | )), |
217 | } |
218 | } |
219 | |
220 | pub fn into_f32_vec(self) -> TiffResult<Vec<f32>> { |
221 | match self { |
222 | List(vec) => { |
223 | let mut new_vec = Vec::with_capacity(vec.len()); |
224 | for v in vec { |
225 | new_vec.push(v.into_f32()?) |
226 | } |
227 | Ok(new_vec) |
228 | } |
229 | Float(val) => Ok(vec![val]), |
230 | val => Err(TiffError::FormatError( |
231 | TiffFormatError::UnsignedIntegerExpected(val), |
232 | )), |
233 | } |
234 | } |
235 | |
236 | pub fn into_f64_vec(self) -> TiffResult<Vec<f64>> { |
237 | match self { |
238 | List(vec) => { |
239 | let mut new_vec = Vec::with_capacity(vec.len()); |
240 | for v in vec { |
241 | new_vec.push(v.into_f64()?) |
242 | } |
243 | Ok(new_vec) |
244 | } |
245 | Double(val) => Ok(vec![val]), |
246 | val => Err(TiffError::FormatError( |
247 | TiffFormatError::UnsignedIntegerExpected(val), |
248 | )), |
249 | } |
250 | } |
251 | |
252 | pub fn into_u64_vec(self) -> TiffResult<Vec<u64>> { |
253 | match self { |
254 | List(vec) => { |
255 | let mut new_vec = Vec::with_capacity(vec.len()); |
256 | for v in vec { |
257 | new_vec.push(v.into_u64()?) |
258 | } |
259 | Ok(new_vec) |
260 | } |
261 | Unsigned(val) => Ok(vec![val.into()]), |
262 | UnsignedBig(val) => Ok(vec![val]), |
263 | Rational(numerator, denominator) => Ok(vec![numerator.into(), denominator.into()]), |
264 | RationalBig(numerator, denominator) => Ok(vec![numerator, denominator]), |
265 | Ifd(val) => Ok(vec![val.into()]), |
266 | IfdBig(val) => Ok(vec![val]), |
267 | Ascii(val) => Ok(val.chars().map(u32::from).map(u64::from).collect()), |
268 | val => Err(TiffError::FormatError( |
269 | TiffFormatError::UnsignedIntegerExpected(val), |
270 | )), |
271 | } |
272 | } |
273 | |
274 | pub fn into_i64_vec(self) -> TiffResult<Vec<i64>> { |
275 | match self { |
276 | List(vec) => { |
277 | let mut new_vec = Vec::with_capacity(vec.len()); |
278 | for v in vec { |
279 | match v { |
280 | SRational(numerator, denominator) => { |
281 | new_vec.push(numerator.into()); |
282 | new_vec.push(denominator.into()); |
283 | } |
284 | SRationalBig(numerator, denominator) => { |
285 | new_vec.push(numerator); |
286 | new_vec.push(denominator); |
287 | } |
288 | _ => new_vec.push(v.into_i64()?), |
289 | } |
290 | } |
291 | Ok(new_vec) |
292 | } |
293 | Signed(val) => Ok(vec![val.into()]), |
294 | SignedBig(val) => Ok(vec![val]), |
295 | SRational(numerator, denominator) => Ok(vec![numerator.into(), denominator.into()]), |
296 | SRationalBig(numerator, denominator) => Ok(vec![numerator, denominator]), |
297 | val => Err(TiffError::FormatError( |
298 | TiffFormatError::SignedIntegerExpected(val), |
299 | )), |
300 | } |
301 | } |
302 | } |
303 | |
304 | #[derive (Clone)] |
305 | pub struct Entry { |
306 | type_: Type, |
307 | count: u64, |
308 | offset: [u8; 8], |
309 | } |
310 | |
311 | impl ::std::fmt::Debug for Entry { |
312 | fn fmt(&self, fmt: &mut ::std::fmt::Formatter) -> Result<(), ::std::fmt::Error> { |
313 | fmt.write_str(&format!( |
314 | "Entry {{ type_: {:?}, count: {:?}, offset: {:?} }}" , |
315 | self.type_, self.count, &self.offset |
316 | )) |
317 | } |
318 | } |
319 | |
320 | impl Entry { |
321 | pub fn new(type_: Type, count: u32, offset: [u8; 4]) -> Entry { |
322 | let mut offset = offset.to_vec(); |
323 | offset.append(&mut vec![0; 4]); |
324 | Entry::new_u64(type_, count.into(), offset[..].try_into().unwrap()) |
325 | } |
326 | |
327 | pub fn new_u64(type_: Type, count: u64, offset: [u8; 8]) -> Entry { |
328 | Entry { |
329 | type_, |
330 | count, |
331 | offset, |
332 | } |
333 | } |
334 | |
335 | /// Returns a mem_reader for the offset/value field |
336 | fn r(&self, byte_order: ByteOrder) -> SmartReader<io::Cursor<Vec<u8>>> { |
337 | SmartReader::wrap(io::Cursor::new(self.offset.to_vec()), byte_order) |
338 | } |
339 | |
340 | pub fn val<R: Read + Seek>( |
341 | &self, |
342 | limits: &super::Limits, |
343 | bigtiff: bool, |
344 | reader: &mut SmartReader<R>, |
345 | ) -> TiffResult<Value> { |
346 | // Case 1: there are no values so we can return immediately. |
347 | if self.count == 0 { |
348 | return Ok(List(Vec::new())); |
349 | } |
350 | |
351 | let bo = reader.byte_order(); |
352 | |
353 | let tag_size = match self.type_ { |
354 | Type::BYTE | Type::SBYTE | Type::ASCII | Type::UNDEFINED => 1, |
355 | Type::SHORT | Type::SSHORT => 2, |
356 | Type::LONG | Type::SLONG | Type::FLOAT | Type::IFD => 4, |
357 | Type::LONG8 |
358 | | Type::SLONG8 |
359 | | Type::DOUBLE |
360 | | Type::RATIONAL |
361 | | Type::SRATIONAL |
362 | | Type::IFD8 => 8, |
363 | }; |
364 | |
365 | let value_bytes = match self.count.checked_mul(tag_size) { |
366 | Some(n) => n, |
367 | None => { |
368 | return Err(TiffError::LimitsExceeded); |
369 | } |
370 | }; |
371 | |
372 | // Case 2: there is one value. |
373 | if self.count == 1 { |
374 | // 2a: the value is 5-8 bytes and we're in BigTiff mode. |
375 | if bigtiff && value_bytes > 4 && value_bytes <= 8 { |
376 | return Ok(match self.type_ { |
377 | Type::LONG8 => UnsignedBig(self.r(bo).read_u64()?), |
378 | Type::SLONG8 => SignedBig(self.r(bo).read_i64()?), |
379 | Type::DOUBLE => Double(self.r(bo).read_f64()?), |
380 | Type::RATIONAL => { |
381 | let mut r = self.r(bo); |
382 | Rational(r.read_u32()?, r.read_u32()?) |
383 | } |
384 | Type::SRATIONAL => { |
385 | let mut r = self.r(bo); |
386 | SRational(r.read_i32()?, r.read_i32()?) |
387 | } |
388 | Type::IFD8 => IfdBig(self.r(bo).read_u64()?), |
389 | Type::BYTE |
390 | | Type::SBYTE |
391 | | Type::ASCII |
392 | | Type::UNDEFINED |
393 | | Type::SHORT |
394 | | Type::SSHORT |
395 | | Type::LONG |
396 | | Type::SLONG |
397 | | Type::FLOAT |
398 | | Type::IFD => unreachable!(), |
399 | }); |
400 | } |
401 | |
402 | // 2b: the value is at most 4 bytes or doesn't fit in the offset field. |
403 | return Ok(match self.type_ { |
404 | Type::BYTE => Unsigned(u32::from(self.offset[0])), |
405 | Type::SBYTE => Signed(i32::from(self.offset[0] as i8)), |
406 | Type::UNDEFINED => Byte(self.offset[0]), |
407 | Type::SHORT => Unsigned(u32::from(self.r(bo).read_u16()?)), |
408 | Type::SSHORT => Signed(i32::from(self.r(bo).read_i16()?)), |
409 | Type::LONG => Unsigned(self.r(bo).read_u32()?), |
410 | Type::SLONG => Signed(self.r(bo).read_i32()?), |
411 | Type::FLOAT => Float(self.r(bo).read_f32()?), |
412 | Type::ASCII => { |
413 | if self.offset[0] == 0 { |
414 | Ascii("" .to_string()) |
415 | } else { |
416 | return Err(TiffError::FormatError(TiffFormatError::InvalidTag)); |
417 | } |
418 | } |
419 | Type::LONG8 => { |
420 | reader.goto_offset(self.r(bo).read_u32()?.into())?; |
421 | UnsignedBig(reader.read_u64()?) |
422 | } |
423 | Type::SLONG8 => { |
424 | reader.goto_offset(self.r(bo).read_u32()?.into())?; |
425 | SignedBig(reader.read_i64()?) |
426 | } |
427 | Type::DOUBLE => { |
428 | reader.goto_offset(self.r(bo).read_u32()?.into())?; |
429 | Double(reader.read_f64()?) |
430 | } |
431 | Type::RATIONAL => { |
432 | reader.goto_offset(self.r(bo).read_u32()?.into())?; |
433 | Rational(reader.read_u32()?, reader.read_u32()?) |
434 | } |
435 | Type::SRATIONAL => { |
436 | reader.goto_offset(self.r(bo).read_u32()?.into())?; |
437 | SRational(reader.read_i32()?, reader.read_i32()?) |
438 | } |
439 | Type::IFD => Ifd(self.r(bo).read_u32()?), |
440 | Type::IFD8 => { |
441 | reader.goto_offset(self.r(bo).read_u32()?.into())?; |
442 | IfdBig(reader.read_u64()?) |
443 | } |
444 | }); |
445 | } |
446 | |
447 | // Case 3: There is more than one value, but it fits in the offset field. |
448 | if value_bytes <= 4 || bigtiff && value_bytes <= 8 { |
449 | match self.type_ { |
450 | Type::BYTE => return offset_to_bytes(self.count as usize, self), |
451 | Type::SBYTE => return offset_to_sbytes(self.count as usize, self), |
452 | Type::ASCII => { |
453 | let mut buf = vec![0; self.count as usize]; |
454 | self.r(bo).read_exact(&mut buf)?; |
455 | if buf.is_ascii() && buf.ends_with(&[0]) { |
456 | let v = str::from_utf8(&buf)?; |
457 | let v = v.trim_matches(char::from(0)); |
458 | return Ok(Ascii(v.into())); |
459 | } else { |
460 | return Err(TiffError::FormatError(TiffFormatError::InvalidTag)); |
461 | } |
462 | } |
463 | Type::UNDEFINED => { |
464 | return Ok(List( |
465 | self.offset[0..self.count as usize] |
466 | .iter() |
467 | .map(|&b| Byte(b)) |
468 | .collect(), |
469 | )); |
470 | } |
471 | Type::SHORT => { |
472 | let mut r = self.r(bo); |
473 | let mut v = Vec::new(); |
474 | for _ in 0..self.count { |
475 | v.push(Short(r.read_u16()?)); |
476 | } |
477 | return Ok(List(v)); |
478 | } |
479 | Type::SSHORT => { |
480 | let mut r = self.r(bo); |
481 | let mut v = Vec::new(); |
482 | for _ in 0..self.count { |
483 | v.push(Signed(i32::from(r.read_i16()?))); |
484 | } |
485 | return Ok(List(v)); |
486 | } |
487 | Type::LONG => { |
488 | let mut r = self.r(bo); |
489 | let mut v = Vec::new(); |
490 | for _ in 0..self.count { |
491 | v.push(Unsigned(r.read_u32()?)); |
492 | } |
493 | return Ok(List(v)); |
494 | } |
495 | Type::SLONG => { |
496 | let mut r = self.r(bo); |
497 | let mut v = Vec::new(); |
498 | for _ in 0..self.count { |
499 | v.push(Signed(r.read_i32()?)); |
500 | } |
501 | return Ok(List(v)); |
502 | } |
503 | Type::FLOAT => { |
504 | let mut r = self.r(bo); |
505 | let mut v = Vec::new(); |
506 | for _ in 0..self.count { |
507 | v.push(Float(r.read_f32()?)); |
508 | } |
509 | return Ok(List(v)); |
510 | } |
511 | Type::IFD => { |
512 | let mut r = self.r(bo); |
513 | let mut v = Vec::new(); |
514 | for _ in 0..self.count { |
515 | v.push(Ifd(r.read_u32()?)); |
516 | } |
517 | return Ok(List(v)); |
518 | } |
519 | Type::LONG8 |
520 | | Type::SLONG8 |
521 | | Type::RATIONAL |
522 | | Type::SRATIONAL |
523 | | Type::DOUBLE |
524 | | Type::IFD8 => { |
525 | unreachable!() |
526 | } |
527 | } |
528 | } |
529 | |
530 | // Case 4: there is more than one value, and it doesn't fit in the offset field. |
531 | match self.type_ { |
532 | // TODO check if this could give wrong results |
533 | // at a different endianess of file/computer. |
534 | Type::BYTE => self.decode_offset(self.count, bo, bigtiff, limits, reader, |reader| { |
535 | let mut buf = [0; 1]; |
536 | reader.read_exact(&mut buf)?; |
537 | Ok(UnsignedBig(u64::from(buf[0]))) |
538 | }), |
539 | Type::SBYTE => self.decode_offset(self.count, bo, bigtiff, limits, reader, |reader| { |
540 | Ok(SignedBig(i64::from(reader.read_i8()?))) |
541 | }), |
542 | Type::SHORT => self.decode_offset(self.count, bo, bigtiff, limits, reader, |reader| { |
543 | Ok(UnsignedBig(u64::from(reader.read_u16()?))) |
544 | }), |
545 | Type::SSHORT => self.decode_offset(self.count, bo, bigtiff, limits, reader, |reader| { |
546 | Ok(SignedBig(i64::from(reader.read_i16()?))) |
547 | }), |
548 | Type::LONG => self.decode_offset(self.count, bo, bigtiff, limits, reader, |reader| { |
549 | Ok(Unsigned(reader.read_u32()?)) |
550 | }), |
551 | Type::SLONG => self.decode_offset(self.count, bo, bigtiff, limits, reader, |reader| { |
552 | Ok(Signed(reader.read_i32()?)) |
553 | }), |
554 | Type::FLOAT => self.decode_offset(self.count, bo, bigtiff, limits, reader, |reader| { |
555 | Ok(Float(reader.read_f32()?)) |
556 | }), |
557 | Type::DOUBLE => self.decode_offset(self.count, bo, bigtiff, limits, reader, |reader| { |
558 | Ok(Double(reader.read_f64()?)) |
559 | }), |
560 | Type::RATIONAL => { |
561 | self.decode_offset(self.count, bo, bigtiff, limits, reader, |reader| { |
562 | Ok(Rational(reader.read_u32()?, reader.read_u32()?)) |
563 | }) |
564 | } |
565 | Type::SRATIONAL => { |
566 | self.decode_offset(self.count, bo, bigtiff, limits, reader, |reader| { |
567 | Ok(SRational(reader.read_i32()?, reader.read_i32()?)) |
568 | }) |
569 | } |
570 | Type::LONG8 => self.decode_offset(self.count, bo, bigtiff, limits, reader, |reader| { |
571 | Ok(UnsignedBig(reader.read_u64()?)) |
572 | }), |
573 | Type::SLONG8 => self.decode_offset(self.count, bo, bigtiff, limits, reader, |reader| { |
574 | Ok(SignedBig(reader.read_i64()?)) |
575 | }), |
576 | Type::IFD => self.decode_offset(self.count, bo, bigtiff, limits, reader, |reader| { |
577 | Ok(Ifd(reader.read_u32()?)) |
578 | }), |
579 | Type::IFD8 => self.decode_offset(self.count, bo, bigtiff, limits, reader, |reader| { |
580 | Ok(IfdBig(reader.read_u64()?)) |
581 | }), |
582 | Type::UNDEFINED => { |
583 | self.decode_offset(self.count, bo, bigtiff, limits, reader, |reader| { |
584 | let mut buf = [0; 1]; |
585 | reader.read_exact(&mut buf)?; |
586 | Ok(Byte(buf[0])) |
587 | }) |
588 | } |
589 | Type::ASCII => { |
590 | let n = usize::try_from(self.count)?; |
591 | if n > limits.decoding_buffer_size { |
592 | return Err(TiffError::LimitsExceeded); |
593 | } |
594 | |
595 | if bigtiff { |
596 | reader.goto_offset(self.r(bo).read_u64()?)? |
597 | } else { |
598 | reader.goto_offset(self.r(bo).read_u32()?.into())? |
599 | } |
600 | |
601 | let mut out = vec![0; n]; |
602 | reader.read_exact(&mut out)?; |
603 | // Strings may be null-terminated, so we trim anything downstream of the null byte |
604 | if let Some(first) = out.iter().position(|&b| b == 0) { |
605 | out.truncate(first); |
606 | } |
607 | Ok(Ascii(String::from_utf8(out)?)) |
608 | } |
609 | } |
610 | } |
611 | |
612 | #[inline ] |
613 | fn decode_offset<R, F>( |
614 | &self, |
615 | value_count: u64, |
616 | bo: ByteOrder, |
617 | bigtiff: bool, |
618 | limits: &super::Limits, |
619 | reader: &mut SmartReader<R>, |
620 | decode_fn: F, |
621 | ) -> TiffResult<Value> |
622 | where |
623 | R: Read + Seek, |
624 | F: Fn(&mut SmartReader<R>) -> TiffResult<Value>, |
625 | { |
626 | let value_count = usize::try_from(value_count)?; |
627 | if value_count > limits.decoding_buffer_size / mem::size_of::<Value>() { |
628 | return Err(TiffError::LimitsExceeded); |
629 | } |
630 | |
631 | let mut v = Vec::with_capacity(value_count); |
632 | |
633 | let offset = if bigtiff { |
634 | self.r(bo).read_u64()? |
635 | } else { |
636 | self.r(bo).read_u32()?.into() |
637 | }; |
638 | reader.goto_offset(offset)?; |
639 | |
640 | for _ in 0..value_count { |
641 | v.push(decode_fn(reader)?) |
642 | } |
643 | Ok(List(v)) |
644 | } |
645 | } |
646 | |
647 | /// Extracts a list of BYTE tags stored in an offset |
648 | #[inline ] |
649 | fn offset_to_bytes(n: usize, entry: &Entry) -> TiffResult<Value> { |
650 | Ok(List( |
651 | entryimpl Iterator .offset[0..n] |
652 | .iter() |
653 | .map(|&e: u8| Unsigned(u32::from(e))) |
654 | .collect(), |
655 | )) |
656 | } |
657 | |
658 | /// Extracts a list of SBYTE tags stored in an offset |
659 | #[inline ] |
660 | fn offset_to_sbytes(n: usize, entry: &Entry) -> TiffResult<Value> { |
661 | Ok(List( |
662 | entryimpl Iterator .offset[0..n] |
663 | .iter() |
664 | .map(|&e: u8| Signed(i32::from(e as i8))) |
665 | .collect(), |
666 | )) |
667 | } |
668 | |
669 | /// Type representing an Image File Directory |
670 | pub type Directory = HashMap<Tag, Entry>; |
671 | |