// Copyright 2024 RustFS Team // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // Default encryption block size - aligned with system default read buffer size (1MB) pub const DEFAULT_ENCRYPTION_BLOCK_SIZE: usize = 1024 * 1024; /// Feature-gated wrapper around `hotpath::measure_block!` for expression /// positions (e.g. inside `poll_read`) where an attribute cannot be used. /// With the `hotpath` feature off it expands to the body unchanged, so the /// default build carries zero profiling overhead and no hotpath dependency. #[cfg(feature = "hotpath")] #[macro_export] macro_rules! hp_measure_block { ($label:expr, $body:expr) => { ::hotpath::measure_block!($label, $body) }; } #[cfg(not(feature = "hotpath"))] #[macro_export] macro_rules! hp_measure_block { ($label:expr, $body:expr) => { $body }; } macro_rules! delegate_reader_capabilities_generic { ($name:ident<$inner_ty:ident>, $inner:ident) => { impl<$inner_ty> crate::EtagResolvable for $name<$inner_ty> where $inner_ty: crate::EtagResolvable, { fn try_resolve_etag(&mut self) -> Option { self.$inner.try_resolve_etag() } } impl<$inner_ty> crate::HashReaderDetector for $name<$inner_ty> where $inner_ty: crate::HashReaderDetector, { fn is_hash_reader(&self) -> bool { self.$inner.is_hash_reader() } fn as_hash_reader_mut(&mut self) -> Option<&mut dyn crate::HashReaderMut> { self.$inner.as_hash_reader_mut() } } impl<$inner_ty> crate::TryGetIndex for $name<$inner_ty> where $inner_ty: crate::TryGetIndex, { fn try_get_index(&self) -> Option<&crate::compress_index::Index> { self.$inner.try_get_index() } } }; } macro_rules! delegate_reader_capabilities_generic_no_index { ($name:ident<$inner_ty:ident>, $inner:ident) => { impl<$inner_ty> crate::EtagResolvable for $name<$inner_ty> where $inner_ty: crate::EtagResolvable, { fn try_resolve_etag(&mut self) -> Option { self.$inner.try_resolve_etag() } } impl<$inner_ty> crate::HashReaderDetector for $name<$inner_ty> where $inner_ty: crate::HashReaderDetector, { fn is_hash_reader(&self) -> bool { self.$inner.is_hash_reader() } fn as_hash_reader_mut(&mut self) -> Option<&mut dyn crate::HashReaderMut> { self.$inner.as_hash_reader_mut() } } }; } mod limit_reader; pub use limit_reader::LimitReader; mod etag_reader; pub use etag_reader::EtagReader; mod compress_index; mod compress_reader; pub use compress_reader::{CompressReader, DecompressReader}; mod encrypt_reader; pub use encrypt_reader::{DecryptReader, EncryptReader, multipart_part_nonce}; mod hardlimit_reader; pub use hardlimit_reader::HardLimitReader; mod hash_reader; pub use hash_reader::*; mod checksum; pub use checksum::*; mod errors; pub use errors::*; pub mod reader; pub use reader::WarpReader; mod writer; pub use writer::*; mod http_reader; pub use http_reader::*; mod http_runtime_sources; pub use compress_index::{Index, TryGetIndex}; mod etag; pub trait ReadStream: tokio::io::AsyncRead + Unpin + Send + Sync {} impl ReadStream for T where T: tokio::io::AsyncRead + Unpin + Send + Sync {} pub trait ReaderCapabilities: EtagResolvable + HashReaderDetector + TryGetIndex {} impl ReaderCapabilities for T where T: EtagResolvable + HashReaderDetector + TryGetIndex {} pub trait Reader: ReadStream + ReaderCapabilities {} impl Reader for T where T: ReadStream + ReaderCapabilities {} pub type DynReader = Box; // Trait for types that can be recursively searched for etag capability pub trait EtagResolvable { fn is_etag_reader(&self) -> bool { false } fn try_resolve_etag(&mut self) -> Option { None } } // Generic function that can work with any EtagResolvable type pub fn resolve_etag_generic(reader: &mut R) -> Option where R: EtagResolvable, { reader.try_resolve_etag() } /// Trait to detect and manipulate HashReader instances pub trait HashReaderDetector { fn is_hash_reader(&self) -> bool { false } fn as_hash_reader_mut(&mut self) -> Option<&mut dyn HashReaderMut> { None } } pub fn boxed_reader(reader: R) -> DynReader where R: Reader + 'static, { Box::new(reader) } pub fn wrap_reader(reader: R) -> DynReader where R: ReadStream + 'static, { boxed_reader(WarpReader::new(reader)) } impl EtagResolvable for Box where T: EtagResolvable + ?Sized, { fn try_resolve_etag(&mut self) -> Option { self.as_mut().try_resolve_etag() } } impl HashReaderDetector for Box where T: HashReaderDetector + ?Sized, { fn is_hash_reader(&self) -> bool { self.as_ref().is_hash_reader() } fn as_hash_reader_mut(&mut self) -> Option<&mut dyn HashReaderMut> { self.as_mut().as_hash_reader_mut() } } impl TryGetIndex for Box where T: TryGetIndex + ?Sized, { fn try_get_index(&self) -> Option<&compress_index::Index> { self.as_ref().try_get_index() } }