Revert the type of Context back from struct to enum.
This commit is contained in:
parent
47ab7e4764
commit
8825fcca62
|
@ -54,9 +54,6 @@
|
||||||
//! images, which were distinguished by `bool` previously. Function
|
//! images, which were distinguished by `bool` previously. Function
|
||||||
//! parameters and struct members now take `In`s instead of `bool`s.
|
//! parameters and struct members now take `In`s instead of `bool`s.
|
||||||
//! `Field::thumbnail` was renamed to `Field::ifd_num` accordingly.
|
//! `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`
|
//! * `Value` became a self-contained type. The structures of `Value::Ascii`
|
||||||
//! and `Value::Undefined` have been changed to use Vec<u8> instead of &[u8].
|
//! and `Value::Undefined` have been changed to use Vec<u8> instead of &[u8].
|
||||||
//! * `Reader::fields` now returns an iterator instead of a slice.
|
//! * `Reader::fields` now returns an iterator instead of a slice.
|
||||||
|
|
93
src/tag.rs
93
src/tag.rs
|
@ -60,8 +60,8 @@ impl Tag {
|
||||||
/// # Examples
|
/// # Examples
|
||||||
/// ```
|
/// ```
|
||||||
/// use exif::{Context, Tag};
|
/// use exif::{Context, Tag};
|
||||||
/// assert_eq!(Tag::DateTime.context(), Context::TIFF);
|
/// assert_eq!(Tag::DateTime.context(), Context::Tiff);
|
||||||
/// assert_eq!(Tag::ExposureTime.context(), Context::EXIF);
|
/// assert_eq!(Tag::ExposureTime.context(), Context::Exif);
|
||||||
/// ```
|
/// ```
|
||||||
#[inline]
|
#[inline]
|
||||||
pub fn context(self) -> Context {
|
pub fn context(self) -> Context {
|
||||||
|
@ -102,75 +102,22 @@ impl fmt::Display for Tag {
|
||||||
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
|
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
|
||||||
match get_tag_info(*self) {
|
match get_tag_info(*self) {
|
||||||
Some(ti) => f.pad(ti.name),
|
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.
|
/// An enum that indicates how a tag number is interpreted.
|
||||||
// This type is not an enum to keep API compatibilities when
|
|
||||||
// new contexts are introduced.
|
|
||||||
#[derive(Debug, Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Hash)]
|
#[derive(Debug, Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Hash)]
|
||||||
pub struct Context(std::num::NonZeroU16);
|
pub enum Context {
|
||||||
|
|
||||||
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! {
|
|
||||||
/// TIFF attributes defined in the TIFF Rev. 6.0 specification.
|
/// 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 attributes.
|
||||||
EXIF = 2, "Exif"; // -- Exif IFD
|
Exif, // -- Exif IFD
|
||||||
/// GPS attributes.
|
/// GPS attributes.
|
||||||
GPS = 3, "GPS"; // -- GPS IFD
|
Gps, // -- GPS IFD
|
||||||
/// Interoperability attributes.
|
/// Interoperability attributes.
|
||||||
INTEROP = 4, "Interop"; // -- Exif IFD -- Interoperability IFD
|
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)
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Debug)]
|
#[derive(Debug)]
|
||||||
|
@ -268,7 +215,7 @@ macro_rules! generate_well_known_tag_constants {
|
||||||
// the Exif field names: camel cases and all-capital acronyms.
|
// the Exif field names: camel cases and all-capital acronyms.
|
||||||
generate_well_known_tag_constants!(
|
generate_well_known_tag_constants!(
|
||||||
// Exif-specific IFDs [EXIF23 4.6.3].
|
// Exif-specific IFDs [EXIF23 4.6.3].
|
||||||
|Context::TIFF|
|
|Context::Tiff|
|
||||||
|
|
||||||
/// A pointer to the Exif IFD. This is used for the internal structure
|
/// A pointer to the Exif IFD. This is used for the internal structure
|
||||||
/// of Exif data and will not be returned to the user.
|
/// of Exif data and will not be returned to the user.
|
||||||
|
@ -281,7 +228,7 @@ generate_well_known_tag_constants!(
|
||||||
unit![],
|
unit![],
|
||||||
"GPS Info IFD pointer"),
|
"GPS Info IFD pointer"),
|
||||||
|
|
||||||
|Context::EXIF|
|
|Context::Exif|
|
||||||
|
|
||||||
/// A pointer to the interoperability IFD. This is used for the internal
|
/// A pointer to the interoperability IFD. This is used for the internal
|
||||||
/// structure of Exif data and will not be returned to the user.
|
/// 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,
|
// TIFF primary and thumbnail attributes [EXIF23 4.6.4 Table 4,
|
||||||
// 4.6.8 Table 17, and 4.6.8 Table 21].
|
// 4.6.8 Table 17, and 4.6.8 Table 21].
|
||||||
|Context::TIFF|
|
|Context::Tiff|
|
||||||
|
|
||||||
(ImageWidth, 0x100, DefaultValue::None, d_default,
|
(ImageWidth, 0x100, DefaultValue::None, d_default,
|
||||||
unit!["pixels"],
|
unit!["pixels"],
|
||||||
|
@ -393,7 +340,7 @@ generate_well_known_tag_constants!(
|
||||||
"Copyright holder"),
|
"Copyright holder"),
|
||||||
|
|
||||||
// Exif IFD attributes [EXIF23 4.6.5 Table 7 and 4.6.8 Table 18].
|
// 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,
|
(ExposureTime, 0x829a, DefaultValue::None, d_exptime,
|
||||||
unit!["s"],
|
unit!["s"],
|
||||||
|
@ -635,7 +582,7 @@ generate_well_known_tag_constants!(
|
||||||
"Gamma"),
|
"Gamma"),
|
||||||
|
|
||||||
// GPS attributes [EXIF23 4.6.6 Table 15 and 4.6.8 Table 19].
|
// GPS attributes [EXIF23 4.6.6 Table 15 and 4.6.8 Table 19].
|
||||||
|Context::GPS|
|
|Context::Gps|
|
||||||
|
|
||||||
// Depends on the Exif version.
|
// Depends on the Exif version.
|
||||||
(GPSVersionID, 0x0, DefaultValue::ContextDependent, d_gpsver,
|
(GPSVersionID, 0x0, DefaultValue::ContextDependent, d_gpsver,
|
||||||
|
@ -736,7 +683,7 @@ generate_well_known_tag_constants!(
|
||||||
"Horizontal positioning error"),
|
"Horizontal positioning error"),
|
||||||
|
|
||||||
// Interoperability attributes [EXIF23 4.6.7 Table 16 and 4.6.8 Table 20].
|
// Interoperability attributes [EXIF23 4.6.7 Table 16 and 4.6.8 Table 20].
|
||||||
|Context::INTEROP|
|
|Context::Interop|
|
||||||
|
|
||||||
(InteroperabilityIndex, 0x1, DefaultValue::None, d_default,
|
(InteroperabilityIndex, 0x1, DefaultValue::None, d_default,
|
||||||
unit![],
|
unit![],
|
||||||
|
@ -1510,12 +1457,12 @@ mod tests {
|
||||||
#[test]
|
#[test]
|
||||||
fn tag_constant_in_pattern() {
|
fn tag_constant_in_pattern() {
|
||||||
// Destructuring, which will always work.
|
// Destructuring, which will always work.
|
||||||
match Tag(Context::TIFF, 0x132) {
|
match Tag(Context::Tiff, 0x132) {
|
||||||
Tag(Context::TIFF, 0x132) => {},
|
Tag(Context::Tiff, 0x132) => {},
|
||||||
_ => panic!("failed to match Tag"),
|
_ => panic!("failed to match Tag"),
|
||||||
}
|
}
|
||||||
// Matching against a constant. Test if this compiles.
|
// Matching against a constant. Test if this compiles.
|
||||||
match Tag(Context::TIFF, 0x132) {
|
match Tag(Context::Tiff, 0x132) {
|
||||||
Tag::DateTime => {},
|
Tag::DateTime => {},
|
||||||
_ => panic!("failed to match Tag"),
|
_ => panic!("failed to match Tag"),
|
||||||
}
|
}
|
||||||
|
@ -1552,11 +1499,11 @@ mod tests {
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn tag_fmt_display() {
|
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!("{:>15}", tag1), " DateTime");
|
assert_eq!(format!("{:>15}", tag1), " DateTime");
|
||||||
assert_eq!(format!("{:5.6}", tag1), "DateTi");
|
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!("{:>15}", tag2), " Tag(Exif, 0)");
|
assert_eq!(format!("{:>15}", tag2), " Tag(Exif, 0)");
|
||||||
assert_eq!(format!("{:5.6}", tag2), "Tag(Ex");
|
assert_eq!(format!("{:5.6}", tag2), "Tag(Ex");
|
||||||
|
|
|
@ -187,7 +187,7 @@ fn parse_exif_sub<E>(data: &[u8])
|
||||||
return Err(Error::InvalidFormat("Limit the IFD count to 8"));
|
return Err(Error::InvalidFormat("Limit the IFD count to 8"));
|
||||||
}
|
}
|
||||||
ifd_offset = parse_ifd::<E>(
|
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);
|
ifd_num_ck = ifd_num.checked_add(1);
|
||||||
}
|
}
|
||||||
Ok(entries)
|
Ok(entries)
|
||||||
|
@ -230,11 +230,11 @@ fn parse_ifd<E>(entries: &mut Vec<IfdEntry>, data: &[u8],
|
||||||
let tag = Tag(ctx, tag);
|
let tag = Tag(ctx, tag);
|
||||||
match tag {
|
match tag {
|
||||||
Tag::ExifIFDPointer => parse_child_ifd::<E>(
|
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>(
|
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>(
|
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 {
|
_ => entries.push(IfdEntry { field: Field {
|
||||||
tag: tag, ifd_num: In(ifd_num), value: val }.into()}),
|
tag: tag, ifd_num: In(ifd_num), value: val }.into()}),
|
||||||
}
|
}
|
||||||
|
|
|
@ -130,11 +130,10 @@ impl<'a> Writer<'a> {
|
||||||
Field { tag: Tag(ctx, _), ifd_num, .. } => {
|
Field { tag: Tag(ctx, _), ifd_num, .. } => {
|
||||||
let ifd = self.pick_ifd(ifd_num);
|
let ifd = self.pick_ifd(ifd_num);
|
||||||
match ctx {
|
match ctx {
|
||||||
Context::TIFF => ifd.tiff_fields.push(field),
|
Context::Tiff => ifd.tiff_fields.push(field),
|
||||||
Context::EXIF => ifd.exif_fields.push(field),
|
Context::Exif => ifd.exif_fields.push(field),
|
||||||
Context::GPS => ifd.gps_fields.push(field),
|
Context::Gps => ifd.gps_fields.push(field),
|
||||||
Context::INTEROP => ifd.interop_fields.push(field),
|
Context::Interop => ifd.interop_fields.push(field),
|
||||||
_ => unimplemented!(),
|
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue