diff --git a/src/buf/chain.rs b/src/buf/chain.rs index c8bc36de9..316cbdf1d 100644 --- a/src/buf/chain.rs +++ b/src/buf/chain.rs @@ -1,5 +1,5 @@ use crate::buf::{IntoIter, UninitSlice}; -use crate::{Buf, BufMut}; +use crate::{Buf, BufMut, Cursor, CursorMut}; #[cfg(feature = "std")] use std::io::IoSlice; @@ -226,6 +226,33 @@ where } } +impl Cursor for Chain { + type Cursor<'a> + = Chain, U::Cursor<'a>> + where + Self: 'a; + + fn cursor(&self, index: usize) -> Self::Cursor<'_> { + let mut chain = self.a.cursor(0).chain(self.b.cursor(0)); + chain.advance(index); + chain + } +} + +unsafe impl CursorMut for Chain { + type CursorMut<'a> + = Chain, U::CursorMut<'a>> + where + Self: 'a; + + fn cursor_mut(&mut self, index: usize) -> Self::CursorMut<'_> { + let mut chain = self.a.cursor_mut(0).chain_mut(self.b.cursor_mut(0)); + // SAFETY: advance_mut must be safe on CursorMut::CursorMut + unsafe { chain.advance_mut(index) }; + chain + } +} + impl IntoIterator for Chain where T: Buf, diff --git a/src/buf/cursor.rs b/src/buf/cursor.rs new file mode 100644 index 000000000..5825efc3f --- /dev/null +++ b/src/buf/cursor.rs @@ -0,0 +1,35 @@ +use crate::{buf::Chain, Buf}; +use std::collections::VecDeque; + +pub trait Cursor: Buf { + type Cursor<'a>: Buf + where + Self: 'a; + + fn cursor(&self, index: usize) -> Self::Cursor<'_>; +} + +impl Cursor for &[u8] { + type Cursor<'a> + = &'a [u8] + where + Self: 'a; + + fn cursor(&self, index: usize) -> Self::Cursor<'_> { + &self[index..] + } +} + +impl Cursor for VecDeque { + type Cursor<'a> + = Chain<&'a [u8], &'a [u8]> + where + Self: 'a; + + fn cursor(&self, index: usize) -> Self::Cursor<'_> { + let (s1, s2) = self.as_slices(); + let mut chain = s1.chain(s2); + chain.advance(index); + chain + } +} diff --git a/src/buf/cursor_mut.rs b/src/buf/cursor_mut.rs new file mode 100644 index 000000000..152dd1111 --- /dev/null +++ b/src/buf/cursor_mut.rs @@ -0,0 +1,26 @@ +use crate::BufMut; + +/// # Safety +/// +/// It must be safe to call Self::CursorMut::advance_mut. This should be true +/// if the type Self::CursorMut does not allow to access bytes writen to it. +/// For exemple, Vec is not ok, as the content written to it is accesible. +/// On the other hand &mut [u8] is ok, as the content written cant't be accessed. +pub unsafe trait CursorMut: BufMut { + type CursorMut<'a>: BufMut + where + Self: 'a; + + fn cursor_mut(&mut self, index: usize) -> Self::CursorMut<'_>; +} + +unsafe impl CursorMut for &mut [u8] { + type CursorMut<'a> + = &'a mut [u8] + where + Self: 'a; + + fn cursor_mut(&mut self, index: usize) -> Self::CursorMut<'_> { + &mut self[index..] + } +} diff --git a/src/buf/limit.rs b/src/buf/limit.rs index b422be538..f4785f635 100644 --- a/src/buf/limit.rs +++ b/src/buf/limit.rs @@ -1,5 +1,6 @@ use crate::buf::UninitSlice; use crate::BufMut; +use crate::CursorMut; use core::cmp; @@ -73,3 +74,14 @@ unsafe impl BufMut for Limit { self.limit -= cnt; } } + +unsafe impl CursorMut for Limit { + type CursorMut<'a> + = Limit> + where + Self: 'a; + + fn cursor_mut(&mut self, index: usize) -> Self::CursorMut<'_> { + self.inner.cursor_mut(index).limit(self.limit - index) + } +} diff --git a/src/buf/mod.rs b/src/buf/mod.rs index 1bf0a47e8..23b74815f 100644 --- a/src/buf/mod.rs +++ b/src/buf/mod.rs @@ -17,6 +17,8 @@ mod buf_impl; mod buf_mut; mod chain; +mod cursor; +mod cursor_mut; mod iter; mod limit; #[cfg(feature = "std")] @@ -30,6 +32,8 @@ mod writer; pub use self::buf_impl::Buf; pub use self::buf_mut::BufMut; pub use self::chain::Chain; +pub use self::cursor::Cursor; +pub use self::cursor_mut::CursorMut; pub use self::iter::IntoIter; pub use self::limit::Limit; pub use self::take::Take; diff --git a/src/buf/take.rs b/src/buf/take.rs index d8621f3f3..90a96297d 100644 --- a/src/buf/take.rs +++ b/src/buf/take.rs @@ -1,4 +1,4 @@ -use crate::Buf; +use crate::{Buf, Cursor}; use core::cmp; @@ -185,3 +185,14 @@ impl Buf for Take { cnt } } + +impl Cursor for Take { + type Cursor<'a> + = Take> + where + Self: 'a; + + fn cursor(&self, index: usize) -> Self::Cursor<'_> { + self.inner.cursor(index).take(self.limit - index) + } +} diff --git a/src/lib.rs b/src/lib.rs index 1916b6043..47af429c2 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -77,7 +77,7 @@ extern crate alloc; extern crate std; pub mod buf; -pub use crate::buf::{Buf, BufMut}; +pub use crate::buf::{Buf, BufMut, Cursor, CursorMut}; mod bytes; mod bytes_mut;