exif/
value.rs

1//
2// Copyright (c) 2016 KAMADA Ken'ichi.
3// All rights reserved.
4//
5// Redistribution and use in source and binary forms, with or without
6// modification, are permitted provided that the following conditions
7// are met:
8// 1. Redistributions of source code must retain the above copyright
9//    notice, this list of conditions and the following disclaimer.
10// 2. Redistributions in binary form must reproduce the above copyright
11//    notice, this list of conditions and the following disclaimer in the
12//    documentation and/or other materials provided with the distribution.
13//
14// THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
15// ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
16// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
17// ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
18// FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
19// DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
20// OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
21// HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
22// LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
23// OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
24// SUCH DAMAGE.
25//
26
27use std::fmt;
28use std::fmt::Write as _;
29
30use crate::endian::Endian;
31use crate::error::Error;
32
33/// A type and values of a TIFF/Exif field.
34#[derive(Clone)]
35pub enum Value {
36    /// Vector of 8-bit unsigned integers.
37    Byte(Vec<u8>),
38    /// Vector of slices of 8-bit bytes containing 7-bit ASCII characters.
39    /// The trailing null characters are not included.  Note that
40    /// the 8th bits may present if a non-conforming data is given.
41    Ascii(Vec<Vec<u8>>),
42    /// Vector of 16-bit unsigned integers.
43    Short(Vec<u16>),
44    /// Vector of 32-bit unsigned integers.
45    Long(Vec<u32>),
46    /// Vector of unsigned rationals.
47    /// An unsigned rational number is a pair of 32-bit unsigned integers.
48    Rational(Vec<Rational>),
49    /// Vector of 8-bit signed integers.  Unused in the Exif specification.
50    SByte(Vec<i8>),
51    /// Slice of 8-bit bytes.
52    ///
53    /// The second member keeps the offset of the value in the Exif data.
54    /// The interpretation of the value does not generally depend on
55    /// the location, but if it does, the offset information helps.
56    /// When encoding Exif, it is ignored.
57    Undefined(Vec<u8>, u32),
58    /// Vector of 16-bit signed integers.  Unused in the Exif specification.
59    SShort(Vec<i16>),
60    /// Vector of 32-bit signed integers.
61    SLong(Vec<i32>),
62    /// Vector of signed rationals.
63    /// A signed rational number is a pair of 32-bit signed integers.
64    SRational(Vec<SRational>),
65    /// Vector of 32-bit (single precision) floating-point numbers.
66    /// Unused in the Exif specification.
67    Float(Vec<f32>),
68    /// Vector of 64-bit (double precision) floating-point numbers.
69    /// Unused in the Exif specification.
70    Double(Vec<f64>),
71    /// The type is unknown to this implementation.
72    /// The associated values are the type, the count, and the
73    /// offset of the "Value Offset" element.
74    Unknown(u16, u32, u32),
75}
76
77impl Value {
78    /// Returns an object that implements `std::fmt::Display` for
79    /// printing a value in a tag-specific format.
80    /// The tag of the value is specified as the argument.
81    ///
82    /// If you want to display with the unit, use `Field::display_value`.
83    ///
84    /// # Examples
85    ///
86    /// ```
87    /// use exif::{Value, Tag};
88    /// let val = Value::Undefined(b"0231".to_vec(), 0);
89    /// assert_eq!(val.display_as(Tag::ExifVersion).to_string(), "2.31");
90    /// let val = Value::Short(vec![2]);
91    /// assert_eq!(val.display_as(Tag::ResolutionUnit).to_string(), "inch");
92    /// ```
93    #[inline]
94    pub fn display_as(&self, tag: crate::tag::Tag) -> Display {
95        crate::tag::display_value_as(self, tag)
96    }
97
98    /// Returns the value as a slice if the type is BYTE.
99    #[inline]
100    pub(crate) fn byte(&self) -> Option<&[u8]> {
101        match *self {
102            Value::Byte(ref v) => Some(v),
103            _ => None,
104        }
105    }
106
107    /// Returns the value as `AsciiValues` if the type is ASCII.
108    #[inline]
109    pub(crate) fn ascii(&self) -> Option<AsciiValues> {
110        match *self {
111            Value::Ascii(ref v) => Some(AsciiValues(v)),
112            _ => None,
113        }
114    }
115
116    /// Returns the value as a slice if the type is RATIONAL.
117    #[inline]
118    pub(crate) fn rational(&self) -> Option<&[Rational]> {
119        match *self {
120            Value::Rational(ref v) => Some(v),
121            _ => None,
122        }
123    }
124
125    /// Returns the value as a slice if the type is UNDEFINED.
126    #[inline]
127    pub(crate) fn undefined(&self) -> Option<&[u8]> {
128        match *self {
129            Value::Undefined(ref v, _) => Some(v),
130            _ => None,
131        }
132    }
133
134    /// Returns `UIntValue` if the value type is unsigned integer (BYTE,
135    /// SHORT, or LONG).  Otherwise `exif::Error` is returned.
136    ///
137    /// The integer(s) can be obtained by `get(&self, index: usize)` method
138    /// on `UIntValue`, which returns `Option<u32>`.
139    /// `None` is returned if the index is out of bounds.
140    ///
141    /// # Examples
142    ///
143    /// ```
144    /// # use exif::Value;
145    /// # fn main() -> std::result::Result<(), Box<dyn std::error::Error>> {
146    /// let v = Value::Byte(vec![1u8, 2]);
147    /// assert_eq!(v.as_uint()?.get(0), Some(1u32));
148    /// assert_eq!(v.as_uint()?.get(2), None);
149    /// let v = Value::SLong(vec![1, 2]);
150    /// assert!(v.as_uint().is_err());
151    /// # Ok(()) }
152    /// ```
153    #[inline]
154    pub fn as_uint(&self) -> Result<&UIntValue, Error> {
155        UIntValue::ref_from(self)
156    }
157
158    /// Returns the unsigned integer at the given position.
159    /// None is returned if the value type is not unsigned integer
160    /// (BYTE, SHORT, or LONG) or the position is out of bounds.
161    pub fn get_uint(&self, index: usize) -> Option<u32> {
162        match *self {
163            Value::Byte(ref v) if v.len() > index => Some(v[index] as u32),
164            Value::Short(ref v) if v.len() > index => Some(v[index] as u32),
165            Value::Long(ref v) if v.len() > index => Some(v[index]),
166            _ => None,
167        }
168    }
169
170    /// Returns an iterator over the unsigned integers (BYTE, SHORT, or LONG).
171    /// The iterator yields `u32` regardless of the underlying integer size.
172    /// The returned iterator implements `Iterator` and `ExactSizeIterator`
173    /// traits.
174    /// `None` is returned if the value is not an unsigned integer type.
175    #[inline]
176    pub fn iter_uint(&self) -> Option<UIntIter> {
177        match *self {
178            Value::Byte(ref v) =>
179                Some(UIntIter { iter: Box::new(v.iter().map(|&x| x as u32)) }),
180            Value::Short(ref v) =>
181                Some(UIntIter { iter: Box::new(v.iter().map(|&x| x as u32)) }),
182            Value::Long(ref v) =>
183                Some(UIntIter { iter: Box::new(v.iter().map(|&x| x)) }),
184            _ => None,
185        }
186    }
187}
188
189pub struct AsciiValues<'a>(&'a [Vec<u8>]);
190
191impl<'a> AsciiValues<'a> {
192    pub fn first(&self) -> Option<&'a [u8]> {
193        self.0.first().map(|x| &x[..])
194    }
195}
196
197#[derive(Debug)]
198#[repr(transparent)]
199pub struct UIntValue(Value);
200
201impl UIntValue {
202    #[inline]
203    fn ref_from(v: &Value) -> Result<&Self, Error> {
204        match *v {
205            Value::Byte(_) | Value::Short(_) | Value::Long(_) =>
206                Ok(unsafe { &*(v as *const Value as *const Self) }),
207            _ => Err(Error::UnexpectedValue("Not unsigned integer")),
208        }
209    }
210
211    #[inline]
212    pub fn get(&self, index: usize) -> Option<u32> {
213        match self.0 {
214            Value::Byte(ref v) => v.get(index).map(|&x| x.into()),
215            Value::Short(ref v) => v.get(index).map(|&x| x.into()),
216            Value::Long(ref v) => v.get(index).map(|&x| x),
217            _ => panic!(),
218        }
219    }
220}
221
222// A struct that wraps std::slice::Iter<'a, u8/u16/u32>.
223pub struct UIntIter<'a> {
224    iter: Box<dyn ExactSizeIterator<Item=u32> + 'a>
225}
226
227impl<'a> Iterator for UIntIter<'a> {
228    type Item = u32;
229
230    #[inline]
231    fn next(&mut self) -> Option<u32> {
232        self.iter.next()
233    }
234
235    #[inline]
236    fn size_hint(&self) -> (usize, Option<usize>) {
237        self.iter.size_hint()
238    }
239}
240
241impl<'a> ExactSizeIterator for UIntIter<'a> {}
242
243/// Helper struct for printing a value in a tag-specific format.
244#[derive(Copy, Clone)]
245pub struct Display<'a> {
246    pub fmt: fn(&mut dyn fmt::Write, &Value) -> fmt::Result,
247    pub value: &'a Value,
248}
249
250impl<'a> fmt::Display for Display<'a> {
251    #[inline]
252    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
253        (self.fmt)(f, self.value)
254    }
255}
256
257impl fmt::Debug for Value {
258    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
259        match self {
260            Self::Byte(v) => f.debug_tuple("Byte").field(v).finish(),
261            Self::Ascii(v) => f.debug_tuple("Ascii")
262                .field(&IterDebugAdapter(
263                    || v.iter().map(|x| AsciiDebugAdapter(x)))).finish(),
264            Self::Short(v) => f.debug_tuple("Short").field(v).finish(),
265            Self::Long(v) => f.debug_tuple("Long").field(v).finish(),
266            Self::Rational(v) => f.debug_tuple("Rational").field(v).finish(),
267            Self::SByte(v) => f.debug_tuple("SByte").field(v).finish(),
268            Self::Undefined(v, o) => f.debug_tuple("Undefined")
269                .field(&HexDebugAdapter(v))
270                .field(&format_args!("ofs={:#x}", o)).finish(),
271            Self::SShort(v) => f.debug_tuple("SShort").field(v).finish(),
272            Self::SLong(v) => f.debug_tuple("SLong").field(v).finish(),
273            Self::SRational(v) => f.debug_tuple("SRational").field(v).finish(),
274            Self::Float(v) => f.debug_tuple("Float").field(v).finish(),
275            Self::Double(v) => f.debug_tuple("Double").field(v).finish(),
276            Self::Unknown(t, c, oo) => f.debug_tuple("Unknown")
277                .field(&format_args!("typ={}", t))
278                .field(&format_args!("cnt={}", c))
279                .field(&format_args!("ofs={:#x}", oo)).finish(),
280        }
281    }
282}
283
284struct IterDebugAdapter<F>(F);
285
286impl<F, T, I> fmt::Debug for IterDebugAdapter<F>
287where F: Fn() -> T, T: Iterator<Item = I>, I: fmt::Debug {
288    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
289        f.debug_list().entries(self.0()).finish()
290    }
291}
292
293struct AsciiDebugAdapter<'a>(&'a [u8]);
294
295impl<'a> fmt::Debug for AsciiDebugAdapter<'a> {
296    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
297        f.write_char('"')?;
298        self.0.iter().try_for_each(|&c| match c {
299            b'\\' | b'"' => write!(f, "\\{}", c as char),
300            0x20..=0x7e => f.write_char(c as char),
301            _ => write!(f, "\\x{:02x}", c),
302        })?;
303        f.write_char('"')
304    }
305}
306
307struct HexDebugAdapter<'a>(&'a [u8]);
308
309impl<'a> fmt::Debug for HexDebugAdapter<'a> {
310    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
311        f.write_str("0x")?;
312        self.0.iter().try_for_each(|x| write!(f, "{:02x}", x))
313    }
314}
315
316// Static default values.
317pub enum DefaultValue {
318    None,
319    Byte(&'static [u8]),
320    Ascii(&'static [&'static [u8]]),
321    Short(&'static [u16]),
322    Rational(&'static [(u32, u32)]),
323    Undefined(&'static [u8]),
324    // Depends on other tags, JPEG markers, etc.
325    ContextDependent,
326    // Unspecified in the Exif standard.
327    Unspecified,
328}
329
330impl From<&DefaultValue> for Option<Value> {
331    fn from(defval: &DefaultValue) -> Option<Value> {
332        match *defval {
333            DefaultValue::None => None,
334            DefaultValue::Byte(s) => Some(Value::Byte(s.to_vec())),
335            DefaultValue::Ascii(s) => Some(Value::Ascii(
336                s.iter().map(|&x| x.to_vec()).collect())),
337            DefaultValue::Short(s) => Some(Value::Short(s.to_vec())),
338            DefaultValue::Rational(s) => Some(Value::Rational(
339                s.iter().map(|&x| x.into()).collect())),
340            DefaultValue::Undefined(s) => Some(Value::Undefined(
341                s.to_vec(), 0)),
342            DefaultValue::ContextDependent => None,
343            DefaultValue::Unspecified => None,
344        }
345    }
346}
347
348/// An unsigned rational number, which is a pair of 32-bit unsigned integers.
349#[derive(Copy, Clone)]
350pub struct Rational { pub num: u32, pub denom: u32 }
351
352impl Rational {
353    /// Converts the value to an f32.
354    #[inline]
355    pub fn to_f32(&self) -> f32 {
356        self.to_f64() as f32
357    }
358
359    /// Converts the value to an f64.
360    #[inline]
361    pub fn to_f64(&self) -> f64 {
362        self.num as f64 / self.denom as f64
363    }
364}
365
366impl From<(u32, u32)> for Rational {
367    fn from(t: (u32, u32)) -> Rational {
368        Rational { num: t.0, denom: t.1 }
369    }
370}
371
372impl fmt::Debug for Rational {
373    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
374        write!(f, "Rational({}/{})", self.num, self.denom)
375    }
376}
377
378impl fmt::Display for Rational {
379    /// Formatting parameters other than width are not supported.
380    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
381        let buf = fmt_rational_sub(f, self.num, self.denom);
382        f.pad_integral(true, "", &buf)
383    }
384}
385
386/// A signed rational number, which is a pair of 32-bit signed integers.
387#[derive(Copy, Clone)]
388pub struct SRational { pub num: i32, pub denom: i32 }
389
390impl SRational {
391    /// Converts the value to an f32.
392    #[inline]
393    pub fn to_f32(&self) -> f32 {
394        self.to_f64() as f32
395    }
396
397    /// Converts the value to an f64.
398    #[inline]
399    pub fn to_f64(&self) -> f64 {
400        self.num as f64 / self.denom as f64
401    }
402}
403
404impl From<(i32, i32)> for SRational {
405    fn from(t: (i32, i32)) -> SRational {
406        SRational { num: t.0, denom: t.1 }
407    }
408}
409
410impl fmt::Debug for SRational {
411    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
412        write!(f, "SRational({}/{})", self.num, self.denom)
413    }
414}
415
416impl fmt::Display for SRational {
417    /// Formatting parameters other than width are not supported.
418    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
419        let buf = fmt_rational_sub(
420            f, self.num.wrapping_abs() as u32, self.denom);
421        f.pad_integral(self.num >= 0, "", &buf)
422    }
423}
424
425// Only u32 or i32 are expected for T.
426fn fmt_rational_sub<T>(f: &mut fmt::Formatter, num: u32, denom: T)
427                       -> String where T: fmt::Display {
428    // The API to get the alignment is not yet stable as of Rust 1.16,
429    // so it is not fully supported.
430    match (f.sign_plus(), f.precision(), f.sign_aware_zero_pad()) {
431        (true, Some(prec), true) =>
432            format!("{}/{:+0w$}", num, denom, w = prec),
433        (true, Some(prec), false) =>
434            format!("{}/{:+w$}", num, denom, w = prec),
435        (true, None, _) =>
436            format!("{}/{:+}", num, denom),
437        (false, Some(prec), true) =>
438            format!("{}/{:0w$}", num, denom, w = prec),
439        (false, Some(prec), false) =>
440            format!("{}/{:w$}", num, denom, w = prec),
441        (false, None, _) =>
442            format!("{}/{}", num, denom),
443    }
444}
445
446type Parser = fn(&[u8], usize, usize) -> Value;
447
448// Return the length of a single value and the parser of the type.
449pub fn get_type_info<E>(typecode: u16) -> (usize, Parser) where E: Endian {
450    match typecode {
451        1 => (1, parse_byte),
452        2 => (1, parse_ascii),
453        3 => (2, parse_short::<E>),
454        4 => (4, parse_long::<E>),
455        5 => (8, parse_rational::<E>),
456        6 => (1, parse_sbyte),
457        7 => (1, parse_undefined),
458        8 => (2, parse_sshort::<E>),
459        9 => (4, parse_slong::<E>),
460        10 => (8, parse_srational::<E>),
461        11 => (4, parse_float::<E>),
462        12 => (8, parse_double::<E>),
463        _ => (0, parse_unknown),
464    }
465}
466
467fn parse_byte(data: &[u8], offset: usize, count: usize) -> Value {
468    Value::Byte(data[offset .. offset + count].to_vec())
469}
470
471fn parse_ascii(data: &[u8], offset: usize, count: usize) -> Value {
472    // Any ASCII field can contain multiple strings [TIFF6 Image File
473    // Directory].
474    let iter = (&data[offset .. offset + count]).split(|&b| b == b'\0');
475    let mut v: Vec<Vec<u8>> = iter.map(|x| x.to_vec()).collect();
476    if v.last().map_or(false, |x| x.len() == 0) {
477        v.pop();
478    }
479    Value::Ascii(v)
480}
481
482fn parse_short<E>(data: &[u8], offset: usize, count: usize)
483                  -> Value where E: Endian {
484    let mut val = Vec::with_capacity(count);
485    for i in 0..count {
486        val.push(E::loadu16(data, offset + i * 2));
487    }
488    Value::Short(val)
489}
490
491fn parse_long<E>(data: &[u8], offset: usize, count: usize)
492                 -> Value where E: Endian {
493    let mut val = Vec::with_capacity(count);
494    for i in 0..count {
495        val.push(E::loadu32(data, offset + i * 4));
496    }
497    Value::Long(val)
498}
499
500fn parse_rational<E>(data: &[u8], offset: usize, count: usize)
501                     -> Value where E: Endian {
502    let mut val = Vec::with_capacity(count);
503    for i in 0..count {
504        val.push(Rational {
505            num: E::loadu32(data, offset + i * 8),
506            denom: E::loadu32(data, offset + i * 8 + 4),
507        });
508    }
509    Value::Rational(val)
510}
511
512fn parse_sbyte(data: &[u8], offset: usize, count: usize) -> Value {
513    let bytes = data[offset .. offset + count].iter()
514        .map(|x| *x as i8).collect();
515    Value::SByte(bytes)
516}
517
518fn parse_undefined(data: &[u8], offset: usize, count: usize) -> Value {
519    Value::Undefined(data[offset .. offset + count].to_vec(), offset as u32)
520}
521
522fn parse_sshort<E>(data: &[u8], offset: usize, count: usize)
523                   -> Value where E: Endian {
524    let mut val = Vec::with_capacity(count);
525    for i in 0..count {
526        val.push(E::loadu16(data, offset + i * 2) as i16);
527    }
528    Value::SShort(val)
529}
530
531fn parse_slong<E>(data: &[u8], offset: usize, count: usize)
532                  -> Value where E: Endian {
533    let mut val = Vec::with_capacity(count);
534    for i in 0..count {
535        val.push(E::loadu32(data, offset + i * 4) as i32);
536    }
537    Value::SLong(val)
538}
539
540fn parse_srational<E>(data: &[u8], offset: usize, count: usize)
541                      -> Value where E: Endian {
542    let mut val = Vec::with_capacity(count);
543    for i in 0..count {
544        val.push(SRational {
545            num: E::loadu32(data, offset + i * 8) as i32,
546            denom: E::loadu32(data, offset + i * 8 + 4) as i32,
547        });
548    }
549    Value::SRational(val)
550}
551
552// TIFF and Rust use IEEE 754 format, so no conversion is required.
553fn parse_float<E>(data: &[u8], offset: usize, count: usize)
554                  -> Value where E: Endian {
555    let mut val = Vec::with_capacity(count);
556    for i in 0..count {
557        val.push(f32::from_bits(E::loadu32(data, offset + i * 4)));
558    }
559    Value::Float(val)
560}
561
562// TIFF and Rust use IEEE 754 format, so no conversion is required.
563fn parse_double<E>(data: &[u8], offset: usize, count: usize)
564                   -> Value where E: Endian {
565    let mut val = Vec::with_capacity(count);
566    for i in 0..count {
567        val.push(f64::from_bits(E::loadu64(data, offset + i * 8)));
568    }
569    Value::Double(val)
570}
571
572// This is a dummy function and will never be called.
573#[allow(unused_variables)]
574fn parse_unknown(data: &[u8], offset: usize, count: usize) -> Value {
575    unreachable!()
576}
577
578#[cfg(test)]
579mod tests {
580    use crate::endian::BigEndian;
581    use super::*;
582
583    #[test]
584    fn byte() {
585        let sets: &[(&[u8], &[u8])] = &[
586            (b"x", b""),
587            (b"x\xbe\xad", b"\xbe\xad"),
588        ];
589        let (unitlen, parser) = get_type_info::<BigEndian>(1);
590        for &(data, ans) in sets {
591            assert!((data.len() - 1) % unitlen == 0);
592            match parser(data, 1, (data.len() - 1) / unitlen) {
593                Value::Byte(v) => assert_eq!(v, ans),
594                v => panic!("wrong variant {:?}", v),
595            }
596        }
597    }
598
599    #[test]
600    fn ascii() {
601        let sets: &[(&[u8], Vec<&[u8]>)] = &[
602            (b"x", vec![]),				// malformed
603            (b"x\0", vec![b""]),
604            (b"x\0\0", vec![b"", b""]),
605            (b"xA", vec![b"A"]),			// malformed
606            (b"xA\0", vec![b"A"]),
607            (b"xA\0B", vec![b"A", b"B"]),		// malformed
608            (b"xA\0B\0", vec![b"A", b"B"]),
609            (b"xA\0\xbe\0", vec![b"A", b"\xbe"]),	// not ASCII
610        ];
611        let (unitlen, parser) = get_type_info::<BigEndian>(2);
612        for &(data, ref ans) in sets {
613            match parser(data, 1, (data.len() - 1) / unitlen) {
614                Value::Ascii(v) => assert_eq!(v, *ans),
615                v => panic!("wrong variant {:?}", v),
616            }
617        }
618    }
619
620    #[test]
621    fn short() {
622        let sets: &[(&[u8], Vec<u16>)] = &[
623            (b"x", vec![]),
624            (b"x\x01\x02\x03\x04", vec![0x0102, 0x0304]),
625        ];
626        let (unitlen, parser) = get_type_info::<BigEndian>(3);
627        for &(data, ref ans) in sets {
628            assert!((data.len() - 1) % unitlen == 0);
629            match parser(data, 1, (data.len() - 1) / unitlen) {
630                Value::Short(v) => assert_eq!(v, *ans),
631                v => panic!("wrong variant {:?}", v),
632            }
633        }
634    }
635
636    #[test]
637    fn long() {
638        let sets: &[(&[u8], Vec<u32>)] = &[
639            (b"x", vec![]),
640            (b"x\x01\x02\x03\x04\x05\x06\x07\x08",
641             vec![0x01020304, 0x05060708]),
642        ];
643        let (unitlen, parser) = get_type_info::<BigEndian>(4);
644        for &(data, ref ans) in sets {
645            assert!((data.len() - 1) % unitlen == 0);
646            match parser(data, 1, (data.len() - 1) / unitlen) {
647                Value::Long(v) => assert_eq!(v, *ans),
648                v => panic!("wrong variant {:?}", v),
649            }
650        }
651    }
652
653    #[test]
654    fn rational() {
655        let sets: &[(&[u8], Vec<Rational>)] = &[
656            (b"x", vec![]),
657            (b"x\xa1\x02\x03\x04\x05\x06\x07\x08\
658               \x09\x0a\x0b\x0c\xbd\x0e\x0f\x10",
659             vec![(0xa1020304, 0x05060708).into(),
660                  (0x090a0b0c, 0xbd0e0f10).into()]),
661        ];
662        let (unitlen, parser) = get_type_info::<BigEndian>(5);
663        for &(data, ref ans) in sets {
664            assert!((data.len() - 1) % unitlen == 0);
665            match parser(data, 1, (data.len() - 1) / unitlen) {
666                Value::Rational(v) => {
667                    assert_eq!(v.len(), ans.len());
668                    for (x, y) in v.iter().zip(ans.iter()) {
669                        assert!(x.num == y.num && x.denom == y.denom);
670                    }
671                },
672                v => panic!("wrong variant {:?}", v),
673            }
674        }
675    }
676
677    #[test]
678    fn sbyte() {
679        let sets: &[(&[u8], &[i8])] = &[
680            (b"x", &[]),
681            (b"x\xbe\x7d", &[-0x42, 0x7d]),
682        ];
683        let (unitlen, parser) = get_type_info::<BigEndian>(6);
684        for &(data, ans) in sets {
685            assert!((data.len() - 1) % unitlen == 0);
686            match parser(data, 1, (data.len() - 1) / unitlen) {
687                Value::SByte(v) => assert_eq!(v, ans),
688                v => panic!("wrong variant {:?}", v),
689            }
690        }
691    }
692
693    #[test]
694    fn undefined() {
695        let sets: &[(&[u8], &[u8])] = &[
696            (b"x", b""),
697            (b"x\xbe\xad", b"\xbe\xad"),
698        ];
699        let (unitlen, parser) = get_type_info::<BigEndian>(7);
700        for &(data, ans) in sets {
701            assert!((data.len() - 1) % unitlen == 0);
702            match parser(data, 1, (data.len() - 1) / unitlen) {
703                Value::Undefined(v, o) => {
704                    assert_eq!(v, ans);
705                    assert_eq!(o, 1);
706                },
707                v => panic!("wrong variant {:?}", v),
708            }
709        }
710    }
711
712    #[test]
713    fn sshort() {
714        let sets: &[(&[u8], Vec<i16>)] = &[
715            (b"x", vec![]),
716            (b"x\x01\x02\xf3\x04", vec![0x0102, -0x0cfc]),
717        ];
718        let (unitlen, parser) = get_type_info::<BigEndian>(8);
719        for &(data, ref ans) in sets {
720            assert!((data.len() - 1) % unitlen == 0);
721            match parser(data, 1, (data.len() - 1) / unitlen) {
722                Value::SShort(v) => assert_eq!(v, *ans),
723                v => panic!("wrong variant {:?}", v),
724            }
725        }
726    }
727
728    #[test]
729    fn slong() {
730        let sets: &[(&[u8], Vec<i32>)] = &[
731            (b"x", vec![]),
732            (b"x\x01\x02\x03\x04\x85\x06\x07\x08",
733             vec![0x01020304, -0x7af9f8f8]),
734        ];
735        let (unitlen, parser) = get_type_info::<BigEndian>(9);
736        for &(data, ref ans) in sets {
737            assert!((data.len() - 1) % unitlen == 0);
738            match parser(data, 1, (data.len() - 1) / unitlen) {
739                Value::SLong(v) => assert_eq!(v, *ans),
740                v => panic!("wrong variant {:?}", v),
741            }
742        }
743    }
744
745    #[test]
746    fn srational() {
747        let sets: &[(&[u8], Vec<SRational>)] = &[
748            (b"x", vec![]),
749            (b"x\xa1\x02\x03\x04\x05\x06\x07\x08\
750               \x09\x0a\x0b\x0c\xbd\x0e\x0f\x10",
751             vec![(-0x5efdfcfc, 0x05060708).into(),
752                  (0x090a0b0c, -0x42f1f0f0).into()]),
753        ];
754        let (unitlen, parser) = get_type_info::<BigEndian>(10);
755        for &(data, ref ans) in sets {
756            assert!((data.len() - 1) % unitlen == 0);
757            match parser(data, 1, (data.len() - 1) / unitlen) {
758                Value::SRational(v) => {
759                    assert_eq!(v.len(), ans.len());
760                    for (x, y) in v.iter().zip(ans.iter()) {
761                        assert!(x.num == y.num && x.denom == y.denom);
762                    }
763                },
764                v => panic!("wrong variant {:?}", v),
765            }
766        }
767    }
768
769    #[test]
770    fn float() {
771        let sets: &[(&[u8], Vec<f32>)] = &[
772            (b"x", vec![]),
773            (b"x\x7f\x7f\xff\xff\x80\x80\x00\x00\x40\x00\x00\x00",
774             vec![std::f32::MAX, -std::f32::MIN_POSITIVE, 2.0]),
775        ];
776        let (unitlen, parser) = get_type_info::<BigEndian>(11);
777        for &(data, ref ans) in sets {
778            assert!((data.len() - 1) % unitlen == 0);
779            match parser(data, 1, (data.len() - 1) / unitlen) {
780                Value::Float(v) => assert_eq!(v, *ans),
781                v => panic!("wrong variant {:?}", v),
782            }
783        }
784    }
785
786    #[test]
787    fn double() {
788        let sets: &[(&[u8], Vec<f64>)] = &[
789            (b"x", vec![]),
790            (b"x\x7f\xef\xff\xff\xff\xff\xff\xff\
791               \x80\x10\x00\x00\x00\x00\x00\x00\
792               \x40\x00\x00\x00\x00\x00\x00\x00",
793             vec![std::f64::MAX, -std::f64::MIN_POSITIVE, 2.0]),
794        ];
795        let (unitlen, parser) = get_type_info::<BigEndian>(12);
796        for &(data, ref ans) in sets {
797            assert!((data.len() - 1) % unitlen == 0);
798            match parser(data, 1, (data.len() - 1) / unitlen) {
799                Value::Double(v) => assert_eq!(v, *ans),
800                v => panic!("wrong variant {:?}", v),
801            }
802        }
803    }
804
805    // These functions are never called in a way that an out-of-range access
806    // could happen, so this test is hypothetical but just for safety.
807    #[test]
808    #[should_panic(expected = "index 5 out of range for slice of length 4")]
809    fn short_oor() {
810        parse_short::<BigEndian>(b"\x01\x02\x03\x04", 1, 2);
811    }
812
813    #[test]
814    fn unknown() {
815        let (unitlen, _parser) = get_type_info::<BigEndian>(0xffff);
816        assert_eq!(unitlen, 0);
817    }
818
819    #[test]
820    fn as_uint() {
821        let v = Value::Byte(vec![1, 2]);
822        assert_eq!(v.as_uint().unwrap().get(0), Some(1));
823        assert_eq!(v.as_uint().unwrap().get(1), Some(2));
824        assert_eq!(v.as_uint().unwrap().get(2), None);
825        let v = Value::Short(vec![1, 2]);
826        assert_eq!(v.as_uint().unwrap().get(0), Some(1));
827        assert_eq!(v.as_uint().unwrap().get(1), Some(2));
828        assert_eq!(v.as_uint().unwrap().get(2), None);
829        let v = Value::Long(vec![1, 2]);
830        assert_eq!(v.as_uint().unwrap().get(0), Some(1));
831        assert_eq!(v.as_uint().unwrap().get(1), Some(2));
832        assert_eq!(v.as_uint().unwrap().get(2), None);
833        let v = Value::SLong(vec![1, 2]);
834        assert_err_pat!(v.as_uint(), Error::UnexpectedValue(_));
835    }
836
837    #[test]
838    fn get_uint() {
839        let v = Value::Byte(vec![1, 2]);
840        assert_eq!(v.get_uint(0), Some(1));
841        assert_eq!(v.get_uint(1), Some(2));
842        assert_eq!(v.get_uint(2), None);
843        let v = Value::Short(vec![1, 2]);
844        assert_eq!(v.get_uint(0), Some(1));
845        assert_eq!(v.get_uint(1), Some(2));
846        assert_eq!(v.get_uint(2), None);
847        let v = Value::Long(vec![1, 2]);
848        assert_eq!(v.get_uint(0), Some(1));
849        assert_eq!(v.get_uint(1), Some(2));
850        assert_eq!(v.get_uint(2), None);
851        let v = Value::SLong(vec![1, 2]);
852        assert_eq!(v.get_uint(0), None);
853        assert_eq!(v.get_uint(1), None);
854        assert_eq!(v.get_uint(2), None);
855    }
856
857    #[test]
858    fn iter_uint() {
859        let vlist = &[
860            Value::Byte(vec![1, 2]),
861            Value::Short(vec![1, 2]),
862            Value::Long(vec![1, 2]),
863        ];
864        for v in vlist {
865            let mut it = v.iter_uint().unwrap();
866            assert_eq!(it.next(), Some(1));
867            assert_eq!(it.next(), Some(2));
868            assert_eq!(it.next(), None);
869        }
870
871        let v = Value::SLong(vec![1, 2]);
872        assert!(v.iter_uint().is_none());
873    }
874
875    #[test]
876    fn iter_uint_is_exact_size_iter() {
877        let v = Value::Byte(vec![1, 2, 3]);
878        let mut it = v.iter_uint().unwrap();
879        assert_eq!(it.len(), 3);
880        assert_eq!(it.next(), Some(1));
881        assert_eq!(it.len(), 2);
882    }
883
884    #[test]
885    fn value_fmt_debug() {
886        let v = Value::Byte(b"b\0y".to_vec());
887        assert_eq!(format!("{:?}", v), "Byte([98, 0, 121])");
888        let v = Value::Ascii(vec![]);
889        assert_eq!(format!("{:?}", v), "Ascii([])");
890        let v = Value::Ascii(vec![b"abc\"\\\n\x7f".to_vec(), b"".to_vec()]);
891        assert_eq!(format!("{:?}", v), r#"Ascii(["abc\"\\\x0a\x7f", ""])"#);
892        let v = Value::Short(vec![]);
893        assert_eq!(format!("{:?}", v), "Short([])");
894        let v = Value::Long(vec![1, 2]);
895        assert_eq!(format!("{:?}", v), "Long([1, 2])");
896        let v = Value::Rational(vec![(0, 0).into()]);
897        assert_eq!(format!("{:?}", v), "Rational([Rational(0/0)])");
898        let v = Value::SByte(vec![-3, 4, 5]);
899        assert_eq!(format!("{:?}", v), "SByte([-3, 4, 5])");
900        let v = Value::Undefined(vec![0, 0xff], 0);
901        assert_eq!(format!("{:?}", v), "Undefined(0x00ff, ofs=0x0)");
902        let v = Value::SShort(vec![6, -7]);
903        assert_eq!(format!("{:?}", v), "SShort([6, -7])");
904        let v = Value::SLong(vec![-9]);
905        assert_eq!(format!("{:?}", v), "SLong([-9])");
906        let v = Value::SRational(vec![(-2, -1).into()]);
907        assert_eq!(format!("{:?}", v), "SRational([SRational(-2/-1)])");
908        let v = Value::Float(vec![1.5, 0.0]);
909        assert_eq!(format!("{:?}", v), "Float([1.5, 0.0])");
910        let v = Value::Double(vec![-0.5, 1.0]);
911        assert_eq!(format!("{:?}", v), "Double([-0.5, 1.0])");
912        let v = Value::Unknown(1, 2, 10);
913        assert_eq!(format!("{:?}", v), "Unknown(typ=1, cnt=2, ofs=0xa)");
914    }
915
916    #[test]
917    fn rational_fmt_display() {
918        let r = Rational::from((u32::max_value(), u32::max_value()));
919        assert_eq!(format!("{}", r), "4294967295/4294967295");
920
921        let r = Rational::from((10, 20));
922        assert_eq!(format!("{}", r),         "10/20");
923        assert_eq!(format!("{:11}", r),      "      10/20");
924        assert_eq!(format!("{:3}", r),       "10/20");
925    }
926
927    #[test]
928    fn srational_fmt_display() {
929        let r = SRational::from((i32::min_value(), i32::min_value()));
930        assert_eq!(format!("{}", r), "-2147483648/-2147483648");
931        let r = SRational::from((i32::max_value(), i32::max_value()));
932        assert_eq!(format!("{}", r), "2147483647/2147483647");
933
934        let r = SRational::from((-10, 20));
935        assert_eq!(format!("{}", r),         "-10/20");
936        assert_eq!(format!("{:11}", r),      "     -10/20");
937        assert_eq!(format!("{:3}", r),       "-10/20");
938
939        let r = SRational::from((10, -20));
940        assert_eq!(format!("{}", r),         "10/-20");
941        assert_eq!(format!("{:11}", r),      "     10/-20");
942        assert_eq!(format!("{:3}", r),       "10/-20");
943
944        let r = SRational::from((-10, -20));
945        assert_eq!(format!("{}", r),         "-10/-20");
946        assert_eq!(format!("{:11}", r),      "    -10/-20");
947        assert_eq!(format!("{:3}", r),       "-10/-20");
948    }
949
950    #[test]
951    fn ratioanl_f64() {
952        use std::{f64, u32};
953        assert_eq!(Rational::from((1, 2)).to_f64(), 0.5);
954        assert_eq!(Rational::from((1, u32::MAX)).to_f64(),
955                   2.3283064370807974e-10);
956        assert_eq!(Rational::from((u32::MAX, 1)).to_f64(),
957                   u32::MAX as f64);
958        assert_eq!(Rational::from((u32::MAX - 1, u32::MAX)).to_f64(),
959                   0.9999999997671694);
960        assert_eq!(Rational::from((u32::MAX, u32::MAX - 1)).to_f64(),
961                   1.0000000002328306);
962        assert_eq!(Rational::from((1, 0)).to_f64(), f64::INFINITY);
963        assert!(Rational::from((0, 0)).to_f64().is_nan());
964
965        assert_eq!(SRational::from((1, 2)).to_f64(), 0.5);
966        assert_eq!(SRational::from((-1, 2)).to_f64(), -0.5);
967        assert_eq!(SRational::from((1, -2)).to_f64(), -0.5);
968        assert_eq!(SRational::from((-1, -2)).to_f64(), 0.5);
969        assert_eq!(SRational::from((1, 0)).to_f64(), f64::INFINITY);
970        assert_eq!(SRational::from((-1, 0)).to_f64(), f64::NEG_INFINITY);
971    }
972
973    #[test]
974    fn rational_f32() {
975        // If num and demon are converted to f32 before the division,
976        // the precision is lost in this example.
977        assert_eq!(Rational::from((1, 16777217)).to_f32(), 5.960464e-8);
978    }
979}