-
Notifications
You must be signed in to change notification settings - Fork 6
Updated Folder Structure of the 'slice-codec' Crate to be More Modular #794
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Merged
InsertCreativityHere
merged 3 commits into
icerpc:main
from
InsertCreativityHere:reorg-slice-codec-folders
Jul 30, 2026
Merged
Changes from all commits
Commits
Show all changes
3 commits
Select commit
Hold shift + click to select a range
File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Some comments aren't visible on the classic Files Changed page.
There are no files selected for viewing
This file was deleted.
Oops, something went wrong.
4 changes: 2 additions & 2 deletions
4
slice-codec/src/decode_from.rs → slice-codec/src/decoding/decode_from.rs
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
4 changes: 2 additions & 2 deletions
4
slice-codec/src/decoder.rs → slice-codec/src/decoding/decoder.rs
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
6 changes: 3 additions & 3 deletions
6
slice-codec/src/decoding.rs → slice-codec/src/decoding/implementations.rs
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,7 @@ | ||
| // Copyright (c) ZeroC, Inc. | ||
|
|
||
| pub mod decode_from; | ||
| pub mod decoder; | ||
|
|
||
| // This module is private because it doesn't export any types, just implementations. | ||
| mod implementations; |
4 changes: 2 additions & 2 deletions
4
slice-codec/src/encode_into.rs → slice-codec/src/encoding/encode_into.rs
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
4 changes: 2 additions & 2 deletions
4
slice-codec/src/encoder.rs → slice-codec/src/encoding/encoder.rs
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
6 changes: 3 additions & 3 deletions
6
slice-codec/src/encoding.rs → slice-codec/src/encoding/implementations.rs
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,7 @@ | ||
| // Copyright (c) ZeroC, Inc. | ||
|
|
||
| pub mod encode_into; | ||
| pub mod encoder; | ||
|
|
||
| // This module is private because it doesn't export any types, just implementations. | ||
| mod implementations; |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,39 @@ | ||
| // Copyright (c) ZeroC, Inc. | ||
|
|
||
| //! TODO maybe write a comment explaining this module? | ||
|
|
||
| mod slice_input_source; | ||
| pub use slice_input_source::*; | ||
|
|
||
| use crate::Result; | ||
|
|
||
| /// A trait for types that can be read from by a [Slice decoder](crate::decoder::Decoder). | ||
| pub trait InputSource { | ||
| /// Returns the number of unread bytes currently remaining in the source. | ||
| fn remaining(&self) -> usize; | ||
|
|
||
| /// Returns the next byte available from this source without consuming it. | ||
| /// | ||
| /// If there are no more bytes available from this source, an [`UnexpectedEob`] error is returned instead. | ||
| /// | ||
| /// [`UnexpectedEob`]: crate::ErrorKind::UnexpectedEob | ||
| fn peek_byte(&mut self) -> Result<u8>; | ||
|
|
||
| /// Returns the next byte available from this source, and advances past it (consuming it). | ||
| /// | ||
| /// If there are no more bytes available from this source, an [`UnexpectedEob`] error is returned instead. | ||
| /// | ||
| /// [`UnexpectedEob`]: crate::ErrorKind::UnexpectedEob | ||
| fn read_byte(&mut self) -> Result<u8>; | ||
|
|
||
| // TODO remove these functions after adding `advance_by` and the low-level required API functions. | ||
| fn read_bytes_exact<const N: usize>(&mut self) -> Result<&[u8; N]>; | ||
| fn read_byte_slice_exact(&mut self, count: usize) -> Result<&[u8]>; | ||
|
|
||
| /// Reads bytes from this source into the provided buffer, and advances past them (consuming them). | ||
| /// | ||
| /// This function reads exactly `dest.len()`-many bytes, or if it's unable to, returns an error instead. | ||
| /// If such an error occurs, no guarantees are made about how many bytes were read from the source, except that it | ||
| /// is less than `dest.len()`. | ||
| fn read_bytes_into_exact(&mut self, dest: &mut [u8]) -> Result<()>; | ||
| } |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,204 @@ | ||
| // Copyright (c) ZeroC, Inc. | ||
|
|
||
| //! TODO maybe write a comment explaining this module? | ||
|
|
||
| use super::*; | ||
| use crate::{ErrorKind, Result}; | ||
| use core::borrow::Borrow; | ||
| use core::{debug_assert, debug_assert_eq}; | ||
|
|
||
| /// A wrapper around a `&[u8]` that implements [`InputSource`]. | ||
| #[derive(Debug)] | ||
| pub struct SliceInputSource<'a> { | ||
| /// The underlying buffer that this type wraps. | ||
| buffer: &'a [u8], | ||
| /// Tracks the current position in the buffer that is being read from. | ||
| pos: usize, | ||
| } | ||
|
|
||
| impl<'a> SliceInputSource<'a> { | ||
| /// Checks whether there are at least `requested` unread bytes left in the buffer. | ||
| /// If there are, this returns `Ok`, and if there aren't this returns an [`ErrorKind::UnexpectedEob`] error. | ||
| /// | ||
| /// This function is only used internally to ensure a particular read operation is safe to attempt. | ||
| fn does_buffer_have_at_least(&self, requested: usize) -> Result<()> { | ||
| let remaining = self.remaining(); | ||
| if remaining < requested { | ||
| let error = ErrorKind::UnexpectedEob { requested, remaining }; | ||
| Err(error.into()) | ||
| } else { | ||
| Ok(()) | ||
| } | ||
| } | ||
| } | ||
|
|
||
| impl InputSource for SliceInputSource<'_> { | ||
| fn remaining(&self) -> usize { | ||
| self.buffer.len() - self.pos | ||
| } | ||
|
|
||
| fn peek_byte(&mut self) -> Result<u8> { | ||
| self.does_buffer_have_at_least(1)?; | ||
|
|
||
| // SAFETY: the necessary bounds checking is performed by the above function call. | ||
| unsafe { | ||
| debug_assert!(self.buffer.get(self.pos).is_some()); | ||
| Ok(*self.buffer.get_unchecked(self.pos)) | ||
| } | ||
| } | ||
|
|
||
| fn read_byte(&mut self) -> Result<u8> { | ||
| let byte = self.peek_byte()?; | ||
| self.pos += 1; | ||
| Ok(byte) | ||
| } | ||
|
|
||
| fn read_bytes_exact<const N: usize>(&mut self) -> Result<&[u8; N]> { | ||
| let byte_slice = self.read_byte_slice_exact(N)?; | ||
|
|
||
| // SAFETY: `read_byte_slice_exact` is guaranteed to return exactly 'N' bytes, which means it's safe to | ||
| // convert, since `&[u8; N]` has the same layout as an `&[u8]` over 'N' bytes. | ||
| let byte_array = unsafe { | ||
| debug_assert_eq!(byte_slice.len(), N); | ||
| byte_slice.try_into().unwrap_unchecked() | ||
| }; | ||
|
|
||
| Ok(byte_array) | ||
| } | ||
|
|
||
| fn read_byte_slice_exact(&mut self, count: usize) -> Result<&[u8]> { | ||
| self.does_buffer_have_at_least(count)?; | ||
|
|
||
| // SAFETY: the necessary bounds checking is performed by the above function call. | ||
| let byte_slice = unsafe { | ||
| let end = self.pos + count; | ||
| debug_assert!(self.buffer.get(self.pos..end).is_some()); | ||
| self.buffer.get_unchecked(self.pos..end) | ||
| }; | ||
| self.pos += count; | ||
| Ok(byte_slice) | ||
| } | ||
|
|
||
| fn read_bytes_into_exact(&mut self, dst: &mut [u8]) -> Result<()> { | ||
| let src = self.read_byte_slice_exact(dst.len())?; | ||
|
|
||
| // SAFETY: `read_byte_slice_exact` is guaranteed to return exactly `dst.len()` bytes, so there is enough space | ||
| // in `dst` to write these bytes, and we know the slices cannot overlap because `dst` is mutably borrowed, | ||
| // which guarantees exclusive access. | ||
| unsafe { | ||
| debug_assert_eq!(src.len(), dst.len()); | ||
| core::ptr::copy_nonoverlapping(src.as_ptr(), dst.as_mut_ptr(), dst.len()); | ||
| Ok(()) | ||
| } | ||
| } | ||
| } | ||
|
|
||
| impl<'a, T> From<&'a T> for SliceInputSource<'a> | ||
| where | ||
| T: Borrow<[u8]> + ?Sized, | ||
| { | ||
| /// Creates a new [`SliceInputSource`] that wraps the provided buffer. | ||
| fn from(value: &'a T) -> Self { | ||
| Self { | ||
| buffer: value.borrow(), | ||
| pos: 0, | ||
| } | ||
| } | ||
| } | ||
|
|
||
| // Allows users to create a [`Decoder`] directly from a slice, | ||
| // without needing to construct an intermediate [`SliceInputSource`]. | ||
| impl<'a, T> From<T> for crate::decoding::decoder::Decoder<SliceInputSource<'a>> | ||
| where | ||
| T: Into<SliceInputSource<'a>>, | ||
| { | ||
| fn from(value: T) -> Self { | ||
| crate::decoding::decoder::Decoder::new(value.into()) | ||
| } | ||
| } | ||
|
|
||
| #[cfg(test)] | ||
| mod tests { | ||
| use super::*; | ||
|
|
||
| /// Verifies that [`does_buffer_have_at_least`] returns the correct number of remaining bytes in the buffer | ||
| /// when the remaining bytes number are greater than or equal to the number of requested bytes. | ||
| #[test] | ||
| fn does_buffer_has_at_least_returns_ok() { | ||
| // Arrange | ||
| let buffer = [115, 108, 105, 99, 101]; | ||
| let source = SliceInputSource::from(&buffer); | ||
|
|
||
| // Act | ||
| let result = source.does_buffer_have_at_least(5); | ||
|
|
||
| // Assert | ||
| assert!(result.is_ok()); | ||
| } | ||
|
|
||
| /// Verifies that [`does_buffer_have_at_least`] returns an error when the remaining bytes number are less than | ||
| /// the number of requested bytes. | ||
| #[test] | ||
| fn does_buffer_have_at_least_returns_error() { | ||
| // Arrange | ||
| let source = SliceInputSource::from(&[115, 108, 105, 99, 101]); | ||
|
|
||
| // Act | ||
| let result = source.does_buffer_have_at_least(6); | ||
|
|
||
| // Assert | ||
| assert!(result.is_err()); | ||
| assert!(matches!(result.unwrap_err().kind(), ErrorKind::UnexpectedEob { | ||
| requested: 6, | ||
| remaining: 5 | ||
| })); | ||
| } | ||
|
|
||
| /// Verifies that [`peek_byte`] returns the correct byte from the buffer without consuming it. | ||
| #[test] | ||
| fn peek_byte_returns_correct_byte() { | ||
| // Arrange | ||
| let mut source = SliceInputSource::from(&[115, 108, 105, 99, 101]); | ||
|
|
||
| // Act | ||
| let result = source.peek_byte(); | ||
|
|
||
| // Assert | ||
| assert!(result.is_ok()); | ||
| assert_eq!(result.unwrap(), 115); | ||
| assert_eq!(source.pos, 0); | ||
| assert_eq!(source.remaining(), 5); | ||
| } | ||
|
|
||
| /// Verifies that [`read_byte`] returns the correct byte from the buffer and consumes it. | ||
| #[test] | ||
| fn read_byte_returns_correct_byte() { | ||
| // Arrange | ||
| let mut source = SliceInputSource::from(&[115, 108, 105, 99, 101]); | ||
|
|
||
| // Act | ||
| let result = source.read_byte(); | ||
|
|
||
| // Assert | ||
| assert!(result.is_ok()); | ||
| assert_eq!(result.unwrap(), 115); | ||
| assert_eq!(source.pos, 1); | ||
| assert_eq!(source.remaining(), 4); | ||
| } | ||
|
|
||
| /// Verifies that [`read_bytes_exact`] returns the correct number of bytes from the buffer and consumes them. | ||
| #[test] | ||
| fn read_bytes_exact_returns_correct_bytes() { | ||
| // Arrange | ||
| let mut source = SliceInputSource::from(&[115, 108, 105, 99, 101]); | ||
|
|
||
| // Act | ||
| let result = source.read_bytes_exact::<3>(); | ||
|
|
||
| // Assert | ||
| assert!(result.is_ok()); | ||
| assert_eq!(result.unwrap(), &[115, 108, 105]); | ||
| assert_eq!(source.pos, 3); | ||
| assert_eq!(source.remaining(), 2); | ||
| } | ||
| } |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
Uh oh!
There was an error while loading. Please reload this page.