ciborium-io-0.2.0/.cargo_vcs_info.json0000644000000001120000000000100132430ustar { "git": { "sha1": "e8512abee2f126ae60923be4362c175703550894" } } ciborium-io-0.2.0/Cargo.toml0000644000000022350000000000100112510ustar # THIS FILE IS AUTOMATICALLY GENERATED BY CARGO # # When uploading crates to the registry Cargo will automatically # "normalize" Cargo.toml files for maximal compatibility # with all versions of Cargo and also rewrite `path` dependencies # to registry (e.g., crates.io) dependencies. # # If you are reading this file be aware that the original Cargo.toml # will likely look very different (and much more reasonable). # See Cargo.toml.orig for the original contents. [package] edition = "2021" name = "ciborium-io" version = "0.2.0" authors = ["Nathaniel McCallum "] description = "Simplified Read/Write traits for no_std usage" homepage = "https://github.com/enarx/ciborium" readme = "README.md" keywords = ["io", "read", "write"] categories = ["data-structures", "embedded", "no-std"] license = "Apache-2.0" repository = "https://github.com/enarx/ciborium" [features] alloc = [] std = ["alloc"] [badges.github] repository = "enarx/ciborium" workflow = "test" [badges.is-it-maintained-issue-resolution] repository = "enarx/ciborium" [badges.is-it-maintained-open-issues] repository = "enarx/ciborium" [badges.maintenance] status = "actively-developed" ciborium-io-0.2.0/Cargo.toml.orig000064400000000000000000000015260072674642500147640ustar 00000000000000[package] name = "ciborium-io" version = "0.2.0" authors = ["Nathaniel McCallum "] license = "Apache-2.0" edition = "2021" homepage = "https://github.com/enarx/ciborium" repository = "https://github.com/enarx/ciborium" description = "Simplified Read/Write traits for no_std usage" readme = "README.md" keywords = ["io", "read", "write"] categories = ["data-structures", "embedded", "no-std"] [badges] # See https://doc.rust-lang.org/cargo/reference/manifest.html#the-badges-section github = { repository = "enarx/ciborium", workflow = "test" } #github = { repository = "enarx/ciborium", workflow = "lint" } maintenance = { status = "actively-developed" } is-it-maintained-issue-resolution = { repository = "enarx/ciborium" } is-it-maintained-open-issues = { repository = "enarx/ciborium" } [features] alloc = [] std = ["alloc"] ciborium-io-0.2.0/README.md000064400000000000000000000023750072674642500133570ustar 00000000000000[![Workflow Status](https://github.com/enarx/ciborium/workflows/test/badge.svg)](https://github.com/enarx/ciborium/actions?query=workflow%3A%22test%22) [![Average time to resolve an issue](https://isitmaintained.com/badge/resolution/enarx/ciborium.svg)](https://isitmaintained.com/project/enarx/ciborium "Average time to resolve an issue") [![Percentage of issues still open](https://isitmaintained.com/badge/open/enarx/ciborium.svg)](https://isitmaintained.com/project/enarx/ciborium "Percentage of issues still open") ![Maintenance](https://img.shields.io/badge/maintenance-activly--developed-brightgreen.svg) # ciborium-io Simple, Low-level I/O traits This crate provides two simple traits: `Read` and `Write`. These traits mimic their counterparts in `std::io`, but are trimmed for simplicity and can be used in `no_std` and `no_alloc` environments. Since this crate contains only traits, inline functions and unit structs, it should be a zero-cost abstraction. If the `std` feature is enabled, we provide blanket implementations for all `std::io` types. If the `alloc` feature is enabled, we provide implementations for `Vec`. In all cases, you get implementations for byte slices. You can, of course, implement the traits for your own types. License: Apache-2.0 ciborium-io-0.2.0/src/lib.rs000064400000000000000000000147660072674642500140120ustar 00000000000000// SPDX-License-Identifier: Apache-2.0 //! Simple, Low-level I/O traits //! //! This crate provides two simple traits: `Read` and `Write`. These traits //! mimic their counterparts in `std::io`, but are trimmed for simplicity //! and can be used in `no_std` and `no_alloc` environments. Since this //! crate contains only traits, inline functions and unit structs, it should //! be a zero-cost abstraction. //! //! If the `std` feature is enabled, we provide blanket implementations for //! all `std::io` types. If the `alloc` feature is enabled, we provide //! implementations for `Vec`. In all cases, you get implementations //! for byte slices. You can, of course, implement the traits for your own //! types. #![cfg_attr(not(feature = "std"), no_std)] #![deny(missing_docs)] #![deny(clippy::all)] #![deny(clippy::cargo)] #[cfg(feature = "alloc")] extern crate alloc; /// A trait indicating a type that can read bytes /// /// Note that this is similar to `std::io::Read`, but simplified for use in a /// `no_std` context. pub trait Read { /// The error type type Error; /// Reads exactly `data.len()` bytes or fails fn read_exact(&mut self, data: &mut [u8]) -> Result<(), Self::Error>; } /// A trait indicating a type that can write bytes /// /// Note that this is similar to `std::io::Write`, but simplified for use in a /// `no_std` context. pub trait Write { /// The error type type Error; /// Writes all bytes from `data` or fails fn write_all(&mut self, data: &[u8]) -> Result<(), Self::Error>; /// Flushes all output fn flush(&mut self) -> Result<(), Self::Error>; } #[cfg(feature = "std")] impl Read for T { type Error = std::io::Error; #[inline] fn read_exact(&mut self, data: &mut [u8]) -> Result<(), Self::Error> { self.read_exact(data) } } #[cfg(feature = "std")] impl Write for T { type Error = std::io::Error; #[inline] fn write_all(&mut self, data: &[u8]) -> Result<(), Self::Error> { self.write_all(data) } #[inline] fn flush(&mut self) -> Result<(), Self::Error> { self.flush() } } #[cfg(not(feature = "std"))] impl Read for &mut R { type Error = R::Error; #[inline] fn read_exact(&mut self, data: &mut [u8]) -> Result<(), Self::Error> { (**self).read_exact(data) } } #[cfg(not(feature = "std"))] impl Write for &mut W { type Error = W::Error; #[inline] fn write_all(&mut self, data: &[u8]) -> Result<(), Self::Error> { (**self).write_all(data) } #[inline] fn flush(&mut self) -> Result<(), Self::Error> { (**self).flush() } } /// An error indicating there are no more bytes to read #[cfg(not(feature = "std"))] #[derive(Debug)] pub struct EndOfFile(()); #[cfg(not(feature = "std"))] impl Read for &[u8] { type Error = EndOfFile; #[inline] fn read_exact(&mut self, data: &mut [u8]) -> Result<(), Self::Error> { if data.len() > self.len() { return Err(EndOfFile(())); } let (prefix, suffix) = self.split_at(data.len()); data.copy_from_slice(prefix); *self = suffix; Ok(()) } } /// An error indicating that the output cannot accept more bytes #[cfg(not(feature = "std"))] #[derive(Debug)] pub struct OutOfSpace(()); #[cfg(not(feature = "std"))] impl Write for &mut [u8] { type Error = OutOfSpace; #[inline] fn write_all(&mut self, data: &[u8]) -> Result<(), Self::Error> { if data.len() > self.len() { return Err(OutOfSpace(())); } let (prefix, suffix) = core::mem::replace(self, &mut []).split_at_mut(data.len()); prefix.copy_from_slice(data); *self = suffix; Ok(()) } #[inline] fn flush(&mut self) -> Result<(), Self::Error> { Ok(()) } } #[cfg(all(not(feature = "std"), feature = "alloc"))] impl Write for alloc::vec::Vec { type Error = core::convert::Infallible; #[inline] fn write_all(&mut self, data: &[u8]) -> Result<(), Self::Error> { self.extend_from_slice(data); Ok(()) } #[inline] fn flush(&mut self) -> Result<(), Self::Error> { Ok(()) } } #[cfg(test)] mod test { use super::*; #[test] fn read_eof() { let mut reader = &[1u8; 0][..]; let mut buffer = [0u8; 1]; reader.read_exact(&mut buffer[..]).unwrap_err(); } #[test] fn read_one() { let mut reader = &[1u8; 1][..]; let mut buffer = [0u8; 1]; reader.read_exact(&mut buffer[..]).unwrap(); assert_eq!(buffer[0], 1); reader.read_exact(&mut buffer[..]).unwrap_err(); } #[test] fn read_two() { let mut reader = &[1u8; 2][..]; let mut buffer = [0u8; 1]; reader.read_exact(&mut buffer[..]).unwrap(); assert_eq!(buffer[0], 1); reader.read_exact(&mut buffer[..]).unwrap(); assert_eq!(buffer[0], 1); reader.read_exact(&mut buffer[..]).unwrap_err(); } #[test] #[cfg(feature = "std")] fn read_std() { let mut reader = std::io::repeat(1); let mut buffer = [0u8; 2]; reader.read_exact(&mut buffer[..]).unwrap(); assert_eq!(buffer[0], 1); assert_eq!(buffer[1], 1); } #[test] fn write_oos() { let mut writer = &mut [0u8; 0][..]; writer.write_all(&[1u8; 1][..]).unwrap_err(); } #[test] fn write_one() { let mut buffer = [0u8; 1]; let mut writer = &mut buffer[..]; writer.write_all(&[1u8; 1][..]).unwrap(); writer.write_all(&[1u8; 1][..]).unwrap_err(); assert_eq!(buffer[0], 1); } #[test] fn write_two() { let mut buffer = [0u8; 2]; let mut writer = &mut buffer[..]; writer.write_all(&[1u8; 1][..]).unwrap(); writer.write_all(&[1u8; 1][..]).unwrap(); writer.write_all(&[1u8; 1][..]).unwrap_err(); assert_eq!(buffer[0], 1); assert_eq!(buffer[1], 1); } #[test] #[cfg(feature = "alloc")] fn write_vec() { let mut buffer = alloc::vec::Vec::new(); buffer.write_all(&[1u8; 1][..]).unwrap(); buffer.write_all(&[1u8; 1][..]).unwrap(); assert_eq!(buffer.len(), 2); assert_eq!(buffer[0], 1); assert_eq!(buffer[1], 1); } #[test] #[cfg(feature = "std")] fn write_std() { let mut writer = std::io::sink(); writer.write_all(&[1u8; 1][..]).unwrap(); writer.write_all(&[1u8; 1][..]).unwrap(); } }