diff --git a/Cargo.toml b/Cargo.toml index 1c4ed93..96f1cd2 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -15,10 +15,10 @@ flate2 = "1.0.20" futures = "0.3.31" jpeg = { package = "jpeg-decoder", version = "0.3.0", default-features = false } num_enum = "0.7.3" -object_store = "0.12" +object_store = { version = "0.12", optional = true } # In the future we could make this feature-flagged, but for now we depend on # object_store which uses reqwest. -reqwest = { version = "0.12", default-features = false } +reqwest = { version = "0.12", default-features = false, optional = true } thiserror = "1" tokio = { version = "1.43.0", optional = true } weezl = "0.1.0" @@ -26,3 +26,16 @@ weezl = "0.1.0" [dev-dependencies] tiff = "0.9.1" tokio = { version = "1.9", features = ["macros", "fs", "rt-multi-thread"] } + +[features] +default = ["object_store", "reqwest"] +reqwest = ["dep:reqwest"] +object_store = ["dep:object_store"] + +[package.metadata.cargo-all-features] + +# If your crate has a large number of optional dependencies, skip them for speed +skip_optional_dependencies = true + +# Exclude certain features from the build matrix +denylist = ["default"] diff --git a/src/cog.rs b/src/cog.rs index e9e3c5b..69a5d98 100644 --- a/src/cog.rs +++ b/src/cog.rs @@ -56,6 +56,7 @@ impl TIFF { } } +#[cfg(feature = "object_store")] #[cfg(test)] mod test { use std::io::BufReader; diff --git a/src/error.rs b/src/error.rs index 9f5b7f0..ae0b7eb 100644 --- a/src/error.rs +++ b/src/error.rs @@ -24,6 +24,7 @@ pub enum AsyncTiffError { JPEGDecodingError(#[from] jpeg::Error), /// Error while fetching data using object store. + #[cfg(feature = "object_store")] #[error(transparent)] ObjectStore(#[from] object_store::Error), @@ -32,6 +33,7 @@ pub enum AsyncTiffError { InternalTIFFError(#[from] crate::tiff::TiffError), /// Reqwest error + #[cfg(feature = "reqwest")] #[error(transparent)] ReqwestError(#[from] reqwest::Error), diff --git a/src/ifd.rs b/src/ifd.rs index d522826..d5b1f9c 100644 --- a/src/ifd.rs +++ b/src/ifd.rs @@ -779,7 +779,7 @@ impl ImageFileDirectory { let range = self .get_tile_byte_range(x, y) .ok_or(AsyncTiffError::General("Not a tiled TIFF".to_string()))?; - let compressed_bytes = reader.get_bytes(range).await?; + let compressed_bytes = reader.get_tile_bytes(range).await?; Ok(Tile { x, y, @@ -810,7 +810,7 @@ impl ImageFileDirectory { .collect::>>()?; // 2: Fetch using `get_ranges - let buffers = reader.get_byte_ranges(byte_ranges).await?; + let buffers = reader.get_tile_byte_ranges(byte_ranges).await?; // 3: Create tile objects let mut tiles = vec![]; diff --git a/src/reader.rs b/src/reader.rs index 8563077..9e0e7fe 100644 --- a/src/reader.rs +++ b/src/reader.rs @@ -9,6 +9,7 @@ use byteorder::{BigEndian, LittleEndian, ReadBytesExt}; use bytes::buf::Reader; use bytes::{Buf, Bytes}; use futures::future::{BoxFuture, FutureExt, TryFutureExt}; +#[cfg(feature = "object_store")] use object_store::ObjectStore; use crate::error::{AsyncTiffError, AsyncTiffResult}; @@ -51,6 +52,18 @@ pub trait AsyncFileReader: Debug + Send + Sync { } .boxed() } + + /// Same as [`get_bytes`], but this function is called when retrieving + /// compressed tile data + fn get_tile_bytes(&self, range: Range) -> BoxFuture<'_, AsyncTiffResult> { + self.get_bytes(range) + } + + /// Same as [`get_byte_ranges`], but this function is only called when retrieving + /// compressed tile data + fn get_tile_byte_ranges(&self, ranges: Vec>) -> BoxFuture<'_, AsyncTiffResult>> { + self.get_byte_ranges(ranges) + } } /// This allows Box to be used as an AsyncFileReader, @@ -91,12 +104,13 @@ impl AsyncFileReader for Box { // } /// An AsyncFileReader that reads from an [`ObjectStore`] instance. +#[cfg(feature = "object_store")] #[derive(Clone, Debug)] pub struct ObjectReader { store: Arc, path: object_store::path::Path, } - +#[cfg(feature = "object_store")] impl ObjectReader { /// Creates a new [`ObjectReader`] for the provided [`ObjectStore`] and path /// @@ -105,7 +119,7 @@ impl ObjectReader { Self { store, path } } } - +#[cfg(feature = "object_store")] impl AsyncFileReader for ObjectReader { fn get_bytes(&self, range: Range) -> BoxFuture<'_, AsyncTiffResult> { let range = range.start as _..range.end as _; @@ -134,19 +148,20 @@ impl AsyncFileReader for ObjectReader { } /// An AsyncFileReader that reads from a URL using reqwest. +#[cfg(feature = "reqwest")] #[derive(Debug, Clone)] pub struct ReqwestReader { client: reqwest::Client, url: reqwest::Url, } - +#[cfg(feature = "reqwest")] impl ReqwestReader { /// Construct a new ReqwestReader from a reqwest client and URL. pub fn new(client: reqwest::Client, url: reqwest::Url) -> Self { Self { client, url } } } - +#[cfg(feature = "reqwest")] impl AsyncFileReader for ReqwestReader { fn get_bytes(&self, range: Range) -> BoxFuture<'_, AsyncTiffResult> { let url = self.url.clone();