diff --git a/inout/CHANGELOG.md b/inout/CHANGELOG.md index 180e2c1a..81ad63f9 100644 --- a/inout/CHANGELOG.md +++ b/inout/CHANGELOG.md @@ -11,10 +11,12 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 ### Added - `InOut::into_out` and `InOutBufReserved::into_out` methods ([#1132]) +- `InOutBufReserved::split_reserved` method ([#1133]) [#944]: https://github.com/RustCrypto/utils/pull/944 [#1116]: https://github.com/RustCrypto/utils/pull/1116 [#1132]: https://github.com/RustCrypto/utils/pull/1132 +[#1132]: https://github.com/RustCrypto/utils/pull/1132 ## 0.1.3 (2022-03-31) ### Fixed diff --git a/inout/src/reserved.rs b/inout/src/reserved.rs index 587756b3..05ecf586 100644 --- a/inout/src/reserved.rs +++ b/inout/src/reserved.rs @@ -1,14 +1,12 @@ -use crate::errors::OutIsTooSmallError; +use crate::{errors::OutIsTooSmallError, InOutBuf}; use core::{marker::PhantomData, slice}; #[cfg(feature = "block-padding")] -use crate::errors::PadError; -#[cfg(feature = "block-padding")] -use crate::{InOut, InOutBuf}; -#[cfg(feature = "block-padding")] -use block_padding::{PadType, Padding}; -#[cfg(feature = "block-padding")] -use hybrid_array::{Array, ArraySize}; +use { + crate::{errors::PadError, InOut}, + block_padding::{PadType, Padding}, + hybrid_array::{Array, ArraySize}, +}; /// Custom slice type which references one immutable (input) slice and one /// mutable (output) slice. Input and output slices are either the same or @@ -38,7 +36,9 @@ impl<'a, T> InOutBufReserved<'a, 'a, T> { _pd: PhantomData, }) } +} +impl InOutBufReserved<'_, '_, T> { /// Create [`InOutBufReserved`] from raw input and output pointers. /// /// # Safety @@ -93,6 +93,23 @@ impl<'a, T> InOutBufReserved<'a, 'a, T> { pub fn get_out_len(&self) -> usize { self.in_len } + + /// Split buffer into `InOutBuf` with input length and mutable slice pointing to + /// the reamining reserved suffix. + pub fn split_reserved<'a>(&'a mut self) -> (InOutBuf<'a, 'a, T>, &'a mut [T]) { + let in_len = self.get_in_len(); + let out_len = self.get_out_len(); + let in_ptr = self.get_in().as_ptr(); + let out_ptr = self.get_out().as_mut_ptr(); + // This never underflows because the type ensures that `out_len` is + // bigger or equal to `in_len`. + let tail_len = out_len - in_len; + unsafe { + let body = InOutBuf::from_raw(in_ptr, out_ptr, in_len); + let tail = slice::from_raw_parts_mut(out_ptr.add(in_len), tail_len); + (body, tail) + } + } } impl<'inp, 'out, T> InOutBufReserved<'inp, 'out, T> {