diff --git a/core/core/src/types/read/futures_async_reader.rs b/core/core/src/types/read/futures_async_reader.rs index cfb41f0b506a..ad7e10799e5a 100644 --- a/core/core/src/types/read/futures_async_reader.rs +++ b/core/core/src/types/read/futures_async_reader.rs @@ -54,6 +54,25 @@ pub struct FuturesAsyncReader { /// Safety: FuturesAsyncReader only exposes `&mut self` to the outside world, unsafe impl Sync for FuturesAsyncReader {} +impl std::fmt::Debug for FuturesAsyncReader { + fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { + let info = self.ctx.accessor().info(); + let root = info.root(); + + f.debug_struct("FuturesAsyncReader") + .field("scheme", &info.scheme()) + .field("root", &root) + .field("path", &self.ctx.path()) + .field("args", self.ctx.args()) + .field("options", self.ctx.options()) + .field("start", &self.start) + .field("end", &self.end) + .field("pos", &self.pos) + .field("buffered", &self.buf.len()) + .finish_non_exhaustive() + } +} + impl FuturesAsyncReader { /// NOTE: don't allow users to create FuturesAsyncReader directly. /// @@ -215,8 +234,10 @@ mod tests { let srv = op.service().clone(); let ctx = Arc::new(new_read_context(ctx, srv, "test", OpReader::new())?); - let v = FuturesAsyncReader::new(ctx, 4..8); + fn assert_reader_traits(_: &T) {} + let v = FuturesAsyncReader::new(ctx, 4..8); + assert_reader_traits(&v); let _: Box = Box::new(v); Ok(()) } diff --git a/core/core/src/types/read/reader.rs b/core/core/src/types/read/reader.rs index 9fcfa691a7f5..06fcbb2c6e09 100644 --- a/core/core/src/types/read/reader.rs +++ b/core/core/src/types/read/reader.rs @@ -108,6 +108,21 @@ struct FetchReadOutput { buffer: Buffer, } +impl std::fmt::Debug for Reader { + fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { + let info = self.ctx.accessor().info(); + let root = info.root(); + + f.debug_struct("Reader") + .field("scheme", &info.scheme()) + .field("root", &root) + .field("path", &self.ctx.path()) + .field("args", self.ctx.args()) + .field("options", self.ctx.options()) + .finish_non_exhaustive() + } +} + impl Reader { /// Create a new reader. /// @@ -649,7 +664,28 @@ mod tests { let srv = op.service().clone(); let ctx = new_read_context(ctx, srv, "test", OpReader::new())?; - let _: Box = Box::new(Reader::new(ctx)); + fn assert_reader_traits(_: &T) {} + + let reader = Reader::new(ctx); + assert_reader_traits(&reader); + let _: Box = Box::new(reader); + + Ok(()) + } + + #[tokio::test] + async fn test_debug() -> Result<()> { + let op = Operator::via_iter(services::MEMORY_SCHEME, [])?; + op.write("test", "hello").await?; + + let reader = op.reader_with("test").chunk(8).await?; + let output = format!("{reader:?}"); + + assert!(output.contains("Reader"), "{output}"); + assert!(output.contains("memory"), "{output}"); + assert!(output.contains("test"), "{output}"); + assert!(output.contains("args"), "{output}"); + assert!(output.contains("options"), "{output}"); Ok(()) } diff --git a/core/core/src/types/write/futures_async_writer.rs b/core/core/src/types/write/futures_async_writer.rs index 2e92386bd208..8917c5c86624 100644 --- a/core/core/src/types/write/futures_async_writer.rs +++ b/core/core/src/types/write/futures_async_writer.rs @@ -37,6 +37,12 @@ pub struct FuturesAsyncWriter { buf: oio::FlexBuf, } +impl std::fmt::Debug for FuturesAsyncWriter { + fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { + f.debug_struct("FuturesAsyncWriter").finish_non_exhaustive() + } +} + impl FuturesAsyncWriter { /// NOTE: don't allow users to create directly. #[inline] @@ -131,8 +137,10 @@ mod tests { )); let write_gen = WriteGenerator::create(ctx).unwrap(); - let v = FuturesAsyncWriter::new(write_gen); + fn assert_writer_traits(_: &T) {} + let v = FuturesAsyncWriter::new(write_gen); + assert_writer_traits(&v); let _: Box = Box::new(v); } } diff --git a/core/core/src/types/write/writer.rs b/core/core/src/types/write/writer.rs index 80dbd3153c2b..1541aa53ec05 100644 --- a/core/core/src/types/write/writer.rs +++ b/core/core/src/types/write/writer.rs @@ -99,17 +99,32 @@ use crate::*; /// creating writer with `append` enabled. pub struct Writer { /// Keep a reference to write context in writer. - _ctx: Arc, + ctx: Arc, inner: WriteGenerator, } +impl std::fmt::Debug for Writer { + fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { + let info = self.ctx.accessor().info(); + let root = info.root(); + + f.debug_struct("Writer") + .field("scheme", &info.scheme()) + .field("root", &root) + .field("path", &self.ctx.path()) + .field("args", self.ctx.args()) + .field("options", self.ctx.options()) + .finish_non_exhaustive() + } +} + impl Writer { /// Create a new writer from an `oio::Writer`. pub(crate) async fn new(ctx: WriteContext) -> Result { let ctx = Arc::new(ctx); let inner = std::future::ready(WriteGenerator::create(ctx.clone())).await?; - Ok(Self { _ctx: ctx, inner }) + Ok(Self { ctx, inner }) } /// Write [`Buffer`] into writer. @@ -383,6 +398,7 @@ mod tests { use rand::{Rng, RngExt}; use crate::Operator; + use crate::Result; use crate::services; fn gen_random_bytes() -> Vec { @@ -452,4 +468,22 @@ mod tests { chain_same.copy_to_bytes(chain_same.remaining()) ); } + + #[tokio::test] + async fn test_debug() -> Result<()> { + let op = Operator::new(services::Memory::default()).unwrap().finish(); + let path = "test_file"; + + let mut writer = op.writer_with(path).chunk(8).await?; + let output = format!("{writer:?}"); + writer.abort().await?; + + assert!(output.contains("Writer"), "{output}"); + assert!(output.contains("memory"), "{output}"); + assert!(output.contains(path), "{output}"); + assert!(output.contains("args"), "{output}"); + assert!(output.contains("options"), "{output}"); + + Ok(()) + } }