use byteorder::{BigEndian, LittleEndian, ReadBytesExt};
use std::io::Result;
use crate::io::seekable::SeekableReader;
use crate::tiff::errors::{TiffError, TiffResult};
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub enum ByteOrder {
LittleEndian,
BigEndian,
}
impl ByteOrder {
pub fn detect(reader: &mut dyn SeekableReader) -> TiffResult<Self> {
let byte_order = reader.read_u16::<LittleEndian>()?;
match byte_order {
0x4949 => Ok(ByteOrder::LittleEndian), 0x4D4D => Ok(ByteOrder::BigEndian), _ => Err(TiffError::InvalidByteOrder(byte_order)),
}
}
pub fn name(&self) -> &'static str {
match self {
ByteOrder::LittleEndian => "Little Endian (II)",
ByteOrder::BigEndian => "Big Endian (MM)",
}
}
pub fn create_handler(&self) -> Box<dyn ByteOrderHandler> {
match self {
ByteOrder::LittleEndian => Box::new(LittleEndianHandler),
ByteOrder::BigEndian => Box::new(BigEndianHandler),
}
}
}
pub trait ByteOrderHandler: Send + Sync {
fn read_u16(&self, reader: &mut dyn SeekableReader) -> Result<u16>;
fn read_u32(&self, reader: &mut dyn SeekableReader) -> Result<u32>;
fn read_u64(&self, reader: &mut dyn SeekableReader) -> Result<u64>;
fn read_f32(&self, reader: &mut dyn SeekableReader) -> Result<f32>;
fn read_f64(&self, reader: &mut dyn SeekableReader) -> Result<f64>;
fn read_rational(&self, reader: &mut dyn SeekableReader) -> Result<(u32, u32)>;
fn read_srational(&self, reader: &mut dyn SeekableReader) -> Result<(i32, i32)>;
}
pub struct LittleEndianHandler;
impl ByteOrderHandler for LittleEndianHandler {
fn read_u16(&self, reader: &mut dyn SeekableReader) -> Result<u16> {
reader.read_u16::<LittleEndian>()
}
fn read_u32(&self, reader: &mut dyn SeekableReader) -> Result<u32> {
reader.read_u32::<LittleEndian>()
}
fn read_u64(&self, reader: &mut dyn SeekableReader) -> Result<u64> {
reader.read_u64::<LittleEndian>()
}
fn read_f32(&self, reader: &mut dyn SeekableReader) -> Result<f32> {
reader.read_f32::<LittleEndian>()
}
fn read_f64(&self, reader: &mut dyn SeekableReader) -> Result<f64> {
reader.read_f64::<LittleEndian>()
}
fn read_rational(&self, reader: &mut dyn SeekableReader) -> Result<(u32, u32)> {
let numerator = reader.read_u32::<LittleEndian>()?;
let denominator = reader.read_u32::<LittleEndian>()?;
Ok((numerator, denominator))
}
fn read_srational(&self, reader: &mut dyn SeekableReader) -> Result<(i32, i32)> {
let numerator = reader.read_i32::<LittleEndian>()?;
let denominator = reader.read_i32::<LittleEndian>()?;
Ok((numerator, denominator))
}
}
pub struct BigEndianHandler;
impl ByteOrderHandler for BigEndianHandler {
fn read_u16(&self, reader: &mut dyn SeekableReader) -> Result<u16> {
reader.read_u16::<BigEndian>()
}
fn read_u32(&self, reader: &mut dyn SeekableReader) -> Result<u32> {
reader.read_u32::<BigEndian>()
}
fn read_u64(&self, reader: &mut dyn SeekableReader) -> Result<u64> {
reader.read_u64::<BigEndian>()
}
fn read_f32(&self, reader: &mut dyn SeekableReader) -> Result<f32> {
reader.read_f32::<BigEndian>()
}
fn read_f64(&self, reader: &mut dyn SeekableReader) -> Result<f64> {
reader.read_f64::<BigEndian>()
}
fn read_rational(&self, reader: &mut dyn SeekableReader) -> Result<(u32, u32)> {
let numerator = reader.read_u32::<BigEndian>()?;
let denominator = reader.read_u32::<BigEndian>()?;
Ok((numerator, denominator))
}
fn read_srational(&self, reader: &mut dyn SeekableReader) -> Result<(i32, i32)> {
let numerator = reader.read_i32::<BigEndian>()?;
let denominator = reader.read_i32::<BigEndian>()?;
Ok((numerator, denominator))
}
}