Skip to main content

rustiff/
tag.rs

1
2use std::fmt::{
3    self,
4    Display,
5};
6use std::io::{
7    Read,
8    Seek,
9};
10use error::{
11    DecodeResult,
12    DecodeError,
13    DecodeErrorKind,
14};
15use ifd::DataType;
16use byte::{
17    Endian,
18    EndianReadExt,
19    SeekExt,
20};
21
22pub trait TagType: Clone + Copy {
23    type Value;
24
25    fn id(&self) -> u16;
26    fn default_value() -> Option<Self::Value>;
27    fn decode<'a, R: Read + Seek + 'a>(&'a self, reader: R, offset: &'a [u8], endian: Endian, datatype: DataType, count: usize) -> DecodeResult<Self::Value>;
28}
29
30macro_rules! define_tags {
31    ($($name:ident, $id:expr;)*) => {
32        $(#[derive(Debug, Clone, Copy, PartialEq, Eq, Fail)]
33        pub struct $name;
34
35        impl Display for $name {
36            fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
37                write!(f, "{}", $name)
38            }
39        })*
40        
41        #[derive(Debug, Fail)]
42        pub enum AnyTag {
43            $($name,)*
44            Unknown(u16),
45        }
46
47        impl AnyTag {
48            pub fn id(&self) -> u16 {
49                match *self {
50                    $(AnyTag::$name => $id,)*
51                    AnyTag::Unknown(n) => n,
52                }
53            }
54        }
55
56        impl Display for AnyTag {
57            fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
58                match *self {
59                    $(AnyTag::$name => $name.fmt(f),)*
60                    AnyTag::Unknown(n) => write!(f, "Unknown tag: {}", n),
61                }
62            }
63        }
64
65        impl<T> From<T> for AnyTag where T: TagType {
66            fn from(x: T) -> AnyTag {
67                match x.id() {
68                    $($id => AnyTag::$name,)*
69                    _ => AnyTag::Unknown(x.id()),
70                }
71            }
72        }
73
74        impl From<u16> for AnyTag {
75            fn from(n: u16) -> AnyTag {
76                match n {
77                    $($id => AnyTag::$name,)*
78                    _ => AnyTag::Unknown(n),
79                }
80            }
81        }
82    }
83}
84
85macro_rules! tag_short_or_long_value {
86    ($($name:ident, $id:expr, $def:expr;)*) => {
87        $(impl TagType for $name {
88            type Value = u32;
89
90            fn id(&self) -> u16 { $id }
91            fn default_value() -> Option<u32> { $def }
92            fn decode<'a, R: Read + Seek + 'a>(&'a self, mut _reader: R, mut offset: &'a [u8], endian: Endian, datatype: DataType, count: usize) -> DecodeResult<Self::Value> {
93                match datatype {
94                    DataType::Short if count == 1 => Ok(offset.read_u16(endian)? as u32),
95                    DataType::Long if count == 1 => Ok(offset.read_u32(endian)?),
96                    _ => Err(DecodeError::from(DecodeErrorKind::NoSupportDataType { tag: AnyTag::from(*self), datatype: datatype, count: count })),
97                }
98            }
99        })*
100    };
101}
102
103macro_rules! tag_short_value {
104    ($($name:ident, $id:expr, $def:expr;)*) => {
105        $(impl TagType for $name {
106            type Value = u16;
107
108            fn id(&self) -> u16 { $id }
109            fn default_value() -> Option<u16> { $def }
110            fn decode<'a, R: Read + Seek + 'a>(&'a self, mut _reader: R, mut offset: &'a [u8], endian: Endian, datatype: DataType, count: usize) -> DecodeResult<Self::Value> {
111                match datatype {
112                    DataType::Short if count == 1 => Ok(offset.read_u16(endian)?),
113                    _ => Err(DecodeError::from(DecodeErrorKind::NoSupportDataType { tag: AnyTag::from(*self), datatype: datatype, count: count })),
114                }
115            }
116        })*
117    };
118}
119
120macro_rules! tag_short_or_long_values {
121    ($($name:ident, $id:expr, $def:expr;)*) => {
122        $(impl TagType for $name {
123            type Value = Vec<u32>;
124
125            fn id(&self) -> u16 { $id }
126            fn default_value() -> Option<Vec<u32>> { $def }
127            fn decode<'a, R: Read + Seek + 'a>(&'a self, mut reader: R, mut offset: &'a [u8], endian: Endian, datatype: DataType, count: usize) -> DecodeResult<Self::Value> {
128                match datatype {
129                    DataType::Short if count == 1 => Ok(vec![offset.read_u16(endian)? as u32]),
130                    DataType::Short if count == 2 => Ok(vec![
131                        offset.read_u16(endian)? as u32,
132                        offset.read_u16(endian)? as u32,
133                    ]),
134                    DataType::Short if count > 2 => {
135                        let offset = offset.read_u32(endian)? as u64;
136                        reader.goto(offset)?;
137                        let mut v = Vec::with_capacity(count);
138                        for _ in 0..count {
139                            v.push(reader.read_u16(endian)? as u32);
140                        }
141
142                        Ok(v)
143                    }
144                    DataType::Long if count == 1 => Ok(vec![offset.read_u32(endian)?]),
145                    DataType::Long if count > 1 => {
146                        let offset = offset.read_u32(endian)? as u64;
147                        reader.goto(offset)?;
148                        let mut v = Vec::with_capacity(count);
149                        for _ in 0..count {
150                            v.push(reader.read_u32(endian)?);
151                        }
152
153                        Ok(v)
154                    }
155                    _ => Err(DecodeError::from(DecodeErrorKind::NoSupportDataType { tag: AnyTag::from(*self), datatype: datatype, count: count })),
156                }
157            }
158        })*
159    };
160}
161
162macro_rules! tag_short_values {
163    ($($name:ident, $id:expr, $def:expr;)*) => {
164        $(impl TagType for $name {
165            type Value = Vec<u16>;
166
167            fn id(&self) -> u16 { $id }
168            fn default_value() -> Option<Vec<u16>> { $def }
169            fn decode<'a, R: Read + Seek + 'a>(&'a self, mut reader: R, mut offset: &'a [u8], endian: Endian, datatype: DataType, count: usize) -> DecodeResult<Self::Value> {
170                match datatype {
171                    DataType::Short if count == 1 => Ok(vec![offset.read_u16(endian)?]),
172                    DataType::Short if count == 2 => Ok(vec![
173                        offset.read_u16(endian)?,
174                        offset.read_u16(endian)?,
175                    ]),
176                    DataType::Short if count > 2 => {
177                        let offset = offset.read_u32(endian)? as u64;
178                        reader.goto(offset)?;
179                        let mut v = Vec::with_capacity(count);
180                        for _ in 0..count {
181                            v.push(reader.read_u16(endian)?);
182                        }
183
184                        Ok(v)
185                    }
186                    _ => Err(DecodeError::from(DecodeErrorKind::NoSupportDataType { tag: AnyTag::from(*self), datatype: datatype, count: count })),
187                }
188            }
189        })*
190    };
191}
192
193define_tags! {
194    ImageWidth, 256;
195    ImageLength, 257;
196    BitsPerSample, 258;
197    Compression, 259;
198    PhotometricInterpretation, 262;
199    StripOffsets, 273;
200    SamplesPerPixel, 277;
201    RowsPerStrip, 278;
202    StripByteCounts, 279;
203}
204
205tag_short_or_long_value! {
206    ImageWidth, 256, None;
207    ImageLength, 257, None;
208    RowsPerStrip, 278, Some(u32::max_value());
209}
210
211tag_short_or_long_values! {
212    StripOffsets, 273, None;
213    StripByteCounts, 279, None;
214}
215
216tag_short_value! {
217    PhotometricInterpretation, 262, None;
218    Compression, 259, Some(1);
219    SamplesPerPixel, 277, Some(1);
220}
221
222tag_short_values! {
223    BitsPerSample, 258, Some(vec![1]);
224}
225
226