use std::collections::HashMap;
use std::io::Read;
use bytes::Bytes;
use crate::error::{AsyncTiffError, AsyncTiffResult, TiffError, TiffFormatError};
use crate::metadata::fetch::MetadataCursor;
use crate::metadata::MetadataFetch;
use crate::reader::Endianness;
use crate::tag_value::TagValue;
use crate::tags::{Tag, Type};
use crate::{ImageFileDirectory, TIFF};
pub struct TiffMetadataReader {
endianness: Endianness,
bigtiff: bool,
next_ifd_offset: Option<u64>,
}
impl TiffMetadataReader {
pub async fn try_open<F: MetadataFetch>(fetch: &F) -> AsyncTiffResult<Self> {
let magic_bytes = fetch.fetch(0..2).await?;
let endianness = if magic_bytes == Bytes::from_static(b"II") {
Endianness::LittleEndian
} else if magic_bytes == Bytes::from_static(b"MM") {
Endianness::BigEndian
} else {
return Err(AsyncTiffError::General(format!(
"unexpected magic bytes {magic_bytes:?}"
)));
};
let mut cursor = MetadataCursor::new(fetch, endianness).with_offset(2);
let version = cursor.read_u16().await?;
let bigtiff = match version {
42 => false,
43 => {
if cursor.read_u16().await? != 8 {
return Err(
TiffError::FormatError(TiffFormatError::TiffSignatureNotFound).into(),
);
}
if cursor.read_u16().await? != 0 {
return Err(
TiffError::FormatError(TiffFormatError::TiffSignatureNotFound).into(),
);
}
true
}
_ => return Err(TiffError::FormatError(TiffFormatError::TiffSignatureInvalid).into()),
};
let first_ifd_location = if bigtiff {
cursor.read_u64().await?
} else {
cursor.read_u32().await?.into()
};
Ok(Self {
endianness,
bigtiff,
next_ifd_offset: Some(first_ifd_location),
})
}
pub fn endianness(&self) -> Endianness {
self.endianness
}
pub fn bigtiff(&self) -> bool {
self.bigtiff
}
pub fn has_next_ifd(&self) -> bool {
self.next_ifd_offset.is_some()
}
pub fn next_ifd_offset(&self) -> Option<u64> {
self.next_ifd_offset
}
pub async fn read_next_ifd<F: MetadataFetch>(
&mut self,
fetch: &F,
) -> AsyncTiffResult<Option<ImageFileDirectory>> {
if let Some(ifd_start) = self.next_ifd_offset {
let ifd_reader =
ImageFileDirectoryReader::open(fetch, ifd_start, self.bigtiff, self.endianness)
.await?;
let ifd = ifd_reader.read(fetch).await?;
let next_ifd_offset = ifd_reader.finish(fetch).await?;
self.next_ifd_offset = next_ifd_offset;
Ok(Some(ifd))
} else {
Ok(None)
}
}
pub async fn read_all_ifds<F: MetadataFetch>(
&mut self,
fetch: &F,
) -> AsyncTiffResult<Vec<ImageFileDirectory>> {
let mut ifds = vec![];
while let Some(ifd) = self.read_next_ifd(fetch).await? {
ifds.push(ifd);
}
Ok(ifds)
}
pub async fn read<F: MetadataFetch>(&mut self, fetch: &F) -> AsyncTiffResult<TIFF> {
let ifds = self.read_all_ifds(fetch).await?;
Ok(TIFF::new(ifds, self.endianness))
}
}
pub struct ImageFileDirectoryReader {
endianness: Endianness,
bigtiff: bool,
ifd_start_offset: u64,
tag_count: u64,
ifd_entry_byte_size: u64,
tag_count_byte_size: u64,
}
impl ImageFileDirectoryReader {
pub async fn open<F: MetadataFetch>(
fetch: &F,
ifd_start_offset: u64,
bigtiff: bool,
endianness: Endianness,
) -> AsyncTiffResult<Self> {
let mut cursor = MetadataCursor::new_with_offset(fetch, endianness, ifd_start_offset);
let ifd_entry_byte_size = if bigtiff { 20 } else { 12 };
let tag_count_byte_size = if bigtiff { 8 } else { 2 };
let tag_count = if bigtiff {
cursor.read_u64().await?
} else {
cursor.read_u16().await?.into()
};
Ok(Self {
endianness,
bigtiff,
ifd_entry_byte_size,
tag_count,
tag_count_byte_size,
ifd_start_offset,
})
}
pub async fn read_tag<F: MetadataFetch>(
&self,
fetch: &F,
tag_idx: u64,
) -> AsyncTiffResult<(Tag, TagValue)> {
assert!(tag_idx < self.tag_count);
let tag_offset =
self.ifd_start_offset + self.tag_count_byte_size + (self.ifd_entry_byte_size * tag_idx);
let (tag_name, tag_value) =
read_tag(fetch, tag_offset, self.endianness, self.bigtiff).await?;
Ok((tag_name, tag_value))
}
pub async fn read<F: MetadataFetch>(&self, fetch: &F) -> AsyncTiffResult<ImageFileDirectory> {
let mut tags = HashMap::with_capacity(self.tag_count as usize);
for tag_idx in 0..self.tag_count {
let (tag, value) = self.read_tag(fetch, tag_idx).await?;
tags.insert(tag, value);
}
ImageFileDirectory::from_tags(tags, self.endianness)
}
pub async fn finish<F: MetadataFetch>(self, fetch: &F) -> AsyncTiffResult<Option<u64>> {
let next_ifd_byte_offset = self.ifd_start_offset
+ self.tag_count_byte_size
+ (self.ifd_entry_byte_size * self.tag_count);
let mut cursor =
MetadataCursor::new_with_offset(fetch, self.endianness, next_ifd_byte_offset);
let next_ifd_offset = if self.bigtiff {
cursor.read_u64().await?
} else {
cursor.read_u32().await?.into()
};
if next_ifd_offset == 0 {
Ok(None)
} else {
Ok(Some(next_ifd_offset))
}
}
}
async fn read_tag<F: MetadataFetch>(
fetch: &F,
tag_offset: u64,
endianness: Endianness,
bigtiff: bool,
) -> AsyncTiffResult<(Tag, TagValue)> {
let mut cursor = MetadataCursor::new_with_offset(fetch, endianness, tag_offset);
let tag_name = Tag::from_u16_exhaustive(cursor.read_u16().await?);
let tag_type_code = cursor.read_u16().await?;
let tag_type = Type::from_u16(tag_type_code).expect(
"Unknown tag type {tag_type_code}. TODO: we should skip entries with unknown tag types.",
);
let count = if bigtiff {
cursor.read_u64().await?
} else {
cursor.read_u32().await?.into()
};
let tag_value = read_tag_value(&mut cursor, tag_type, count, bigtiff).await?;
Ok((tag_name, tag_value))
}
async fn read_tag_value<F: MetadataFetch>(
cursor: &mut MetadataCursor<'_, F>,
tag_type: Type,
count: u64,
bigtiff: bool,
) -> AsyncTiffResult<TagValue> {
if count == 0 {
return Ok(TagValue::List(vec![]));
}
let tag_size = match tag_type {
Type::BYTE | Type::SBYTE | Type::ASCII | Type::UNDEFINED => 1,
Type::SHORT | Type::SSHORT => 2,
Type::LONG | Type::SLONG | Type::FLOAT | Type::IFD => 4,
Type::LONG8
| Type::SLONG8
| Type::DOUBLE
| Type::RATIONAL
| Type::SRATIONAL
| Type::IFD8 => 8,
};
let value_byte_length = count.checked_mul(tag_size).unwrap();
if count == 1 {
if bigtiff && value_byte_length > 4 && value_byte_length <= 8 {
let mut data = cursor.read(value_byte_length).await?;
return Ok(match tag_type {
Type::LONG8 => TagValue::UnsignedBig(data.read_u64()?),
Type::SLONG8 => TagValue::SignedBig(data.read_i64()?),
Type::DOUBLE => TagValue::Double(data.read_f64()?),
Type::RATIONAL => TagValue::Rational(data.read_u32()?, data.read_u32()?),
Type::SRATIONAL => TagValue::SRational(data.read_i32()?, data.read_i32()?),
Type::IFD8 => TagValue::IfdBig(data.read_u64()?),
Type::BYTE
| Type::SBYTE
| Type::ASCII
| Type::UNDEFINED
| Type::SHORT
| Type::SSHORT
| Type::LONG
| Type::SLONG
| Type::FLOAT
| Type::IFD => unreachable!(),
});
}
let mut data = cursor.read(value_byte_length).await?;
return Ok(match tag_type {
Type::BYTE | Type::UNDEFINED => TagValue::Byte(data.read_u8()?),
Type::SBYTE => TagValue::SignedByte(data.read_i8()?),
Type::SHORT => TagValue::Short(data.read_u16()?),
Type::SSHORT => TagValue::SignedShort(data.read_i16()?),
Type::LONG => TagValue::Unsigned(data.read_u32()?),
Type::SLONG => TagValue::Signed(data.read_i32()?),
Type::FLOAT => TagValue::Float(data.read_f32()?),
Type::ASCII => {
if data.as_ref()[0] == 0 {
TagValue::Ascii("".to_string())
} else {
panic!("Invalid tag");
}
}
Type::LONG8 => {
let offset = data.read_u32()?;
cursor.seek(offset as _);
TagValue::UnsignedBig(cursor.read_u64().await?)
}
Type::SLONG8 => {
let offset = data.read_u32()?;
cursor.seek(offset as _);
TagValue::SignedBig(cursor.read_i64().await?)
}
Type::DOUBLE => {
let offset = data.read_u32()?;
cursor.seek(offset as _);
TagValue::Double(cursor.read_f64().await?)
}
Type::RATIONAL => {
let offset = data.read_u32()?;
cursor.seek(offset as _);
let numerator = cursor.read_u32().await?;
let denominator = cursor.read_u32().await?;
TagValue::Rational(numerator, denominator)
}
Type::SRATIONAL => {
let offset = data.read_u32()?;
cursor.seek(offset as _);
let numerator = cursor.read_i32().await?;
let denominator = cursor.read_i32().await?;
TagValue::SRational(numerator, denominator)
}
Type::IFD => TagValue::Ifd(data.read_u32()?),
Type::IFD8 => {
let offset = data.read_u32()?;
cursor.seek(offset as _);
TagValue::IfdBig(cursor.read_u64().await?)
}
});
}
if value_byte_length <= 4 || bigtiff && value_byte_length <= 8 {
let mut data = cursor.read(value_byte_length).await?;
if bigtiff {
cursor.advance(8 - value_byte_length);
} else {
cursor.advance(4 - value_byte_length);
}
match tag_type {
Type::BYTE | Type::UNDEFINED => {
return {
Ok(TagValue::List(
(0..count)
.map(|_| TagValue::Byte(data.read_u8().unwrap()))
.collect(),
))
};
}
Type::SBYTE => {
return {
Ok(TagValue::List(
(0..count)
.map(|_| TagValue::SignedByte(data.read_i8().unwrap()))
.collect(),
))
}
}
Type::ASCII => {
let mut buf = vec![0; count as usize];
data.read_exact(&mut buf)?;
if buf.is_ascii() && buf.ends_with(&[0]) {
let v = std::str::from_utf8(&buf)
.map_err(|err| AsyncTiffError::General(err.to_string()))?;
let v = v.trim_matches(char::from(0));
return Ok(TagValue::Ascii(v.into()));
} else {
panic!("Invalid tag");
}
}
Type::SHORT => {
let mut v = Vec::new();
for _ in 0..count {
v.push(TagValue::Short(data.read_u16()?));
}
return Ok(TagValue::List(v));
}
Type::SSHORT => {
let mut v = Vec::new();
for _ in 0..count {
v.push(TagValue::SignedShort(data.read_i16()?));
}
return Ok(TagValue::List(v));
}
Type::LONG => {
let mut v = Vec::new();
for _ in 0..count {
v.push(TagValue::Unsigned(data.read_u32()?));
}
return Ok(TagValue::List(v));
}
Type::SLONG => {
let mut v = Vec::new();
for _ in 0..count {
v.push(TagValue::Signed(data.read_i32()?));
}
return Ok(TagValue::List(v));
}
Type::FLOAT => {
let mut v = Vec::new();
for _ in 0..count {
v.push(TagValue::Float(data.read_f32()?));
}
return Ok(TagValue::List(v));
}
Type::IFD => {
let mut v = Vec::new();
for _ in 0..count {
v.push(TagValue::Ifd(data.read_u32()?));
}
return Ok(TagValue::List(v));
}
Type::LONG8
| Type::SLONG8
| Type::RATIONAL
| Type::SRATIONAL
| Type::DOUBLE
| Type::IFD8 => {
unreachable!()
}
}
}
let offset = if bigtiff {
cursor.read_u64().await?
} else {
cursor.read_u32().await?.into()
};
cursor.seek(offset);
match tag_type {
Type::BYTE | Type::UNDEFINED => {
let mut v = Vec::with_capacity(count as _);
for _ in 0..count {
v.push(TagValue::Byte(cursor.read_u8().await?))
}
Ok(TagValue::List(v))
}
Type::SBYTE => {
let mut v = Vec::with_capacity(count as _);
for _ in 0..count {
v.push(TagValue::SignedByte(cursor.read_i8().await?))
}
Ok(TagValue::List(v))
}
Type::SHORT => {
let mut v = Vec::with_capacity(count as _);
for _ in 0..count {
v.push(TagValue::Short(cursor.read_u16().await?))
}
Ok(TagValue::List(v))
}
Type::SSHORT => {
let mut v = Vec::with_capacity(count as _);
for _ in 0..count {
v.push(TagValue::SignedShort(cursor.read_i16().await?))
}
Ok(TagValue::List(v))
}
Type::LONG => {
let mut v = Vec::with_capacity(count as _);
for _ in 0..count {
v.push(TagValue::Unsigned(cursor.read_u32().await?))
}
Ok(TagValue::List(v))
}
Type::SLONG => {
let mut v = Vec::with_capacity(count as _);
for _ in 0..count {
v.push(TagValue::Signed(cursor.read_i32().await?))
}
Ok(TagValue::List(v))
}
Type::FLOAT => {
let mut v = Vec::with_capacity(count as _);
for _ in 0..count {
v.push(TagValue::Float(cursor.read_f32().await?))
}
Ok(TagValue::List(v))
}
Type::DOUBLE => {
let mut v = Vec::with_capacity(count as _);
for _ in 0..count {
v.push(TagValue::Double(cursor.read_f64().await?))
}
Ok(TagValue::List(v))
}
Type::RATIONAL => {
let mut v = Vec::with_capacity(count as _);
for _ in 0..count {
v.push(TagValue::Rational(
cursor.read_u32().await?,
cursor.read_u32().await?,
))
}
Ok(TagValue::List(v))
}
Type::SRATIONAL => {
let mut v = Vec::with_capacity(count as _);
for _ in 0..count {
v.push(TagValue::SRational(
cursor.read_i32().await?,
cursor.read_i32().await?,
))
}
Ok(TagValue::List(v))
}
Type::LONG8 => {
let mut v = Vec::with_capacity(count as _);
for _ in 0..count {
v.push(TagValue::UnsignedBig(cursor.read_u64().await?))
}
Ok(TagValue::List(v))
}
Type::SLONG8 => {
let mut v = Vec::with_capacity(count as _);
for _ in 0..count {
v.push(TagValue::SignedBig(cursor.read_i64().await?))
}
Ok(TagValue::List(v))
}
Type::IFD => {
let mut v = Vec::with_capacity(count as _);
for _ in 0..count {
v.push(TagValue::Ifd(cursor.read_u32().await?))
}
Ok(TagValue::List(v))
}
Type::IFD8 => {
let mut v = Vec::with_capacity(count as _);
for _ in 0..count {
v.push(TagValue::IfdBig(cursor.read_u64().await?))
}
Ok(TagValue::List(v))
}
Type::ASCII => {
let mut out = vec![0; count as _];
let mut buf = cursor.read(count).await?;
buf.read_exact(&mut out)?;
if let Some(first) = out.iter().position(|&b| b == 0) {
out.truncate(first);
}
Ok(TagValue::Ascii(String::from_utf8_lossy(&out).into_owned()))
}
}
}
#[cfg(test)]
mod test {
use async_trait::async_trait;
use super::*;
#[async_trait]
impl MetadataFetch for Bytes {
async fn fetch(&self, range: std::ops::Range<u64>) -> crate::error::AsyncTiffResult<Bytes> {
let usize_range = range.start as usize..range.end as usize;
Ok(self.slice(usize_range))
}
}
#[tokio::test]
#[rustfmt::skip]
async fn test_single_fits_notbig() {
assert_eq!(u16::from_le_bytes([42,0]),42);
assert_eq!(u16::from_be_bytes([0,42]),42);
assert_eq!(f32::from_le_bytes([0x42,0,0,0]),f32::from_bits(0x00_00_00_42));
assert_eq!(f32::from_be_bytes([0,0,0,0x42]),f32::from_bits(0x00_00_00_42));
let cases= [
([1,1, 1, 0, 1,0,0,0, 42, 0, 0, 0], Endianness::LittleEndian, TagValue::Byte (42 )),
([1,1, 0, 1, 0,0,0,1, 42, 0, 0, 0], Endianness::BigEndian, TagValue::Byte (42 )),
([1,1, 6, 0, 1,0,0,0, 42, 0, 0, 0], Endianness::LittleEndian, TagValue::SignedByte(42 )),
([1,1, 0, 6, 0,0,0,1, 42, 0, 0, 0], Endianness::BigEndian, TagValue::SignedByte(42 )),
([1,1, 7, 0, 1,0,0,0, 42, 0, 0, 0], Endianness::LittleEndian, TagValue::Byte (42 )), ([1,1, 0, 7, 0,0,0,1, 42, 0, 0, 0], Endianness::BigEndian, TagValue::Byte (42 )), ([1,1, 2, 0, 1,0,0,0, 0, 0, 0, 0], Endianness::LittleEndian, TagValue::Ascii ("".into() )),
([1,1, 0, 2, 0,0,0,1, 0, 0, 0, 0], Endianness::BigEndian, TagValue::Ascii ("".into() )),
([1,1, 3, 0, 1,0,0,0, 42, 0, 0, 0], Endianness::LittleEndian, TagValue::Short (42 )),
([1,1, 0, 3, 0,0,0,1, 0,42, 0, 0], Endianness::BigEndian, TagValue::Short (42 )),
([1,1, 8, 0, 1,0,0,0, 42, 0, 0, 0], Endianness::LittleEndian, TagValue::SignedShort (42 )),
([1,1, 0, 8, 0,0,0,1, 0,42, 0, 0], Endianness::BigEndian, TagValue::SignedShort (42 )),
([1,1, 4, 0, 1,0,0,0, 42, 0, 0, 0], Endianness::LittleEndian, TagValue::Unsigned (42 )),
([1,1, 0, 4, 0,0,0,1, 0, 0, 0,42], Endianness::BigEndian, TagValue::Unsigned (42 )),
([1,1, 9, 0, 1,0,0,0, 42, 0, 0, 0], Endianness::LittleEndian, TagValue::Signed (42 )),
([1,1, 0, 9, 0,0,0,1, 0, 0, 0,42], Endianness::BigEndian, TagValue::Signed (42 )),
([1,1,13, 0, 1,0,0,0, 42, 0, 0, 0], Endianness::LittleEndian, TagValue::Ifd (42 )),
([1,1, 0,13, 0,0,0,1, 0, 0, 0,42], Endianness::BigEndian, TagValue::Ifd (42 )),
([1,1,11, 0, 1,0,0,0, 42, 0, 0, 0], Endianness::LittleEndian, TagValue::Float (f32::from_bits(42))),
([1,1, 0,11, 0,0,0,1, 0, 0, 0,42], Endianness::BigEndian, TagValue::Float (f32::from_bits(42))),
];
for (buf, byte_order, res) in cases {
let fetch = Bytes::copy_from_slice(&buf);
assert_eq!(
read_tag(&fetch, 0, byte_order, false).await.unwrap(),
(Tag::from_u16_exhaustive(0x01_01),res)
);
}
}
#[tokio::test]
#[rustfmt::skip]
async fn test_single_fits_big() {
assert_eq!(u16::from_le_bytes([42,0]),42);
assert_eq!(u16::from_be_bytes([0,42]),42);
assert_eq!(f32::from_le_bytes([0x42,0,0,0]),f32::from_bits(0x00_00_00_42));
assert_eq!(f32::from_be_bytes([0,0,0,0x42]),f32::from_bits(0x00_00_00_42));
let cases = [
([1,1, 1, 0, 1,0,0,0,0,0,0,0, 42, 0, 0, 0, 0, 0, 0, 0], Endianness::LittleEndian, TagValue::Byte (42) ),
([1,1, 0, 1, 0,0,0,0,0,0,0,1, 42, 0, 0, 0, 0, 0, 0, 0], Endianness::BigEndian, TagValue::Byte (42) ),
([1,1, 6, 0, 1,0,0,0,0,0,0,0, 42, 0, 0, 0, 0, 0, 0, 0], Endianness::LittleEndian, TagValue::SignedByte (42) ),
([1,1, 0, 6, 0,0,0,0,0,0,0,1, 42, 0, 0, 0, 0, 0, 0, 0], Endianness::BigEndian, TagValue::SignedByte (42) ),
([1,1, 7, 0, 1,0,0,0,0,0,0,0, 42, 0, 0, 0, 0, 0, 0, 0], Endianness::LittleEndian, TagValue::Byte (42) ), ([1,1, 0, 7, 0,0,0,0,0,0,0,1, 42, 0, 0, 0, 0, 0, 0, 0], Endianness::BigEndian, TagValue::Byte (42) ), ([1,1, 2, 0, 1,0,0,0,0,0,0,0, 0, 0, 0, 0, 0, 0, 0, 0], Endianness::LittleEndian, TagValue::Ascii ("".into()) ),
([1,1, 0, 2, 0,0,0,0,0,0,0,1, 0, 0, 0, 0, 0, 0, 0, 0], Endianness::BigEndian, TagValue::Ascii ("".into()) ),
([1,1, 3, 0, 1,0,0,0,0,0,0,0, 42, 0, 0, 0, 0, 0, 0, 0], Endianness::LittleEndian, TagValue::Short (42) ),
([1,1, 0, 3, 0,0,0,0,0,0,0,1, 0,42, 0, 0, 0, 0, 0, 0], Endianness::BigEndian, TagValue::Short (42) ),
([1,1, 8, 0, 1,0,0,0,0,0,0,0, 42, 0, 0, 0, 0, 0, 0, 0], Endianness::LittleEndian, TagValue::SignedShort(42) ),
([1,1, 0, 8, 0,0,0,0,0,0,0,1, 0,42, 0, 0, 0, 0, 0, 0], Endianness::BigEndian, TagValue::SignedShort(42) ),
([1,1, 4, 0, 1,0,0,0,0,0,0,0, 42, 0, 0, 0, 0, 0, 0, 0], Endianness::LittleEndian, TagValue::Unsigned (42) ),
([1,1, 0, 4, 0,0,0,0,0,0,0,1, 0, 0, 0,42, 0, 0, 0, 0], Endianness::BigEndian, TagValue::Unsigned (42) ),
([1,1, 9, 0, 1,0,0,0,0,0,0,0, 42, 0, 0, 0, 0, 0, 0, 0], Endianness::LittleEndian, TagValue::Signed (42) ),
([1,1, 0, 9, 0,0,0,0,0,0,0,1, 0, 0, 0,42, 0, 0, 0, 0], Endianness::BigEndian, TagValue::Signed (42) ),
([1,1, 13, 0, 1,0,0,0,0,0,0,0, 42, 0, 0, 0, 0, 0, 0, 0], Endianness::LittleEndian, TagValue::Ifd (42) ),
([1,1, 0,13, 0,0,0,0,0,0,0,1, 0, 0, 0,42, 0, 0, 0, 0], Endianness::BigEndian, TagValue::Ifd (42) ),
([1,1, 16, 0, 1,0,0,0,0,0,0,0, 42, 0, 0, 0, 0, 0, 0, 0], Endianness::LittleEndian, TagValue::UnsignedBig(42) ),
([1,1, 0,16, 0,0,0,0,0,0,0,1, 0, 0, 0, 0, 0, 0, 0,42], Endianness::BigEndian, TagValue::UnsignedBig(42) ),
([1,1, 17, 0, 1,0,0,0,0,0,0,0, 42, 0, 0, 0, 0, 0, 0, 0], Endianness::LittleEndian, TagValue::SignedBig (42) ),
([1,1, 0,17, 0,0,0,0,0,0,0,1, 0, 0, 0, 0, 0, 0, 0,42], Endianness::BigEndian, TagValue::SignedBig (42) ),
([1,1, 18, 0, 1,0,0,0,0,0,0,0, 42, 0, 0, 0, 0, 0, 0, 0], Endianness::LittleEndian, TagValue::IfdBig (42) ),
([1,1, 0,18, 0,0,0,0,0,0,0,1, 0, 0, 0, 0, 0, 0, 0,42], Endianness::BigEndian, TagValue::IfdBig (42) ),
([1,1, 11, 0, 1,0,0,0,0,0,0,0, 42, 0, 0, 0, 0, 0, 0, 0], Endianness::LittleEndian, TagValue::Float (f32::from_bits(42))),
([1,1, 0,11, 0,0,0,0,0,0,0,1, 0, 0, 0,42, 0, 0, 0, 0], Endianness::BigEndian, TagValue::Float (f32::from_bits(42))),
([1,1, 12, 0, 1,0,0,0,0,0,0,0, 42, 0, 0, 0, 0, 0, 0, 0], Endianness::LittleEndian, TagValue::Double (f64::from_bits(42))),
([1,1, 0,12, 0,0,0,0,0,0,0,1, 0, 0, 0, 0, 0, 0, 0,42], Endianness::BigEndian, TagValue::Double (f64::from_bits(42))),
([1,1, 5, 0, 1,0,0,0,0,0,0,0, 42,0, 0, 0,43, 0, 0, 0], Endianness::LittleEndian, TagValue::Rational (42, 43) ),
([1,1, 0, 5, 0,0,0,0,0,0,0,1, 0, 0, 0,42, 0, 0, 0,43], Endianness::BigEndian, TagValue::Rational (42, 43) ),
([1,1, 10,0, 1,0,0,0,0,0,0,0, 42, 0, 0, 0,43, 0, 0, 0], Endianness::LittleEndian, TagValue::SRational (42, 43) ),
([1,1, 0,10, 0,0,0,0,0,0,0,1, 0, 0, 0,42, 0, 0, 0,43], Endianness::BigEndian, TagValue::SRational (42, 43) ),
];
for (buf, byte_order, res) in cases {
let fetch = Bytes::copy_from_slice(&buf);
assert_eq!(
read_tag(&fetch, 0, byte_order, true).await.unwrap(),
(Tag::from_u16_exhaustive(0x0101), res)
)
}
}
#[tokio::test]
#[rustfmt::skip]
async fn test_fits_multi_notbig() {
assert_eq!(u16::from_le_bytes([42,0]),42);
assert_eq!(u16::from_be_bytes([0,42]),42);
assert_eq!(f32::from_le_bytes([0x42,0,0,0]),f32::from_bits(0x00_00_00_42));
assert_eq!(f32::from_be_bytes([0,0,0,0x42]),f32::from_bits(0x00_00_00_42));
let cases = [
([1,1, 1, 0, 4,0,0,0, 42,42,42,42], Endianness::LittleEndian, TagValue::List(vec![TagValue::Byte (42); 4]) ),
([1,1, 0, 1, 0,0,0,4, 42,42,42,42], Endianness::BigEndian, TagValue::List(vec![TagValue::Byte (42); 4]) ),
([1,1, 6, 0, 4,0,0,0, 42,42,42,42], Endianness::LittleEndian, TagValue::List(vec![TagValue::SignedByte (42); 4]) ),
([1,1, 0, 6, 0,0,0,4, 42,42,42,42], Endianness::BigEndian, TagValue::List(vec![TagValue::SignedByte (42); 4]) ),
([1,1, 7, 0, 4,0,0,0, 42,42,42,42], Endianness::LittleEndian, TagValue::List(vec![TagValue::Byte (42); 4]) ), ([1,1, 0, 7, 0,0,0,4, 42,42,42,42], Endianness::BigEndian, TagValue::List(vec![TagValue::Byte (42); 4]) ), ([1,1, 2, 0, 4,0,0,0, 42,42,42, 0], Endianness::LittleEndian, TagValue::Ascii("***".into())),
([1,1, 0, 2, 0,0,0,4, 42,42,42, 0], Endianness::BigEndian, TagValue::Ascii("***".into())),
([1,1, 3, 0, 2,0,0,0, 42, 0,42, 0], Endianness::LittleEndian, TagValue::List(vec![TagValue::Short (42); 2]) ),
([1,1, 0, 3, 0,0,0,2, 0,42, 0,42], Endianness::BigEndian, TagValue::List(vec![TagValue::Short (42); 2]) ),
([1,1, 8, 0, 2,0,0,0, 42, 0,42, 0], Endianness::LittleEndian, TagValue::List(vec![TagValue::SignedShort (42); 2]) ),
([1,1, 0, 8, 0,0,0,2, 0,42, 0,42], Endianness::BigEndian, TagValue::List(vec![TagValue::SignedShort (42); 2]) ),
([1,1, 0, 2, 0,0,0,4, b'A',b'B',b'C',0], Endianness::BigEndian, TagValue::Ascii("ABC".into())),
];
for (buf, byte_order, res) in cases {
println!("testing {buf:?} to be {res:?}");
let fetch = Bytes::copy_from_slice(&buf);
assert_eq!(
read_tag(&fetch, 0, byte_order, false).await.unwrap(),
(Tag::from_u16_exhaustive(0x0101), res)
)
}
}
#[tokio::test]
#[rustfmt::skip]
async fn test_fits_multi_big() {
assert_eq!(u16::from_le_bytes([42,0]),42);
assert_eq!(u16::from_be_bytes([0,42]),42);
assert_eq!(f32::from_le_bytes([0x42,0,0,0]),f32::from_bits(0x00_00_00_42));
assert_eq!(f32::from_be_bytes([0,0,0,0x42]),f32::from_bits(0x00_00_00_42));
let cases = [
([1,1, 1, 0, 8,0,0,0,0,0,0,0, 42,42,42,42,42,42,42,42], Endianness::LittleEndian, TagValue::List(vec![TagValue::Byte (42) ; 8])),
([1,1, 0, 1, 0,0,0,0,0,0,0,8, 42,42,42,42,42,42,42,42], Endianness::BigEndian, TagValue::List(vec![TagValue::Byte (42) ; 8])),
([1,1, 6, 0, 8,0,0,0,0,0,0,0, 42,42,42,42,42,42,42,42], Endianness::LittleEndian, TagValue::List(vec![TagValue::SignedByte(42) ; 8])),
([1,1, 0, 6, 0,0,0,0,0,0,0,8, 42,42,42,42,42,42,42,42], Endianness::BigEndian, TagValue::List(vec![TagValue::SignedByte(42) ; 8])),
([1,1, 7, 0, 8,0,0,0,0,0,0,0, 42,42,42,42,42,42,42,42], Endianness::LittleEndian, TagValue::List(vec![TagValue::Byte (42) ; 8])), ([1,1, 0, 7, 0,0,0,0,0,0,0,8, 42,42,42,42,42,42,42,42], Endianness::BigEndian, TagValue::List(vec![TagValue::Byte (42) ; 8])), ([1,1, 2, 0, 8,0,0,0,0,0,0,0, 42,42,42,42,42,42,42, 0], Endianness::LittleEndian, TagValue::Ascii ("*******".into() )),
([1,1, 0, 2, 0,0,0,0,0,0,0,8, 42,42,42,42,42,42,42, 0], Endianness::BigEndian, TagValue::Ascii ("*******".into() )),
([1,1, 3, 0, 4,0,0,0,0,0,0,0, 42, 0,42, 0,42, 0,42, 0], Endianness::LittleEndian, TagValue::List(vec![TagValue::Short (42) ; 4])),
([1,1, 0, 3, 0,0,0,0,0,0,0,4, 0,42, 0,42, 0,42, 0,42], Endianness::BigEndian, TagValue::List(vec![TagValue::Short (42) ; 4])),
([1,1, 8, 0, 4,0,0,0,0,0,0,0, 42, 0,42, 0,42, 0,42, 0], Endianness::LittleEndian, TagValue::List(vec![TagValue::SignedShort (42) ; 4])),
([1,1, 0, 8, 0,0,0,0,0,0,0,4, 0,42, 0,42, 0,42, 0,42], Endianness::BigEndian, TagValue::List(vec![TagValue::SignedShort (42) ; 4])),
([1,1, 4, 0, 2,0,0,0,0,0,0,0, 42, 0, 0, 0,42, 0, 0, 0], Endianness::LittleEndian, TagValue::List(vec![TagValue::Unsigned (42) ; 2])),
([1,1, 0, 4, 0,0,0,0,0,0,0,2, 0, 0, 0,42, 0, 0, 0,42], Endianness::BigEndian, TagValue::List(vec![TagValue::Unsigned (42) ; 2])),
([1,1, 9, 0, 2,0,0,0,0,0,0,0, 42, 0, 0, 0,42, 0, 0, 0], Endianness::LittleEndian, TagValue::List(vec![TagValue::Signed (42) ; 2])),
([1,1, 0, 9, 0,0,0,0,0,0,0,2, 0, 0, 0,42, 0, 0, 0,42], Endianness::BigEndian, TagValue::List(vec![TagValue::Signed (42) ; 2])),
([1,1,13, 0, 2,0,0,0,0,0,0,0, 42, 0, 0, 0,42, 0, 0, 0], Endianness::LittleEndian, TagValue::List(vec![TagValue::Ifd (42) ; 2])),
([1,1, 0,13, 0,0,0,0,0,0,0,2, 0, 0, 0,42, 0, 0, 0,42], Endianness::BigEndian, TagValue::List(vec![TagValue::Ifd (42) ; 2])),
([1,1,11, 0, 2,0,0,0,0,0,0,0, 42, 0, 0, 0,42, 0, 0, 0], Endianness::LittleEndian, TagValue::List(vec![TagValue::Float (f32::from_bits(42)); 2])),
([1,1, 0,11, 0,0,0,0,0,0,0,2, 0, 0, 0,42, 0, 0, 0,42], Endianness::BigEndian, TagValue::List(vec![TagValue::Float (f32::from_bits(42)); 2])),
];
for (buf, byte_order, res) in cases {
let fetch = Bytes::copy_from_slice(&buf);
assert_eq!(
read_tag(&fetch, 0, byte_order, true).await.unwrap(),
(Tag::from_u16_exhaustive(0x0101), res)
)
}
}
#[tokio::test]
#[rustfmt::skip]
async fn test_notfits_notbig() {
assert_eq!(u16::from_le_bytes([42,0]),42);
assert_eq!(u16::from_be_bytes([0,42]),42);
assert_eq!(f32::from_le_bytes([0x42,0,0,0]),f32::from_bits(0x00_00_00_42));
assert_eq!(f32::from_be_bytes([0,0,0,0x42]),f32::from_bits(0x00_00_00_42));
let cases = [
(vec![1,1, 1, 0, 5,0,0,0, 12, 0, 0, 0, 42,42,42,42,42], Endianness::LittleEndian, TagValue::List(vec![TagValue::Byte (42 );5])),
(vec![1,1, 0, 1, 0,0,0,5, 0, 0, 0,12, 42,42,42,42,42], Endianness::BigEndian , TagValue::List(vec![TagValue::Byte (42 );5])),
(vec![1,1, 6, 0, 5,0,0,0, 12, 0, 0, 0, 42,42,42,42,42], Endianness::LittleEndian, TagValue::List(vec![TagValue::SignedByte (42 );5])),
(vec![1,1, 0, 6, 0,0,0,5, 0, 0, 0,12, 42,42,42,42,42], Endianness::BigEndian , TagValue::List(vec![TagValue::SignedByte (42 );5])),
(vec![1,1, 7, 0, 5,0,0,0, 12, 0, 0, 0, 42,42,42,42,42], Endianness::LittleEndian, TagValue::List(vec![TagValue::Byte (42 );5])), (vec![1,1, 0, 7, 0,0,0,5, 0, 0, 0,12, 42,42,42,42,42], Endianness::BigEndian , TagValue::List(vec![TagValue::Byte (42 );5])), (vec![1,1, 2, 0, 5,0,0,0, 12, 0, 0, 0, 42,42,42,42, 0], Endianness::LittleEndian, TagValue::Ascii ("****".into() ) ),
(vec![1,1, 0, 2, 0,0,0,5, 0, 0, 0,12, 42,42,42,42, 0], Endianness::BigEndian , TagValue::Ascii ("****".into() ) ),
(vec![1,1, 3, 0, 3,0,0,0, 12, 0, 0, 0, 42, 0,42, 0,42, 0], Endianness::LittleEndian, TagValue::List(vec![TagValue::Short (42 );3])),
(vec![1,1, 0, 3, 0,0,0,3, 0, 0, 0,12, 0,42, 0,42, 0,42], Endianness::BigEndian , TagValue::List(vec![TagValue::Short (42 );3])),
(vec![1,1, 8, 0, 3,0,0,0, 12, 0, 0, 0, 42, 0,42, 0,42, 0], Endianness::LittleEndian, TagValue::List(vec![TagValue::SignedShort(42 );3])),
(vec![1,1, 0, 8, 0,0,0,3, 0, 0, 0,12, 0,42, 0,42, 0,42], Endianness::BigEndian , TagValue::List(vec![TagValue::SignedShort(42 );3])),
(vec![1,1, 4, 0, 2,0,0,0, 12, 0, 0, 0, 42, 0, 0, 0,42, 0, 0, 0], Endianness::LittleEndian, TagValue::List(vec![TagValue::Unsigned (42 );2])),
(vec![1,1, 0, 4, 0,0,0,2, 0, 0, 0,12, 0, 0, 0,42, 0, 0, 0,42], Endianness::BigEndian , TagValue::List(vec![TagValue::Unsigned (42 );2])),
(vec![1,1, 9, 0, 2,0,0,0, 12, 0, 0, 0, 42, 0, 0, 0,42, 0, 0, 0], Endianness::LittleEndian, TagValue::List(vec![TagValue::Signed (42 );2])),
(vec![1,1, 0, 9, 0,0,0,2, 0, 0, 0,12, 0, 0, 0,42, 0, 0, 0,42], Endianness::BigEndian , TagValue::List(vec![TagValue::Signed (42 );2])),
(vec![1,1,13, 0, 2,0,0,0, 12, 0, 0, 0, 42, 0, 0, 0,42, 0, 0, 0], Endianness::LittleEndian, TagValue::List(vec![TagValue::Ifd (42 );2])),
(vec![1,1, 0,13, 0,0,0,2, 0, 0, 0,12, 0, 0, 0,42, 0, 0, 0,42], Endianness::BigEndian , TagValue::List(vec![TagValue::Ifd (42 );2])),
(vec![1,1, 16,0, 1,0,0,0, 12, 0, 0, 0, 42, 0, 0, 0, 0, 0, 0, 0], Endianness::LittleEndian, TagValue::UnsignedBig(42 ) ),
(vec![1,1, 0,16, 0,0,0,1, 0, 0, 0,12, 0, 0, 0, 0, 0, 0, 0,42], Endianness::BigEndian , TagValue::UnsignedBig(42 ) ),
(vec![1,1, 17,0, 1,0,0,0, 12, 0, 0, 0, 42, 0, 0, 0, 0, 0, 0, 0], Endianness::LittleEndian, TagValue::SignedBig (42 ) ),
(vec![1,1, 0,17, 0,0,0,1, 0, 0, 0,12, 0, 0, 0, 0, 0, 0, 0,42], Endianness::BigEndian , TagValue::SignedBig (42 ) ),
(vec![1,1, 18,0, 1,0,0,0, 12, 0, 0, 0, 42, 0, 0, 0, 0, 0, 0, 0], Endianness::LittleEndian, TagValue::IfdBig (42 ) ),
(vec![1,1, 0,18, 0,0,0,1, 0, 0, 0,12, 0, 0, 0, 0, 0, 0, 0,42], Endianness::BigEndian , TagValue::IfdBig (42 ) ),
(vec![1,1, 11,0, 2,0,0,0, 12, 0, 0, 0, 42, 0, 0, 0,42, 0, 0, 0], Endianness::LittleEndian, TagValue::List(vec![TagValue::Float (f32::from_bits(42) );2])),
(vec![1,1, 0,11, 0,0,0,2, 0, 0, 0,12, 0, 0, 0,42, 0, 0, 0,42], Endianness::BigEndian , TagValue::List(vec![TagValue::Float (f32::from_bits(42) );2])),
(vec![1,1, 12,0, 1,0,0,0, 12, 0, 0, 0, 42, 0, 0, 0, 0, 0, 0, 0], Endianness::LittleEndian, TagValue::Double (f64::from_bits(42)) ),
(vec![1,1, 0,12, 0,0,0,1, 0, 0, 0,12, 0, 0, 0, 0, 0, 0, 0,42], Endianness::BigEndian , TagValue::Double (f64::from_bits(42)) ),
(vec![1,1, 5, 0, 1,0,0,0, 12, 0, 0, 0, 42, 0, 0, 0,42, 0, 0, 0], Endianness::LittleEndian, TagValue::Rational (42, 42 ) ),
(vec![1,1, 0, 5, 0,0,0,1, 0, 0, 0,12, 0, 0, 0,42, 0, 0, 0,42], Endianness::BigEndian , TagValue::Rational (42, 42 ) ),
(vec![1,1, 10,0, 1,0,0,0, 12, 0, 0, 0, 42, 0, 0, 0,42, 0, 0, 0], Endianness::LittleEndian, TagValue::SRational (42, 42 ) ),
(vec![1,1, 0,10, 0,0,0,1, 0, 0, 0,12, 0, 0, 0,42, 0, 0, 0,42], Endianness::BigEndian , TagValue::SRational (42, 42 ) ),
];
for (buf, byte_order, res) in cases {
println!("reading {buf:?} to be {res:?}");
let fetch = Bytes::from_owner(buf);
assert_eq!(
read_tag(&fetch, 0, byte_order, false).await.unwrap(),
(Tag::from_u16_exhaustive(0x0101), res)
)
}
}
#[tokio::test]
#[rustfmt::skip]
async fn test_notfits_big() {
assert_eq!(u16::from_le_bytes([42,0]),42);
assert_eq!(u16::from_be_bytes([0,42]),42);
assert_eq!(f32::from_le_bytes([0x42,0,0,0]),f32::from_bits(0x00_00_00_42));
assert_eq!(f32::from_be_bytes([0,0,0,0x42]),f32::from_bits(0x00_00_00_42));
let cases = [
(vec![1,1, 1, 0, 9,0,0,0,0,0,0,0, 20, 0, 0, 0, 0, 0, 0, 0, 42,42,42,42,42,42,42,42,42], Endianness::LittleEndian, TagValue::List(vec![TagValue::Byte (42 );9])),
(vec![1,1, 0, 1, 0,0,0,0,0,0,0,9, 0, 0, 0, 0, 0, 0, 0,20, 42,42,42,42,42,42,42,42,42], Endianness::BigEndian , TagValue::List(vec![TagValue::Byte (42 );9])),
(vec![1,1, 6, 0, 9,0,0,0,0,0,0,0, 20, 0, 0, 0, 0, 0, 0, 0, 42,42,42,42,42,42,42,42,42], Endianness::LittleEndian, TagValue::List(vec![TagValue::SignedByte (42 );9])),
(vec![1,1, 0, 6, 0,0,0,0,0,0,0,9, 0, 0, 0, 0, 0, 0, 0,20, 42,42,42,42,42,42,42,42,42], Endianness::BigEndian , TagValue::List(vec![TagValue::SignedByte (42 );9])),
(vec![1,1, 7, 0, 9,0,0,0,0,0,0,0, 20, 0, 0, 0, 0, 0, 0, 0, 42,42,42,42,42,42,42,42,42], Endianness::LittleEndian, TagValue::List(vec![TagValue::Byte (42 );9])), (vec![1,1, 0, 7, 0,0,0,0,0,0,0,9, 0, 0, 0, 0, 0, 0, 0,20, 42,42,42,42,42,42,42,42,42], Endianness::BigEndian , TagValue::List(vec![TagValue::Byte (42 );9])), (vec![1,1, 2, 0, 9,0,0,0,0,0,0,0, 20, 0, 0, 0, 0, 0, 0, 0, 42,42,42,42,42,42,42,42, 0], Endianness::LittleEndian, TagValue::Ascii ("********".into() ) ),
(vec![1,1, 0, 2, 0,0,0,0,0,0,0,9, 0, 0, 0, 0, 0, 0, 0,20, 42,42,42,42,42,42,42,42, 0], Endianness::BigEndian , TagValue::Ascii ("********".into() ) ),
(vec![1,1, 3, 0, 5,0,0,0,0,0,0,0, 20, 0, 0, 0, 0, 0, 0, 0, 42, 0,42, 0,42, 0,42, 0,42, 0], Endianness::LittleEndian, TagValue::List(vec![TagValue::Short (42 );5])),
(vec![1,1, 0, 3, 0,0,0,0,0,0,0,5, 0, 0, 0, 0, 0, 0, 0,20, 0,42, 0,42, 0,42, 0,42, 0,42], Endianness::BigEndian , TagValue::List(vec![TagValue::Short (42 );5])),
(vec![1,1, 8, 0, 5,0,0,0,0,0,0,0, 20, 0, 0, 0, 0, 0, 0, 0, 42, 0,42, 0,42, 0,42, 0,42, 0], Endianness::LittleEndian, TagValue::List(vec![TagValue::SignedShort(42 );5])),
(vec![1,1, 0, 8, 0,0,0,0,0,0,0,5, 0, 0, 0, 0, 0, 0, 0,20, 0,42, 0,42, 0,42, 0,42, 0,42], Endianness::BigEndian , TagValue::List(vec![TagValue::SignedShort(42 );5])),
(vec![1,1, 4, 0, 3,0,0,0,0,0,0,0, 20, 0, 0, 0, 0, 0, 0, 0, 42, 0, 0, 0,42, 0, 0, 0,42, 0, 0, 0], Endianness::LittleEndian, TagValue::List(vec![TagValue::Unsigned (42 );3])),
(vec![1,1, 0, 4, 0,0,0,0,0,0,0,3, 0, 0, 0, 0, 0, 0, 0,20, 0, 0, 0,42, 0, 0, 0,42, 0, 0, 0,42], Endianness::BigEndian , TagValue::List(vec![TagValue::Unsigned (42 );3])),
(vec![1,1, 9, 0, 3,0,0,0,0,0,0,0, 20, 0, 0, 0, 0, 0, 0, 0, 42, 0, 0, 0,42, 0, 0, 0,42, 0, 0, 0], Endianness::LittleEndian, TagValue::List(vec![TagValue::Signed (42 );3])),
(vec![1,1, 0, 9, 0,0,0,0,0,0,0,3, 0, 0, 0, 0, 0, 0, 0,20, 0, 0, 0,42, 0, 0, 0,42, 0, 0, 0,42], Endianness::BigEndian , TagValue::List(vec![TagValue::Signed (42 );3])),
(vec![1,1, 13, 0, 3,0,0,0,0,0,0,0, 20, 0, 0, 0, 0, 0, 0, 0, 42, 0, 0, 0,42, 0, 0, 0,42, 0, 0, 0], Endianness::LittleEndian, TagValue::List(vec![TagValue::Ifd (42 );3])),
(vec![1,1, 0,13, 0,0,0,0,0,0,0,3, 0, 0, 0, 0, 0, 0, 0,20, 0, 0, 0,42, 0, 0, 0,42, 0, 0, 0,42], Endianness::BigEndian , TagValue::List(vec![TagValue::Ifd (42 );3])),
(vec![1,1, 16, 0, 2,0,0,0,0,0,0,0, 20, 0, 0, 0, 0, 0, 0, 0, 42, 0, 0, 0, 0, 0, 0, 0,42, 0, 0, 0, 0, 0, 0, 0], Endianness::LittleEndian, TagValue::List(vec![TagValue::UnsignedBig(42 );2])),
(vec![1,1, 0,16, 0,0,0,0,0,0,0,2, 0, 0, 0, 0, 0, 0, 0,20, 0, 0, 0, 0, 0, 0, 0,42, 0, 0, 0, 0, 0, 0, 0,42], Endianness::BigEndian , TagValue::List(vec![TagValue::UnsignedBig(42 );2])),
(vec![1,1, 17, 0, 2,0,0,0,0,0,0,0, 20, 0, 0, 0, 0, 0, 0, 0, 42, 0, 0, 0, 0, 0, 0, 0,42, 0, 0, 0, 0, 0, 0, 0], Endianness::LittleEndian, TagValue::List(vec![TagValue::SignedBig (42 );2])),
(vec![1,1, 0,17, 0,0,0,0,0,0,0,2, 0, 0, 0, 0, 0, 0, 0,20, 0, 0, 0, 0, 0, 0, 0,42, 0, 0, 0, 0, 0, 0, 0,42], Endianness::BigEndian , TagValue::List(vec![TagValue::SignedBig (42 );2])),
(vec![1,1, 18, 0, 2,0,0,0,0,0,0,0, 20, 0, 0, 0, 0, 0, 0, 0, 42, 0, 0, 0, 0, 0, 0, 0,42, 0, 0, 0, 0, 0, 0, 0], Endianness::LittleEndian, TagValue::List(vec![TagValue::IfdBig (42 );2])),
(vec![1,1, 0,18, 0,0,0,0,0,0,0,2, 0, 0, 0, 0, 0, 0, 0,20, 0, 0, 0, 0, 0, 0, 0,42, 0, 0, 0, 0, 0, 0, 0,42], Endianness::BigEndian , TagValue::List(vec![TagValue::IfdBig (42 );2])),
(vec![1,1, 11, 0, 3,0,0,0,0,0,0,0, 20, 0, 0, 0, 0, 0, 0, 0, 42, 0, 0, 0,42, 0, 0, 0,42, 0, 0, 0,], Endianness::LittleEndian, TagValue::List(vec![TagValue::Float (f32::from_bits(42));3])),
(vec![1,1, 0,11, 0,0,0,0,0,0,0,3, 0, 0, 0, 0, 0, 0, 0,20, 0, 0, 0,42, 0, 0, 0,42, 0, 0, 0,42,], Endianness::BigEndian , TagValue::List(vec![TagValue::Float (f32::from_bits(42));3])),
(vec![1,1, 12, 0, 2,0,0,0,0,0,0,0, 20, 0, 0, 0, 0, 0, 0, 0, 42, 0, 0, 0, 0, 0, 0, 0,42, 0, 0, 0, 0, 0, 0, 0], Endianness::LittleEndian, TagValue::List(vec![TagValue::Double (f64::from_bits(42));2])),
(vec![1,1, 0,12, 0,0,0,0,0,0,0,2, 0, 0, 0, 0, 0, 0, 0,20, 0, 0, 0, 0, 0, 0, 0,42, 0, 0, 0, 0, 0, 0, 0,42], Endianness::BigEndian , TagValue::List(vec![TagValue::Double (f64::from_bits(42));2])),
(vec![1,1, 5, 0, 2,0,0,0,0,0,0,0, 20, 0, 0, 0, 0, 0, 0, 0, 42, 0, 0, 0,42, 0, 0, 0,42, 0, 0, 0,42, 0, 0, 0], Endianness::LittleEndian, TagValue::List(vec![TagValue::Rational (42, 42 );2])),
(vec![1,1, 0, 5, 0,0,0,0,0,0,0,2, 0, 0, 0, 0, 0, 0, 0,20, 0, 0, 0,42, 0, 0, 0,42, 0, 0, 0,42, 0, 0, 0,42], Endianness::BigEndian , TagValue::List(vec![TagValue::Rational (42, 42 );2])),
(vec![1,1, 10, 0, 2,0,0,0,0,0,0,0, 20, 0, 0, 0, 0, 0, 0, 0, 42, 0, 0, 0,42, 0, 0, 0,42, 0, 0, 0,42, 0, 0, 0], Endianness::LittleEndian, TagValue::List(vec![TagValue::SRational (42, 42 );2])),
(vec![1,1, 0,10, 0,0,0,0,0,0,0,2, 0, 0, 0, 0, 0, 0, 0,20, 0, 0, 0,42, 0, 0, 0,42, 0, 0, 0,42, 0, 0, 0,42], Endianness::BigEndian , TagValue::List(vec![TagValue::SRational (42, 42 );2])),
];
for (buf, byte_order, res) in cases {
println!("reading {buf:?} to be {res:?}");
let fetch = Bytes::from_owner(buf);
assert_eq!(read_tag(&fetch, 0, byte_order, true).await.unwrap(), (Tag::from_u16_exhaustive(0x0101), res))
}
}
}