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, $($unknown_doc)*);
43     };
44     // For u16 tags, provide direct inherent primitive conversion methods.
45     ($name:tt, u16, $($unknown_doc:literal)*) => {
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             $(
53             #[inline(always)]
54             pub fn from_u16_exhaustive(val: u16) -> Self {
55                 $unknown_doc;
56                 Self::__from_inner_type(val).unwrap_or_else(|_| $name::Unknown(val))
57             }
58             )*
59 
60             #[inline(always)]
61             pub fn to_u16(&self) -> u16 {
62                 Self::__to_inner_type(self)
63             }
64         }
65     };
66     // For other tag types, do nothing for now. With concat_idents one could
67     // provide inherent conversion methods for all types.
68     ($name:tt, $ty:tt, $($unknown_doc:literal)*) => {};
69 }
70 
71 // Note: These tags appear in the order they are mentioned in the TIFF reference
72 tags! {
73 /// TIFF tags
74 pub enum Tag(u16) unknown("A private or extension tag") {
75     // Baseline tags:
76     Artist = 315,
77     // grayscale images PhotometricInterpretation 1 or 3
78     BitsPerSample = 258,
79     CellLength = 265, // TODO add support
80     CellWidth = 264, // TODO add support
81     // palette-color images (PhotometricInterpretation 3)
82     ColorMap = 320, // TODO add support
83     Compression = 259, // TODO add support for 2 and 32773
84     Copyright = 33_432,
85     DateTime = 306,
86     ExtraSamples = 338, // TODO add support
87     FillOrder = 266, // TODO add support
88     FreeByteCounts = 289, // TODO add support
89     FreeOffsets = 288, // TODO add support
90     GrayResponseCurve = 291, // TODO add support
91     GrayResponseUnit = 290, // TODO add support
92     HostComputer = 316,
93     ImageDescription = 270,
94     ImageLength = 257,
95     ImageWidth = 256,
96     Make = 271,
97     MaxSampleValue = 281, // TODO add support
98     MinSampleValue = 280, // TODO add support
99     Model = 272,
100     NewSubfileType = 254, // TODO add support
101     Orientation = 274, // TODO add support
102     PhotometricInterpretation = 262,
103     PlanarConfiguration = 284,
104     ResolutionUnit = 296, // TODO add support
105     RowsPerStrip = 278,
106     SamplesPerPixel = 277,
107     Software = 305,
108     StripByteCounts = 279,
109     StripOffsets = 273,
110     SubfileType = 255, // TODO add support
111     Threshholding = 263, // TODO add support
112     XResolution = 282,
113     YResolution = 283,
114     // JPEG
115     JPEGTables = 347,
116     // Advanced tags
117     Predictor = 317,
118     TileWidth = 322,
119     TileLength = 323,
120     TileOffsets = 324,
121     TileByteCounts = 325,
122     SampleFormat = 339,
123     // GeoTIFF
124     ModelPixelScaleTag = 33550, // (SoftDesk)
125     ModelTransformationTag = 34264, // (JPL Carto Group)
126     ModelTiepointTag = 33922, // (Intergraph)
127     GeoKeyDirectoryTag = 34735, // (SPOT)
128     GeoDoubleParamsTag = 34736, // (SPOT)
129     GeoAsciiParamsTag = 34737, // (SPOT)
130     GdalNodata = 42113, // Contains areas with missing data
131 }
132 }
133 
134 tags! {
135 /// The type of an IFD entry (a 2 byte field).
136 pub enum Type(u16) {
137     BYTE = 1,
138     ASCII = 2,
139     SHORT = 3,
140     LONG = 4,
141     RATIONAL = 5,
142     SBYTE = 6,
143     UNDEFINED = 7,
144     SSHORT = 8,
145     SLONG = 9,
146     SRATIONAL = 10,
147     FLOAT = 11,
148     DOUBLE = 12,
149     /// BigTIFF 64-bit unsigned integer
150     LONG8 = 16,
151 }
152 }
153 
154 tags! {
155 /// See [TIFF compression tags](https://www.awaresystems.be/imaging/tiff/tifftags/compression.html)
156 /// for reference.
157 pub enum CompressionMethod(u16) {
158     None = 1,
159     Huffman = 2,
160     Fax3 = 3,
161     Fax4 = 4,
162     LZW = 5,
163     JPEG = 6,
164     // "Extended JPEG" or "new JPEG" style
165     ModernJPEG = 7,
166     Deflate = 8,
167     OldDeflate = 0x80B2,
168     PackBits = 0x8005,
169 }
170 }
171 
172 tags! {
173 pub enum PhotometricInterpretation(u16) {
174     WhiteIsZero = 0,
175     BlackIsZero = 1,
176     RGB = 2,
177     RGBPalette = 3,
178     TransparencyMask = 4,
179     CMYK = 5,
180     YCbCr = 6,
181     CIELab = 8,
182 }
183 }
184 
185 tags! {
186 pub enum PlanarConfiguration(u16) {
187     Chunky = 1,
188     Planar = 2,
189 }
190 }
191 
192 tags! {
193 pub enum Predictor(u16) {
194     None = 1,
195     Horizontal = 2,
196 }
197 }
198 
199 tags! {
200 /// Type to represent resolution units
201 pub enum ResolutionUnit(u16) {
202     None = 1,
203     Inch = 2,
204     Centimeter = 3,
205 }
206 }
207 
208 tags! {
209 pub enum SampleFormat(u16) unknown("An unknown extension sample format") {
210     Uint = 1,
211     Int = 2,
212     IEEEFP = 3,
213     Void = 4,
214 }
215 }
216