1use crate::error::{Error, Result};
2use crate::header::ByteOrder;
3use crate::io::Cursor;
4use crate::source::TiffSource;
5
6#[derive(Debug, Clone, Copy, PartialEq, Eq)]
8pub enum TagType {
9 Byte, Ascii, Short, Long, Rational, SByte, Undefined, SShort, SLong, SRational, Float, Double, Long8, SLong8, Ifd8, Unknown(u16),
25}
26
27impl TagType {
28 pub fn from_code(code: u16) -> Self {
29 match code {
30 1 => Self::Byte,
31 2 => Self::Ascii,
32 3 => Self::Short,
33 4 => Self::Long,
34 5 => Self::Rational,
35 6 => Self::SByte,
36 7 => Self::Undefined,
37 8 => Self::SShort,
38 9 => Self::SLong,
39 10 => Self::SRational,
40 11 => Self::Float,
41 12 => Self::Double,
42 16 => Self::Long8,
43 17 => Self::SLong8,
44 18 => Self::Ifd8,
45 _ => Self::Unknown(code),
46 }
47 }
48
49 pub fn element_size(&self) -> usize {
51 match self {
52 Self::Byte | Self::Ascii | Self::SByte | Self::Undefined => 1,
53 Self::Short | Self::SShort => 2,
54 Self::Long | Self::SLong | Self::Float => 4,
55 Self::Rational
56 | Self::SRational
57 | Self::Double
58 | Self::Long8
59 | Self::SLong8
60 | Self::Ifd8 => 8,
61 Self::Unknown(_) => 1,
62 }
63 }
64}
65
66#[derive(Debug, Clone)]
68pub struct Tag {
69 pub code: u16,
70 pub tag_type: TagType,
71 pub count: u64,
72 pub value: TagValue,
73}
74
75#[derive(Debug, Clone)]
77pub enum TagValue {
78 Byte(Vec<u8>),
79 Ascii(String),
80 Short(Vec<u16>),
81 Long(Vec<u32>),
82 Rational(Vec<[u32; 2]>),
83 SByte(Vec<i8>),
84 Undefined(Vec<u8>),
85 SShort(Vec<i16>),
86 SLong(Vec<i32>),
87 SRational(Vec<[i32; 2]>),
88 Float(Vec<f32>),
89 Double(Vec<f64>),
90 Long8(Vec<u64>),
91 SLong8(Vec<i64>),
92}
93
94impl TagValue {
95 pub fn as_u16(&self) -> Option<u16> {
97 match self {
98 Self::Short(v) => v.first().copied(),
99 Self::Byte(v) => v.first().map(|&b| b as u16),
100 Self::Long(v) => v.first().map(|&l| l as u16),
101 _ => None,
102 }
103 }
104
105 pub fn as_u32(&self) -> Option<u32> {
107 match self {
108 Self::Long(v) => v.first().copied(),
109 Self::Short(v) => v.first().map(|&s| s as u32),
110 Self::Long8(v) => v.first().map(|&l| l as u32),
111 _ => None,
112 }
113 }
114
115 pub fn as_u64(&self) -> Option<u64> {
117 match self {
118 Self::Long8(v) => v.first().copied(),
119 Self::Long(v) => v.first().map(|&l| l as u64),
120 Self::Short(v) => v.first().map(|&s| s as u64),
121 _ => None,
122 }
123 }
124
125 pub fn as_f64(&self) -> Option<f64> {
127 match self {
128 Self::Double(v) => v.first().copied(),
129 Self::Float(v) => v.first().map(|&f| f as f64),
130 Self::Long(v) => v.first().map(|&l| l as f64),
131 Self::Short(v) => v.first().map(|&s| s as f64),
132 _ => None,
133 }
134 }
135
136 pub fn as_str(&self) -> Option<&str> {
138 match self {
139 Self::Ascii(s) => Some(s.as_str()),
140 _ => None,
141 }
142 }
143
144 pub fn as_bytes(&self) -> Option<&[u8]> {
146 match self {
147 Self::Byte(v) | Self::Undefined(v) => Some(v.as_slice()),
148 _ => None,
149 }
150 }
151
152 pub fn as_f64_vec(&self) -> Option<Vec<f64>> {
154 match self {
155 Self::Double(v) => Some(v.clone()),
156 Self::Float(v) => Some(v.iter().map(|&f| f as f64).collect()),
157 _ => None,
158 }
159 }
160
161 pub fn as_u64_vec(&self) -> Option<Vec<u64>> {
163 match self {
164 Self::Byte(v) => Some(v.iter().map(|&x| x as u64).collect()),
165 Self::Short(v) => Some(v.iter().map(|&x| x as u64).collect()),
166 Self::Long(v) => Some(v.iter().map(|&x| x as u64).collect()),
167 Self::Long8(v) => Some(v.clone()),
168 _ => None,
169 }
170 }
171
172 pub fn as_u16_slice(&self) -> Option<&[u16]> {
174 match self {
175 Self::Short(v) => Some(v.as_slice()),
176 _ => None,
177 }
178 }
179}
180
181impl Tag {
182 pub fn parse_classic(
184 code: u16,
185 type_code: u16,
186 count: u64,
187 value_offset_bytes: &[u8],
188 source: &dyn TiffSource,
189 byte_order: ByteOrder,
190 ) -> Result<Self> {
191 let tag_type = TagType::from_code(type_code);
192 let total_size = value_len(code, count, tag_type.element_size())?;
193
194 let owned;
195 let value_bytes = if total_size <= 4 {
196 &value_offset_bytes[..total_size]
197 } else {
198 let offset = match byte_order {
199 ByteOrder::LittleEndian => {
200 u32::from_le_bytes(value_offset_bytes.try_into().unwrap())
201 }
202 ByteOrder::BigEndian => u32::from_be_bytes(value_offset_bytes.try_into().unwrap()),
203 } as u64;
204 owned = read_value_bytes(source, offset, total_size)?;
205 owned.as_slice()
206 };
207
208 let value = decode_value(&tag_type, count, value_bytes, byte_order)?;
209 Ok(Self {
210 code,
211 tag_type,
212 count,
213 value,
214 })
215 }
216
217 pub fn parse_bigtiff(
219 code: u16,
220 type_code: u16,
221 count: u64,
222 value_offset_bytes: &[u8],
223 source: &dyn TiffSource,
224 byte_order: ByteOrder,
225 ) -> Result<Self> {
226 let tag_type = TagType::from_code(type_code);
227 let total_size = value_len(code, count, tag_type.element_size())?;
228
229 let owned;
230 let value_bytes = if total_size <= 8 {
231 &value_offset_bytes[..total_size]
232 } else {
233 let offset = match byte_order {
234 ByteOrder::LittleEndian => {
235 u64::from_le_bytes(value_offset_bytes.try_into().unwrap())
236 }
237 ByteOrder::BigEndian => u64::from_be_bytes(value_offset_bytes.try_into().unwrap()),
238 };
239 owned = read_value_bytes(source, offset, total_size)?;
240 owned.as_slice()
241 };
242
243 let value = decode_value(&tag_type, count, value_bytes, byte_order)?;
244 Ok(Self {
245 code,
246 tag_type,
247 count,
248 value,
249 })
250 }
251}
252
253fn read_value_bytes(source: &dyn TiffSource, offset: u64, len: usize) -> Result<Vec<u8>> {
254 if let Some(data) = source.as_slice() {
255 return Ok(slice_at(data, offset, len)?.to_vec());
256 }
257 source.read_exact_at(offset, len)
258}
259
260fn value_len(tag: u16, count: u64, element_size: usize) -> Result<usize> {
261 let count = usize::try_from(count).map_err(|_| Error::InvalidTagValue {
262 tag,
263 reason: "value count does not fit in memory".into(),
264 })?;
265 count
266 .checked_mul(element_size)
267 .ok_or_else(|| Error::InvalidTagValue {
268 tag,
269 reason: "value byte length overflows usize".into(),
270 })
271}
272
273fn slice_at(data: &[u8], offset: u64, len: usize) -> Result<&[u8]> {
274 let start = usize::try_from(offset).map_err(|_| Error::OffsetOutOfBounds {
275 offset,
276 length: len as u64,
277 data_len: data.len() as u64,
278 })?;
279 let end = start.checked_add(len).ok_or(Error::OffsetOutOfBounds {
280 offset,
281 length: len as u64,
282 data_len: data.len() as u64,
283 })?;
284 if end > data.len() {
285 return Err(Error::OffsetOutOfBounds {
286 offset,
287 length: len as u64,
288 data_len: data.len() as u64,
289 });
290 }
291 Ok(&data[start..end])
292}
293
294fn decode_value(
295 tag_type: &TagType,
296 count: u64,
297 bytes: &[u8],
298 byte_order: ByteOrder,
299) -> Result<TagValue> {
300 let mut cursor = Cursor::new(bytes, byte_order);
301 let n = count as usize;
302
303 Ok(match tag_type {
304 TagType::Byte | TagType::Unknown(_) => TagValue::Byte(cursor.read_bytes(n)?.to_vec()),
305 TagType::Ascii => {
306 let raw = cursor.read_bytes(n)?;
307 let s = String::from_utf8_lossy(raw)
308 .trim_end_matches('\0')
309 .to_string();
310 TagValue::Ascii(s)
311 }
312 TagType::Short => {
313 let mut v = Vec::with_capacity(n);
314 for _ in 0..n {
315 v.push(cursor.read_u16()?);
316 }
317 TagValue::Short(v)
318 }
319 TagType::Long => {
320 let mut v = Vec::with_capacity(n);
321 for _ in 0..n {
322 v.push(cursor.read_u32()?);
323 }
324 TagValue::Long(v)
325 }
326 TagType::Rational => {
327 let mut v = Vec::with_capacity(n);
328 for _ in 0..n {
329 let num = cursor.read_u32()?;
330 let den = cursor.read_u32()?;
331 v.push([num, den]);
332 }
333 TagValue::Rational(v)
334 }
335 TagType::SByte => {
336 let raw = cursor.read_bytes(n)?;
337 TagValue::SByte(raw.iter().map(|&b| b as i8).collect())
338 }
339 TagType::Undefined => TagValue::Undefined(cursor.read_bytes(n)?.to_vec()),
340 TagType::SShort => {
341 let mut v = Vec::with_capacity(n);
342 for _ in 0..n {
343 v.push(cursor.read_u16()? as i16);
344 }
345 TagValue::SShort(v)
346 }
347 TagType::SLong => {
348 let mut v = Vec::with_capacity(n);
349 for _ in 0..n {
350 v.push(cursor.read_u32()? as i32);
351 }
352 TagValue::SLong(v)
353 }
354 TagType::SRational => {
355 let mut v = Vec::with_capacity(n);
356 for _ in 0..n {
357 let num = cursor.read_u32()? as i32;
358 let den = cursor.read_u32()? as i32;
359 v.push([num, den]);
360 }
361 TagValue::SRational(v)
362 }
363 TagType::Float => {
364 let mut v = Vec::with_capacity(n);
365 for _ in 0..n {
366 let bits = cursor.read_u32()?;
367 v.push(f32::from_bits(bits));
368 }
369 TagValue::Float(v)
370 }
371 TagType::Double => {
372 let mut v = Vec::with_capacity(n);
373 for _ in 0..n {
374 v.push(cursor.read_f64()?);
375 }
376 TagValue::Double(v)
377 }
378 TagType::Long8 | TagType::Ifd8 => {
379 let mut v = Vec::with_capacity(n);
380 for _ in 0..n {
381 v.push(cursor.read_u64()?);
382 }
383 TagValue::Long8(v)
384 }
385 TagType::SLong8 => {
386 let mut v = Vec::with_capacity(n);
387 for _ in 0..n {
388 v.push(cursor.read_u64()? as i64);
389 }
390 TagValue::SLong8(v)
391 }
392 })
393}