1use std::fmt;
28use mutate_once::MutOnce;
29
30use crate::endian::{Endian, BigEndian, LittleEndian};
31use crate::error::Error;
32use crate::tag::{Context, Tag, UnitPiece};
33use crate::value;
34use crate::value::Value;
35use crate::value::get_type_info;
36use crate::util::{atou16, ctou32};
37
38const TIFF_BE: u16 = 0x4d4d;
40const TIFF_LE: u16 = 0x4949;
41const TIFF_FORTY_TWO: u16 = 0x002a;
42pub const TIFF_BE_SIG: [u8; 4] = [0x4d, 0x4d, 0x00, 0x2a];
43pub const TIFF_LE_SIG: [u8; 4] = [0x49, 0x49, 0x2a, 0x00];
44
45#[derive(Debug)]
49pub struct IfdEntry {
50 field: MutOnce<Field>,
53}
54
55impl IfdEntry {
56 pub fn ifd_num_tag(&self) -> (In, Tag) {
57 if self.field.is_fixed() {
58 let field = self.field.get_ref();
59 (field.ifd_num, field.tag)
60 } else {
61 let field = self.field.get_mut();
62 (field.ifd_num, field.tag)
63 }
64 }
65
66 pub fn ref_field<'a>(&'a self, data: &[u8], le: bool) -> &'a Field {
67 self.parse(data, le);
68 self.field.get_ref()
69 }
70
71 fn into_field(self, data: &[u8], le: bool) -> Field {
72 self.parse(data, le);
73 self.field.into_inner()
74 }
75
76 fn parse(&self, data: &[u8], le: bool) {
77 if !self.field.is_fixed() {
78 let mut field = self.field.get_mut();
79 if le {
80 Self::parse_value::<LittleEndian>(&mut field.value, data);
81 } else {
82 Self::parse_value::<BigEndian>(&mut field.value, data);
83 }
84 }
85 }
86
87 fn parse_value<E>(value: &mut Value, data: &[u8]) where E: Endian {
89 match *value {
90 Value::Unknown(typ, cnt, ofs) => {
91 let (unitlen, parser) = get_type_info::<E>(typ);
92 if unitlen != 0 {
93 *value = parser(data, ofs as usize, cnt as usize);
94 }
95 },
96 _ => panic!("value is already parsed"),
97 }
98 }
99}
100
101#[derive(Debug, Clone)]
103pub struct Field {
104 pub tag: Tag,
106 pub ifd_num: In,
108 pub value: Value,
110}
111
112#[derive(Debug, Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Hash)]
125pub struct In(pub u16);
126
127impl In {
128 pub const PRIMARY: In = In(0);
129 pub const THUMBNAIL: In = In(1);
130
131 #[inline]
133 pub fn index(self) -> u16 {
134 self.0
135 }
136}
137
138impl fmt::Display for In {
139 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
140 match self.0 {
141 0 => f.pad("primary"),
142 1 => f.pad("thumbnail"),
143 n => f.pad(&format!("IFD{}", n)),
144 }
145 }
146}
147
148pub fn parse_exif(data: &[u8]) -> Result<(Vec<Field>, bool), Error> {
154 let mut parser = Parser::new();
155 parser.parse(data)?;
156 let (entries, le) = (parser.entries, parser.little_endian);
157 Ok((entries.into_iter().map(|e| e.into_field(data, le)).collect(), le))
158}
159
160#[derive(Debug)]
161pub struct Parser {
162 pub entries: Vec<IfdEntry>,
163 pub little_endian: bool,
164}
165
166impl Parser {
167 pub fn new() -> Self {
168 Self { entries: Vec::new(), little_endian: false }
169 }
170
171 pub fn parse(&mut self, data: &[u8]) -> Result<(), Error> {
172 if data.len() < 8 {
174 return Err(Error::InvalidFormat("Truncated TIFF header"));
175 }
176 match BigEndian::loadu16(data, 0) {
177 TIFF_BE => {
178 self.little_endian = false;
179 self.parse_sub::<BigEndian>(data)
180 },
181 TIFF_LE => {
182 self.little_endian = true;
183 self.parse_sub::<LittleEndian>(data)
184 },
185 _ => Err(Error::InvalidFormat("Invalid TIFF byte order")),
186 }
187 }
188
189 fn parse_sub<E>(&mut self, data: &[u8])
190 -> Result<(), Error> where E: Endian {
191 if E::loadu16(data, 2) != TIFF_FORTY_TWO {
193 return Err(Error::InvalidFormat("Invalid forty two"));
194 }
195 let mut ifd_offset = E::loadu32(data, 4) as usize;
196 let mut ifd_num_ck = Some(0);
197 while ifd_offset != 0 {
198 let ifd_num = ifd_num_ck
199 .ok_or(Error::InvalidFormat("Too many IFDs"))?;
200 if ifd_num >= 8 {
203 return Err(Error::InvalidFormat("Limit the IFD count to 8"));
204 }
205 ifd_offset = self.parse_ifd::<E>(
206 data, ifd_offset, Context::Tiff, ifd_num)?;
207 ifd_num_ck = ifd_num.checked_add(1);
208 }
209 Ok(())
210 }
211
212 fn parse_ifd<E>(&mut self, data: &[u8],
214 offset: usize, ctx: Context, ifd_num: u16)
215 -> Result<usize, Error> where E: Endian {
216 if data.len() < offset || data.len() - offset < 2 {
218 return Err(Error::InvalidFormat("Truncated IFD count"));
219 }
220 let count = E::loadu16(data, offset) as usize;
221
222 if data.len() - offset - 2 < count * 12 {
224 return Err(Error::InvalidFormat("Truncated IFD"));
225 }
226 for i in 0..count as usize {
227 let tag = E::loadu16(data, offset + 2 + i * 12);
228 let typ = E::loadu16(data, offset + 2 + i * 12 + 2);
229 let cnt = E::loadu32(data, offset + 2 + i * 12 + 4);
230 let valofs_at = offset + 2 + i * 12 + 8;
231 let (unitlen, _parser) = get_type_info::<E>(typ);
232 let vallen = unitlen.checked_mul(cnt as usize).ok_or(
233 Error::InvalidFormat("Invalid entry count"))?;
234 let mut val = if vallen <= 4 {
235 Value::Unknown(typ, cnt, valofs_at as u32)
236 } else {
237 let ofs = E::loadu32(data, valofs_at) as usize;
238 if data.len() < ofs || data.len() - ofs < vallen {
239 return Err(Error::InvalidFormat("Truncated field value"));
240 }
241 Value::Unknown(typ, cnt, ofs as u32)
242 };
243
244 let tag = Tag(ctx, tag);
247 match tag {
248 Tag::ExifIFDPointer => self.parse_child_ifd::<E>(
249 data, &mut val, Context::Exif, ifd_num)?,
250 Tag::GPSInfoIFDPointer => self.parse_child_ifd::<E>(
251 data, &mut val, Context::Gps, ifd_num)?,
252 Tag::InteropIFDPointer => self.parse_child_ifd::<E>(
253 data, &mut val, Context::Interop, ifd_num)?,
254 _ => self.entries.push(IfdEntry { field: Field {
255 tag: tag, ifd_num: In(ifd_num), value: val }.into()}),
256 }
257 }
258
259 if data.len() - offset - 2 - count * 12 < 4 {
261 return Err(Error::InvalidFormat("Truncated next IFD offset"));
262 }
263 let next_ifd_offset = E::loadu32(data, offset + 2 + count * 12);
264 Ok(next_ifd_offset as usize)
265 }
266
267 fn parse_child_ifd<E>(&mut self, data: &[u8],
268 pointer: &mut Value, ctx: Context, ifd_num: u16)
269 -> Result<(), Error> where E: Endian {
270 IfdEntry::parse_value::<E>(pointer, data);
272
273 let ofs = pointer.get_uint(0).ok_or(
277 Error::InvalidFormat("Invalid pointer"))? as usize;
278 match self.parse_ifd::<E>(data, ofs, ctx, ifd_num)? {
279 0 => Ok(()),
280 _ => Err(Error::InvalidFormat("Unexpected next IFD")),
281 }
282 }
283}
284
285pub fn is_tiff(buf: &[u8]) -> bool {
286 buf.starts_with(&TIFF_BE_SIG) || buf.starts_with(&TIFF_LE_SIG)
287}
288
289#[derive(Debug)]
301pub struct DateTime {
302 pub year: u16,
303 pub month: u8,
304 pub day: u8,
305 pub hour: u8,
306 pub minute: u8,
307 pub second: u8,
308 pub nanosecond: Option<u32>,
311 pub offset: Option<i16>,
313}
314
315impl DateTime {
316 pub fn from_ascii(data: &[u8]) -> Result<DateTime, Error> {
321 if data == b" : : : : " || data == b" " {
322 return Err(Error::BlankValue("DateTime is blank"));
323 } else if data.len() < 19 {
324 return Err(Error::InvalidFormat("DateTime too short"));
325 } else if !(data[4] == b':' && data[7] == b':' && data[10] == b' ' &&
326 data[13] == b':' && data[16] == b':') {
327 return Err(Error::InvalidFormat("Invalid DateTime delimiter"));
328 }
329 Ok(DateTime {
330 year: atou16(&data[0..4])?,
331 month: atou16(&data[5..7])? as u8,
332 day: atou16(&data[8..10])? as u8,
333 hour: atou16(&data[11..13])? as u8,
334 minute: atou16(&data[14..16])? as u8,
335 second: atou16(&data[17..19])? as u8,
336 nanosecond: None,
337 offset: None,
338 })
339 }
340
341 pub fn parse_subsec(&mut self, data: &[u8]) -> Result<(), Error> {
343 let mut subsec = 0;
344 let mut ndigits = 0;
345 for &c in data {
346 if c == b' ' {
347 break;
348 }
349 subsec = subsec * 10 + ctou32(c)?;
350 ndigits += 1;
351 if ndigits >= 9 {
352 break;
353 }
354 }
355 if ndigits == 0 {
356 self.nanosecond = None;
357 } else {
358 for _ in ndigits..9 {
359 subsec *= 10;
360 }
361 self.nanosecond = Some(subsec);
362 }
363 Ok(())
364 }
365
366 pub fn parse_offset(&mut self, data: &[u8]) -> Result<(), Error> {
368 if data == b" : " || data == b" " {
369 return Err(Error::BlankValue("OffsetTime is blank"));
370 } else if data.len() < 6 {
371 return Err(Error::InvalidFormat("OffsetTime too short"));
372 } else if data[3] != b':' {
373 return Err(Error::InvalidFormat("Invalid OffsetTime delimiter"));
374 }
375 let hour = atou16(&data[1..3])?;
376 let min = atou16(&data[4..6])?;
377 let offset = (hour * 60 + min) as i16;
378 self.offset = Some(match data[0] {
379 b'+' => offset,
380 b'-' => -offset,
381 _ => return Err(Error::InvalidFormat("Invalid OffsetTime sign")),
382 });
383 Ok(())
384 }
385}
386
387impl fmt::Display for DateTime {
388 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
389 write!(f, "{:04}-{:02}-{:02} {:02}:{:02}:{:02}",
390 self.year, self.month, self.day,
391 self.hour, self.minute, self.second)
392 }
393}
394
395impl Field {
396 #[inline]
444 pub fn display_value(&self) -> DisplayValue {
445 DisplayValue {
446 tag: self.tag,
447 ifd_num: self.ifd_num,
448 value_display: self.value.display_as(self.tag),
449 }
450 }
451}
452
453pub struct DisplayValue<'a> {
455 tag: Tag,
456 ifd_num: In,
457 value_display: value::Display<'a>,
458}
459
460impl<'a> DisplayValue<'a> {
461 #[inline]
462 pub fn with_unit<T>(&self, unit_provider: T)
463 -> DisplayValueUnit<'a, T> where T: ProvideUnit<'a> {
464 DisplayValueUnit {
465 ifd_num: self.ifd_num,
466 value_display: self.value_display,
467 unit: self.tag.unit(),
468 unit_provider: unit_provider,
469 }
470 }
471}
472
473impl<'a> fmt::Display for DisplayValue<'a> {
474 #[inline]
475 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
476 self.value_display.fmt(f)
477 }
478}
479
480pub struct DisplayValueUnit<'a, T> where T: ProvideUnit<'a> {
482 ifd_num: In,
483 value_display: value::Display<'a>,
484 unit: Option<&'static [UnitPiece]>,
485 unit_provider: T,
486}
487
488impl<'a, T> fmt::Display for DisplayValueUnit<'a, T> where T: ProvideUnit<'a> {
489 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
490 if let Some(unit) = self.unit {
491 assert!(!unit.is_empty());
492 for piece in unit {
493 match *piece {
494 UnitPiece::Value => self.value_display.fmt(f),
495 UnitPiece::Str(s) => f.write_str(s),
496 UnitPiece::Tag(tag) =>
497 if let Some(x) = self.unit_provider.get_field(
498 tag, self.ifd_num) {
499 x.value.display_as(tag).fmt(f)
500 } else if let Some(x) = tag.default_value() {
501 x.display_as(tag).fmt(f)
502 } else {
503 write!(f, "[{} missing]", tag)
504 },
505 }?
506 }
507 Ok(())
508 } else {
509 self.value_display.fmt(f)
510 }
511 }
512}
513
514pub trait ProvideUnit<'a>: Copy {
515 fn get_field(self, tag: Tag, ifd_num: In) -> Option<&'a Field>;
516}
517
518impl<'a> ProvideUnit<'a> for () {
519 fn get_field(self, _tag: Tag, _ifd_num: In) -> Option<&'a Field> {
520 None
521 }
522}
523
524impl<'a> ProvideUnit<'a> for &'a Field {
525 fn get_field(self, tag: Tag, ifd_num: In) -> Option<&'a Field> {
526 Some(self).filter(|x| x.tag == tag && x.ifd_num == ifd_num)
527 }
528}
529
530#[cfg(test)]
531mod tests {
532 use super::*;
533
534 #[test]
535 fn in_convert() {
536 assert_eq!(In::PRIMARY.index(), 0);
537 assert_eq!(In::THUMBNAIL.index(), 1);
538 assert_eq!(In(2).index(), 2);
539 assert_eq!(In(65535).index(), 65535);
540 assert_eq!(In::PRIMARY, In(0));
541 }
542
543 #[test]
544 fn in_display() {
545 assert_eq!(format!("{:10}", In::PRIMARY), "primary ");
546 assert_eq!(format!("{:>10}", In::THUMBNAIL), " thumbnail");
547 assert_eq!(format!("{:10}", In(2)), "IFD2 ");
548 assert_eq!(format!("{:^10}", In(65535)), " IFD65535 ");
549 }
550
551 #[test]
552 fn truncated() {
553 let mut data =
554 b"MM\0\x2a\0\0\0\x08\
555 \0\x01\x01\0\0\x03\0\0\0\x01\0\x14\0\0\0\0\0\0".to_vec();
556 parse_exif(&data).unwrap();
557 while let Some(_) = data.pop() {
558 parse_exif(&data).unwrap_err();
559 }
560 }
561
562 #[test]
565 fn inf_loop_by_next() {
566 let data = b"MM\0\x2a\0\0\0\x08\
567 \0\x01\x01\0\0\x03\0\0\0\x01\0\x14\0\0\0\0\0\x08";
568 assert_err_pat!(parse_exif(data),
569 Error::InvalidFormat("Limit the IFD count to 8"));
570 }
571
572 #[test]
573 fn inf_loop_by_exif_next() {
574 let data = b"MM\x00\x2a\x00\x00\x00\x08\
575 \x00\x01\x87\x69\x00\x04\x00\x00\x00\x01\x00\x00\x00\x1a\
576 \x00\x00\x00\x00\
577 \x00\x01\x90\x00\x00\x07\x00\x00\x00\x040231\
578 \x00\x00\x00\x08";
579 assert_err_pat!(parse_exif(data),
580 Error::InvalidFormat("Unexpected next IFD"));
581 }
582
583 #[test]
584 fn unknown_field() {
585 let data = b"MM\0\x2a\0\0\0\x08\
586 \0\x01\x01\0\xff\xff\0\0\0\x01\0\x14\0\0\0\0\0\0";
587 let (v, _le) = parse_exif(data).unwrap();
588 assert_eq!(v.len(), 1);
589 assert_pat!(v[0].value, Value::Unknown(0xffff, 1, 0x12));
590 }
591
592 #[test]
593 fn date_time() {
594 let mut dt = DateTime::from_ascii(b"2016:05:04 03:02:01").unwrap();
595 assert_eq!(dt.year, 2016);
596 assert_eq!(dt.to_string(), "2016-05-04 03:02:01");
597
598 dt.parse_subsec(b"987").unwrap();
599 assert_eq!(dt.nanosecond.unwrap(), 987000000);
600 dt.parse_subsec(b"000987").unwrap();
601 assert_eq!(dt.nanosecond.unwrap(), 987000);
602 dt.parse_subsec(b"987654321").unwrap();
603 assert_eq!(dt.nanosecond.unwrap(), 987654321);
604 dt.parse_subsec(b"9876543219").unwrap();
605 assert_eq!(dt.nanosecond.unwrap(), 987654321);
606 dt.parse_subsec(b"130 ").unwrap();
607 assert_eq!(dt.nanosecond.unwrap(), 130000000);
608 dt.parse_subsec(b"0").unwrap();
609 assert_eq!(dt.nanosecond.unwrap(), 0);
610 dt.parse_subsec(b"").unwrap();
611 assert!(dt.nanosecond.is_none());
612 dt.parse_subsec(b" ").unwrap();
613 assert!(dt.nanosecond.is_none());
614
615 dt.parse_offset(b"+00:00").unwrap();
616 assert_eq!(dt.offset.unwrap(), 0);
617 dt.parse_offset(b"+01:23").unwrap();
618 assert_eq!(dt.offset.unwrap(), 83);
619 dt.parse_offset(b"+99:99").unwrap();
620 assert_eq!(dt.offset.unwrap(), 6039);
621 dt.parse_offset(b"-01:23").unwrap();
622 assert_eq!(dt.offset.unwrap(), -83);
623 dt.parse_offset(b"-99:99").unwrap();
624 assert_eq!(dt.offset.unwrap(), -6039);
625 assert_err_pat!(dt.parse_offset(b" : "), Error::BlankValue(_));
626 assert_err_pat!(dt.parse_offset(b" "), Error::BlankValue(_));
627 }
628
629 #[test]
630 fn display_value_with_unit() {
631 let cm = Field {
632 tag: Tag::ResolutionUnit,
633 ifd_num: In::PRIMARY,
634 value: Value::Short(vec![3]),
635 };
636 let cm_tn = Field {
637 tag: Tag::ResolutionUnit,
638 ifd_num: In::THUMBNAIL,
639 value: Value::Short(vec![3]),
640 };
641 let exifver = Field {
643 tag: Tag::ExifVersion,
644 ifd_num: In::PRIMARY,
645 value: Value::Undefined(b"0231".to_vec(), 0),
646 };
647 assert_eq!(exifver.display_value().to_string(),
648 "2.31");
649 assert_eq!(exifver.display_value().with_unit(()).to_string(),
650 "2.31");
651 assert_eq!(exifver.display_value().with_unit(&cm).to_string(),
652 "2.31");
653 let width = Field {
655 tag: Tag::ImageWidth,
656 ifd_num: In::PRIMARY,
657 value: Value::Short(vec![257]),
658 };
659 assert_eq!(width.display_value().to_string(),
660 "257");
661 assert_eq!(width.display_value().with_unit(()).to_string(),
662 "257 pixels");
663 assert_eq!(width.display_value().with_unit(&cm).to_string(),
664 "257 pixels");
665 let xres = Field {
668 tag: Tag::XResolution,
669 ifd_num: In::PRIMARY,
670 value: Value::Rational(vec![(300, 1).into()]),
671 };
672 assert_eq!(xres.display_value().to_string(),
673 "300");
674 assert_eq!(xres.display_value().with_unit(()).to_string(),
675 "300 pixels per inch");
676 assert_eq!(xres.display_value().with_unit(&cm).to_string(),
677 "300 pixels per cm");
678 assert_eq!(xres.display_value().with_unit(&cm_tn).to_string(),
679 "300 pixels per inch");
680 let gpslat = Field {
682 tag: Tag::GPSLatitude,
683 ifd_num: In::PRIMARY,
684 value: Value::Rational(vec![
685 (10, 1).into(), (0, 1).into(), (1, 10).into()]),
686 };
687 assert_eq!(gpslat.display_value().to_string(),
688 "10 deg 0 min 0.1 sec");
689 assert_eq!(gpslat.display_value().with_unit(()).to_string(),
690 "10 deg 0 min 0.1 sec [GPSLatitudeRef missing]");
691 assert_eq!(gpslat.display_value().with_unit(&cm).to_string(),
692 "10 deg 0 min 0.1 sec [GPSLatitudeRef missing]");
693 }
694
695 #[test]
696 fn no_borrow_no_move() {
697 let resunit = Field {
698 tag: Tag::ResolutionUnit,
699 ifd_num: In::PRIMARY,
700 value: Value::Short(vec![3]),
701 };
702 let d = resunit.display_value().with_unit(());
705 assert_eq!(d.to_string(), "cm");
706 let d1 = resunit.display_value();
708 let d2 = d1.with_unit(());
709 assert_eq!(d1.to_string(), "cm");
710 assert_eq!(d2.to_string(), "cm");
711 }
712}