From 77482308a04a6396d0ab3ce4b57c3568e273d1f3 Mon Sep 17 00:00:00 2001 From: Fee Fladder Date: Thu, 5 Feb 2026 20:41:10 +0100 Subject: [PATCH 1/5] feat:metadata publish MetadataCursor and it's read u16,u32,u64 methods --- src/metadata/fetch.rs | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/src/metadata/fetch.rs b/src/metadata/fetch.rs index 90050f83..a9655e9f 100644 --- a/src/metadata/fetch.rs +++ b/src/metadata/fetch.rs @@ -28,7 +28,7 @@ impl MetadataFetch for T { } } -pub(crate) struct MetadataCursor<'a, F: MetadataFetch> { +pub struct MetadataCursor<'a, F: MetadataFetch> { fetch: &'a F, offset: u64, endianness: Endianness, @@ -84,7 +84,7 @@ impl<'a, F: MetadataFetch> MetadataCursor<'a, F> { } /// Read a u16 from the cursor, advancing the internal state by 2 bytes. - pub(crate) async fn read_u16(&mut self) -> AsyncTiffResult { + pub async fn read_u16(&mut self) -> AsyncTiffResult { self.read(2).await?.read_u16() } @@ -94,7 +94,7 @@ impl<'a, F: MetadataFetch> MetadataCursor<'a, F> { } /// Read a u32 from the cursor, advancing the internal state by 4 bytes. - pub(crate) async fn read_u32(&mut self) -> AsyncTiffResult { + pub async fn read_u32(&mut self) -> AsyncTiffResult { self.read(4).await?.read_u32() } @@ -104,7 +104,7 @@ impl<'a, F: MetadataFetch> MetadataCursor<'a, F> { } /// Read a u64 from the cursor, advancing the internal state by 8 bytes. - pub(crate) async fn read_u64(&mut self) -> AsyncTiffResult { + pub async fn read_u64(&mut self) -> AsyncTiffResult { self.read(8).await?.read_u64() } From 8ea5328bd2c58377146f42a8f11a0f03662fb026 Mon Sep 17 00:00:00 2001 From: Fee Fladder Date: Thu, 5 Feb 2026 21:04:58 +0100 Subject: [PATCH 2/5] feat:metadata expose accessors to ifd tag_count, ifd_entry_byte_size and tag_count_byte_size --- src/metadata/reader.rs | 16 ++++++++++++++++ 1 file changed, 16 insertions(+) diff --git a/src/metadata/reader.rs b/src/metadata/reader.rs index 9488f1f6..fbe0fbf5 100644 --- a/src/metadata/reader.rs +++ b/src/metadata/reader.rs @@ -257,6 +257,22 @@ impl ImageFileDirectoryReader { Ok(Some(next_ifd_offset)) } } + + /// The number of tags in this IFD + pub fn tag_count(&self) -> u64 { + self.tag_count + } + + /// The number of bytes that each IFD entry takes up. + /// This is 12 bytes for normal TIFF and 20 bytes for BigTIFF. + pub fn ifd_entry_byte_size(&self) -> u64 { + self.ifd_entry_byte_size + } + + /// The number of bytes that the value for the number of tags takes up. + pub fn tag_count_byte_size(&self) -> u64 { + self.tag_count_byte_size + } } /// Read a single tag from the cursor From e09e8399860dd75865e589509e9c0ea165c6f253 Mon Sep 17 00:00:00 2001 From: Fee Fladder Date: Thu, 5 Feb 2026 21:17:33 +0100 Subject: [PATCH 3/5] feat:metadata expose MetadataCursor in metadata --- src/metadata/mod.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/metadata/mod.rs b/src/metadata/mod.rs index 79498140..39e9e753 100644 --- a/src/metadata/mod.rs +++ b/src/metadata/mod.rs @@ -61,5 +61,5 @@ pub mod cache; mod fetch; mod reader; -pub use fetch::MetadataFetch; +pub use fetch::{MetadataFetch, MetadataCursor}; pub use reader::{ImageFileDirectoryReader, TiffMetadataReader}; From 379aa4198694845dd9c34a02b6c010e9250422ee Mon Sep 17 00:00:00 2001 From: Fee Fladder Date: Thu, 5 Feb 2026 21:55:24 +0100 Subject: [PATCH 4/5] feat:metadata add docs to public methods --- src/metadata/fetch.rs | 11 +++++++++++ src/metadata/mod.rs | 2 +- src/metadata/reader.rs | 2 +- 3 files changed, 13 insertions(+), 2 deletions(-) diff --git a/src/metadata/fetch.rs b/src/metadata/fetch.rs index a9655e9f..1f06e90f 100644 --- a/src/metadata/fetch.rs +++ b/src/metadata/fetch.rs @@ -28,6 +28,8 @@ impl MetadataFetch for T { } } +/// An endian-aware cursor into the tiff +#[derive(Debug)] pub struct MetadataCursor<'a, F: MetadataFetch> { fetch: &'a F, offset: u64, @@ -35,6 +37,7 @@ pub struct MetadataCursor<'a, F: MetadataFetch> { } impl<'a, F: MetadataFetch> MetadataCursor<'a, F> { + /// Create a new MetadataCursor pointing at the start of the tiff pub fn new(fetch: &'a F, endianness: Endianness) -> Self { Self { fetch, @@ -43,6 +46,7 @@ impl<'a, F: MetadataFetch> MetadataCursor<'a, F> { } } + /// Create a new Metadata cursor at the specified offset pub fn new_with_offset(fetch: &'a F, endianness: Endianness, offset: u64) -> Self { Self { fetch, @@ -51,11 +55,18 @@ impl<'a, F: MetadataFetch> MetadataCursor<'a, F> { } } + /// set the offset on this cursor + /// + /// ```ignore + /// use async_tiff::metadata::MetadataCursor; + /// let cursor = MetadataCursor::new().with_offset(42); + /// ``` pub fn with_offset(mut self, offset: u64) -> Self { self.offset = offset; self } + /// seek to a pre-determined offset in the tiff pub fn seek(&mut self, offset: u64) { self.offset = offset; } diff --git a/src/metadata/mod.rs b/src/metadata/mod.rs index 39e9e753..78055033 100644 --- a/src/metadata/mod.rs +++ b/src/metadata/mod.rs @@ -61,5 +61,5 @@ pub mod cache; mod fetch; mod reader; -pub use fetch::{MetadataFetch, MetadataCursor}; +pub use fetch::{MetadataCursor, MetadataFetch}; pub use reader::{ImageFileDirectoryReader, TiffMetadataReader}; diff --git a/src/metadata/reader.rs b/src/metadata/reader.rs index fbe0fbf5..31f64edb 100644 --- a/src/metadata/reader.rs +++ b/src/metadata/reader.rs @@ -262,7 +262,7 @@ impl ImageFileDirectoryReader { pub fn tag_count(&self) -> u64 { self.tag_count } - + /// The number of bytes that each IFD entry takes up. /// This is 12 bytes for normal TIFF and 20 bytes for BigTIFF. pub fn ifd_entry_byte_size(&self) -> u64 { From 4b14620f54827877ba75325c984c0e2059498f22 Mon Sep 17 00:00:00 2001 From: Fee Fladder Date: Fri, 6 Feb 2026 09:39:42 +0100 Subject: [PATCH 5/5] feat: metadata only exposed a tag_offset function --- src/metadata/reader.rs | 15 ++++----------- 1 file changed, 4 insertions(+), 11 deletions(-) diff --git a/src/metadata/reader.rs b/src/metadata/reader.rs index 31f64edb..e26db6a9 100644 --- a/src/metadata/reader.rs +++ b/src/metadata/reader.rs @@ -215,8 +215,7 @@ impl ImageFileDirectoryReader { 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_offset = self.tag_offset(tag_idx); let (tag_name, tag_value) = read_tag(fetch, tag_offset, self.endianness, self.bigtiff).await?; Ok((tag_name, tag_value)) @@ -263,15 +262,9 @@ impl ImageFileDirectoryReader { self.tag_count } - /// The number of bytes that each IFD entry takes up. - /// This is 12 bytes for normal TIFF and 20 bytes for BigTIFF. - pub fn ifd_entry_byte_size(&self) -> u64 { - self.ifd_entry_byte_size - } - - /// The number of bytes that the value for the number of tags takes up. - pub fn tag_count_byte_size(&self) -> u64 { - self.tag_count_byte_size + /// The offset of the nth IFD tag in the tiff + pub fn tag_offset(&self, tag_idx: u64) -> u64 { + self.ifd_start_offset + self.tag_count_byte_size + (self.ifd_entry_byte_size * tag_idx) } }