1 macro_rules! tags {
2     {
3         // Permit arbitrary meta items, which include documentation.
4         $( #[$enum_attr:meta] )*
5         $vis:vis enum $name:ident($ty:tt) $(unknown($unknown_doc:literal))* {
6             // Each of the `Name = Val,` permitting documentation.
7             $($(#[$ident_attr:meta])* $tag:ident = $val:expr,)*
8         }
9     } => {
10         $( #[$enum_attr] )*
11         #[derive(Clone, Copy, PartialEq, Eq, Debug, Hash)]
12         pub enum $name {
13             $($(#[$ident_attr])* $tag,)*
14             // FIXME: switch to non_exhaustive once stabilized and compiler requirement new enough
15             #[doc(hidden)]
16             __NonExhaustive,
17             $(
18                 #[doc = $unknown_doc]
19                 Unknown($ty),
20             )*
21         }
22 
23         impl $name {
24             #[inline(always)]
25             fn __from_inner_type(n: $ty) -> Result<Self, $ty> {
26                 match n {
27                     $( $val => Ok($name::$tag), )*
28                     n => Err(n),
29                 }
30             }
31 
32             #[inline(always)]
33             fn __to_inner_type(&self) -> $ty {
34                 match *self {
35                     $( $name::$tag => $val, )*
36                     $( $name::Unknown(n) => { $unknown_doc; n }, )*
37                     $name::__NonExhaustive => unreachable!(),
38                 }
39             }
40         }
41 
42         tags!($name, $ty);
43     };
44     // For u16 tags, provide direct inherent primitive conversion methods.
45     ($name:tt, u16) => {
46         impl $name {
47             #[inline(always)]
48             pub fn from_u16(val: u16) -> Option<Self> {
49                 Self::__from_inner_type(val).ok()
50             }
51 
52             #[inline(always)]
53             pub fn to_u16(&self) -> u16 {
54                 Self::__to_inner_type(self)
55             }
56         }
57     };
58     // For other tag types, do nothing for now. With concat_idents one could
59     // provide inherent conversion methods for all types.
60     ($name:tt, $ty:tt) => {};
61 }
62 
63 // Note: These tags appear in the order they are mentioned in the TIFF reference
64 tags! {
65 /// TIFF tags
66 pub enum Tag(u16) unknown("A private or extension tag") {
67     // Baseline tags:
68     Artist = 315,
69     // grayscale images PhotometricInterpretation 1 or 3
70     BitsPerSample = 258,
71     CellLength = 265, // TODO add support
72     CellWidth = 264, // TODO add support
73     // palette-color images (PhotometricInterpretation 3)
74     ColorMap = 320, // TODO add support
75     Compression = 259, // TODO add support for 2 and 32773
76     Copyright = 33_432,
77     DateTime = 306,
78     ExtraSamples = 338, // TODO add support
79     FillOrder = 266, // TODO add support
80     FreeByteCounts = 289, // TODO add support
81     FreeOffsets = 288, // TODO add support
82     GrayResponseCurve = 291, // TODO add support
83     GrayResponseUnit = 290, // TODO add support
84     HostComputer = 316,
85     ImageDescription = 270,
86     ImageLength = 257,
87     ImageWidth = 256,
88     Make = 271,
89     MaxSampleValue = 281, // TODO add support
90     MinSampleValue = 280, // TODO add support
91     Model = 272,
92     NewSubfileType = 254, // TODO add support
93     Orientation = 274, // TODO add support
94     PhotometricInterpretation = 262,
95     PlanarConfiguration = 284,
96     ResolutionUnit = 296, // TODO add support
97     RowsPerStrip = 278,
98     SamplesPerPixel = 277,
99     Software = 305,
100     StripByteCounts = 279,
101     StripOffsets = 273,
102     SubfileType = 255, // TODO add support
103     Threshholding = 263, // TODO add support
104     XResolution = 282,
105     YResolution = 283,
106     // Advanced tags
107     Predictor = 317,
108 }
109 }
110 
111 impl Tag {
from_u16_exhaustive(val: u16) -> Self112     pub fn from_u16_exhaustive(val: u16) -> Self {
113         Self::from_u16(val).unwrap_or_else(|| Tag::Unknown(val))
114     }
115 }
116 
117 tags! {
118 /// The type of an IFD entry (a 2 byte field).
119 pub enum Type(u16) {
120     BYTE = 1,
121     ASCII = 2,
122     SHORT = 3,
123     LONG = 4,
124     RATIONAL = 5,
125     SBYTE = 6,
126     SSHORT = 8,
127     SLONG = 9,
128     SRATIONAL = 10,
129     /// BigTIFF 64-bit unsigned integer
130     LONG8 = 16,
131 }
132 }
133 
134 
135 tags! {
136 pub enum CompressionMethod(u16) {
137     None = 1,
138     Huffman = 2,
139     Fax3 = 3,
140     Fax4 = 4,
141     LZW = 5,
142     JPEG = 6,
143     Deflate = 8,
144     OldDeflate = 0x80B2,
145     PackBits = 0x8005,
146 }
147 }
148 
149 tags! {
150 pub enum PhotometricInterpretation(u16) {
151     WhiteIsZero = 0,
152     BlackIsZero = 1,
153     RGB = 2,
154     RGBPalette = 3,
155     TransparencyMask = 4,
156     CMYK = 5,
157     YCbCr = 6,
158     CIELab = 8,
159 }
160 }
161 
162 tags! {
163 pub enum PlanarConfiguration(u16) {
164     Chunky = 1,
165     Planar = 2,
166 }
167 }
168 
169 tags! {
170 pub enum Predictor(u16) {
171     None = 1,
172     Horizontal = 2,
173 }
174 }
175 
176 tags!{
177 /// Type to represent resolution units
178 pub enum ResolutionUnit(u16) {
179     None = 1,
180     Inch = 2,
181     Centimeter = 3,
182 }
183 }