Add Reader::get_field().
Specify the same type for the input/output of a transmute when it is not expected to change the type.
This commit is contained in:
parent
db718fe75a
commit
165f95fc8e
|
@ -24,12 +24,14 @@
|
|||
// SUCH DAMAGE.
|
||||
//
|
||||
|
||||
use std::collections::HashMap;
|
||||
use std::io;
|
||||
use std::io::Read;
|
||||
use std::mem;
|
||||
|
||||
use error::Error;
|
||||
use jpeg;
|
||||
use tag_priv::Tag;
|
||||
use tiff;
|
||||
use tiff::Field;
|
||||
|
||||
|
@ -55,6 +57,8 @@ pub struct Reader {
|
|||
fields: Vec<Field<'static>>,
|
||||
// True if the TIFF data is little endian.
|
||||
little_endian: bool,
|
||||
// HashMap to find a field quickly.
|
||||
field_map: HashMap<(Tag, bool), &'static Field<'static>>,
|
||||
}
|
||||
|
||||
impl Reader {
|
||||
|
@ -76,11 +80,23 @@ impl Reader {
|
|||
|
||||
// Cheat on the type system and erase the lifetime by transmute().
|
||||
// The scope releases the inner `v` to unborrow `buf`.
|
||||
let (v, le) = {
|
||||
let (fields, le) = {
|
||||
let (v, le) = try!(tiff::parse_exif(&buf));
|
||||
(unsafe { mem::transmute(v) }, le) };
|
||||
let r = Reader { buf: buf, fields: v, little_endian: le };
|
||||
Ok(r)
|
||||
(unsafe { mem::transmute::<Vec<Field>, Vec<Field>>(v) }, le) };
|
||||
|
||||
// Initialize the HashMap of all fields.
|
||||
let mut field_map = HashMap::new();
|
||||
for f in &fields {
|
||||
field_map.insert((f.tag, f.thumbnail),
|
||||
unsafe { mem::transmute::<&Field, &Field>(f) });
|
||||
}
|
||||
|
||||
Ok(Reader {
|
||||
buf: buf,
|
||||
fields: fields,
|
||||
little_endian: le,
|
||||
field_map: field_map
|
||||
})
|
||||
}
|
||||
|
||||
/// Returns the slice that contains the TIFF data.
|
||||
|
@ -100,12 +116,21 @@ impl Reader {
|
|||
pub fn little_endian(&self) -> bool {
|
||||
self.little_endian
|
||||
}
|
||||
|
||||
/// Returns a reference to the Exif field specified by the tag
|
||||
/// and the thumbnail flag.
|
||||
#[inline]
|
||||
pub fn get_field(&self, tag: Tag, thumbnail: bool) -> Option<&Field> {
|
||||
self.field_map.get(&(tag, thumbnail)).map(|&f| f)
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use std::fs::File;
|
||||
use std::io::BufReader;
|
||||
use value::Value;
|
||||
use tag_priv::constants as tag;
|
||||
use super::*;
|
||||
|
||||
static TIFF_ASCII: &'static [u8] =
|
||||
|
@ -155,4 +180,12 @@ mod tests {
|
|||
panic!("TIFF ASCII field is expected");
|
||||
}
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn get_field() {
|
||||
let file = File::open("tests/exif.jpg").unwrap();
|
||||
let reader = Reader::new(&mut BufReader::new(&file)).unwrap();
|
||||
assert_pat!(reader.get_field(tag::ExifVersion, false).unwrap().value,
|
||||
Value::Undefined(b"0230"));
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue