1use gamut_core::{Error, Result};
4
5use crate::byte_order::ByteOrder;
6use crate::types::FieldType;
7
8#[derive(Debug, Clone, PartialEq)]
16pub enum Value {
17 Byte(Vec<u8>),
19 Ascii(String),
21 Short(Vec<u16>),
23 Long(Vec<u32>),
25 Rational(Vec<(u32, u32)>),
27 SByte(Vec<i8>),
29 Undefined(Vec<u8>),
31 SShort(Vec<i16>),
33 SLong(Vec<i32>),
35 SRational(Vec<(i32, i32)>),
37 Float(Vec<f32>),
39 Double(Vec<f64>),
41 #[cfg(feature = "bigtiff")]
43 Long8(Vec<u64>),
44 #[cfg(feature = "bigtiff")]
46 SLong8(Vec<i64>),
47 #[cfg(feature = "bigtiff")]
49 Ifd8(Vec<u64>),
50}
51
52impl Value {
53 #[must_use]
55 pub fn field_type(&self) -> FieldType {
56 match self {
57 Value::Byte(_) => FieldType::Byte,
58 Value::Ascii(_) => FieldType::Ascii,
59 Value::Short(_) => FieldType::Short,
60 Value::Long(_) => FieldType::Long,
61 Value::Rational(_) => FieldType::Rational,
62 Value::SByte(_) => FieldType::SByte,
63 Value::Undefined(_) => FieldType::Undefined,
64 Value::SShort(_) => FieldType::SShort,
65 Value::SLong(_) => FieldType::SLong,
66 Value::SRational(_) => FieldType::SRational,
67 Value::Float(_) => FieldType::Float,
68 Value::Double(_) => FieldType::Double,
69 #[cfg(feature = "bigtiff")]
70 Value::Long8(_) => FieldType::Long8,
71 #[cfg(feature = "bigtiff")]
72 Value::SLong8(_) => FieldType::SLong8,
73 #[cfg(feature = "bigtiff")]
74 Value::Ifd8(_) => FieldType::Ifd8,
75 }
76 }
77
78 #[must_use]
81 pub fn count(&self) -> usize {
82 match self {
83 Value::Byte(v) | Value::Undefined(v) => v.len(),
84 Value::Ascii(s) => s.len() + 1,
85 Value::Short(v) => v.len(),
86 Value::Long(v) => v.len(),
87 Value::Rational(v) => v.len(),
88 Value::SByte(v) => v.len(),
89 Value::SShort(v) => v.len(),
90 Value::SLong(v) => v.len(),
91 Value::SRational(v) => v.len(),
92 Value::Float(v) => v.len(),
93 Value::Double(v) => v.len(),
94 #[cfg(feature = "bigtiff")]
95 Value::Long8(v) | Value::Ifd8(v) => v.len(),
96 #[cfg(feature = "bigtiff")]
97 Value::SLong8(v) => v.len(),
98 }
99 }
100
101 #[must_use]
103 pub fn byte_len(&self) -> usize {
104 self.count() * self.field_type().size()
105 }
106
107 #[must_use]
114 pub fn as_u32(&self) -> Option<u32> {
115 match self {
116 Value::Byte(v) if v.len() == 1 => Some(u32::from(v[0])),
117 Value::Short(v) if v.len() == 1 => Some(u32::from(v[0])),
118 Value::Long(v) if v.len() == 1 => Some(v[0]),
119 #[cfg(feature = "bigtiff")]
120 Value::Long8(v) | Value::Ifd8(v) if v.len() == 1 => u32::try_from(v[0]).ok(),
121 _ => None,
122 }
123 }
124
125 #[must_use]
132 pub fn as_u32_vec(&self) -> Option<Vec<u32>> {
133 match self {
134 Value::Byte(v) => Some(v.iter().map(|&x| u32::from(x)).collect()),
135 Value::Short(v) => Some(v.iter().map(|&x| u32::from(x)).collect()),
136 Value::Long(v) => Some(v.clone()),
137 #[cfg(feature = "bigtiff")]
138 Value::Long8(v) | Value::Ifd8(v) => v.iter().map(|&x| u32::try_from(x).ok()).collect(),
139 _ => None,
140 }
141 }
142
143 #[must_use]
145 pub fn encode(&self, order: ByteOrder) -> Vec<u8> {
146 let mut out = Vec::with_capacity(self.byte_len());
147 match self {
148 Value::Byte(v) | Value::Undefined(v) => out.extend_from_slice(v),
149 Value::Ascii(s) => {
150 out.extend_from_slice(s.as_bytes());
151 out.push(0);
152 }
153 Value::SByte(v) => out.extend(v.iter().map(|&x| x as u8)),
154 Value::Short(v) => {
155 for &x in v {
156 out.extend_from_slice(&order.pack_u16(x));
157 }
158 }
159 Value::SShort(v) => {
160 for &x in v {
161 out.extend_from_slice(&order.pack_u16(x as u16));
162 }
163 }
164 Value::Long(v) => {
165 for &x in v {
166 out.extend_from_slice(&order.pack_u32(x));
167 }
168 }
169 Value::SLong(v) => {
170 for &x in v {
171 out.extend_from_slice(&order.pack_u32(x as u32));
172 }
173 }
174 Value::Float(v) => {
175 for &x in v {
176 out.extend_from_slice(&order.pack_u32(x.to_bits()));
177 }
178 }
179 Value::Rational(v) => {
180 for &(n, d) in v {
181 out.extend_from_slice(&order.pack_u32(n));
182 out.extend_from_slice(&order.pack_u32(d));
183 }
184 }
185 Value::SRational(v) => {
186 for &(n, d) in v {
187 out.extend_from_slice(&order.pack_u32(n as u32));
188 out.extend_from_slice(&order.pack_u32(d as u32));
189 }
190 }
191 Value::Double(v) => {
192 for &x in v {
193 let b = x.to_bits();
194 let lo = order.pack_u32(b as u32);
195 let hi = order.pack_u32((b >> 32) as u32);
196 match order {
197 ByteOrder::LittleEndian => {
198 out.extend_from_slice(&lo);
199 out.extend_from_slice(&hi);
200 }
201 ByteOrder::BigEndian => {
202 out.extend_from_slice(&hi);
203 out.extend_from_slice(&lo);
204 }
205 }
206 }
207 }
208 #[cfg(feature = "bigtiff")]
209 Value::Long8(v) | Value::Ifd8(v) => {
210 for &x in v {
211 out.extend_from_slice(&order.pack_u64(x));
212 }
213 }
214 #[cfg(feature = "bigtiff")]
215 Value::SLong8(v) => {
216 for &x in v {
217 out.extend_from_slice(&order.pack_u64(x as u64));
218 }
219 }
220 }
221 out
222 }
223
224 pub fn decode(ty: FieldType, count: usize, bytes: &[u8], order: ByteOrder) -> Result<Value> {
231 let need = count
232 .checked_mul(ty.size())
233 .ok_or(Error::InvalidInput("TIFF: field length overflow"))?;
234 let bytes = bytes
235 .get(..need)
236 .ok_or(Error::InvalidInput("TIFF: field value out of bounds"))?;
237 let u16s =
238 |b: &[u8]| -> Vec<u16> { b.chunks_exact(2).map(|c| order.u16([c[0], c[1]])).collect() };
239 let u32s = |b: &[u8]| -> Vec<u32> {
240 b.chunks_exact(4)
241 .map(|c| order.u32([c[0], c[1], c[2], c[3]]))
242 .collect()
243 };
244 #[cfg(feature = "bigtiff")]
245 let u64s = |b: &[u8]| -> Vec<u64> {
246 b.chunks_exact(8)
247 .map(|c| order.u64([c[0], c[1], c[2], c[3], c[4], c[5], c[6], c[7]]))
248 .collect()
249 };
250 Ok(match ty {
251 FieldType::Byte => Value::Byte(bytes.to_vec()),
252 FieldType::Undefined => Value::Undefined(bytes.to_vec()),
253 FieldType::SByte => Value::SByte(bytes.iter().map(|&x| x as i8).collect()),
254 FieldType::Ascii => {
255 let end = bytes.iter().position(|&b| b == 0).unwrap_or(bytes.len());
256 let s = core::str::from_utf8(&bytes[..end])
257 .map_err(|_| Error::InvalidInput("TIFF: non-UTF-8 ASCII field"))?;
258 Value::Ascii(s.to_owned())
259 }
260 FieldType::Short => Value::Short(u16s(bytes)),
261 FieldType::SShort => Value::SShort(u16s(bytes).into_iter().map(|x| x as i16).collect()),
262 FieldType::Long => Value::Long(u32s(bytes)),
263 FieldType::SLong => Value::SLong(u32s(bytes).into_iter().map(|x| x as i32).collect()),
264 FieldType::Float => Value::Float(u32s(bytes).into_iter().map(f32::from_bits).collect()),
265 FieldType::Rational => {
266 let w = u32s(bytes);
267 Value::Rational(w.chunks_exact(2).map(|c| (c[0], c[1])).collect())
268 }
269 FieldType::SRational => {
270 let w = u32s(bytes);
271 Value::SRational(
272 w.chunks_exact(2)
273 .map(|c| (c[0] as i32, c[1] as i32))
274 .collect(),
275 )
276 }
277 FieldType::Double => {
278 let mut v = Vec::with_capacity(count);
279 for c in bytes.chunks_exact(8) {
280 let (a, b) = (
281 order.u32([c[0], c[1], c[2], c[3]]),
282 order.u32([c[4], c[5], c[6], c[7]]),
283 );
284 let bits = match order {
285 ByteOrder::LittleEndian => u64::from(a) | (u64::from(b) << 32),
286 ByteOrder::BigEndian => u64::from(b) | (u64::from(a) << 32),
287 };
288 v.push(f64::from_bits(bits));
289 }
290 Value::Double(v)
291 }
292 #[cfg(feature = "bigtiff")]
293 FieldType::Long8 => Value::Long8(u64s(bytes)),
294 #[cfg(feature = "bigtiff")]
295 FieldType::Ifd8 => Value::Ifd8(u64s(bytes)),
296 #[cfg(feature = "bigtiff")]
297 FieldType::SLong8 => Value::SLong8(u64s(bytes).into_iter().map(|x| x as i64).collect()),
298 })
299 }
300}
301
302#[cfg(test)]
303mod tests {
304 use super::*;
305
306 fn value_roundtrip(value: Value, order: ByteOrder) {
307 let bytes = value.encode(order);
308 let decoded =
309 Value::decode(value.field_type(), value.count(), &bytes, order).expect("decode");
310 assert_eq!(decoded, value);
311 }
312
313 #[test]
314 fn values_roundtrip_in_both_orders() {
315 for order in [ByteOrder::LittleEndian, ByteOrder::BigEndian] {
316 value_roundtrip(Value::Byte(vec![1, 2, 3]), order);
317 value_roundtrip(Value::Ascii("gamut".to_owned()), order);
318 value_roundtrip(Value::Short(vec![256, 257, 0xFFFF]), order);
319 value_roundtrip(Value::Long(vec![0xDEAD_BEEF, 7]), order);
320 value_roundtrip(Value::Rational(vec![(300, 1), (72, 1)]), order);
321 value_roundtrip(Value::SByte(vec![-1, 2, -128]), order);
322 value_roundtrip(Value::SShort(vec![-1, 30000]), order);
323 value_roundtrip(Value::SLong(vec![-1, i32::MIN]), order);
324 value_roundtrip(Value::SRational(vec![(-1, 2)]), order);
325 value_roundtrip(Value::Float(vec![1.5, -0.25]), order);
326 value_roundtrip(Value::Double(vec![1.5, -0.0625]), order);
327 value_roundtrip(Value::Undefined(vec![0, 255, 7]), order);
328 #[cfg(feature = "bigtiff")]
329 {
330 value_roundtrip(
331 Value::Long8(vec![0x0123_4567_89AB_CDEF, 0, u64::MAX]),
332 order,
333 );
334 value_roundtrip(Value::SLong8(vec![-1, i64::MIN, 42]), order);
335 value_roundtrip(Value::Ifd8(vec![16, 0x1_0000_0000]), order);
336 }
337 }
338 }
339
340 #[test]
341 fn integer_coercion_accepts_byte_short_long() {
342 assert_eq!(Value::Byte(vec![5]).as_u32(), Some(5));
343 assert_eq!(Value::Short(vec![300]).as_u32(), Some(300));
344 assert_eq!(Value::Long(vec![70000]).as_u32(), Some(70000));
345 assert_eq!(Value::Short(vec![1, 2]).as_u32(), None);
346 assert_eq!(Value::Ascii("x".into()).as_u32(), None);
347 assert_eq!(
348 Value::Short(vec![1, 2, 3]).as_u32_vec(),
349 Some(vec![1, 2, 3])
350 );
351 }
352
353 #[cfg(feature = "bigtiff")]
356 #[test]
357 fn integer_coercion_accepts_bigtiff_64bit() {
358 assert_eq!(Value::Long8(vec![70000]).as_u32(), Some(70000));
359 assert_eq!(Value::Ifd8(vec![8, 1024]).as_u32_vec(), Some(vec![8, 1024]));
360 assert_eq!(Value::Long8(vec![0x1_0000_0000]).as_u32(), None);
361 assert_eq!(Value::Long8(vec![1, 0x1_0000_0000]).as_u32_vec(), None);
362 }
363
364 #[test]
365 fn decode_rejects_truncated_value() {
366 assert!(Value::decode(FieldType::Long, 1, &[0, 0], ByteOrder::LittleEndian).is_err());
368 }
369}