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