From 078bfcdc78a293ca0ec10504d6380d340614d266 Mon Sep 17 00:00:00 2001 From: KAMADA Ken'ichi Date: Fri, 4 Aug 2017 21:15:19 +0900 Subject: [PATCH] Add the 2nd member to Value::Undefined to keep the offset of the value. --- src/lib.rs | 1 + src/reader.rs | 2 +- src/tag.rs | 14 +++++++------- src/value.rs | 18 +++++++++++++----- src/writer.rs | 8 ++++---- tests/rwrcmp.rs | 2 +- 6 files changed, 27 insertions(+), 18 deletions(-) diff --git a/src/lib.rs b/src/lib.rs index 2c55d16..25e319d 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -48,6 +48,7 @@ //! Major changes between 0.2.3 and 0.3 are listed below. //! //! * Enum Error has two new variants: TooBig and NotSupported. +//! * Value::Undefined has the 2nd member to keep the offset of the value. pub use error::Error; pub use jpeg::get_exif_attr as get_exif_attr_from_jpeg; diff --git a/src/reader.rs b/src/reader.rs index a7e2ffe..3f22fd0 100644 --- a/src/reader.rs +++ b/src/reader.rs @@ -186,6 +186,6 @@ mod tests { 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")); + Value::Undefined(b"0230", _)); } } diff --git a/src/tag.rs b/src/tag.rs index 1c0665e..638c853 100644 --- a/src/tag.rs +++ b/src/tag.rs @@ -670,7 +670,7 @@ fn d_sensitivitytype(w: &mut fmt::Write, value: &Value) -> fmt::Result { // ExifVersion (Exif 0x9000), FlashpixVersion (Exif 0xa000) fn d_exifver(w: &mut fmt::Write, value: &Value) -> fmt::Result { - if let Value::Undefined(u) = *value { + if let Value::Undefined(u, _) = *value { if u.len() == 4 { if let Ok(major) = atou16(&u[0..2]) { if let Ok(minor) = atou16(&u[2..4]) { @@ -688,7 +688,7 @@ fn d_exifver(w: &mut fmt::Write, value: &Value) -> fmt::Result { // ComponentsConfiguration (Exif 0x9101) fn d_cpntcfg(w: &mut fmt::Write, value: &Value) -> fmt::Result { - if let Value::Undefined(u) = *value { + if let Value::Undefined(u, _) = *value { for &x in u { try!(match x { 0 => w.write_char('_'), @@ -859,7 +859,7 @@ fn d_sensingmethod(w: &mut fmt::Write, value: &Value) -> fmt::Result { // FileSource (Exif 0xa300) fn d_filesrc(w: &mut fmt::Write, value: &Value) -> fmt::Result { let s = match match *value { - Value::Undefined(s) => s.first().map(|&x| x), + Value::Undefined(s, _) => s.first().map(|&x| x), _ => None, } { Some(0) => "others", @@ -874,7 +874,7 @@ fn d_filesrc(w: &mut fmt::Write, value: &Value) -> fmt::Result { // SceneType (Exif 0xa301) fn d_scenetype(w: &mut fmt::Write, value: &Value) -> fmt::Result { let s = match match *value { - Value::Undefined(s) => s.first().map(|&x| x), + Value::Undefined(s, _) => s.first().map(|&x| x), _ => None, } { Some(1) => "directly photographed image", @@ -1168,7 +1168,7 @@ fn d_gpsdifferential(w: &mut fmt::Write, value: &Value) -> fmt::Result { fn d_ascii_in_undef(w: &mut fmt::Write, value: &Value) -> fmt::Result { match *value { - Value::Undefined(s) => d_sub_ascii(w, s), + Value::Undefined(s, _) => d_sub_ascii(w, s), _ => d_default(w, value), } } @@ -1205,7 +1205,7 @@ fn d_default(w: &mut fmt::Write, value: &Value) -> fmt::Result { Value::Long(ref v) => d_sub_comma(w, v), Value::Rational(ref v) => d_sub_comma(w, v), Value::SByte(ref v) => d_sub_comma(w, v), - Value::Undefined(ref s) => d_sub_hex(w, s), + Value::Undefined(ref s, _) => d_sub_hex(w, s), Value::SShort(ref v) => d_sub_comma(w, v), Value::SLong(ref v) => d_sub_comma(w, v), Value::SRational(ref v) => d_sub_comma(w, v), @@ -1304,7 +1304,7 @@ mod tests { _ => panic!(), } match tag::FileSource.default_value() { - Some(Value::Undefined(v)) => assert_eq!(v, &[3]), + Some(Value::Undefined(v, _)) => assert_eq!(v, &[3]), _ => panic!(), } match tag::GPSAltitudeRef.default_value() { diff --git a/src/value.rs b/src/value.rs index 6fbdec0..4f1289c 100644 --- a/src/value.rs +++ b/src/value.rs @@ -48,7 +48,12 @@ pub enum Value<'a> { /// Vector of 8-bit signed integers. Unused in the Exif specification. SByte(Vec), /// Slice of 8-bit bytes. - Undefined(&'a [u8]), + /// + /// The second member keeps the offset of the value in the Exif data. + /// The interpretation of the value does not generally depend on + /// the location, but if it does, the offset information helps. + /// When encoding Exif, it is ignored. + Undefined(&'a [u8], u32), /// Vector of 16-bit signed integers. Unused in the Exif specification. SShort(Vec), /// Vector of 32-bit signed integers. @@ -77,7 +82,7 @@ impl<'a> Value<'a> { /// /// ``` /// use exif::{Value, tag}; - /// let val = Value::Undefined(b"0231"); + /// let val = Value::Undefined(b"0231", 0); /// assert_eq!(format!("{}", val.display_as(tag::ExifVersion)), /// "2.31"); /// let val = Value::Short(vec![2]); @@ -177,7 +182,7 @@ impl<'a> From<&'a DefaultValue> for Option> { DefaultValue::Short(s) => Some(Value::Short(s.to_vec())), DefaultValue::Rational(s) => Some(Value::Rational( s.iter().map(|&t| tuple2rational(t)).collect())), - DefaultValue::Undefined(s) => Some(Value::Undefined(s)), + DefaultValue::Undefined(s) => Some(Value::Undefined(s, 0)), DefaultValue::ContextDependent => None, DefaultValue::Unspecified => None, } @@ -361,7 +366,7 @@ fn parse_sbyte<'a>(data: &'a [u8], offset: usize, count: usize) fn parse_undefined<'a>(data: &'a [u8], offset: usize, count: usize) -> Value<'a> { - Value::Undefined(&data[offset .. offset + count]) + Value::Undefined(&data[offset .. offset + count], offset as u32) } fn parse_sshort<'a, E>(data: &'a [u8], offset: usize, count: usize) @@ -546,7 +551,10 @@ mod tests { for &(data, ans) in sets { assert!((data.len() - 1) % unitlen == 0); match parser(data, 1, (data.len() - 1) / unitlen) { - Value::Undefined(v) => assert_eq!(v, ans), + Value::Undefined(v, o) => { + assert_eq!(v, ans); + assert_eq!(o, 1); + }, v => panic!("wrong variant {:?}", v), } } diff --git a/src/writer.rs b/src/writer.rs index f2b7c7b..6a54e06 100644 --- a/src/writer.rs +++ b/src/writer.rs @@ -509,7 +509,7 @@ fn compose_value(value: &Value) vec.as_ptr() as *const u8, vec.len()) }; Ok((6, vec.len(), uslice.to_vec())) }, - Value::Undefined(ref s) => + Value::Undefined(ref s, _) => Ok((7, s.len(), s.to_vec())), Value::SShort(ref vec) => { let mut buf = Vec::new(); @@ -614,7 +614,7 @@ mod tests { let exif_ver = Field { tag: tag::ExifVersion, thumbnail: false, - value: Value::Undefined(b"0231"), + value: Value::Undefined(b"0231", 0), }; let mut writer = Writer::new(); let mut buf = Cursor::new(Vec::new()); @@ -692,7 +692,7 @@ mod tests { let exif_ver = Field { tag: tag::ExifVersion, thumbnail: false, - value: Value::Undefined(b"0231"), + value: Value::Undefined(b"0231", 0), }; let gps_ver = Field { tag: tag::GPSVersionID, @@ -772,7 +772,7 @@ mod tests { (Value::SByte(vec![-2, -128]), (6, 2, b"\xfe\x80".to_vec()), (6, 2, b"\xfe\x80".to_vec())), - (Value::Undefined(b"abc"), + (Value::Undefined(b"abc", 0), (7, 3, b"abc".to_vec()), (7, 3, b"abc".to_vec())), (Value::SShort(vec![-2, -0x8000]), diff --git a/tests/rwrcmp.rs b/tests/rwrcmp.rs index 101b7ac..26a905c 100644 --- a/tests/rwrcmp.rs +++ b/tests/rwrcmp.rs @@ -155,7 +155,7 @@ fn compare_field_value(value1: &Value, value2: &Value) { }, (&Value::SByte(ref v1), &Value::SByte(ref v2)) => assert_eq!(v1, v2), - (&Value::Undefined(ref v1), &Value::Undefined(ref v2)) => + (&Value::Undefined(ref v1, _), &Value::Undefined(ref v2, _)) => assert_eq!(v1, v2), (&Value::SShort(ref v1), &Value::SShort(ref v2)) => assert_eq!(v1, v2),