Skip to main content

async_tiff/metadata/
fetch.rs

1use std::fmt::Debug;
2use std::ops::Range;
3
4use async_trait::async_trait;
5use bytes::Bytes;
6
7use crate::error::AsyncTiffResult;
8use crate::reader::{AsyncFileReader, EndianAwareReader, Endianness};
9
10/// A data source that can be used with [`TiffMetadataReader`][crate::metadata::TiffMetadataReader]
11/// and [`ImageFileDirectoryReader`][crate::metadata::ImageFileDirectoryReader] to load
12/// [`ImageFileDirectory`][crate::ImageFileDirectory]s.
13///
14/// Note that implementation is provided for [`AsyncFileReader`].
15#[async_trait]
16pub trait MetadataFetch: Debug + Send + Sync + 'static {
17    /// Return a future that fetches the specified range of bytes asynchronously
18    ///
19    /// Note the returned type is a boxed future, often created by
20    /// [futures::FutureExt::boxed]. See the trait documentation for an example.
21    async fn fetch(&self, range: Range<u64>) -> AsyncTiffResult<Bytes>;
22}
23
24#[async_trait]
25impl<T: AsyncFileReader> MetadataFetch for T {
26    async fn fetch(&self, range: Range<u64>) -> AsyncTiffResult<Bytes> {
27        self.get_bytes(range).await
28    }
29}
30
31pub(crate) struct MetadataCursor<'a, F: MetadataFetch> {
32    fetch: &'a F,
33    offset: u64,
34    endianness: Endianness,
35}
36
37impl<'a, F: MetadataFetch> MetadataCursor<'a, F> {
38    pub fn new(fetch: &'a F, endianness: Endianness) -> Self {
39        Self {
40            fetch,
41            offset: 0,
42            endianness,
43        }
44    }
45
46    pub fn new_with_offset(fetch: &'a F, endianness: Endianness, offset: u64) -> Self {
47        Self {
48            fetch,
49            offset,
50            endianness,
51        }
52    }
53
54    pub fn with_offset(mut self, offset: u64) -> Self {
55        self.offset = offset;
56        self
57    }
58
59    pub fn seek(&mut self, offset: u64) {
60        self.offset = offset;
61    }
62
63    /// Advance cursor position by a set amount
64    pub(crate) fn advance(&mut self, amount: u64) {
65        self.offset += amount;
66    }
67
68    /// Read the given number of bytes, advancing the internal cursor state by the same amount.
69    pub(crate) async fn read(&mut self, length: u64) -> AsyncTiffResult<EndianAwareReader> {
70        let range = self.offset as _..(self.offset + length) as _;
71        self.offset += length;
72        let bytes = self.fetch.fetch(range).await?;
73        Ok(EndianAwareReader::new(bytes, self.endianness))
74    }
75
76    /// Read a u8 from the cursor, advancing the internal state by 1 byte.
77    pub(crate) async fn read_u8(&mut self) -> AsyncTiffResult<u8> {
78        self.read(1).await?.read_u8()
79    }
80
81    /// Read a i8 from the cursor, advancing the internal state by 1 byte.
82    pub(crate) async fn read_i8(&mut self) -> AsyncTiffResult<i8> {
83        self.read(1).await?.read_i8()
84    }
85
86    /// Read a u16 from the cursor, advancing the internal state by 2 bytes.
87    pub(crate) async fn read_u16(&mut self) -> AsyncTiffResult<u16> {
88        self.read(2).await?.read_u16()
89    }
90
91    /// Read a i16 from the cursor, advancing the internal state by 2 bytes.
92    pub(crate) async fn read_i16(&mut self) -> AsyncTiffResult<i16> {
93        self.read(2).await?.read_i16()
94    }
95
96    /// Read a u32 from the cursor, advancing the internal state by 4 bytes.
97    pub(crate) async fn read_u32(&mut self) -> AsyncTiffResult<u32> {
98        self.read(4).await?.read_u32()
99    }
100
101    /// Read a i32 from the cursor, advancing the internal state by 4 bytes.
102    pub(crate) async fn read_i32(&mut self) -> AsyncTiffResult<i32> {
103        self.read(4).await?.read_i32()
104    }
105
106    /// Read a u64 from the cursor, advancing the internal state by 8 bytes.
107    pub(crate) async fn read_u64(&mut self) -> AsyncTiffResult<u64> {
108        self.read(8).await?.read_u64()
109    }
110
111    /// Read a i64 from the cursor, advancing the internal state by 8 bytes.
112    pub(crate) async fn read_i64(&mut self) -> AsyncTiffResult<i64> {
113        self.read(8).await?.read_i64()
114    }
115
116    pub(crate) async fn read_f32(&mut self) -> AsyncTiffResult<f32> {
117        self.read(4).await?.read_f32()
118    }
119
120    pub(crate) async fn read_f64(&mut self) -> AsyncTiffResult<f64> {
121        self.read(8).await?.read_f64()
122    }
123}