-
Notifications
You must be signed in to change notification settings - Fork 63
Embed minimal required no_std_io2 traits
#411
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
Merged
Changes from all commits
Commits
Show all changes
2 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
There are no files selected for viewing
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
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
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
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,68 @@ | ||
| use core::{fmt, result}; | ||
|
|
||
| pub(super) type Result<T> = result::Result<T, Error>; | ||
|
|
||
| /// A minimal backfill of the [`std::io::Error`] for `no_std` environments. | ||
| #[derive(Debug)] | ||
| pub struct Error { | ||
| kind: ErrorKind, | ||
| error: &'static str, | ||
| } | ||
|
|
||
| impl core::error::Error for Error {} | ||
|
|
||
| /// A list specifying general categories of I/O error. | ||
| /// | ||
| /// This list is intended to grow over time and it is not recommended to | ||
| /// exhaustively match against it. | ||
| /// | ||
| /// It is used with the [`io::Error`] type. | ||
| /// | ||
| /// [`io::Error`]: Error | ||
| #[derive(Clone, Copy, Debug, Eq, Hash, Ord, PartialEq, PartialOrd)] | ||
| pub(super) enum ErrorKind { | ||
| /// An error returned when an operation could not be completed because a | ||
| /// call to [`write`] returned [`Ok(0)`]. | ||
| /// | ||
| /// This typically means that an operation could only succeed if it wrote a | ||
| /// particular number of bytes but only a smaller number of bytes could be | ||
| /// written. | ||
| /// | ||
| /// [`write`]: crate::io::Write::write | ||
| /// [`Ok(0)`]: Ok | ||
| WriteZero, | ||
| /// This operation was interrupted. | ||
| /// | ||
| /// Interrupted operations can typically be retried. | ||
| Interrupted, | ||
| /// An error returned when an operation could not be completed because an | ||
| /// "end of file" was reached prematurely. | ||
| /// | ||
| /// This typically means that an operation could only succeed if it read a | ||
| /// particular number of bytes but only a smaller number of bytes could be | ||
| /// read. | ||
| UnexpectedEof, | ||
| } | ||
|
|
||
| impl Error { | ||
| /// Creates a new I/O error from a known kind of error as well as an | ||
| /// arbitrary error payload. | ||
| /// | ||
| /// This function is used to generically create I/O errors which do not | ||
| /// originate from the OS itself. The `error` argument is an arbitrary | ||
| /// payload which will be contained in this [`Error`]. | ||
| pub(super) fn new(kind: ErrorKind, error: &'static str) -> Error { | ||
| Error { kind, error } | ||
| } | ||
|
|
||
| /// Returns the corresponding [`ErrorKind`] for this error. | ||
| pub(super) fn kind(&self) -> ErrorKind { | ||
| self.kind | ||
| } | ||
| } | ||
|
|
||
| impl fmt::Display for Error { | ||
| fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result { | ||
| self.error.fmt(fmt) | ||
| } | ||
| } |
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,113 @@ | ||
| use super::error::{Error, ErrorKind, Result}; | ||
| use super::traits::{Read, Write}; | ||
|
|
||
| impl<R: Read + ?Sized> Read for &mut R { | ||
| #[inline] | ||
| fn read(&mut self, buf: &mut [u8]) -> Result<usize> { | ||
| (**self).read(buf) | ||
| } | ||
|
|
||
| #[inline] | ||
| fn read_exact(&mut self, buf: &mut [u8]) -> Result<()> { | ||
| (**self).read_exact(buf) | ||
| } | ||
| } | ||
|
|
||
| impl<W: Write + ?Sized> Write for &mut W { | ||
| #[inline] | ||
| fn write(&mut self, buf: &[u8]) -> Result<usize> { | ||
| (**self).write(buf) | ||
| } | ||
| } | ||
|
|
||
| /// Read is implemented for `&[u8]` by copying from the slice. | ||
| /// | ||
| /// Note that reading updates the slice to point to the yet unread part. | ||
| /// The slice will be empty when EOF is reached. | ||
| impl Read for &[u8] { | ||
| #[inline] | ||
| fn read(&mut self, buf: &mut [u8]) -> Result<usize> { | ||
| let amt = core::cmp::min(buf.len(), self.len()); | ||
| let (a, b) = self.split_at(amt); | ||
|
|
||
| // First check if the amount of bytes we want to read is small: | ||
| // `copy_from_slice` will generally expand to a call to `memcpy`, and | ||
| // for a single byte the overhead is significant. | ||
| if amt == 1 { | ||
| buf[0] = a[0]; | ||
| } else { | ||
| buf[..amt].copy_from_slice(a); | ||
| } | ||
|
|
||
| *self = b; | ||
| Ok(amt) | ||
| } | ||
|
|
||
| #[inline] | ||
| fn read_exact(&mut self, buf: &mut [u8]) -> Result<()> { | ||
| if buf.len() > self.len() { | ||
| return Err(Error::new( | ||
| ErrorKind::UnexpectedEof, | ||
| "failed to fill whole buffer", | ||
| )); | ||
| } | ||
| let (a, b) = self.split_at(buf.len()); | ||
|
|
||
| // First check if the amount of bytes we want to read is small: | ||
| // `copy_from_slice` will generally expand to a call to `memcpy`, and | ||
| // for a single byte the overhead is significant. | ||
| if buf.len() == 1 { | ||
| buf[0] = a[0]; | ||
| } else { | ||
| buf.copy_from_slice(a); | ||
| } | ||
|
|
||
| *self = b; | ||
| Ok(()) | ||
| } | ||
| } | ||
|
|
||
| /// Write is implemented for `&mut [u8]` by copying into the slice, overwriting | ||
| /// its data. | ||
| /// | ||
| /// Note that writing updates the slice to point to the yet unwritten part. | ||
| /// The slice will be empty when it has been completely overwritten. | ||
| impl Write for &mut [u8] { | ||
| #[inline] | ||
| fn write(&mut self, data: &[u8]) -> Result<usize> { | ||
| let amt = core::cmp::min(data.len(), self.len()); | ||
| let (a, b) = core::mem::take(self).split_at_mut(amt); | ||
| a.copy_from_slice(&data[..amt]); | ||
| *self = b; | ||
| Ok(amt) | ||
| } | ||
|
|
||
| #[inline] | ||
| fn write_all(&mut self, data: &[u8]) -> Result<()> { | ||
| if self.write(data)? == data.len() { | ||
| Ok(()) | ||
| } else { | ||
| Err(Error::new( | ||
| ErrorKind::WriteZero, | ||
| "failed to write whole buffer", | ||
| )) | ||
| } | ||
| } | ||
| } | ||
|
|
||
| /// Write is implemented for `Vec<u8>` by appending to the vector. | ||
| /// The vector will grow as needed. | ||
| #[cfg(feature = "alloc")] | ||
| impl Write for alloc::vec::Vec<u8> { | ||
| #[inline] | ||
| fn write(&mut self, buf: &[u8]) -> Result<usize> { | ||
| self.extend_from_slice(buf); | ||
| Ok(buf.len()) | ||
| } | ||
|
|
||
| #[inline] | ||
| fn write_all(&mut self, buf: &[u8]) -> Result<()> { | ||
| self.extend_from_slice(buf); | ||
| Ok(()) | ||
| } | ||
| } |
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,11 @@ | ||
| //! No-std I/O utilities for the multihash crate. | ||
| //! | ||
| //! This module provides a minimal compatibility layer for I/O operations in `no_std` environments. | ||
| //! Source code is ported and adapted from the [`core2`](https://docs.rs/crate/core2/0.4.0/source/) crate. | ||
|
|
||
| mod error; | ||
| mod impls; | ||
| mod traits; | ||
|
|
||
| pub use error::Error; | ||
| pub use traits::{Read, Write}; |
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,54 @@ | ||
| use super::error::{Error, ErrorKind, Result}; | ||
|
|
||
| /// A minimal backfill of the [`std::io::Read`] for `no_std` environments. | ||
| pub trait Read { | ||
| /// Backfill of the [`std::io::Read::read`]. | ||
| fn read(&mut self, buf: &mut [u8]) -> Result<usize>; | ||
|
|
||
| /// Backfill of the [`std::io::Read::read_exact`]. | ||
| fn read_exact(&mut self, mut buf: &mut [u8]) -> Result<()> { | ||
| while !buf.is_empty() { | ||
| match self.read(buf) { | ||
| Ok(0) => break, | ||
| Ok(n) => { | ||
| let tmp = buf; | ||
| buf = &mut tmp[n..]; | ||
| } | ||
| Err(ref e) if e.kind() == ErrorKind::Interrupted => {} | ||
| Err(e) => return Err(e), | ||
| } | ||
| } | ||
| if !buf.is_empty() { | ||
| Err(Error::new( | ||
| ErrorKind::UnexpectedEof, | ||
| "failed to fill whole buffer", | ||
| )) | ||
| } else { | ||
| Ok(()) | ||
| } | ||
| } | ||
| } | ||
|
|
||
| /// A minimal backfill of the [`std::io::Write`] for `no_std` environments. | ||
| pub trait Write { | ||
| /// Backfill of the [`std::io::Write::write`]. | ||
| fn write(&mut self, buf: &[u8]) -> Result<usize>; | ||
|
|
||
| /// Backfill of the [`std::io::Write::write_all`]. | ||
| fn write_all(&mut self, mut buf: &[u8]) -> Result<()> { | ||
| while !buf.is_empty() { | ||
| match self.write(buf) { | ||
| Ok(0) => { | ||
| return Err(Error::new( | ||
| ErrorKind::WriteZero, | ||
| "failed to write whole buffer", | ||
| )); | ||
| } | ||
| Ok(n) => buf = &buf[n..], | ||
| Err(ref e) if e.kind() == ErrorKind::Interrupted => {} | ||
| Err(e) => return Err(e), | ||
| } | ||
| } | ||
| Ok(()) | ||
| } | ||
| } |
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.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Wouldn't it make sense to just add something like this at the top:
Uh oh!
There was an error while loading. Please reload this page.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Fixed.
(Did not implement the custom
Writetrait to not allow downstream crates to depend on it. But that might not be an issue.)(Top-level use may not work when the macro is used in another file, using the full trait name instead)
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
That's actually a good point. My thought was "just keep the current behaviour" without questioning it. I don't have much experience with no-std environments. I guess you would probably implement your own
Write-like trait that fits your purpose. You wouldn't want to take a random, stripped down implementation from multihash.@hanabi1224 it sounds like you've more experience with no-std. So sorry for the back and forth, but I think it makes sense to implement
Writeonly for std. If if it turns out to be a problem for downstream users, they'll tell us.There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@vmx reverted.