Remove most unchecked size/index casts

Convert most unchecked size/index `as` casts to checked casts with
`TryFrom`, included another top-level error variant.

This has several motivations:
- Making the library as robust as possible, including to platform
differences.
- Unchecked casts are susceptible to breakage during refactorings.
- Preparing for BigTIFF support, which will require the introduction of
generics and associated types for some parts of the de/encoders.
Unchecked primitive casts cannot be bound, while TryFrom can, and
overflowing conversions become more likely.
- Remaining u16 casts may be prone in failure in existing practice and
not just in theory during future changes.
This commit is contained in:
Andrew Champion committed 2019-12-21 15:57:24 +00:00
1 parent 462697e373
commit eadec8f0b9
5 files changed
+100 -81

No files matched your search

+7 -4
View File
@@ -1,6 +1,7 @@
//! Function for reading TIFF tags //! Function for reading TIFF tags
use std::collections::HashMap; use std::collections::HashMap;
use std::convert::TryFrom;
use std::io::{self, Read, Seek}; use std::io::{self, Read, Seek};
use std::mem; use std::mem;
@@ -193,11 +194,12 @@ impl Entry {
)) ))
}), }),
(Type::ASCII, n) => { (Type::ASCII, n) => {
if n as usize > limits.decoding_buffer_size { let n = usize::try_from(n)?;
if n > limits.decoding_buffer_size {
return Err(TiffError::LimitsExceeded); return Err(TiffError::LimitsExceeded);
} }
decoder.goto_offset(self.r(bo).read_u32()?)?; decoder.goto_offset(self.r(bo).read_u32()?)?;
let string = decoder.read_string(n as usize)?; let string = decoder.read_string(n)?;
Ok(Ascii(string)) Ok(Ascii(string))
} }
_ => Err(TiffError::UnsupportedError( _ => Err(TiffError::UnsupportedError(
@@ -212,11 +214,12 @@ impl Entry {
R: Read + Seek, R: Read + Seek,
F: Fn(&mut super::Decoder<R>) -> TiffResult<Value>, F: Fn(&mut super::Decoder<R>) -> TiffResult<Value>,
{ {
if value_count as usize > limits.decoding_buffer_size / mem::size_of::<Value>() { let value_count = usize::try_from(value_count)?;
if value_count > limits.decoding_buffer_size / mem::size_of::<Value>() {
return Err(TiffError::LimitsExceeded); return Err(TiffError::LimitsExceeded);
} }
let mut v = Vec::with_capacity(value_count as usize); let mut v = Vec::with_capacity(value_count);
decoder.goto_offset(self.r(bo).read_u32()?)?; decoder.goto_offset(self.r(bo).read_u32()?)?;
for _ in 0..value_count { for _ in 0..value_count {
v.push(decode_fn(decoder)?) v.push(decode_fn(decoder)?)
+27 -26
View File
@@ -197,12 +197,12 @@ impl Wrapping for u64 {
} }
} }
fn rev_hpredict_nsamp<T>(image: &mut [T], size: (u32, u32), samples: usize) fn rev_hpredict_nsamp<T>(image: &mut [T], size: (u32, u32), samples: usize) -> TiffResult<()>
where where
T: Copy + Wrapping, T: Copy + Wrapping,
{ {
let width = size.0 as usize; let width = usize::try_from(size.0)?;
let height = size.1 as usize; let height = usize::try_from(size.1)?;
for row in 0..height { for row in 0..height {
for col in samples..width * samples { for col in samples..width * samples {
let prev_pixel = image[(row * width * samples + col - samples)]; let prev_pixel = image[(row * width * samples + col - samples)];
@@ -210,6 +210,7 @@ where
*pixel = pixel.wrapping_add(prev_pixel); *pixel = pixel.wrapping_add(prev_pixel);
} }
} }
Ok(())
} }
fn rev_hpredict(image: DecodingBuffer, size: (u32, u32), color_type: ColorType) -> TiffResult<()> { fn rev_hpredict(image: DecodingBuffer, size: (u32, u32), color_type: ColorType) -> TiffResult<()> {
@@ -226,16 +227,16 @@ fn rev_hpredict(image: DecodingBuffer, size: (u32, u32), color_type: ColorType)
}; };
match image { match image {
DecodingBuffer::U8(buf) => { DecodingBuffer::U8(buf) => {
rev_hpredict_nsamp(buf, size, samples); rev_hpredict_nsamp(buf, size, samples)?;
} }
DecodingBuffer::U16(buf) => { DecodingBuffer::U16(buf) => {
rev_hpredict_nsamp(buf, size, samples); rev_hpredict_nsamp(buf, size, samples)?;
} }
DecodingBuffer::U32(buf) => { DecodingBuffer::U32(buf) => {
rev_hpredict_nsamp(buf, size, samples); rev_hpredict_nsamp(buf, size, samples)?;
} }
DecodingBuffer::U64(buf) => { DecodingBuffer::U64(buf) => {
rev_hpredict_nsamp(buf, size, samples); rev_hpredict_nsamp(buf, size, samples)?;
} }
} }
Ok(()) Ok(())
@@ -575,14 +576,14 @@ impl<R: Read + Seek> Decoder<R> {
CompressionMethod::None => { CompressionMethod::None => {
let order = self.reader.byte_order; let order = self.reader.byte_order;
( (
length as usize, usize::try_from(length)?,
Box::new(SmartReader::wrap(&mut self.reader, order)), Box::new(SmartReader::wrap(&mut self.reader, order)),
) )
} }
CompressionMethod::LZW => { CompressionMethod::LZW => {
let (bytes, reader) = LZWReader::new( let (bytes, reader) = LZWReader::new(
&mut self.reader, &mut self.reader,
length as usize, usize::try_from(length)?,
max_uncompressed_length max_uncompressed_length
)?; )?;
(bytes, Box::new(reader)) (bytes, Box::new(reader))
@@ -592,7 +593,7 @@ impl<R: Read + Seek> Decoder<R> {
let (bytes, reader) = PackBitsReader::new( let (bytes, reader) = PackBitsReader::new(
&mut self.reader, &mut self.reader,
order, order,
length as usize usize::try_from(length)?,
)?; )?;
(bytes, Box::new(reader)) (bytes, Box::new(reader))
} }
@@ -732,18 +733,18 @@ impl<R: Read + Seek> Decoder<R> {
TiffFormatError::InconsistentSizesEncountered, TiffFormatError::InconsistentSizesEncountered,
))?; ))?;
let rows_per_strip = self let rows_per_strip = usize::try_from(self
.get_tag_u32(Tag::RowsPerStrip) .get_tag_u32(Tag::RowsPerStrip)
.unwrap_or(self.height) as usize; .unwrap_or(self.height))?;
let strip_height = cmp::min( let strip_height = cmp::min(
rows_per_strip, rows_per_strip,
self.height as usize - index * rows_per_strip, usize::try_from(self.height)? - index * rows_per_strip,
); );
let buffer_size = self.width as usize * strip_height * self.bits_per_sample.len(); let buffer_size = usize::try_from(self.width)? * strip_height * self.bits_per_sample.len();
if buffer.len() < buffer_size || byte_count as usize / buffer.byte_len() > buffer_size { if buffer.len() < buffer_size || usize::try_from(byte_count)? / buffer.byte_len() > buffer_size {
return Err(TiffError::FormatError( return Err(TiffError::FormatError(
TiffFormatError::InconsistentSizesEncountered, TiffFormatError::InconsistentSizesEncountered,
)); ));
@@ -753,7 +754,7 @@ impl<R: Read + Seek> Decoder<R> {
self.strip_decoder.as_mut().unwrap().strip_index += 1; self.strip_decoder.as_mut().unwrap().strip_index += 1;
if index as u32 == self.strip_count()? { if u32::try_from(index)? == self.strip_count()? {
self.strip_decoder = None; self.strip_decoder = None;
} }
@@ -768,7 +769,7 @@ impl<R: Read + Seek> Decoder<R> {
Some(Predictor::Horizontal) => { Some(Predictor::Horizontal) => {
rev_hpredict( rev_hpredict(
buffer.copy(), buffer.copy(),
(self.width, strip_height as u32), (self.width, u32::try_from(strip_height)?),
self.colortype()?, self.colortype()?,
)?; )?;
} }
@@ -784,7 +785,7 @@ impl<R: Read + Seek> Decoder<R> {
} }
fn result_buffer(&self, height: usize) -> TiffResult<DecodingResult> { fn result_buffer(&self, height: usize) -> TiffResult<DecodingResult> {
let buffer_size = self.width as usize * height * self.bits_per_sample.len(); let buffer_size = usize::try_from(self.width)? * height * self.bits_per_sample.len();
match self.bits_per_sample.iter().cloned().max().unwrap_or(8) { match self.bits_per_sample.iter().cloned().max().unwrap_or(8) {
n if n <= 8 => DecodingResult::new_u8(buffer_size, &self.limits), n if n <= 8 => DecodingResult::new_u8(buffer_size, &self.limits),
@@ -804,13 +805,13 @@ impl<R: Read + Seek> Decoder<R> {
self.initialize_strip_decoder()?; self.initialize_strip_decoder()?;
let index = self.strip_decoder.as_ref().unwrap().strip_index; let index = self.strip_decoder.as_ref().unwrap().strip_index;
let rows_per_strip = self let rows_per_strip = usize::try_from(self
.get_tag_u32(Tag::RowsPerStrip) .get_tag_u32(Tag::RowsPerStrip)
.unwrap_or(self.height) as usize; .unwrap_or(self.height))?;
let strip_height = cmp::min( let strip_height = cmp::min(
rows_per_strip, rows_per_strip,
self.height as usize - index * rows_per_strip, usize::try_from(self.height)? - index * rows_per_strip,
); );
let mut result = self.result_buffer(strip_height)?; let mut result = self.result_buffer(strip_height)?;
@@ -823,16 +824,16 @@ impl<R: Read + Seek> Decoder<R> {
/// Decodes the entire image and return it as a Vector /// Decodes the entire image and return it as a Vector
pub fn read_image(&mut self) -> TiffResult<DecodingResult> { pub fn read_image(&mut self) -> TiffResult<DecodingResult> {
self.initialize_strip_decoder()?; self.initialize_strip_decoder()?;
let rows_per_strip = self let rows_per_strip = usize::try_from(self
.get_tag_u32(Tag::RowsPerStrip) .get_tag_u32(Tag::RowsPerStrip)
.unwrap_or(self.height) as usize; .unwrap_or(self.height))?;
let samples_per_strip = let samples_per_strip =
self.width as usize * rows_per_strip * self.bits_per_sample.len(); usize::try_from(self.width)? * rows_per_strip * self.bits_per_sample.len();
let mut result = self.result_buffer(self.height as usize)?; let mut result = self.result_buffer(usize::try_from(self.height)?)?;
for i in 0..self.strip_count()? as usize { for i in 0..usize::try_from(self.strip_count()?)? {
self.read_strip_to_buffer(result.as_buffer(samples_per_strip * i))?; self.read_strip_to_buffer(result.as_buffer(samples_per_strip * i))?;
} }
+34 -31
View File
@@ -1,5 +1,6 @@
use byteorder::NativeEndian; use byteorder::NativeEndian;
use std::collections::BTreeMap; use std::collections::BTreeMap;
use std::convert::TryFrom;
use std::io::{Seek, Write}; use std::io::{Seek, Write};
use std::mem; use std::mem;
@@ -406,7 +407,7 @@ impl<W: Write + Seek> TiffEncoder<W> {
where where
[C::Inner]: TiffValue, [C::Inner]: TiffValue,
{ {
let num_pix = (width as usize).checked_mul(height as usize) let num_pix = usize::try_from(width)?.checked_mul(usize::try_from(height)?)
.ok_or_else(|| ::std::io::Error::new( .ok_or_else(|| ::std::io::Error::new(
::std::io::ErrorKind::InvalidInput, ::std::io::ErrorKind::InvalidInput,
"Image width * height exceeds usize"))?; "Image width * height exceeds usize"))?;
@@ -421,7 +422,7 @@ impl<W: Write + Seek> TiffEncoder<W> {
let mut idx = 0; let mut idx = 0;
while image.next_strip_sample_count() > 0 { while image.next_strip_sample_count() > 0 {
let sample_count = image.next_strip_sample_count() as usize; let sample_count = usize::try_from(image.next_strip_sample_count())?;
image.write_strip(&data[idx..idx + sample_count])?; image.write_strip(&data[idx..idx + sample_count])?;
idx += sample_count; idx += sample_count;
} }
@@ -444,7 +445,7 @@ pub struct DirectoryEncoder<'a, W: 'a + Write + Seek> {
impl<'a, W: 'a + Write + Seek> DirectoryEncoder<'a, W> { impl<'a, W: 'a + Write + Seek> DirectoryEncoder<'a, W> {
fn new(writer: &'a mut TiffWriter<W>) -> TiffResult<DirectoryEncoder<'a, W>> { fn new(writer: &'a mut TiffWriter<W>) -> TiffResult<DirectoryEncoder<'a, W>> {
// the previous word is the IFD offset position // the previous word is the IFD offset position
let ifd_pointer_pos = writer.offset() - mem::size_of::<u32>() as u64; let ifd_pointer_pos = writer.offset() - u64::try_from(mem::size_of::<u32>())?;
writer.pad_word_boundary()?; writer.pad_word_boundary()?;
Ok(DirectoryEncoder { Ok(DirectoryEncoder {
writer, writer,
@@ -455,16 +456,18 @@ impl<'a, W: 'a + Write + Seek> DirectoryEncoder<'a, W> {
} }
/// Write a single ifd tag. /// Write a single ifd tag.
pub fn write_tag<T: TiffValue>(&mut self, tag: Tag, value: T) { pub fn write_tag<T: TiffValue>(&mut self, tag: Tag, value: T) -> TiffResult<()> {
let len = <T>::BYTE_LEN * value.count(); let len = <T>::BYTE_LEN * value.count();
let mut bytes = Vec::with_capacity(len as usize); let mut bytes = Vec::with_capacity(usize::try_from(len)?);
{ {
let mut writer = TiffWriter::new(&mut bytes); let mut writer = TiffWriter::new(&mut bytes);
value.write(&mut writer).unwrap(); value.write(&mut writer)?;
} }
self.ifd self.ifd
.insert(tag.to_u16(), (<T>::FIELD_TYPE.to_u16(), value.count(), bytes)); .insert(tag.to_u16(), (<T>::FIELD_TYPE.to_u16(), value.count(), bytes));
Ok(())
} }
fn write_directory(&mut self) -> TiffResult<u64> { fn write_directory(&mut self) -> TiffResult<u64> {
@@ -475,7 +478,7 @@ impl<'a, W: 'a + Write + Seek> DirectoryEncoder<'a, W> {
self.writer.write_bytes(bytes)?; self.writer.write_bytes(bytes)?;
*bytes = vec![0, 0, 0, 0]; *bytes = vec![0, 0, 0, 0];
let mut writer = TiffWriter::new(bytes as &mut [u8]); let mut writer = TiffWriter::new(bytes as &mut [u8]);
writer.write_u32(offset as u32)?; writer.write_u32(u32::try_from(offset)?)?;
} else { } else {
while bytes.len() < 4 { while bytes.len() < 4 {
bytes.push(0); bytes.push(0);
@@ -485,7 +488,7 @@ impl<'a, W: 'a + Write + Seek> DirectoryEncoder<'a, W> {
let offset = self.writer.offset(); let offset = self.writer.offset();
self.writer.write_u16(self.ifd.len() as u16)?; self.writer.write_u16(u16::try_from(self.ifd.len())?)?;
for (tag, &(ref field_type, ref count, ref offset)) in self.ifd.iter() { for (tag, &(ref field_type, ref count, ref offset)) in self.ifd.iter() {
self.writer.write_u16(*tag)?; self.writer.write_u16(*tag)?;
self.writer.write_u16(*field_type)?; self.writer.write_u16(*field_type)?;
@@ -510,7 +513,7 @@ impl<'a, W: 'a + Write + Seek> DirectoryEncoder<'a, W> {
let curr_pos = self.writer.offset(); let curr_pos = self.writer.offset();
self.writer.goto_offset(self.ifd_pointer_pos)?; self.writer.goto_offset(self.ifd_pointer_pos)?;
self.writer.write_u32(ifd_pointer as u32)?; self.writer.write_u32(u32::try_from(ifd_pointer)?)?;
self.writer.goto_offset(curr_pos)?; self.writer.goto_offset(curr_pos)?;
self.writer.write_u32(0)?; self.writer.write_u32(0)?;
@@ -577,7 +580,7 @@ impl<'a, W: 'a + Write + Seek, T: ColorType> ImageEncoder<'a, W, T> {
width: u32, width: u32,
height: u32, height: u32,
) -> TiffResult<ImageEncoder<'a, W, T>> { ) -> TiffResult<ImageEncoder<'a, W, T>> {
let row_samples = u64::from(width) * <T>::BITS_PER_SAMPLE.len() as u64; let row_samples = u64::from(width) * u64::try_from(<T>::BITS_PER_SAMPLE.len())?;
let row_bytes = row_samples * u64::from(<T::Inner>::BYTE_LEN); let row_bytes = row_samples * u64::from(<T::Inner>::BYTE_LEN);
// As per tiff spec each strip should be about 8k long // As per tiff spec each strip should be about 8k long
@@ -585,19 +588,19 @@ impl<'a, W: 'a + Write + Seek, T: ColorType> ImageEncoder<'a, W, T> {
let strip_count = (u64::from(height) + rows_per_strip - 1) / rows_per_strip; let strip_count = (u64::from(height) + rows_per_strip - 1) / rows_per_strip;
encoder.write_tag(Tag::ImageWidth, width); encoder.write_tag(Tag::ImageWidth, width)?;
encoder.write_tag(Tag::ImageLength, height); encoder.write_tag(Tag::ImageLength, height)?;
encoder.write_tag(Tag::Compression, tags::CompressionMethod::None.to_u16()); encoder.write_tag(Tag::Compression, tags::CompressionMethod::None.to_u16())?;
encoder.write_tag(Tag::BitsPerSample, <T>::BITS_PER_SAMPLE); encoder.write_tag(Tag::BitsPerSample, <T>::BITS_PER_SAMPLE)?;
encoder.write_tag(Tag::PhotometricInterpretation, <T>::TIFF_VALUE.to_u16()); encoder.write_tag(Tag::PhotometricInterpretation, <T>::TIFF_VALUE.to_u16())?;
encoder.write_tag(Tag::RowsPerStrip, rows_per_strip as u32); encoder.write_tag(Tag::RowsPerStrip, u32::try_from(rows_per_strip)?)?;
encoder.write_tag(Tag::SamplesPerPixel, <T>::BITS_PER_SAMPLE.len() as u16); encoder.write_tag(Tag::SamplesPerPixel, u16::try_from(<T>::BITS_PER_SAMPLE.len())?)?;
encoder.write_tag(Tag::XResolution, Rational { n: 1, d: 1 }); encoder.write_tag(Tag::XResolution, Rational { n: 1, d: 1 })?;
encoder.write_tag(Tag::YResolution, Rational { n: 1, d: 1 }); encoder.write_tag(Tag::YResolution, Rational { n: 1, d: 1 })?;
encoder.write_tag(Tag::ResolutionUnit, ResolutionUnit::None.to_u16()); encoder.write_tag(Tag::ResolutionUnit, ResolutionUnit::None.to_u16())?;
Ok(ImageEncoder { Ok(ImageEncoder {
encoder, encoder,
@@ -635,15 +638,15 @@ impl<'a, W: 'a + Write + Seek, T: ColorType> ImageEncoder<'a, W, T> {
{ {
// TODO: Compression // TODO: Compression
let samples = self.next_strip_sample_count(); let samples = self.next_strip_sample_count();
if value.len() as u64 != samples { if u64::try_from(value.len())? != samples {
return Err(::std::io::Error::new( return Err(::std::io::Error::new(
::std::io::ErrorKind::InvalidData, ::std::io::ErrorKind::InvalidData,
"Slice is wrong size for strip").into()); "Slice is wrong size for strip").into());
} }
let offset = self.encoder.write_data(value)?; let offset = self.encoder.write_data(value)?;
self.strip_offsets.push(offset as u32); self.strip_offsets.push(u32::try_from(offset)?);
self.strip_byte_count.push(value.bytes() as u32); self.strip_byte_count.push(value.bytes());
self.strip_idx += 1; self.strip_idx += 1;
Ok(()) Ok(())
@@ -651,31 +654,31 @@ impl<'a, W: 'a + Write + Seek, T: ColorType> ImageEncoder<'a, W, T> {
/// Set image resolution /// Set image resolution
pub fn resolution(&mut self, unit: ResolutionUnit, value: Rational) { pub fn resolution(&mut self, unit: ResolutionUnit, value: Rational) {
self.encoder.write_tag(Tag::ResolutionUnit, unit.to_u16()); self.encoder.write_tag(Tag::ResolutionUnit, unit.to_u16()).unwrap();
self.encoder.write_tag(Tag::XResolution, value.clone()); self.encoder.write_tag(Tag::XResolution, value.clone()).unwrap();
self.encoder.write_tag(Tag::YResolution, value); self.encoder.write_tag(Tag::YResolution, value).unwrap();
} }
/// Set image resolution unit /// Set image resolution unit
pub fn resolution_unit(&mut self, unit: ResolutionUnit) { pub fn resolution_unit(&mut self, unit: ResolutionUnit) {
self.encoder.write_tag(Tag::ResolutionUnit, unit.to_u16()); self.encoder.write_tag(Tag::ResolutionUnit, unit.to_u16()).unwrap();
} }
/// Set image x-resolution /// Set image x-resolution
pub fn x_resolution(&mut self, value: Rational) { pub fn x_resolution(&mut self, value: Rational) {
self.encoder.write_tag(Tag::XResolution, value); self.encoder.write_tag(Tag::XResolution, value).unwrap();
} }
/// Set image y-resolution /// Set image y-resolution
pub fn y_resolution(&mut self, value: Rational) { pub fn y_resolution(&mut self, value: Rational) {
self.encoder.write_tag(Tag::YResolution, value); self.encoder.write_tag(Tag::YResolution, value).unwrap();
} }
fn finish_internal(&mut self) -> TiffResult<()> { fn finish_internal(&mut self) -> TiffResult<()> {
self.encoder self.encoder
.write_tag(Tag::StripOffsets, &*self.strip_offsets); .write_tag(Tag::StripOffsets, &*self.strip_offsets)?;
self.encoder self.encoder
.write_tag(Tag::StripByteCounts, &*self.strip_byte_count); .write_tag(Tag::StripByteCounts, &*self.strip_byte_count)?;
self.dropped = true; self.dropped = true;
self.encoder.finish_internal() self.encoder.finish_internal()
+12
View File
@@ -22,6 +22,10 @@ pub enum TiffError {
/// The Limits of the Decoder is exceeded. /// The Limits of the Decoder is exceeded.
LimitsExceeded, LimitsExceeded,
/// An integer conversion to or from a platform size failed, either due to
/// limits of the platform size or limits of the format.
IntSizeError,
} }
/// The image is not formatted properly. /// The image is not formatted properly.
@@ -171,6 +175,7 @@ impl fmt::Display for TiffError {
), ),
TiffError::IoError(ref e) => e.fmt(fmt), TiffError::IoError(ref e) => e.fmt(fmt),
TiffError::LimitsExceeded => write!(fmt, "The Decoder limits are exceeded"), TiffError::LimitsExceeded => write!(fmt, "The Decoder limits are exceeded"),
TiffError::IntSizeError => write!(fmt, "Platform or format size limits exceeded"),
} }
} }
} }
@@ -182,6 +187,7 @@ impl Error for TiffError {
TiffError::UnsupportedError(..) => "Unsupported error", TiffError::UnsupportedError(..) => "Unsupported error",
TiffError::IoError(..) => "IO error", TiffError::IoError(..) => "IO error",
TiffError::LimitsExceeded => "Decoder limits exceeded", TiffError::LimitsExceeded => "Decoder limits exceeded",
TiffError::IntSizeError => "Platform or format size limits exceeded",
} }
} }
@@ -217,5 +223,11 @@ impl From<TiffUnsupportedError> for TiffError {
} }
} }
impl From<std::num::TryFromIntError> for TiffError {
fn from(_err: std::num::TryFromIntError) -> TiffError {
TiffError::IntSizeError
}
}
/// Result of an image decoding/encoding process /// Result of an image decoding/encoding process
pub type TiffResult<T> = Result<T, TiffError>; pub type TiffResult<T> = Result<T, TiffError>;
+20 -20
View File
@@ -144,11 +144,11 @@ fn test_multiple_byte() {
let mut image_encoder = tiff.new_image::<colortype::Gray8>(1, 1).unwrap(); let mut image_encoder = tiff.new_image::<colortype::Gray8>(1, 1).unwrap();
let encoder = image_encoder.encoder(); let encoder = image_encoder.encoder();
encoder.write_tag(Tag::Unknown(65000), &[1_u8][..]); encoder.write_tag(Tag::Unknown(65000), &[1_u8][..]).unwrap();
encoder.write_tag(Tag::Unknown(65001), &[1_u8, 2][..]); encoder.write_tag(Tag::Unknown(65001), &[1_u8, 2][..]).unwrap();
encoder.write_tag(Tag::Unknown(65002), &[1_u8, 2, 3][..]); encoder.write_tag(Tag::Unknown(65002), &[1_u8, 2, 3][..]).unwrap();
encoder.write_tag(Tag::Unknown(65003), &[1_u8, 2, 3, 4][..]); encoder.write_tag(Tag::Unknown(65003), &[1_u8, 2, 3, 4][..]).unwrap();
encoder.write_tag(Tag::Unknown(65004), &[1_u8, 2, 3, 4, 5][..]); encoder.write_tag(Tag::Unknown(65004), &[1_u8, 2, 3, 4, 5][..]).unwrap();
} }
data.set_position(0); data.set_position(0);
@@ -174,24 +174,24 @@ fn test_signed() {
let encoder = image_encoder.encoder(); let encoder = image_encoder.encoder();
//Use the "reusable" tags section as per the TIFF6 spec //Use the "reusable" tags section as per the TIFF6 spec
encoder.write_tag(Tag::Unknown(65000), -1_i8); encoder.write_tag(Tag::Unknown(65000), -1_i8).unwrap();
encoder.write_tag(Tag::Unknown(65001), &[-1_i8][..]); encoder.write_tag(Tag::Unknown(65001), &[-1_i8][..]).unwrap();
encoder.write_tag(Tag::Unknown(65002), &[-1_i8, 2][..]); encoder.write_tag(Tag::Unknown(65002), &[-1_i8, 2][..]).unwrap();
encoder.write_tag(Tag::Unknown(65003), &[-1_i8, 2, -3][..]); encoder.write_tag(Tag::Unknown(65003), &[-1_i8, 2, -3][..]).unwrap();
encoder.write_tag(Tag::Unknown(65004), &[-1_i8, 2, -3, 4][..]); encoder.write_tag(Tag::Unknown(65004), &[-1_i8, 2, -3, 4][..]).unwrap();
encoder.write_tag(Tag::Unknown(65005), &[-1_i8, 2, -3, 4, -5][..]); encoder.write_tag(Tag::Unknown(65005), &[-1_i8, 2, -3, 4, -5][..]).unwrap();
encoder.write_tag(Tag::Unknown(65010), -1_i16); encoder.write_tag(Tag::Unknown(65010), -1_i16).unwrap();
encoder.write_tag(Tag::Unknown(65011), -1_i16); encoder.write_tag(Tag::Unknown(65011), -1_i16).unwrap();
encoder.write_tag(Tag::Unknown(65012), &[-1_i16, 2][..]); encoder.write_tag(Tag::Unknown(65012), &[-1_i16, 2][..]).unwrap();
encoder.write_tag(Tag::Unknown(65013), &[-1_i16, 2, -3][..]); encoder.write_tag(Tag::Unknown(65013), &[-1_i16, 2, -3][..]).unwrap();
encoder.write_tag(Tag::Unknown(65020), -1_i32); encoder.write_tag(Tag::Unknown(65020), -1_i32).unwrap();
encoder.write_tag(Tag::Unknown(65021), &[-1_i32][..]); encoder.write_tag(Tag::Unknown(65021), &[-1_i32][..]).unwrap();
encoder.write_tag(Tag::Unknown(65022), &[-1_i32, 2][..]); encoder.write_tag(Tag::Unknown(65022), &[-1_i32, 2][..]).unwrap();
encoder.write_tag(Tag::Unknown(65030), SRational { n: -1, d: 100 }); encoder.write_tag(Tag::Unknown(65030), SRational { n: -1, d: 100 }).unwrap();
encoder.write_tag(Tag::Unknown(65031), &[SRational { n: -1, d: 100 }, SRational { n: 2, d: 100 }][..]); encoder.write_tag(Tag::Unknown(65031), &[SRational { n: -1, d: 100 }, SRational { n: 2, d: 100 }][..]).unwrap();
} }
//Rewind the cursor for reading //Rewind the cursor for reading