Skip to main content

tiff_reader/
io.rs

1use crate::error::{Error, Result};
2use crate::header::ByteOrder;
3
4/// A cursor over a byte slice with byte-order-aware reads.
5pub struct Cursor<'a> {
6    data: &'a [u8],
7    pos: usize,
8    byte_order: ByteOrder,
9}
10
11impl<'a> Cursor<'a> {
12    pub fn new(data: &'a [u8], byte_order: ByteOrder) -> Self {
13        Self {
14            data,
15            pos: 0,
16            byte_order,
17        }
18    }
19
20    pub fn with_offset(data: &'a [u8], offset: usize, byte_order: ByteOrder) -> Result<Self> {
21        if offset > data.len() {
22            return Err(Error::Truncated {
23                offset: offset as u64,
24                needed: 0,
25                available: data.len() as u64,
26            });
27        }
28        Ok(Self {
29            data,
30            pos: offset,
31            byte_order,
32        })
33    }
34
35    pub fn position(&self) -> usize {
36        self.pos
37    }
38
39    pub fn remaining(&self) -> usize {
40        self.data.len().saturating_sub(self.pos)
41    }
42
43    pub fn read_u8(&mut self) -> Result<u8> {
44        self.ensure(1)?;
45        let v = self.data[self.pos];
46        self.pos += 1;
47        Ok(v)
48    }
49
50    pub fn read_u16(&mut self) -> Result<u16> {
51        self.ensure(2)?;
52        let bytes = [self.data[self.pos], self.data[self.pos + 1]];
53        self.pos += 2;
54        Ok(match self.byte_order {
55            ByteOrder::LittleEndian => u16::from_le_bytes(bytes),
56            ByteOrder::BigEndian => u16::from_be_bytes(bytes),
57        })
58    }
59
60    pub fn read_u32(&mut self) -> Result<u32> {
61        self.ensure(4)?;
62        let bytes: [u8; 4] = self.data[self.pos..self.pos + 4].try_into().unwrap();
63        self.pos += 4;
64        Ok(match self.byte_order {
65            ByteOrder::LittleEndian => u32::from_le_bytes(bytes),
66            ByteOrder::BigEndian => u32::from_be_bytes(bytes),
67        })
68    }
69
70    pub fn read_u64(&mut self) -> Result<u64> {
71        self.ensure(8)?;
72        let bytes: [u8; 8] = self.data[self.pos..self.pos + 8].try_into().unwrap();
73        self.pos += 8;
74        Ok(match self.byte_order {
75            ByteOrder::LittleEndian => u64::from_le_bytes(bytes),
76            ByteOrder::BigEndian => u64::from_be_bytes(bytes),
77        })
78    }
79
80    pub fn read_f64(&mut self) -> Result<f64> {
81        self.ensure(8)?;
82        let bytes: [u8; 8] = self.data[self.pos..self.pos + 8].try_into().unwrap();
83        self.pos += 8;
84        Ok(match self.byte_order {
85            ByteOrder::LittleEndian => f64::from_le_bytes(bytes),
86            ByteOrder::BigEndian => f64::from_be_bytes(bytes),
87        })
88    }
89
90    pub fn read_bytes(&mut self, n: usize) -> Result<&'a [u8]> {
91        self.ensure(n)?;
92        let slice = &self.data[self.pos..self.pos + n];
93        self.pos += n;
94        Ok(slice)
95    }
96
97    pub fn skip(&mut self, n: usize) -> Result<()> {
98        self.ensure(n)?;
99        self.pos += n;
100        Ok(())
101    }
102
103    fn ensure(&self, n: usize) -> Result<()> {
104        if self.pos + n > self.data.len() {
105            return Err(Error::Truncated {
106                offset: self.pos as u64,
107                needed: n as u64,
108                available: self.data.len().saturating_sub(self.pos) as u64,
109            });
110        }
111        Ok(())
112    }
113}