Skip to main content

async_tiff/
tag_value.rs

1use self::TagValue::{
2    Ascii, Byte, Double, Float, Ifd, IfdBig, List, Rational, RationalBig, SRational, SRationalBig,
3    Short, Signed, SignedBig, SignedByte, SignedShort, Unsigned, UnsignedBig,
4};
5use crate::error::{TiffError, TiffFormatError, TiffResult};
6// use super::error::{TiffError, TiffFormatError, TiffResult};
7
8/// A dynamically-typed value parsed from a TIFF IFD entry.
9///
10/// Each variant corresponds to one of the TIFF data types. Multi-value entries are represented
11/// as [`TagValue::List`].
12///
13/// Conversion methods like [`into_u16`](TagValue::into_u16) and
14/// [`into_f64_vec`](TagValue::into_f64_vec) handle widening casts and return an error on
15/// type mismatches.
16#[derive(Debug, Clone, PartialEq)]
17#[non_exhaustive]
18pub enum TagValue {
19    /// 8-bit unsigned integer (TIFF type BYTE).
20    Byte(u8),
21    /// 16-bit unsigned integer (TIFF type SHORT).
22    Short(u16),
23    /// 8-bit signed integer (TIFF type SBYTE).
24    SignedByte(i8),
25    /// 16-bit signed integer (TIFF type SSHORT).
26    SignedShort(i16),
27    /// 32-bit signed integer (TIFF type SLONG).
28    Signed(i32),
29    /// 64-bit signed integer (BigTIFF type SLONG8).
30    SignedBig(i64),
31    /// 32-bit unsigned integer (TIFF type LONG).
32    Unsigned(u32),
33    /// 64-bit unsigned integer (BigTIFF type LONG8).
34    UnsignedBig(u64),
35    /// 32-bit IEEE floating point (TIFF type FLOAT).
36    Float(f32),
37    /// 64-bit IEEE floating point (TIFF type DOUBLE).
38    Double(f64),
39    /// A sequence of values from a multi-count IFD entry.
40    List(Vec<TagValue>),
41    /// Unsigned rational: numerator and denominator (TIFF type RATIONAL).
42    Rational(u32, u32),
43    /// Unsigned rational with 64-bit components (BigTIFF).
44    RationalBig(u64, u64),
45    /// Signed rational: numerator and denominator (TIFF type SRATIONAL).
46    SRational(i32, i32),
47    /// Signed rational with 64-bit components (BigTIFF).
48    SRationalBig(i64, i64),
49    /// ASCII string parsed from TIFF type ASCII
50    Ascii(String),
51    /// 32-bit IFD offset (TIFF type IFD).
52    Ifd(u32),
53    /// 64-bit IFD offset (BigTIFF type IFD8).
54    IfdBig(u64),
55}
56
57impl TagValue {
58    /// Convert this TagValue into a u8, returning an error if the type is incompatible.
59    pub fn into_u8(self) -> TiffResult<u8> {
60        match self {
61            Byte(val) => Ok(val),
62            val => Err(TiffError::FormatError(TiffFormatError::ByteExpected(val))),
63        }
64    }
65
66    /// Convert this TagValue into an i8, returning an error if the type is incompatible.
67    pub fn into_i8(self) -> TiffResult<i8> {
68        match self {
69            SignedByte(val) => Ok(val),
70            val => Err(TiffError::FormatError(TiffFormatError::SignedByteExpected(
71                val,
72            ))),
73        }
74    }
75
76    /// Convert this TagValue into a u16, returning an error if the type is incompatible.
77    pub fn into_u16(self) -> TiffResult<u16> {
78        match self {
79            Byte(val) => Ok(val.into()),
80            Short(val) => Ok(val),
81            Unsigned(val) => Ok(u16::try_from(val)?),
82            UnsignedBig(val) => Ok(u16::try_from(val)?),
83            val => Err(TiffError::FormatError(TiffFormatError::ShortExpected(val))),
84        }
85    }
86
87    /// Convert this TagValue into an i16, returning an error if the type is incompatible.
88    pub fn into_i16(self) -> TiffResult<i16> {
89        match self {
90            SignedByte(val) => Ok(val.into()),
91            SignedShort(val) => Ok(val),
92            Signed(val) => Ok(i16::try_from(val)?),
93            SignedBig(val) => Ok(i16::try_from(val)?),
94            val => Err(TiffError::FormatError(
95                TiffFormatError::SignedShortExpected(val),
96            )),
97        }
98    }
99
100    /// Convert this TagValue into a u32, returning an error if the type is incompatible.
101    pub fn into_u32(self) -> TiffResult<u32> {
102        match self {
103            Byte(val) => Ok(val.into()),
104            Short(val) => Ok(val.into()),
105            Unsigned(val) => Ok(val),
106            UnsignedBig(val) => Ok(u32::try_from(val)?),
107            Ifd(val) => Ok(val),
108            IfdBig(val) => Ok(u32::try_from(val)?),
109            val => Err(TiffError::FormatError(
110                TiffFormatError::UnsignedIntegerExpected(val),
111            )),
112        }
113    }
114
115    /// Convert this TagValue into an i32, returning an error if the type is incompatible.
116    pub fn into_i32(self) -> TiffResult<i32> {
117        match self {
118            SignedByte(val) => Ok(val.into()),
119            SignedShort(val) => Ok(val.into()),
120            Signed(val) => Ok(val),
121            SignedBig(val) => Ok(i32::try_from(val)?),
122            val => Err(TiffError::FormatError(
123                TiffFormatError::SignedIntegerExpected(val),
124            )),
125        }
126    }
127
128    /// Convert this TagValue into a u64, returning an error if the type is incompatible.
129    pub fn into_u64(self) -> TiffResult<u64> {
130        match self {
131            Byte(val) => Ok(val.into()),
132            Short(val) => Ok(val.into()),
133            Unsigned(val) => Ok(val.into()),
134            UnsignedBig(val) => Ok(val),
135            Ifd(val) => Ok(val.into()),
136            IfdBig(val) => Ok(val),
137            val => Err(TiffError::FormatError(
138                TiffFormatError::UnsignedIntegerExpected(val),
139            )),
140        }
141    }
142
143    /// Convert this TagValue into an i64, returning an error if the type is incompatible.
144    pub fn into_i64(self) -> TiffResult<i64> {
145        match self {
146            SignedByte(val) => Ok(val.into()),
147            SignedShort(val) => Ok(val.into()),
148            Signed(val) => Ok(val.into()),
149            SignedBig(val) => Ok(val),
150            val => Err(TiffError::FormatError(
151                TiffFormatError::SignedIntegerExpected(val),
152            )),
153        }
154    }
155
156    /// Convert this TagValue into a f32, returning an error if the type is incompatible.
157    pub fn into_f32(self) -> TiffResult<f32> {
158        match self {
159            Float(val) => Ok(val),
160            val => Err(TiffError::FormatError(
161                TiffFormatError::SignedIntegerExpected(val),
162            )),
163        }
164    }
165
166    /// Convert this TagValue into a f64, returning an error if the type is incompatible.
167    pub fn into_f64(self) -> TiffResult<f64> {
168        match self {
169            Double(val) => Ok(val),
170            val => Err(TiffError::FormatError(
171                TiffFormatError::SignedIntegerExpected(val),
172            )),
173        }
174    }
175
176    /// Convert this TagValue into a String, returning an error if the type is incompatible.
177    pub fn into_string(self) -> TiffResult<String> {
178        match self {
179            Ascii(val) => Ok(val),
180            val => Err(TiffError::FormatError(
181                TiffFormatError::SignedIntegerExpected(val),
182            )),
183        }
184    }
185
186    /// Convert this TagValue into a `Vec<u32>`, returning an error if the type is incompatible.
187    pub fn into_u32_vec(self) -> TiffResult<Vec<u32>> {
188        match self {
189            List(vec) => {
190                let mut new_vec = Vec::with_capacity(vec.len());
191                for v in vec {
192                    new_vec.push(v.into_u32()?)
193                }
194                Ok(new_vec)
195            }
196            Byte(val) => Ok(vec![val.into()]),
197            Short(val) => Ok(vec![val.into()]),
198            Unsigned(val) => Ok(vec![val]),
199            UnsignedBig(val) => Ok(vec![u32::try_from(val)?]),
200            Rational(numerator, denominator) => Ok(vec![numerator, denominator]),
201            RationalBig(numerator, denominator) => {
202                Ok(vec![u32::try_from(numerator)?, u32::try_from(denominator)?])
203            }
204            Ifd(val) => Ok(vec![val]),
205            IfdBig(val) => Ok(vec![u32::try_from(val)?]),
206            Ascii(val) => Ok(val.chars().map(u32::from).collect()),
207            val => Err(TiffError::FormatError(
208                TiffFormatError::UnsignedIntegerExpected(val),
209            )),
210        }
211    }
212
213    /// Convert this TagValue into a `Vec<u8>`, returning an error if the type is incompatible.
214    pub fn into_u8_vec(self) -> TiffResult<Vec<u8>> {
215        match self {
216            List(vec) => {
217                let mut new_vec = Vec::with_capacity(vec.len());
218                for v in vec {
219                    new_vec.push(v.into_u8()?)
220                }
221                Ok(new_vec)
222            }
223            Byte(val) => Ok(vec![val]),
224            val => Err(TiffError::FormatError(TiffFormatError::ByteExpected(val))),
225        }
226    }
227
228    /// Convert this TagValue into a `Vec<u16>`, returning an error if the type is incompatible.
229    pub fn into_u16_vec(self) -> TiffResult<Vec<u16>> {
230        match self {
231            List(vec) => {
232                let mut new_vec = Vec::with_capacity(vec.len());
233                for v in vec {
234                    new_vec.push(v.into_u16()?)
235                }
236                Ok(new_vec)
237            }
238            Byte(val) => Ok(vec![val.into()]),
239            Short(val) => Ok(vec![val]),
240            val => Err(TiffError::FormatError(TiffFormatError::ShortExpected(val))),
241        }
242    }
243
244    /// Convert this TagValue into a `Vec<i32>`, returning an error if the type is incompatible.
245    pub fn into_i32_vec(self) -> TiffResult<Vec<i32>> {
246        match self {
247            List(vec) => {
248                let mut new_vec = Vec::with_capacity(vec.len());
249                for v in vec {
250                    match v {
251                        SRational(numerator, denominator) => {
252                            new_vec.push(numerator);
253                            new_vec.push(denominator);
254                        }
255                        SRationalBig(numerator, denominator) => {
256                            new_vec.push(i32::try_from(numerator)?);
257                            new_vec.push(i32::try_from(denominator)?);
258                        }
259                        _ => new_vec.push(v.into_i32()?),
260                    }
261                }
262                Ok(new_vec)
263            }
264            SignedByte(val) => Ok(vec![val.into()]),
265            SignedShort(val) => Ok(vec![val.into()]),
266            Signed(val) => Ok(vec![val]),
267            SignedBig(val) => Ok(vec![i32::try_from(val)?]),
268            SRational(numerator, denominator) => Ok(vec![numerator, denominator]),
269            SRationalBig(numerator, denominator) => {
270                Ok(vec![i32::try_from(numerator)?, i32::try_from(denominator)?])
271            }
272            val => Err(TiffError::FormatError(
273                TiffFormatError::SignedIntegerExpected(val),
274            )),
275        }
276    }
277
278    /// Convert this TagValue into a `Vec<f32>`, returning an error if the type is incompatible.
279    pub fn into_f32_vec(self) -> TiffResult<Vec<f32>> {
280        match self {
281            List(vec) => {
282                let mut new_vec = Vec::with_capacity(vec.len());
283                for v in vec {
284                    new_vec.push(v.into_f32()?)
285                }
286                Ok(new_vec)
287            }
288            Float(val) => Ok(vec![val]),
289            val => Err(TiffError::FormatError(
290                TiffFormatError::UnsignedIntegerExpected(val),
291            )),
292        }
293    }
294
295    /// Convert this TagValue into a `Vec<f64>`, returning an error if the type is incompatible.
296    pub fn into_f64_vec(self) -> TiffResult<Vec<f64>> {
297        match self {
298            List(vec) => {
299                let mut new_vec = Vec::with_capacity(vec.len());
300                for v in vec {
301                    new_vec.push(v.into_f64()?)
302                }
303                Ok(new_vec)
304            }
305            Double(val) => Ok(vec![val]),
306            val => Err(TiffError::FormatError(
307                TiffFormatError::UnsignedIntegerExpected(val),
308            )),
309        }
310    }
311
312    /// Convert this TagValue into a `Vec<u64>`, returning an error if the type is incompatible.
313    pub fn into_u64_vec(self) -> TiffResult<Vec<u64>> {
314        match self {
315            List(vec) => {
316                let mut new_vec = Vec::with_capacity(vec.len());
317                for v in vec {
318                    new_vec.push(v.into_u64()?)
319                }
320                Ok(new_vec)
321            }
322            Byte(val) => Ok(vec![val.into()]),
323            Short(val) => Ok(vec![val.into()]),
324            Unsigned(val) => Ok(vec![val.into()]),
325            UnsignedBig(val) => Ok(vec![val]),
326            Rational(numerator, denominator) => Ok(vec![numerator.into(), denominator.into()]),
327            RationalBig(numerator, denominator) => Ok(vec![numerator, denominator]),
328            Ifd(val) => Ok(vec![val.into()]),
329            IfdBig(val) => Ok(vec![val]),
330            Ascii(val) => Ok(val.chars().map(u32::from).map(u64::from).collect()),
331            val => Err(TiffError::FormatError(
332                TiffFormatError::UnsignedIntegerExpected(val),
333            )),
334        }
335    }
336
337    /// Convert this TagValue into a `Vec<i64>`, returning an error if the type is incompatible.
338    pub fn into_i64_vec(self) -> TiffResult<Vec<i64>> {
339        match self {
340            List(vec) => {
341                let mut new_vec = Vec::with_capacity(vec.len());
342                for v in vec {
343                    match v {
344                        SRational(numerator, denominator) => {
345                            new_vec.push(numerator.into());
346                            new_vec.push(denominator.into());
347                        }
348                        SRationalBig(numerator, denominator) => {
349                            new_vec.push(numerator);
350                            new_vec.push(denominator);
351                        }
352                        _ => new_vec.push(v.into_i64()?),
353                    }
354                }
355                Ok(new_vec)
356            }
357            SignedByte(val) => Ok(vec![val.into()]),
358            SignedShort(val) => Ok(vec![val.into()]),
359            Signed(val) => Ok(vec![val.into()]),
360            SignedBig(val) => Ok(vec![val]),
361            SRational(numerator, denominator) => Ok(vec![numerator.into(), denominator.into()]),
362            SRationalBig(numerator, denominator) => Ok(vec![numerator, denominator]),
363            val => Err(TiffError::FormatError(
364                TiffFormatError::SignedIntegerExpected(val),
365            )),
366        }
367    }
368}