Revert the type of Context back from struct to enum.

This commit is contained in:
KAMADA Ken'ichi 2019-12-22 20:31:44 +09:00
parent 47ab7e4764
commit 8825fcca62
4 changed files with 28 additions and 85 deletions

View File

@ -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<u8> instead of &[u8].
//! * `Reader::fields` now returns an iterator instead of a slice.

View File

@ -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");

View File

@ -187,7 +187,7 @@ fn parse_exif_sub<E>(data: &[u8])
return Err(Error::InvalidFormat("Limit the IFD count to 8"));
}
ifd_offset = parse_ifd::<E>(
&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<E>(entries: &mut Vec<IfdEntry>, data: &[u8],
let tag = Tag(ctx, tag);
match tag {
Tag::ExifIFDPointer => parse_child_ifd::<E>(
entries, data, &mut val, Context::EXIF, ifd_num)?,
entries, data, &mut val, Context::Exif, ifd_num)?,
Tag::GPSInfoIFDPointer => parse_child_ifd::<E>(
entries, data, &mut val, Context::GPS, ifd_num)?,
entries, data, &mut val, Context::Gps, ifd_num)?,
Tag::InteropIFDPointer => parse_child_ifd::<E>(
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()}),
}

View File

@ -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),
}
},
}