diff --git a/src/lib.rs b/src/lib.rs index a5dade8..79a94de 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -54,9 +54,6 @@ //! images, which were distinguished by `bool` previously. Function //! parameters and struct members now take `In`s instead of `bool`s. //! `Field::thumbnail` was renamed to `Field::ifd_num` accordingly. -//! * The type of `Context` was changed from enum to struct. The variants -//! (e.g., `Context::Tiff`) were changed to associated constants and -//! they are now spelled in all uppercase (e.g., `Context::TIFF`). //! * `Value` became a self-contained type. The structures of `Value::Ascii` //! and `Value::Undefined` have been changed to use Vec instead of &[u8]. //! * `Reader::fields` now returns an iterator instead of a slice. diff --git a/src/tag.rs b/src/tag.rs index 31f1a77..fed9611 100644 --- a/src/tag.rs +++ b/src/tag.rs @@ -60,8 +60,8 @@ impl Tag { /// # Examples /// ``` /// use exif::{Context, Tag}; - /// assert_eq!(Tag::DateTime.context(), Context::TIFF); - /// assert_eq!(Tag::ExposureTime.context(), Context::EXIF); + /// assert_eq!(Tag::DateTime.context(), Context::Tiff); + /// assert_eq!(Tag::ExposureTime.context(), Context::Exif); /// ``` #[inline] pub fn context(self) -> Context { @@ -102,75 +102,22 @@ impl fmt::Display for Tag { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { match get_tag_info(*self) { Some(ti) => f.pad(ti.name), - None => f.pad(&format!("Tag({}, {})", self.0, self.1)), + None => f.pad(&format!("{:?}", self)), } } } -/// A type that indicates how a tag number is interpreted. -// This type is not an enum to keep API compatibilities when -// new contexts are introduced. +/// An enum that indicates how a tag number is interpreted. #[derive(Debug, Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Hash)] -pub struct Context(std::num::NonZeroU16); - -macro_rules! generate_context { - ( - $( - // Copy the doc attribute to the actual definition. - $( #[$attr:meta] )* - $name: ident = $num: expr, $disp: expr; - )+ - ) => ( - impl Context { - $( - $( #[$attr] )* - pub const $name: Self = Self( - unsafe { std::num::NonZeroU16::new_unchecked($num) }); - )+ - } - - fn display_context(ctx: &Context, f: &mut fmt::Formatter) - -> fmt::Result { - let name = match ctx.0.get() { - $( $num => $disp, )+ - _ => return fmt::Debug::fmt(ctx, f), - }; - f.write_str(name) - } - ) -} - -generate_context! { +pub enum Context { /// TIFF attributes defined in the TIFF Rev. 6.0 specification. - TIFF = 1, "TIFF"; // 0th/1st IFD (toplevel) + Tiff, // 0th/1st IFD (toplevel) /// Exif attributes. - EXIF = 2, "Exif"; // -- Exif IFD + Exif, // -- Exif IFD /// GPS attributes. - GPS = 3, "GPS"; // -- GPS IFD + Gps, // -- GPS IFD /// Interoperability attributes. - INTEROP = 4, "Interop"; // -- Exif IFD -- Interoperability IFD -} - -impl Context { - // Compatibility with 0.3.x. - #[allow(non_upper_case_globals)] - #[deprecated(since = "0.4.0", note = "use Context::TIFF instead")] - pub const Tiff: Self = Self::TIFF; - #[allow(non_upper_case_globals)] - #[deprecated(since = "0.4.0", note = "use Context::EXIF instead")] - pub const Exif: Self = Self::EXIF; - #[allow(non_upper_case_globals)] - #[deprecated(since = "0.4.0", note = "use Context::GPS instead")] - pub const Gps: Self = Self::GPS; - #[allow(non_upper_case_globals)] - #[deprecated(since = "0.4.0", note = "use Context::INTEROP instead")] - pub const Interop: Self = Self::INTEROP; -} - -impl fmt::Display for Context { - fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { - display_context(self, f) - } + Interop, // -- Exif IFD -- Interoperability IFD } #[derive(Debug)] @@ -268,7 +215,7 @@ macro_rules! generate_well_known_tag_constants { // the Exif field names: camel cases and all-capital acronyms. generate_well_known_tag_constants!( // Exif-specific IFDs [EXIF23 4.6.3]. - |Context::TIFF| + |Context::Tiff| /// A pointer to the Exif IFD. This is used for the internal structure /// of Exif data and will not be returned to the user. @@ -281,7 +228,7 @@ generate_well_known_tag_constants!( unit![], "GPS Info IFD pointer"), - |Context::EXIF| + |Context::Exif| /// A pointer to the interoperability IFD. This is used for the internal /// structure of Exif data and will not be returned to the user. @@ -291,7 +238,7 @@ generate_well_known_tag_constants!( // TIFF primary and thumbnail attributes [EXIF23 4.6.4 Table 4, // 4.6.8 Table 17, and 4.6.8 Table 21]. - |Context::TIFF| + |Context::Tiff| (ImageWidth, 0x100, DefaultValue::None, d_default, unit!["pixels"], @@ -393,7 +340,7 @@ generate_well_known_tag_constants!( "Copyright holder"), // Exif IFD attributes [EXIF23 4.6.5 Table 7 and 4.6.8 Table 18]. - |Context::EXIF| + |Context::Exif| (ExposureTime, 0x829a, DefaultValue::None, d_exptime, unit!["s"], @@ -635,7 +582,7 @@ generate_well_known_tag_constants!( "Gamma"), // GPS attributes [EXIF23 4.6.6 Table 15 and 4.6.8 Table 19]. - |Context::GPS| + |Context::Gps| // Depends on the Exif version. (GPSVersionID, 0x0, DefaultValue::ContextDependent, d_gpsver, @@ -736,7 +683,7 @@ generate_well_known_tag_constants!( "Horizontal positioning error"), // Interoperability attributes [EXIF23 4.6.7 Table 16 and 4.6.8 Table 20]. - |Context::INTEROP| + |Context::Interop| (InteroperabilityIndex, 0x1, DefaultValue::None, d_default, unit![], @@ -1510,12 +1457,12 @@ mod tests { #[test] fn tag_constant_in_pattern() { // Destructuring, which will always work. - match Tag(Context::TIFF, 0x132) { - Tag(Context::TIFF, 0x132) => {}, + match Tag(Context::Tiff, 0x132) { + Tag(Context::Tiff, 0x132) => {}, _ => panic!("failed to match Tag"), } // Matching against a constant. Test if this compiles. - match Tag(Context::TIFF, 0x132) { + match Tag(Context::Tiff, 0x132) { Tag::DateTime => {}, _ => panic!("failed to match Tag"), } @@ -1552,11 +1499,11 @@ mod tests { #[test] fn tag_fmt_display() { - let tag1 = Tag(Context::TIFF, 0x132); + let tag1 = Tag(Context::Tiff, 0x132); assert_eq!(format!("{:15}", tag1), "DateTime "); assert_eq!(format!("{:>15}", tag1), " DateTime"); assert_eq!(format!("{:5.6}", tag1), "DateTi"); - let tag2 = Tag(Context::EXIF, 0); + let tag2 = Tag(Context::Exif, 0); assert_eq!(format!("{:15}", tag2), "Tag(Exif, 0) "); assert_eq!(format!("{:>15}", tag2), " Tag(Exif, 0)"); assert_eq!(format!("{:5.6}", tag2), "Tag(Ex"); diff --git a/src/tiff.rs b/src/tiff.rs index fe9ac1f..773d663 100644 --- a/src/tiff.rs +++ b/src/tiff.rs @@ -187,7 +187,7 @@ fn parse_exif_sub(data: &[u8]) return Err(Error::InvalidFormat("Limit the IFD count to 8")); } ifd_offset = parse_ifd::( - &mut entries, data, ifd_offset, Context::TIFF, ifd_num)?; + &mut entries, data, ifd_offset, Context::Tiff, ifd_num)?; ifd_num_ck = ifd_num.checked_add(1); } Ok(entries) @@ -230,11 +230,11 @@ fn parse_ifd(entries: &mut Vec, data: &[u8], let tag = Tag(ctx, tag); match tag { Tag::ExifIFDPointer => parse_child_ifd::( - entries, data, &mut val, Context::EXIF, ifd_num)?, + entries, data, &mut val, Context::Exif, ifd_num)?, Tag::GPSInfoIFDPointer => parse_child_ifd::( - entries, data, &mut val, Context::GPS, ifd_num)?, + entries, data, &mut val, Context::Gps, ifd_num)?, Tag::InteropIFDPointer => parse_child_ifd::( - entries, data, &mut val, Context::INTEROP, ifd_num)?, + entries, data, &mut val, Context::Interop, ifd_num)?, _ => entries.push(IfdEntry { field: Field { tag: tag, ifd_num: In(ifd_num), value: val }.into()}), } diff --git a/src/writer.rs b/src/writer.rs index 8f22f5e..d340930 100644 --- a/src/writer.rs +++ b/src/writer.rs @@ -130,11 +130,10 @@ impl<'a> Writer<'a> { Field { tag: Tag(ctx, _), ifd_num, .. } => { let ifd = self.pick_ifd(ifd_num); match ctx { - Context::TIFF => ifd.tiff_fields.push(field), - Context::EXIF => ifd.exif_fields.push(field), - Context::GPS => ifd.gps_fields.push(field), - Context::INTEROP => ifd.interop_fields.push(field), - _ => unimplemented!(), + Context::Tiff => ifd.tiff_fields.push(field), + Context::Exif => ifd.exif_fields.push(field), + Context::Gps => ifd.gps_fields.push(field), + Context::Interop => ifd.interop_fields.push(field), } }, }