From 87e2400992e1010379705ad9c4eddf6d6201719b Mon Sep 17 00:00:00 2001 From: Eric Holk Date: Tue, 18 Jan 2022 10:08:48 -0800 Subject: [PATCH 1/5] Add impls for Read, Write, Seek to Arc, Rc --- library/std/src/io/impls.rs | 3 ++ library/std/src/io/impls/arc.rs | 96 +++++++++++++++++++++++++++++++++ library/std/src/io/impls/rc.rs | 96 +++++++++++++++++++++++++++++++++ 3 files changed, 195 insertions(+) create mode 100644 library/std/src/io/impls/arc.rs create mode 100644 library/std/src/io/impls/rc.rs diff --git a/library/std/src/io/impls.rs b/library/std/src/io/impls.rs index 23201f9fc5c94..38d066a696755 100644 --- a/library/std/src/io/impls.rs +++ b/library/std/src/io/impls.rs @@ -1,6 +1,9 @@ #[cfg(test)] mod tests; +mod arc; +mod rc; + use crate::alloc::Allocator; use crate::cmp; use crate::fmt; diff --git a/library/std/src/io/impls/arc.rs b/library/std/src/io/impls/arc.rs new file mode 100644 index 0000000000000..fe5369d6d0dcc --- /dev/null +++ b/library/std/src/io/impls/arc.rs @@ -0,0 +1,96 @@ +//! Forwarding implementations for Rc + +use crate::fmt; +use crate::io::{self, IoSlice, IoSliceMut, Read, ReadBuf, Seek, SeekFrom, Write}; +use alloc::sync::Arc; + +#[stable(feature = "io_delegation_rc", since = "1.60.0")] +impl Read for Arc +where + for<'a> &'a T: Read, +{ + #[inline] + fn read(&mut self, buf: &mut [u8]) -> io::Result { + (self as &T).read(buf) + } + + #[inline] + fn read_buf(&mut self, buf: &mut ReadBuf<'_>) -> io::Result<()> { + (self as &T).read_buf(buf) + } + + #[inline] + fn read_vectored(&mut self, bufs: &mut [IoSliceMut<'_>]) -> io::Result { + (self as &T).read_vectored(bufs) + } + + #[inline] + fn is_read_vectored(&self) -> bool { + (self as &T).is_read_vectored() + } + + #[inline] + fn read_to_end(&mut self, buf: &mut Vec) -> io::Result { + (self as &T).read_to_end(buf) + } + + #[inline] + fn read_to_string(&mut self, buf: &mut String) -> io::Result { + (self as &T).read_to_string(buf) + } + + #[inline] + fn read_exact(&mut self, buf: &mut [u8]) -> io::Result<()> { + (self as &T).read_exact(buf) + } +} +#[stable(feature = "io_delegation_rc", since = "1.60.0")] +impl Write for Arc +where + for<'a> &'a T: Write, +{ + #[inline] + fn write(&mut self, buf: &[u8]) -> io::Result { + (self as &T).write(buf) + } + + #[inline] + fn write_vectored(&mut self, bufs: &[IoSlice<'_>]) -> io::Result { + (self as &T).write_vectored(bufs) + } + + #[inline] + fn is_write_vectored(&self) -> bool { + (self as &T).is_write_vectored() + } + + #[inline] + fn flush(&mut self) -> io::Result<()> { + (self as &T).flush() + } + + #[inline] + fn write_all(&mut self, buf: &[u8]) -> io::Result<()> { + (self as &T).write_all(buf) + } + + #[inline] + fn write_fmt(&mut self, fmt: fmt::Arguments<'_>) -> io::Result<()> { + (self as &T).write_fmt(fmt) + } +} +#[stable(feature = "io_delegation_rc", since = "1.60.0")] +impl Seek for Arc +where + for<'a> &'a T: Seek, +{ + #[inline] + fn seek(&mut self, pos: SeekFrom) -> io::Result { + (self as &T).seek(pos) + } + + #[inline] + fn stream_position(&mut self) -> io::Result { + (self as &T).stream_position() + } +} diff --git a/library/std/src/io/impls/rc.rs b/library/std/src/io/impls/rc.rs new file mode 100644 index 0000000000000..42c89996c7e67 --- /dev/null +++ b/library/std/src/io/impls/rc.rs @@ -0,0 +1,96 @@ +//! Forwarding implementations for Rc + +use crate::fmt; +use crate::io::{self, IoSlice, IoSliceMut, Read, ReadBuf, Seek, SeekFrom, Write}; +use alloc::rc::Rc; + +#[stable(feature = "io_delegation_rc", since = "1.60.0")] +impl Read for Rc +where + for<'a> &'a T: Read, +{ + #[inline] + fn read(&mut self, buf: &mut [u8]) -> io::Result { + (self as &T).read(buf) + } + + #[inline] + fn read_buf(&mut self, buf: &mut ReadBuf<'_>) -> io::Result<()> { + (self as &T).read_buf(buf) + } + + #[inline] + fn read_vectored(&mut self, bufs: &mut [IoSliceMut<'_>]) -> io::Result { + (self as &T).read_vectored(bufs) + } + + #[inline] + fn is_read_vectored(&self) -> bool { + (self as &T).is_read_vectored() + } + + #[inline] + fn read_to_end(&mut self, buf: &mut Vec) -> io::Result { + (self as &T).read_to_end(buf) + } + + #[inline] + fn read_to_string(&mut self, buf: &mut String) -> io::Result { + (self as &T).read_to_string(buf) + } + + #[inline] + fn read_exact(&mut self, buf: &mut [u8]) -> io::Result<()> { + (self as &T).read_exact(buf) + } +} +#[stable(feature = "io_delegation_rc", since = "1.60.0")] +impl Write for Rc +where + for<'a> &'a T: Write, +{ + #[inline] + fn write(&mut self, buf: &[u8]) -> io::Result { + (self as &T).write(buf) + } + + #[inline] + fn write_vectored(&mut self, bufs: &[IoSlice<'_>]) -> io::Result { + (self as &T).write_vectored(bufs) + } + + #[inline] + fn is_write_vectored(&self) -> bool { + (self as &T).is_write_vectored() + } + + #[inline] + fn flush(&mut self) -> io::Result<()> { + (self as &T).flush() + } + + #[inline] + fn write_all(&mut self, buf: &[u8]) -> io::Result<()> { + (self as &T).write_all(buf) + } + + #[inline] + fn write_fmt(&mut self, fmt: fmt::Arguments<'_>) -> io::Result<()> { + (self as &T).write_fmt(fmt) + } +} +#[stable(feature = "io_delegation_rc", since = "1.60.0")] +impl Seek for Rc +where + for<'a> &'a T: Seek, +{ + #[inline] + fn seek(&mut self, pos: SeekFrom) -> io::Result { + (self as &T).seek(pos) + } + + #[inline] + fn stream_position(&mut self) -> io::Result { + (self as &T).stream_position() + } +} From 6d4ea5a39d57363dc9ae5b010f7bdd4dc7e5b606 Mon Sep 17 00:00:00 2001 From: Eric Holk Date: Tue, 25 Jan 2022 14:58:54 -0800 Subject: [PATCH 2/5] Add test case for Read for Arc --- library/std/src/io/tests.rs | 15 +++++++++++++++ 1 file changed, 15 insertions(+) diff --git a/library/std/src/io/tests.rs b/library/std/src/io/tests.rs index ea49bfe3421d1..e5c258883f41e 100644 --- a/library/std/src/io/tests.rs +++ b/library/std/src/io/tests.rs @@ -602,3 +602,18 @@ fn bench_take_read_buf(b: &mut test::Bencher) { [255; 128].take(64).read_buf(&mut rbuf).unwrap(); }); } + +#[test] +fn read_arc() { + use crate::net::TcpStream; + use crate::sync::Arc; + + // This test is wrapped in a closure to make sure it typechecks + // but we do not run it. + let _ = || { + let stream = TcpStream::connect("localhost:8080").unwrap(); + let mut stream = Arc::new(stream); + let mut buffer = [0; 4]; + stream.read(&mut buffer).unwrap(); + }; +} From 3e72e2824d0c6d6ea69fdb4e7ce45958bbca33bc Mon Sep 17 00:00:00 2001 From: Eric Holk Date: Wed, 26 Jan 2022 15:09:49 -0800 Subject: [PATCH 3/5] Add test cases covering Write, Seek, and Rc --- library/std/src/io/tests.rs | 39 ++++++++++++++++++++++++++++++++++++- 1 file changed, 38 insertions(+), 1 deletion(-) diff --git a/library/std/src/io/tests.rs b/library/std/src/io/tests.rs index e5c258883f41e..3a4f5f85f9d96 100644 --- a/library/std/src/io/tests.rs +++ b/library/std/src/io/tests.rs @@ -604,9 +604,13 @@ fn bench_take_read_buf(b: &mut test::Bencher) { } #[test] -fn read_arc() { +fn forward_arc() { + // Tests forwarding of Read, Write, and Seek through an Arc when &T implements the trait. + use crate::net::TcpStream; + use crate::fs::File; use crate::sync::Arc; + use crate::io::SeekFrom; // This test is wrapped in a closure to make sure it typechecks // but we do not run it. @@ -615,5 +619,38 @@ fn read_arc() { let mut stream = Arc::new(stream); let mut buffer = [0; 4]; stream.read(&mut buffer).unwrap(); + stream.write(&buffer).unwrap(); + }; + + let _ = || { + let file = File::open("foo").unwrap(); + let mut file = Arc::new(file); + file.seek(SeekFrom::Start(10)).unwrap(); + }; +} + +#[test] +fn forward_rc() { + // Tests forwarding of Read, Write, and Seek through an Arc when &T implements the trait. + + use crate::net::TcpStream; + use crate::fs::File; + use crate::rc::Rc; + use crate::io::SeekFrom; + + // This test is wrapped in a closure to make sure it typechecks + // but we do not run it. + let _ = || { + let stream = TcpStream::connect("localhost:8080").unwrap(); + let mut stream = Rc::new(stream); + let mut buffer = [0; 4]; + stream.read(&mut buffer).unwrap(); + stream.write(&buffer).unwrap(); + }; + + let _ = || { + let file = File::open("foo").unwrap(); + let mut file = Rc::new(file); + file.seek(SeekFrom::Start(10)).unwrap(); }; } From 0d94e64fd18fa66c91ae3009ba6bab95097c6efb Mon Sep 17 00:00:00 2001 From: Eric Holk Date: Wed, 26 Jan 2022 15:26:46 -0800 Subject: [PATCH 4/5] Fix formatting --- library/std/src/io/tests.rs | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/library/std/src/io/tests.rs b/library/std/src/io/tests.rs index 3a4f5f85f9d96..cc6b5d4cae8e7 100644 --- a/library/std/src/io/tests.rs +++ b/library/std/src/io/tests.rs @@ -607,10 +607,10 @@ fn bench_take_read_buf(b: &mut test::Bencher) { fn forward_arc() { // Tests forwarding of Read, Write, and Seek through an Arc when &T implements the trait. - use crate::net::TcpStream; use crate::fs::File; - use crate::sync::Arc; use crate::io::SeekFrom; + use crate::net::TcpStream; + use crate::sync::Arc; // This test is wrapped in a closure to make sure it typechecks // but we do not run it. @@ -633,10 +633,10 @@ fn forward_arc() { fn forward_rc() { // Tests forwarding of Read, Write, and Seek through an Arc when &T implements the trait. - use crate::net::TcpStream; use crate::fs::File; - use crate::rc::Rc; use crate::io::SeekFrom; + use crate::net::TcpStream; + use crate::rc::Rc; // This test is wrapped in a closure to make sure it typechecks // but we do not run it. From b95f4cd2f4adeb5a8e7e79ac6ee8d1905e06b963 Mon Sep 17 00:00:00 2001 From: Eric Holk Date: Wed, 26 Jan 2022 15:37:52 -0800 Subject: [PATCH 5/5] Add documentation comments --- library/std/src/io/impls/arc.rs | 20 +++++++++++++++++++- library/std/src/io/impls/rc.rs | 18 ++++++++++++++++++ 2 files changed, 37 insertions(+), 1 deletion(-) diff --git a/library/std/src/io/impls/arc.rs b/library/std/src/io/impls/arc.rs index fe5369d6d0dcc..de111379f0324 100644 --- a/library/std/src/io/impls/arc.rs +++ b/library/std/src/io/impls/arc.rs @@ -1,9 +1,15 @@ -//! Forwarding implementations for Rc +//! Forwarding implementations for Arc use crate::fmt; use crate::io::{self, IoSlice, IoSliceMut, Read, ReadBuf, Seek, SeekFrom, Write}; use alloc::sync::Arc; +/// Enables forwarding `Read` through an `Arc` +/// +/// This only applies for types such as `File` or `TcpStream` that implement Read +/// on `&T`. The reason is that `Read` normally requires `&mut self`, but mutation +/// through an `Arc` is not generally allowed because the value in the `Arc` may be +/// shared. #[stable(feature = "io_delegation_rc", since = "1.60.0")] impl Read for Arc where @@ -44,6 +50,12 @@ where (self as &T).read_exact(buf) } } +/// Enables forwarding `Write` through an `Arc` +/// +/// This only applies for types such as `File` or `TcpStream` that implement Write +/// on `&T`. The reason is that `Write` normally requires `&mut self`, but mutation +/// through an `Arc` is not generally allowed because the value in the `Arc` may be +/// shared. #[stable(feature = "io_delegation_rc", since = "1.60.0")] impl Write for Arc where @@ -79,6 +91,12 @@ where (self as &T).write_fmt(fmt) } } +/// Enables forwarding `Seek` through an `Arc` +/// +/// This only applies for types such as `File` or `TcpStream` that implement Seek +/// on `&T`. The reason is that `Seek` normally requires `&mut self`, but mutation +/// through an `Arc` is not generally allowed because the value in the `Arc` may be +/// shared. #[stable(feature = "io_delegation_rc", since = "1.60.0")] impl Seek for Arc where diff --git a/library/std/src/io/impls/rc.rs b/library/std/src/io/impls/rc.rs index 42c89996c7e67..df67ab8522248 100644 --- a/library/std/src/io/impls/rc.rs +++ b/library/std/src/io/impls/rc.rs @@ -4,6 +4,12 @@ use crate::fmt; use crate::io::{self, IoSlice, IoSliceMut, Read, ReadBuf, Seek, SeekFrom, Write}; use alloc::rc::Rc; +/// Enables forwarding `Read` through an `Rc` +/// +/// This only applies for types such as `File` or `TcpStream` that implement Read +/// on `&T`. The reason is that `Read` normally requires `&mut self`, but mutation +/// through an `Rc` is not generally allowed because the value in the `Rc` may be +/// shared. #[stable(feature = "io_delegation_rc", since = "1.60.0")] impl Read for Rc where @@ -44,6 +50,12 @@ where (self as &T).read_exact(buf) } } +/// Enables forwarding `Write` through an `Rc` +/// +/// This only applies for types such as `File` or `TcpStream` that implement Write +/// on `&T`. The reason is that `Write` normally requires `&mut self`, but mutation +/// through an `Rc` is not generally allowed because the value in the `Rc` may be +/// shared. #[stable(feature = "io_delegation_rc", since = "1.60.0")] impl Write for Rc where @@ -79,6 +91,12 @@ where (self as &T).write_fmt(fmt) } } +/// Enables forwarding `Seek` through an `Rc` +/// +/// This only applies for types such as `File` or `TcpStream` that implement Seek +/// on `&T`. The reason is that `Seek` normally requires `&mut self`, but mutation +/// through an `Rc` is not generally allowed because the value in the `Rc` may be +/// shared. #[stable(feature = "io_delegation_rc", since = "1.60.0")] impl Seek for Rc where