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