From 4dca0550fb1fcfaa41458935eb4b796721119b8c Mon Sep 17 00:00:00 2001 From: Chris Beck Date: Tue, 13 Aug 2019 13:00:56 -0700 Subject: [PATCH] Add no_std support, by adding an `std` feature I was really hopeful initially that this could be done without having an `std` feature, but it turns out that `bytes` has a bunch of special additional integration with `std::io` stuff, e.g. `std::io::Reader` and `std::io::IoSlice`. To make the library work as `no_std` we add an `std` feature which is on by default. When it is off, we compile as `no_std` and make parts of the API that require `std::io` conditional on the `std` feature. --- Cargo.toml | 4 ++++ src/buf/buf.rs | 14 ++++++++++++-- src/buf/buf_mut.rs | 11 +++++++++-- src/buf/chain.rs | 4 ++++ src/buf/mod.rs | 8 +++++++- src/buf/take.rs | 2 +- src/buf/vec_deque.rs | 2 +- src/bytes.rs | 26 +++++++++++++------------- src/debug.rs | 2 +- src/either.rs | 4 ++++ src/lib.rs | 4 ++++ src/serde.rs | 2 +- 12 files changed, 61 insertions(+), 22 deletions(-) diff --git a/Cargo.toml b/Cargo.toml index 9ec601da0..746a193fb 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -19,6 +19,10 @@ edition = "2018" publish = false +[features] +default = ["std"] +std = [] + [dependencies] serde = { version = "1.0", optional = true } either = { version = "1.5", default-features = false, optional = true } diff --git a/src/buf/buf.rs b/src/buf/buf.rs index 97b85fc39..fe00bda82 100644 --- a/src/buf/buf.rs +++ b/src/buf/buf.rs @@ -1,6 +1,12 @@ -use super::{IntoBuf, Take, Reader, FromBuf, Chain}; +use super::{IntoBuf, Take, FromBuf, Chain}; -use std::{cmp, io::IoSlice, ptr, mem}; +#[cfg(feature = "std")] +use super::Reader; + +use core::{cmp, ptr, mem}; + +#[cfg(feature = "std")] +use std::io::IoSlice; macro_rules! buf_get_impl { ($this:ident, $typ:tt::$conv:tt) => ({ @@ -148,6 +154,7 @@ pub trait Buf { /// with `dst` being a zero length slice. /// /// [`writev`]: http://man7.org/linux/man-pages/man2/readv.2.html + #[cfg(feature = "std")] fn bytes_vectored<'a>(&'a self, dst: &mut [IoSlice<'a>]) -> usize { if dst.is_empty() { return 0; @@ -909,6 +916,7 @@ pub trait Buf { /// assert_eq!(11, num); /// assert_eq!(&dst[..11], &b"hello world"[..]); /// ``` + #[cfg(feature = "std")] fn reader(self) -> Reader where Self: Sized { super::reader::new(self) } @@ -923,6 +931,7 @@ impl Buf for &mut T { (**self).bytes() } + #[cfg(feature = "std")] fn bytes_vectored<'b>(&'b self, dst: &mut [IoSlice<'b>]) -> usize { (**self).bytes_vectored(dst) } @@ -941,6 +950,7 @@ impl Buf for Box { (**self).bytes() } + #[cfg(feature = "std")] fn bytes_vectored<'b>(&'b self, dst: &mut [IoSlice<'b>]) -> usize { (**self).bytes_vectored(dst) } diff --git a/src/buf/buf_mut.rs b/src/buf/buf_mut.rs index 05ae794a8..2e2bceb10 100644 --- a/src/buf/buf_mut.rs +++ b/src/buf/buf_mut.rs @@ -1,6 +1,12 @@ -use super::{IntoBuf, Writer}; +use super::{IntoBuf}; -use std::{mem, cmp, io::IoSliceMut, ptr, usize}; +#[cfg(feature = "std")] +use super::Writer; + +use core::{mem, cmp, ptr, usize}; + +#[cfg(feature = "std")] +use std::io::IoSliceMut; /// A trait for values that provide sequential write access to bytes. /// @@ -917,6 +923,7 @@ pub trait BufMut { /// /// assert_eq!(*buf, b"hello world"[..]); /// ``` + #[cfg(feature = "std")] fn writer(self) -> Writer where Self: Sized { super::writer::new(self) } diff --git a/src/buf/chain.rs b/src/buf/chain.rs index 936a086b7..642ed55a4 100644 --- a/src/buf/chain.rs +++ b/src/buf/chain.rs @@ -1,5 +1,7 @@ use crate::{Buf, BufMut}; use crate::buf::IntoIter; + +#[cfg(feature = "std")] use std::io::{IoSlice, IoSliceMut}; /// A `Chain` sequences two buffers. @@ -178,6 +180,7 @@ impl Buf for Chain self.b.advance(cnt); } + #[cfg(feature = "std")] fn bytes_vectored<'a>(&'a self, dst: &mut [IoSlice<'a>]) -> usize { let mut n = self.a.bytes_vectored(dst); n += self.b.bytes_vectored(&mut dst[n..]); @@ -219,6 +222,7 @@ impl BufMut for Chain self.b.advance_mut(cnt); } + #[cfg(feature = "std")] unsafe fn bytes_vectored_mut<'a>(&'a mut self, dst: &mut [IoSliceMut<'a>]) -> usize { let mut n = self.a.bytes_vectored_mut(dst); n += self.b.bytes_vectored_mut(&mut dst[n..]); diff --git a/src/buf/mod.rs b/src/buf/mod.rs index a127549a6..0b9454782 100644 --- a/src/buf/mod.rs +++ b/src/buf/mod.rs @@ -22,9 +22,13 @@ mod from_buf; mod chain; mod into_buf; mod iter; -mod reader; mod take; mod vec_deque; + +// When std::io::Reader etc. traits are not available, skip these +#[cfg(feature = "std")] +mod reader; +#[cfg(feature = "std")] mod writer; pub use self::buf::Buf; @@ -33,6 +37,8 @@ pub use self::from_buf::FromBuf; pub use self::chain::Chain; pub use self::into_buf::IntoBuf; pub use self::iter::IntoIter; +#[cfg(feature = "std")] pub use self::reader::Reader; pub use self::take::Take; +#[cfg(feature = "std")] pub use self::writer::Writer; diff --git a/src/buf/take.rs b/src/buf/take.rs index 559640b10..e92d5ba0e 100644 --- a/src/buf/take.rs +++ b/src/buf/take.rs @@ -1,6 +1,6 @@ use crate::Buf; -use std::cmp; +use core::cmp; /// A `Buf` adapter which limits the bytes read from an underlying buffer. /// diff --git a/src/buf/vec_deque.rs b/src/buf/vec_deque.rs index 1cd650f51..69257e2d3 100644 --- a/src/buf/vec_deque.rs +++ b/src/buf/vec_deque.rs @@ -1,4 +1,4 @@ -use std::collections::VecDeque; +use alloc::collections::VecDeque; use super::Buf; diff --git a/src/bytes.rs b/src/bytes.rs index 9db6362f2..5a3afa021 100644 --- a/src/bytes.rs +++ b/src/bytes.rs @@ -2,12 +2,12 @@ use crate::{Buf, BufMut, IntoBuf}; use crate::buf::IntoIter; use crate::debug; -use std::{cmp, fmt, mem, hash, slice, ptr, usize}; -use std::borrow::{Borrow, BorrowMut}; -use std::ops::{Deref, DerefMut, RangeBounds}; -use std::sync::atomic::{self, AtomicUsize, AtomicPtr}; -use std::sync::atomic::Ordering::{Relaxed, Acquire, Release, AcqRel}; -use std::iter::{FromIterator, Iterator}; +use core::{cmp, fmt, mem, hash, slice, ptr, usize}; +use alloc::borrow::{Borrow, BorrowMut}; +use core::ops::{Deref, DerefMut, RangeBounds}; +use core::sync::atomic::{self, AtomicUsize, AtomicPtr}; +use core::sync::atomic::Ordering::{Relaxed, Acquire, Release, AcqRel}; +use core::iter::{FromIterator, Iterator}; /// A reference counted contiguous slice of memory. /// @@ -316,10 +316,10 @@ struct Inner { } // Thread-safe reference-counted container for the shared storage. This mostly -// the same as `std::sync::Arc` but without the weak counter. The ref counting +// the same as `core::sync::Arc` but without the weak counter. The ref counting // fns are based on the ones found in `std`. // -// The main reason to use `Shared` instead of `std::sync::Arc` is that it ends +// The main reason to use `Shared` instead of `core::sync::Arc` is that it ends // up making the overall code simpler and easier to reason about. This is due to // some of the logic around setting `Inner::arc` and other ways the `arc` field // is used. Using `Arc` ended up requiring a number of funky transmutes and @@ -522,7 +522,7 @@ impl Bytes { /// Requires that `begin <= end` and `end <= self.len()`, otherwise slicing /// will panic. pub fn slice(&self, range: impl RangeBounds) -> Bytes { - use std::ops::Bound; + use core::ops::Bound; let len = self.len(); @@ -852,7 +852,7 @@ impl Bytes { /// assert_eq!(iter.next().map(|b| *b), Some(b'c')); /// assert_eq!(iter.next(), None); /// ``` - pub fn iter<'a>(&'a self) -> std::slice::Iter<'a, u8> { + pub fn iter<'a>(&'a self) -> core::slice::Iter<'a, u8> { self.bytes().iter() } } @@ -1026,7 +1026,7 @@ impl IntoIterator for Bytes { impl<'a> IntoIterator for &'a Bytes { type Item = &'a u8; - type IntoIter = std::slice::Iter<'a, u8>; + type IntoIter = core::slice::Iter<'a, u8>; fn into_iter(self) -> Self::IntoIter { self.as_ref().into_iter() @@ -1534,7 +1534,7 @@ impl BytesMut { /// assert_eq!(iter.next().map(|b| *b), Some(b'c')); /// assert_eq!(iter.next(), None); /// ``` - pub fn iter<'a>(&'a self) -> std::slice::Iter<'a, u8> { + pub fn iter<'a>(&'a self) -> core::slice::Iter<'a, u8> { self.bytes().iter() } } @@ -1783,7 +1783,7 @@ impl IntoIterator for BytesMut { impl<'a> IntoIterator for &'a BytesMut { type Item = &'a u8; - type IntoIter = std::slice::Iter<'a, u8>; + type IntoIter = core::slice::Iter<'a, u8>; fn into_iter(self) -> Self::IntoIter { self.as_ref().into_iter() diff --git a/src/debug.rs b/src/debug.rs index 32d88680c..b1a3cc818 100644 --- a/src/debug.rs +++ b/src/debug.rs @@ -1,4 +1,4 @@ -use std::fmt; +use core::fmt; /// Alternative implementation of `fmt::Debug` for byte slice. /// diff --git a/src/either.rs b/src/either.rs index 954dfff4b..76bee808f 100644 --- a/src/either.rs +++ b/src/either.rs @@ -2,6 +2,8 @@ use crate::{Buf, BufMut}; use either::Either; use either::Either::*; + +#[cfg(feature = "std")] use std::io::{IoSlice, IoSliceMut}; impl Buf for Either @@ -23,6 +25,7 @@ where } } + #[cfg(feature = "std")] fn bytes_vectored<'a>(&'a self, dst: &mut [IoSlice<'a>]) -> usize { match *self { Left(ref b) => b.bytes_vectored(dst), @@ -64,6 +67,7 @@ where } } + #[cfg(feature = "std")] unsafe fn bytes_vectored_mut<'a>(&'a mut self, dst: &mut [IoSliceMut<'a>]) -> usize { match *self { Left(ref mut b) => b.bytes_vectored_mut(dst), diff --git a/src/lib.rs b/src/lib.rs index 031a24cd0..bcc2d0506 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -71,6 +71,10 @@ #![deny(warnings, missing_docs, missing_debug_implementations, rust_2018_idioms)] #![doc(html_root_url = "https://docs.rs/bytes/0.5.0")] +#![cfg_attr(not(feature = "std"), no_std)] + +extern crate alloc; + pub mod buf; pub use crate::buf::{ Buf, diff --git a/src/serde.rs b/src/serde.rs index 7ade4d9d4..8f6b902ea 100644 --- a/src/serde.rs +++ b/src/serde.rs @@ -1,4 +1,4 @@ -use std::{cmp, fmt}; +use core::{cmp, fmt}; use serde::{Serialize, Serializer, Deserialize, Deserializer, de}; use super::{Bytes, BytesMut};