From 647e060a860f3b2c406b55349450e23b9b4dfcd1 Mon Sep 17 00:00:00 2001 From: Filipe Rodrigues Date: Tue, 21 Nov 2023 05:04:23 +0000 Subject: [PATCH] Improved `IoSlice` bounds and impls. Simplified all `&IoSlice` impls. Added `Write` impl for `&IoSlice`. --- tools/ddw3-util/src/io_slice.rs | 98 ++++++++++++++++++++++++--------- tools/ddw3-util/src/lib.rs | 2 +- 2 files changed, 73 insertions(+), 27 deletions(-) diff --git a/tools/ddw3-util/src/io_slice.rs b/tools/ddw3-util/src/io_slice.rs index 72c21c8cb..0ac7d1a1a 100644 --- a/tools/ddw3-util/src/io_slice.rs +++ b/tools/ddw3-util/src/io_slice.rs @@ -13,6 +13,7 @@ use { /// Io slice. /// /// Slices an inner value to only allow access to a range. +// TODO: Now that `std::io::IoSlice` exists, maybe we should rename this? #[derive(Clone, Debug)] pub struct IoSlice { /// Inner value @@ -25,9 +26,12 @@ pub struct IoSlice { end_pos: u64, } -impl IoSlice { +impl IoSlice { /// Creates a new slice given a u64 range - pub fn new>(mut inner: T, range: R) -> Result { + pub fn new>(mut inner: T, range: R) -> Result + where + T: Seek, + { // Get the start position and simplify the end bound // TODO: Check if saturating on overflow is fine here, should be. let start_pos = match range.start_bound().cloned() { @@ -69,7 +73,10 @@ impl IoSlice { } /// Creates a new slice from an offset (from the start of the stream) and a length - pub fn new_with_offset_len(mut inner: T, start_pos: u64, len: u64) -> Result { + pub fn new_with_offset_len(mut inner: T, start_pos: u64, len: u64) -> Result + where + T: Seek, + { // Get the end position // TODO: Check if saturating add is good enough here? Use case is `size == usize::MAX` let end_pos = start_pos.saturating_add(len); @@ -85,11 +92,23 @@ impl IoSlice { } /// Creates a slice from the current position with at most `size` bytes. - pub fn new_take(mut inner: T, size: u64) -> Result { + pub fn new_take(mut inner: T, size: u64) -> Result + where + T: Seek, + { let start_pos = inner.stream_position()?; Self::new_with_offset_len(inner, start_pos, size) } + /// Creates a `IoSlice<&T>` from an `&IoSlice` + pub fn by_inner_ref(&self) -> IoSlice<&T> { + IoSlice { + inner: &self.inner, + start_pos: self.start_pos, + end_pos: self.end_pos, + } + } + /// Consumes this slice and returns the inner value pub fn into_inner(self) -> T { self.inner @@ -102,14 +121,20 @@ impl IoSlice { } /// Returns the current position of the slice - pub fn cur_pos(&mut self) -> Result { + pub fn cur_pos(&mut self) -> Result + where + T: Seek, + { let inner_pos = self.inner.stream_position()?; Ok(inner_pos - self.start_pos) } /// Returns the remaining length of the slice - pub fn remaining_len(&mut self) -> Result { + pub fn remaining_len(&mut self) -> Result + where + T: Seek, + { Ok(self.end_pos - self.inner.stream_position()?) } } @@ -212,61 +237,82 @@ impl Seek for IoSlice { } } - // Impls for `&IoSlice<&T>`, such as `T = std::fs::File` impl<'a, T> Read for &'a IoSlice where - for<'b> &'b mut &'a T: Read + Seek, + &'a T: Read + Seek, { fn read(&mut self, buf: &mut [u8]) -> io::Result { - self::exec_as_ref_ref_mut(self, |mut slice| slice.read(buf)) + self.by_inner_ref().read(buf) } fn read_vectored(&mut self, bufs: &mut [io::IoSliceMut<'_>]) -> io::Result { - self::exec_as_ref_ref_mut(self, |mut slice| slice.read_vectored(bufs)) + self.by_inner_ref().read_vectored(bufs) } fn read_to_end(&mut self, buf: &mut Vec) -> io::Result { - self::exec_as_ref_ref_mut(self, |mut slice| slice.read_to_end(buf)) + self.by_inner_ref().read_to_end(buf) } fn read_to_string(&mut self, buf: &mut String) -> io::Result { - self::exec_as_ref_ref_mut(self, |mut slice| slice.read_to_string(buf)) + self.by_inner_ref().read_to_string(buf) } fn read_exact(&mut self, buf: &mut [u8]) -> io::Result<()> { - self::exec_as_ref_ref_mut(self, |mut slice| slice.read_exact(buf)) + self.by_inner_ref().read_exact(buf) } } impl<'a, T> Seek for &'a IoSlice where - for<'b> &'b mut &'a T: Seek, + &'a T: Seek, { fn seek(&mut self, pos: SeekFrom) -> io::Result { - self::exec_as_ref_ref_mut(self, |mut slice| slice.seek(pos)) + self.by_inner_ref().seek(pos) } fn rewind(&mut self) -> io::Result<()> { - self::exec_as_ref_ref_mut(self, |mut slice| slice.rewind()) + self.by_inner_ref().rewind() } fn stream_len(&mut self) -> io::Result { - self::exec_as_ref_ref_mut(self, |mut slice| slice.stream_len()) + self.by_inner_ref().stream_len() } fn stream_position(&mut self) -> io::Result { - self::exec_as_ref_ref_mut(self, |mut slice| slice.stream_position()) + self.by_inner_ref().stream_position() } } -/// Creates a `IoSlice<&mut &T>` from `&mut & IoSlice` and runs `f` with it -fn exec_as_ref_ref_mut<'a, 'b, T, O>(slice: &'b &'a IoSlice, f: impl FnOnce(IoSlice<&'_ mut &'a T>) -> O) -> O { - let slice = IoSlice { - inner: &mut &slice.inner, - start_pos: slice.start_pos, - end_pos: slice.end_pos, - }; +impl<'a, T> Write for &'a IoSlice +where + &'a T: Write + Seek, +{ + fn write(&mut self, buf: &[u8]) -> Result { + self.by_inner_ref().write(buf) + } - f(slice) + fn flush(&mut self) -> Result<(), io::Error> { + self.by_inner_ref().flush() + } + + fn write_vectored(&mut self, bufs: &[std::io::IoSlice<'_>]) -> Result { + self.by_inner_ref().write_vectored(bufs) + } + + fn is_write_vectored(&self) -> bool { + self.by_inner_ref().is_write_vectored() + } + + fn write_all(&mut self, buf: &[u8]) -> Result<(), io::Error> { + self.by_inner_ref().write_all(buf) + } + + fn write_all_vectored(&mut self, bufs: &mut [std::io::IoSlice<'_>]) -> Result<(), io::Error> { + self.by_inner_ref().write_all_vectored(bufs) + } + + fn write_fmt(&mut self, fmt: std::fmt::Arguments<'_>) -> Result<(), io::Error> { + self.by_inner_ref().write_fmt(fmt) + } } diff --git a/tools/ddw3-util/src/lib.rs b/tools/ddw3-util/src/lib.rs index 79209b409..2fb52147e 100644 --- a/tools/ddw3-util/src/lib.rs +++ b/tools/ddw3-util/src/lib.rs @@ -3,7 +3,7 @@ //! Most here might be moved to external creates if deemed worth it // Features -#![feature(slice_index_methods, seek_stream_len, lint_reasons)] +#![feature(slice_index_methods, seek_stream_len, lint_reasons, can_vector, write_all_vectored)] // Modules pub mod alphabet;