Repository: image-rs/image-tiff
Pull request #51 (2019-08-15 02:19:42)

Signed value support
Add support for SBYTE, SSHORT, SLONG, SRATIONAL as per the Tiff 6.0 spec
Add support for multiple BYTE


Patch:
diff --git a/src/decoder/ifd.rs b/src/decoder/ifd.rs
index ba663d9..672bb87 100644
--- a/src/decoder/ifd.rs
+++ b/src/decoder/ifd.rs
@@ -7,7 +7,7 @@ use std::mem;
 use super::stream::{ByteOrder, EndianReader, SmartReader};
 use {TiffError, TiffFormatError, TiffResult, TiffUnsupportedError};
 
-use self::Value::{Ascii, List, Rational, Unsigned};
+use self::Value::{Ascii, List, Rational, Unsigned, Signed, SRational};
 
 macro_rules! tags {
     {$(
@@ -89,15 +89,20 @@ pub enum Type {
     SHORT = 3,
     LONG = 4,
     RATIONAL = 5,
+    SBYTE = 6,
+    SSHORT = 8,
+    SLONG = 9,
+    SRATIONAL = 10,
 }
 
 #[allow(unused_qualifications)]
 #[derive(Debug, Clone, PartialEq, Eq, Hash)]
 pub enum Value {
-    //Signed(i32),
+    Signed(i32),
     Unsigned(u32),
     List(Vec<Value>),
     Rational(u32, u32),
+    SRational(i32, i32),
     Ascii(String),
 }
 
@@ -110,6 +115,16 @@ impl Value {
             )),
         }
     }
+
+    pub fn into_i32(self) -> TiffResult<i32> {
+        match self {
+            Signed(val) => Ok(val),
+            val => Err(TiffError::FormatError(
+                TiffFormatError::SignedIntegerExpected(val),
+            )),
+        }
+    }
+
     pub fn into_u32_vec(self) -> TiffResult<Vec<u32>> {
         match self {
             List(vec) => {
@@ -122,6 +137,32 @@ impl Value {
             Unsigned(val) => Ok(vec![val]),
             Rational(numerator, denominator) => Ok(vec![numerator, denominator]),
             Ascii(val) => Ok(val.chars().map(|x| x as u32).collect()),
+            val => Err(TiffError::FormatError(
+                TiffFormatError::UnsignedIntegerExpected(val),
+            )),
+        }
+    }
+
+    pub fn into_i32_vec(self) -> TiffResult<Vec<i32>> {
+        match self {
+            List(vec) => {
+                let mut new_vec = Vec::with_capacity(vec.len());
+                for v in vec {
+                    match v {
+                        SRational(numerator, denominator) => {
+                            new_vec.push(numerator);
+                            new_vec.push(denominator);
+                        }
+                        _ => new_vec.push(v.into_i32()?)
+                    }
+                }
+                Ok(new_vec)
+            }
+            Signed(val) => Ok(vec![val]),
+            SRational(numerator, denominator) => Ok(vec![numerator, denominator]),
+            val => Err(TiffError::FormatError(
+                TiffFormatError::SignedIntegerExpected(val),
+            )),
         }
     }
 }
@@ -166,7 +207,21 @@ impl Entry {
             // TODO check if this could give wrong results
             // at a different endianess of file/computer.
             (Type::BYTE, 1) => Ok(Unsigned(u32::from(self.offset[0]))),
+            (Type::BYTE, 2) => offset_to_bytes(2, self),
+            (Type::BYTE, 3) => offset_to_bytes(3, self),
+            (Type::BYTE, 4) => offset_to_bytes(4, self),
+            (Type::BYTE, n) => self.decode_offset(n, bo, limits, decoder, |decoder| {
+                Ok(Unsigned(u32::from(decoder.read_byte()?)))
+            }),
+            (Type::SBYTE, 1) => Ok(Signed(i32::from(self.offset[0] as i8))),
+            (Type::SBYTE, 2) => offset_to_sbytes(2, self),
+            (Type::SBYTE, 3) => offset_to_sbytes(3, self),
+            (Type::SBYTE, 4) => offset_to_sbytes(4, self),
+            (Type::SBYTE, n) => self.decode_offset(n, bo, limits, decoder, |decoder| {
+                Ok(Signed(i32::from(decoder.read_byte()? as i8)))
+            }),
             (Type::SHORT, 1) => Ok(Unsigned(u32::from(self.r(bo).read_u16()?))),
+            (Type::SSHORT, 1) => Ok(Signed(i32::from(self.r(bo).read_i16()?))),
             (Type::SHORT, 2) => {
                 let mut r = self.r(bo);
                 Ok(List(vec![
@@ -174,48 +229,51 @@ impl Entry {
                     Unsigned(u32::from(r.read_u16()?)),
                 ]))
             }
-            (Type::SHORT, n) => {
-                if n as usize > limits.decoding_buffer_size / mem::size_of::<Value>() {
-                    return Err(TiffError::LimitsExceeded);
-                }
-                let mut v = Vec::with_capacity(n as usize);
-                try!(decoder.goto_offset(try!(self.r(bo).read_u32())));
-                for _ in 0..n {
-                    v.push(Unsigned(u32::from(decoder.read_short()?)))
-                }
-                Ok(List(v))
+            (Type::SSHORT, 2) => {
+                let mut r = self.r(bo);
+                Ok(List(vec![
+                    Signed(i32::from(r.read_i16()?)),
+                    Signed(i32::from(r.read_i16()?)),
+                ]))
             }
+            (Type::SHORT, n) => self.decode_offset(n, bo, limits, decoder, |decoder| {
+                Ok(Unsigned(u32::from(decoder.read_short()?)))
+            }),
+            (Type::SSHORT, n) => self.decode_offset(n, bo, limits, decoder, |decoder| {
+                Ok(Signed(i32::from(decoder.read_sshort()?)))
+            }),
             (Type::LONG, 1) => Ok(Unsigned(try!(self.r(bo).read_u32()))),
-            (Type::LONG, n) => {
-                if n as usize > limits.decoding_buffer_size / mem::size_of::<Value>() {
-                    return Err(TiffError::LimitsExceeded);
-                }
-                let mut v = Vec::with_capacity(n as usize);
-                try!(decoder.goto_offset(try!(self.r(bo).read_u32())));
-                for _ in 0..n {
-                    v.push(Unsigned(try!(decoder.read_long())))
-                }
-                Ok(List(v))
-            }
+            (Type::SLONG, 1) => Ok(Signed(self.r(bo).read_i32()?)),
+            (Type::LONG, n) => self.decode_offset(n, bo, limits, decoder, |decoder| {
+                Ok(Unsigned(decoder.read_long()?))
+            }),
+            (Type::SLONG, n) => self.decode_offset(n, bo, limits, decoder, |decoder| {
+                Ok(Signed(decoder.read_slong()?))
+            }),
             (Type::RATIONAL, 1) => {
                 try!(decoder.goto_offset(try!(self.r(bo).read_u32())));
                 let numerator = try!(decoder.read_long());
                 let denominator = try!(decoder.read_long());
                 Ok(Rational(numerator, denominator))
             }
-            (Type::RATIONAL, n) => {
-                if n as usize > limits.decoding_buffer_size / mem::size_of::<Value>() {
-                    return Err(TiffError::LimitsExceeded);
-                }
-                let mut v = Vec::with_capacity(n as usize);
-                try!(decoder.goto_offset(try!(self.r(bo).read_u32())));
-                for _ in 0..n {
-                    let numerator = try!(decoder.read_long());
-                    let denominator = try!(decoder.read_long());
-                    v.push(Rational(numerator, denominator))
-                }
-                Ok(List(v))
+            (Type::SRATIONAL, 1) => {
+                decoder.goto_offset(self.r(bo).read_u32()?)?;
+                let numerator = decoder.read_slong()?;
+                let denominator = decoder.read_slong()?;
+                Ok(SRational(numerator, denominator))
             }
+            (Type::RATIONAL, n) => self.decode_offset(n, bo, limits, decoder, |decoder| {
+                Ok(Rational(
+                    decoder.read_long()?,
+                    decoder.read_long()?,
+                ))
+            }),
+            (Type::SRATIONAL, n) => self.decode_offset(n, bo, limits, decoder, |decoder| {
+                Ok(SRational(
+                    decoder.read_slong()?,
+                    decoder.read_slong()?,
+                ))
+            }),
             (Type::ASCII, n) => {
                 if n as usize > limits.decoding_buffer_size {
                     return Err(TiffError::LimitsExceeded);
@@ -229,6 +287,46 @@ impl Entry {
             )),
         }
     }
+
+    #[inline]
+    fn decode_offset<R, F>(&self, value_count: u32, bo: ByteOrder, limits: &super::Limits, decoder: &mut super::Decoder<R>, decode_fn: F) -> TiffResult<Value>
+        where
+            R: Read + Seek,
+            F: Fn(&mut super::Decoder<R>) -> TiffResult<Value>,
+    {
+        if value_count as usize > limits.decoding_buffer_size / mem::size_of::<Value>() {
+            return Err(TiffError::LimitsExceeded);
+        }
+
+        let mut v = Vec::with_capacity(value_count as usize);
+        decoder.goto_offset(self.r(bo).read_u32()?)?;
+        for _ in 0..value_count {
+            v.push(decode_fn(decoder)?)
+        }
+        Ok(List(v))
+    }
+}
+
+/// Extracts a list of BYTE tags stored in an offset
+#[inline]
+fn offset_to_bytes(n: usize, entry: &Entry) -> TiffResult<Value> {
+    Ok(List(
+        entry.offset[0..n]
+            .iter()
+            .map(|&e| Unsigned(u32::from(e)))
+            .collect()
+    ))
+}
+
+/// Extracts a list of SBYTE tags stored in an offset
+#[inline]
+fn offset_to_sbytes(n: usize, entry: &Entry) -> TiffResult<Value> {
+    Ok(List(
+        entry.offset[0..n]
+            .iter()
+            .map(|&e| Signed(i32::from(e as i8)))
+            .collect()
+    ))
 }
 
 /// Type representing an Image File Directory
diff --git a/src/decoder/mod.rs b/src/decoder/mod.rs
index 21805b7..7a052d7 100644
--- a/src/decoder/mod.rs
+++ b/src/decoder/mod.rs
@@ -380,18 +380,38 @@ impl<R: Read + Seek> Decoder<R> {
         self.byte_order
     }
 
+    /// Reads a TIFF byte value
+    #[inline]
+    pub fn read_byte(&mut self) -> Result<u8, io::Error> {
+        let mut buf = [0; 1];
+        self.reader.read_exact(&mut buf)?;
+        Ok(buf[0])
+    }
+
     /// Reads a TIFF short value
     #[inline]
     pub fn read_short(&mut self) -> Result<u16, io::Error> {
         self.reader.read_u16()
     }
 
+    /// Reads a TIFF sshort value
+    #[inline]
+    pub fn read_sshort(&mut self) -> Result<i16, io::Error> {
+        self.reader.read_i16()
+    }
+
     /// Reads a TIFF long value
     #[inline]
     pub fn read_long(&mut self) -> Result<u32, io::Error> {
         self.reader.read_u32()
     }
 
+    /// Reads a TIFF slong value
+    #[inline]
+    pub fn read_slong(&mut self) -> Result<i32, io::Error> {
+        self.reader.read_i32()
+    }
+
     /// Reads a string
     #[inline]
     pub fn read_string(&mut self, length: usize) -> TiffResult<String> {
diff --git a/src/decoder/stream.rs b/src/decoder/stream.rs
index b9285db..4eb5e91 100644
--- a/src/decoder/stream.rs
+++ b/src/decoder/stream.rs
@@ -39,6 +39,15 @@ pub trait EndianReader: Read {
         }
     }
 
+    /// Reads an i16
+    #[inline(always)]
+    fn read_i16(&mut self) -> Result<i16, io::Error> {
+        match self.byte_order() {
+            ByteOrder::LittleEndian => <Self as ReadBytesExt>::read_i16::<LittleEndian>(self),
+            ByteOrder::BigEndian => <Self as ReadBytesExt>::read_i16::<BigEndian>(self),
+        }
+    }
+
     /// Reads an u32
     #[inline(always)]
     fn read_u32(&mut self) -> Result<u32, io::Error> {
@@ -47,6 +56,15 @@ pub trait EndianReader: Read {
             ByteOrder::BigEndian => <Self as ReadBytesExt>::read_u32::<BigEndian>(self),
         }
     }
+
+    /// Reads an i32
+    #[inline(always)]
+    fn read_i32(&mut self) -> Result<i32, io::Error> {
+        match self.byte_order() {
+            ByteOrder::LittleEndian => <Self as ReadBytesExt>::read_i32::<LittleEndian>(self),
+            ByteOrder::BigEndian => <Self as ReadBytesExt>::read_i32::<BigEndian>(self),
+        }
+    }
 }
 
 /// Reader that decompresses LZW streams
diff --git a/src/encoder/mod.rs b/src/encoder/mod.rs
index ed7ab56..96ba414 100644
--- a/src/encoder/mod.rs
+++ b/src/encoder/mod.rs
@@ -18,6 +18,12 @@ pub struct Rational {
     pub d: u32,
 }
 
+/// Type to represent tiff values of type `SRATIONAL`
+pub struct SRational {
+    pub n: i32,
+    pub d: i32,
+}
+
 /// Type to represent resolution units
 pub enum ResolutionUnit {
     None = 1,
@@ -50,6 +56,23 @@ impl TiffValue for [u8] {
     }
 }
 
+impl TiffValue for [i8] {
+    const BYTE_LEN: u32 = 1;
+    const FIELD_TYPE: ifd::Type = ifd::Type::SBYTE;
+
+    fn count(&self) -> u32 {
+        self.len() as u32
+    }
+
+    fn write<W: Write>(&self, writer: &mut TiffWriter<W>) -> TiffResult<()> {
+        // We write using nativeedian so this should be safe
+        let slice =
+            unsafe { ::std::slice::from_raw_parts(self.as_ptr() as *const u8, self.len()) };
+        writer.write_bytes(slice)?;
+        Ok(())
+    }
+}
+
 impl TiffValue for [u16] {
     const BYTE_LEN: u32 = 2;
     const FIELD_TYPE: ifd::Type = ifd::Type::SHORT;
@@ -67,6 +90,23 @@ impl TiffValue for [u16] {
     }
 }
 
+impl TiffValue for [i16] {
+    const BYTE_LEN: u32 = 2;
+    const FIELD_TYPE: ifd::Type = ifd::Type::SSHORT;
+
+    fn count(&self) -> u32 {
+        self.len() as u32
+    }
+
+    fn write<W: Write>(&self, writer: &mut TiffWriter<W>) -> TiffResult<()> {
+        // We write using nativeedian so this should be safe
+        let slice =
+            unsafe { ::std::slice::from_raw_parts(self.as_ptr() as *const u8, self.len() * Self::BYTE_LEN as usize) };
+        writer.write_bytes(slice)?;
+        Ok(())
+    }
+}
+
 impl TiffValue for [u32] {
     const BYTE_LEN: u32 = 4;
     const FIELD_TYPE: ifd::Type = ifd::Type::LONG;
@@ -84,6 +124,23 @@ impl TiffValue for [u32] {
     }
 }
 
+impl TiffValue for [i32] {
+    const BYTE_LEN: u32 = 4;
+    const FIELD_TYPE: ifd::Type = ifd::Type::SLONG;
+
+    fn count(&self) -> u32 {
+        self.len() as u32
+    }
+
+    fn write<W: Write>(&self, writer: &mut TiffWriter<W>) -> TiffResult<()> {
+        // We write using nativeedian so this should be safe
+        let slice =
+            unsafe { ::std::slice::from_raw_parts(self.as_ptr() as *const u8, self.len() * Self::BYTE_LEN as usize) };
+        writer.write_bytes(slice)?;
+        Ok(())
+    }
+}
+
 impl TiffValue for [Rational] {
     const BYTE_LEN: u32 = 8;
     const FIELD_TYPE: ifd::Type = ifd::Type::RATIONAL;
@@ -100,6 +157,22 @@ impl TiffValue for [Rational] {
     }
 }
 
+impl TiffValue for [SRational] {
+    const BYTE_LEN: u32 = 8;
+    const FIELD_TYPE: ifd::Type = ifd::Type::SRATIONAL;
+
+    fn count(&self) -> u32 {
+        self.len() as u32
+    }
+
+    fn write<W: Write>(&self, writer: &mut TiffWriter<W>) -> TiffResult<()> {
+        for x in self {
+            x.write(writer)?;
+        }
+        Ok(())
+    }
+}
+
 impl TiffValue for u8 {
     const BYTE_LEN: u32 = 1;
     const FIELD_TYPE: ifd::Type = ifd::Type::BYTE;
@@ -114,6 +187,20 @@ impl TiffValue for u8 {
     }
 }
 
+impl TiffValue for i8 {
+    const BYTE_LEN: u32 = 1;
+    const FIELD_TYPE: ifd::Type = ifd::Type::SBYTE;
+
+    fn count(&self) -> u32 {
+        1
+    }
+
+    fn write<W: Write>(&self, writer: &mut TiffWriter<W>) -> TiffResult<()> {
+        writer.write_i8(*self)?;
+        Ok(())
+    }
+}
+
 impl TiffValue for u16 {
     const BYTE_LEN: u32 = 2;
     const FIELD_TYPE: ifd::Type = ifd::Type::SHORT;
@@ -128,6 +215,20 @@ impl TiffValue for u16 {
     }
 }
 
+impl TiffValue for i16 {
+    const BYTE_LEN: u32 = 2;
+    const FIELD_TYPE: ifd::Type = ifd::Type::SSHORT;
+
+    fn count(&self) -> u32 {
+        1
+    }
+
+    fn write<W: Write>(&self, writer: &mut TiffWriter<W>) -> TiffResult<()> {
+        writer.write_i16(*self)?;
+        Ok(())
+    }
+}
+
 impl TiffValue for u32 {
     const BYTE_LEN: u32 = 4;
     const FIELD_TYPE: ifd::Type = ifd::Type::LONG;
@@ -142,6 +243,20 @@ impl TiffValue for u32 {
     }
 }
 
+impl TiffValue for i32 {
+    const BYTE_LEN: u32 = 4;
+    const FIELD_TYPE: ifd::Type = ifd::Type::SLONG;
+
+    fn count(&self) -> u32 {
+        1
+    }
+
+    fn write<W: Write>(&self, writer: &mut TiffWriter<W>) -> TiffResult<()> {
+        writer.write_i32(*self)?;
+        Ok(())
+    }
+}
+
 impl TiffValue for Rational {
     const BYTE_LEN: u32 = 8;
     const FIELD_TYPE: ifd::Type = ifd::Type::RATIONAL;
@@ -157,6 +272,21 @@ impl TiffValue for Rational {
     }
 }
 
+impl TiffValue for SRational {
+    const BYTE_LEN: u32 = 8;
+    const FIELD_TYPE: ifd::Type = ifd::Type::SRATIONAL;
+
+    fn count(&self) -> u32 {
+        1
+    }
+
+    fn write<W: Write>(&self, writer: &mut TiffWriter<W>) -> TiffResult<()> {
+        writer.write_i32(self.n)?;
+        writer.write_i32(self.d)?;
+        Ok(())
+    }
+}
+
 impl TiffValue for str {
     const BYTE_LEN: u32 = 1;
     const FIELD_TYPE: ifd::Type = ifd::Type::ASCII;
diff --git a/src/encoder/writer.rs b/src/encoder/writer.rs
index 812093f..78a128d 100644
--- a/src/encoder/writer.rs
+++ b/src/encoder/writer.rs
@@ -52,6 +52,12 @@ impl<W: Write> TiffWriter<W> {
         Ok(())
     }
 
+    pub fn write_i8(&mut self, n: i8) -> Result<(), io::Error> {
+        self.writer.write_i8(n)?;
+        self.offset += 1;
+        Ok(())
+    }
+
     pub fn write_u16(&mut self, n: u16) -> Result<(), io::Error> {
         self.writer.write_u16::<NativeEndian>(n)?;
         self.offset += 2;
@@ -59,6 +65,13 @@ impl<W: Write> TiffWriter<W> {
         Ok(())
     }
 
+    pub fn write_i16(&mut self, n: i16) -> Result<(), io::Error> {
+        self.writer.write_i16::<NativeEndian>(n)?;
+        self.offset += 2;
+
+        Ok(())
+    }
+
     pub fn write_u32(&mut self, n: u32) -> Result<(), io::Error> {
         self.writer.write_u32::<NativeEndian>(n)?;
         self.offset += 4;
@@ -66,6 +79,13 @@ impl<W: Write> TiffWriter<W> {
         Ok(())
     }
 
+    pub fn write_i32(&mut self, n: i32) -> Result<(), io::Error> {
+        self.writer.write_i32::<NativeEndian>(n)?;
+        self.offset += 4;
+
+        Ok(())
+    }
+
     pub fn write_u64(&mut self, n: u64) -> Result<(), io::Error> {
         self.writer.write_u64::<NativeEndian>(n)?;
         self.offset += 8;
diff --git a/src/error.rs b/src/error.rs
index cc57e62..4e9f127 100644
--- a/src/error.rs
+++ b/src/error.rs
@@ -33,6 +33,7 @@ pub enum TiffFormatError {
     RequiredTagNotFound(Tag),
     UnknownPredictor(u32),
     UnsignedIntegerExpected(Value),
+    SignedIntegerExpected(Value),
 }
 
 impl fmt::Display for TiffFormatError {
@@ -51,6 +52,9 @@ impl fmt::Display for TiffFormatError {
             UnsignedIntegerExpected(ref val) => {
                 write!(fmt, "Expected unsigned integer, {:?} found.", val)
             }
+            SignedIntegerExpected(ref val) => {
+                write!(fmt, "Expected signed integer, {:?} found.", val)
+            }
         }
     }
 }


Test patch:
diff --git a/tests/encode_images.rs b/tests/encode_images.rs
index 34cc8e1..2ae8c1c 100644
--- a/tests/encode_images.rs
+++ b/tests/encode_images.rs
@@ -2,7 +2,8 @@ extern crate tempfile;
 extern crate tiff;
 
 use tiff::decoder::{Decoder, DecodingResult};
-use tiff::encoder::{colortype, TiffEncoder};
+use tiff::decoder::ifd::Tag;
+use tiff::encoder::{colortype, TiffEncoder, SRational};
 use tiff::ColorType;
 
 use std::fs::File;
@@ -175,3 +176,88 @@ fn test_rgb_u16_roundtrip() {
         }
     }
 }
+
+#[test]
+fn test_multiple_byte() {
+    let mut data = Cursor::new(Vec::new());
+
+    {
+        let mut tiff = TiffEncoder::new(&mut data).unwrap();
+        let mut image_encoder = tiff.new_image::<colortype::Gray8>(1, 1).unwrap();
+        let encoder = image_encoder.encoder();
+
+        encoder.write_tag(Tag::Unknown(65000), &[1_u8][..]);
+        encoder.write_tag(Tag::Unknown(65001), &[1_u8, 2][..]);
+        encoder.write_tag(Tag::Unknown(65002), &[1_u8, 2, 3][..]);
+        encoder.write_tag(Tag::Unknown(65003), &[1_u8, 2, 3, 4][..]);
+        encoder.write_tag(Tag::Unknown(65004), &[1_u8, 2, 3, 4, 5][..]);
+    }
+
+    data.set_position(0);
+    {
+        let mut decoder = Decoder::new(&mut data).unwrap();
+
+        assert_eq!(decoder.get_tag(Tag::Unknown(65000)).unwrap().into_u32_vec().unwrap(), [1]);
+        assert_eq!(decoder.get_tag(Tag::Unknown(65001)).unwrap().into_u32_vec().unwrap(), [1, 2]);
+        assert_eq!(decoder.get_tag(Tag::Unknown(65002)).unwrap().into_u32_vec().unwrap(), [1, 2, 3]);
+        assert_eq!(decoder.get_tag(Tag::Unknown(65003)).unwrap().into_u32_vec().unwrap(), [1, 2, 3, 4]);
+        assert_eq!(decoder.get_tag(Tag::Unknown(65004)).unwrap().into_u32_vec().unwrap(), [1, 2, 3, 4, 5]);
+    }
+}
+
+#[test]
+/// Test writing signed tags from TIFF 6.0
+fn test_signed() {
+    let mut data = Cursor::new(Vec::new());
+
+    {
+        let mut tiff = TiffEncoder::new(&mut data).unwrap();
+        let mut image_encoder = tiff.new_image::<colortype::Gray8>(1, 1).unwrap();
+        let encoder = image_encoder.encoder();
+
+        //Use the "reusable" tags section as per the TIFF6 spec
+        encoder.write_tag(Tag::Unknown(65000), -1_i8);
+        encoder.write_tag(Tag::Unknown(65001), &[-1_i8][..]);
+        encoder.write_tag(Tag::Unknown(65002), &[-1_i8, 2][..]);
+        encoder.write_tag(Tag::Unknown(65003), &[-1_i8, 2, -3][..]);
+        encoder.write_tag(Tag::Unknown(65004), &[-1_i8, 2, -3, 4][..]);
+        encoder.write_tag(Tag::Unknown(65005), &[-1_i8, 2, -3, 4, -5][..]);
+
+        encoder.write_tag(Tag::Unknown(65010), -1_i16);
+        encoder.write_tag(Tag::Unknown(65011), -1_i16);
+        encoder.write_tag(Tag::Unknown(65012), &[-1_i16, 2][..]);
+        encoder.write_tag(Tag::Unknown(65013), &[-1_i16, 2, -3][..]);
+
+        encoder.write_tag(Tag::Unknown(65020), -1_i32);
+        encoder.write_tag(Tag::Unknown(65021), &[-1_i32][..]);
+        encoder.write_tag(Tag::Unknown(65022), &[-1_i32, 2][..]);
+
+        encoder.write_tag(Tag::Unknown(65030), SRational { n: -1, d: 100 });
+        encoder.write_tag(Tag::Unknown(65031), &[SRational { n: -1, d: 100 }, SRational { n: 2, d: 100 }][..]);
+    }
+
+    //Rewind the cursor for reading
+    data.set_position(0);
+    {
+        let mut decoder = Decoder::new(&mut data).unwrap();
+
+        assert_eq!(decoder.get_tag(Tag::Unknown(65000)).unwrap().into_i32().unwrap(), -1, );
+        assert_eq!(decoder.get_tag(Tag::Unknown(65001)).unwrap().into_i32_vec().unwrap(), [-1]);
+        assert_eq!(decoder.get_tag(Tag::Unknown(65002)).unwrap().into_i32_vec().unwrap(), [-1, 2]);
+        assert_eq!(decoder.get_tag(Tag::Unknown(65003)).unwrap().into_i32_vec().unwrap(), [-1, 2, -3]);
+        assert_eq!(decoder.get_tag(Tag::Unknown(65004)).unwrap().into_i32_vec().unwrap(), [-1, 2, -3, 4]);
+        assert_eq!(decoder.get_tag(Tag::Unknown(65005)).unwrap().into_i32_vec().unwrap(), [-1, 2, -3, 4, -5], );
+
+        assert_eq!(decoder.get_tag(Tag::Unknown(65010)).unwrap().into_i32().unwrap(), -1);
+        assert_eq!(decoder.get_tag(Tag::Unknown(65011)).unwrap().into_i32_vec().unwrap(), [-1]);
+        assert_eq!(decoder.get_tag(Tag::Unknown(65012)).unwrap().into_i32_vec().unwrap(), [-1, 2]);
+        assert_eq!(decoder.get_tag(Tag::Unknown(65013)).unwrap().into_i32_vec().unwrap(), [-1, 2, -3]);
+
+        assert_eq!(decoder.get_tag(Tag::Unknown(65020)).unwrap().into_i32().unwrap(), -1);
+        assert_eq!(decoder.get_tag(Tag::Unknown(65021)).unwrap().into_i32_vec().unwrap(), [-1]);
+        assert_eq!(decoder.get_tag(Tag::Unknown(65022)).unwrap().into_i32_vec().unwrap(), [-1, 2]);
+
+        assert_eq!(decoder.get_tag(Tag::Unknown(65030)).unwrap().into_i32_vec().unwrap(), [-1, 100]);
+        assert_eq!(decoder.get_tag(Tag::Unknown(65031)).unwrap().into_i32_vec().unwrap(), [-1_i32, 100, 2, 100]);
+    }
+}
\ No newline at end of file