From c23c7ad408371b9939a94a813baf62584aebd1b7 Mon Sep 17 00:00:00 2001 From: Lukasz Anforowicz Date: Wed, 14 Aug 2024 18:47:49 +0000 Subject: [PATCH] `impl Read for UniquePtr where ... Pin<&a mut T> : Read`. MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit This commit implements forwarding of `Read` trait implementation from `UniquePtr` to the pointee type. This is quite similar to how `Box` also forwards - see https://doc.rust-lang.org/std/boxed/struct.Box.html#impl-Read-for-Box%3CR%3E Just as with `Box`, the `impl` cannot be provided in the crate introducing `T`, because this violates the orphan rule. This means that before this commit a wrapper newtype would be required to work around the orphan rule - e.g.: ``` struct UniquePtrOfReadTrait(cxx::UniquePtr); impl Read for UniquePtrOfReadTrait { … } ``` After this commit, one can provide an `impl` that works more directly with the C++ type `T` (the FFI will typically require passing `self: Pin<&mut ffi::ReadTrait>`): ``` impl<'a> Read for Pin<&'a mut ffi::ReadTrait> { … } ``` For a more specific motivating example, please see: https://docs.google.com/document/d/1EPn1Ss-hfOC6Ki_B5CC6GA_UFnY3TmoDLCP2HjP7bms --- src/unique_ptr.rs | 35 +++++++++++++++++++++++++++++++++++ 1 file changed, 35 insertions(+) diff --git a/src/unique_ptr.rs b/src/unique_ptr.rs index 33992059e..c529bb6e6 100644 --- a/src/unique_ptr.rs +++ b/src/unique_ptr.rs @@ -10,6 +10,9 @@ use core::mem::{self, MaybeUninit}; use core::ops::{Deref, DerefMut}; use core::pin::Pin; +#[cfg(feature = "std")] +use std::io::Read; + /// Binding to C++ `std::unique_ptr>`. #[repr(C)] pub struct UniquePtr @@ -181,6 +184,38 @@ where } } +/// Forwarding `Read` trait implementation in a manner similar to `Box`. Note that the +/// implementation will panic for null `UniquePtr`. +#[cfg(feature = "std")] +impl Read for UniquePtr +where + for<'a> Pin<&'a mut T>: Read, + T: UniquePtrTarget, +{ + #[inline] + fn read(&mut self, buf: &mut [u8]) -> std::io::Result { + self.pin_mut().read(buf) + } + + #[inline] + fn read_to_end(&mut self, buf: &mut std::vec::Vec) -> std::io::Result { + self.pin_mut().read_to_end(buf) + } + + #[inline] + fn read_to_string(&mut self, buf: &mut std::string::String) -> std::io::Result { + self.pin_mut().read_to_string(buf) + } + + #[inline] + fn read_exact(&mut self, buf: &mut [u8]) -> std::io::Result<()> { + self.pin_mut().read_exact(buf) + } + + // TODO: Foward other `Read` trait methods when they get stabilized (e.g. + // `read_buf` and/or `is_read_vectored`). +} + /// Trait bound for types which may be used as the `T` inside of a /// `UniquePtr` in generic code. ///