Restore Reader::fields to list all fields including duplicates.

This commit is contained in:
KAMADA Ken'ichi 2019-12-22 20:28:25 +09:00
parent fa34bc9895
commit 47ab7e4764
1 changed files with 12 additions and 9 deletions

View File

@ -24,7 +24,7 @@
// SUCH DAMAGE. // SUCH DAMAGE.
// //
use std::collections::BTreeMap; use std::collections::HashMap;
use std::io; use std::io;
use std::io::Read; use std::io::Read;
@ -62,9 +62,11 @@ use crate::tiff::{Field, IfdEntry, In, ProvideUnit};
pub struct Reader { pub struct Reader {
// TIFF data. // TIFF data.
buf: Vec<u8>, buf: Vec<u8>,
// Exif fields. `BTreeMap` is used so that `Reader::field` returns // Exif fields. Vec is used to keep the ability to enumerate all fields
// the fields in a stable order. // even if there are duplicates.
entries: BTreeMap<(In, Tag), IfdEntry>, entries: Vec<IfdEntry>,
// HashMap to the index of the Vec for faster random access.
entry_map: HashMap<(In, Tag), usize>,
// True if the TIFF data is little endian. // True if the TIFF data is little endian.
little_endian: bool, little_endian: bool,
} }
@ -88,12 +90,13 @@ impl Reader {
} }
let (entries, le) = tiff::parse_exif(&buf)?; let (entries, le) = tiff::parse_exif(&buf)?;
let entries = entries.into_iter() let entry_map = entries.iter().enumerate()
.map(|e| (e.ifd_num_tag(), e)).collect(); .map(|(i, e)| (e.ifd_num_tag(), i)).collect();
Ok(Reader { Ok(Reader {
buf: buf, buf: buf,
entries: entries, entries: entries,
entry_map: entry_map,
little_endian: le, little_endian: le,
}) })
} }
@ -107,7 +110,7 @@ impl Reader {
/// Returns a slice of Exif fields. /// Returns a slice of Exif fields.
#[inline] #[inline]
pub fn fields<'a>(&'a self) -> impl ExactSizeIterator<Item = &'a Field> { pub fn fields<'a>(&'a self) -> impl ExactSizeIterator<Item = &'a Field> {
self.entries.values() self.entries.iter()
.map(move |e| e.ref_field(&self.buf, self.little_endian)) .map(move |e| e.ref_field(&self.buf, self.little_endian))
} }
@ -121,8 +124,8 @@ impl Reader {
/// and the IFD number. /// and the IFD number.
#[inline] #[inline]
pub fn get_field(&self, tag: Tag, ifd_num: In) -> Option<&Field> { pub fn get_field(&self, tag: Tag, ifd_num: In) -> Option<&Field> {
self.entries.get(&(ifd_num, tag)) self.entry_map.get(&(ifd_num, tag))
.map(|e| e.ref_field(&self.buf, self.little_endian)) .map(|&i| self.entries[i].ref_field(&self.buf, self.little_endian))
} }
} }