fix(rio): preserve reader capabilities and crypto safety (#2363)

This commit is contained in:
weisd
2026-04-03 13:57:42 +08:00
committed by GitHub
parent 6a114cd2e0
commit 5d302febb7
20 changed files with 1074 additions and 699 deletions
+97 -13
View File
@@ -15,6 +15,67 @@
// Default encryption block size - aligned with system default read buffer size (1MB)
pub const DEFAULT_ENCRYPTION_BLOCK_SIZE: usize = 1024 * 1024;
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<String> {
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<String> {
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;
@@ -53,7 +114,16 @@ pub use compress_index::{Index, TryGetIndex};
mod etag;
pub trait Reader: tokio::io::AsyncRead + Unpin + Send + Sync + EtagResolvable + HashReaderDetector + TryGetIndex {}
pub trait ReadStream: tokio::io::AsyncRead + Unpin + Send + Sync {}
impl<T> ReadStream for T where T: tokio::io::AsyncRead + Unpin + Send + Sync {}
pub trait ReaderCapabilities: EtagResolvable + HashReaderDetector + TryGetIndex {}
impl<T> ReaderCapabilities for T where T: EtagResolvable + HashReaderDetector + TryGetIndex {}
pub trait Reader: ReadStream + ReaderCapabilities {}
impl<T> Reader for T where T: ReadStream + ReaderCapabilities {}
pub type DynReader = Box<dyn Reader>;
// Trait for types that can be recursively searched for etag capability
pub trait EtagResolvable {
@@ -84,20 +154,33 @@ pub trait HashReaderDetector {
}
}
impl Reader for crate::HashReader {}
impl Reader for crate::HardLimitReader {}
impl Reader for crate::EtagReader {}
impl<R> Reader for crate::LimitReader<R> where R: Reader {}
impl<R> Reader for crate::CompressReader<R> where R: Reader {}
impl<R> Reader for crate::EncryptReader<R> where R: Reader {}
impl<R> Reader for crate::DecryptReader<R> where R: Reader {}
impl EtagResolvable for Box<dyn Reader> {
pub fn boxed_reader<R>(reader: R) -> DynReader
where
R: Reader + 'static,
{
Box::new(reader)
}
pub fn wrap_reader<R>(reader: R) -> DynReader
where
R: ReadStream + 'static,
{
boxed_reader(WarpReader::new(reader))
}
impl<T> EtagResolvable for Box<T>
where
T: EtagResolvable + ?Sized,
{
fn try_resolve_etag(&mut self) -> Option<String> {
self.as_mut().try_resolve_etag()
}
}
impl HashReaderDetector for Box<dyn Reader> {
impl<T> HashReaderDetector for Box<T>
where
T: HashReaderDetector + ?Sized,
{
fn is_hash_reader(&self) -> bool {
self.as_ref().is_hash_reader()
}
@@ -107,10 +190,11 @@ impl HashReaderDetector for Box<dyn Reader> {
}
}
impl TryGetIndex for Box<dyn Reader> {
impl<T> TryGetIndex for Box<T>
where
T: TryGetIndex + ?Sized,
{
fn try_get_index(&self) -> Option<&compress_index::Index> {
self.as_ref().try_get_index()
}
}
impl Reader for Box<dyn Reader> {}