From aaa108345f2160d2b185b60d6864bbb8a593212d Mon Sep 17 00:00:00 2001 From: Chris Beck Date: Tue, 13 Aug 2019 13:00:56 -0700 Subject: [PATCH 1/5] 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_impl.rs | 12 +++++++++++- src/buf/buf_mut.rs | 9 ++++++++- 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, 59 insertions(+), 20 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_impl.rs b/src/buf/buf_impl.rs index e126bb460..e590b7802 100644 --- a/src/buf/buf_impl.rs +++ b/src/buf/buf_impl.rs @@ -1,6 +1,12 @@ use super::{Take, Reader, 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; @@ -884,6 +891,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) } @@ -915,6 +923,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) } @@ -933,6 +942,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 7cd6be803..2bec1e324 100644 --- a/src/buf/buf_mut.rs +++ b/src/buf/buf_mut.rs @@ -1,6 +1,12 @@ use super::{Writer}; -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. /// @@ -913,6 +919,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 7d03d3699..a66e3e8dc 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..]); @@ -227,6 +230,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 cd7373efb..15e032de0 100644 --- a/src/buf/mod.rs +++ b/src/buf/mod.rs @@ -20,15 +20,21 @@ mod buf_impl; mod buf_mut; mod chain; 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_impl::Buf; pub use self::buf_mut::BufMut; pub use self::chain::Chain; 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 d4b1881d3..03f314108 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 4464426b6..0b48b0ab8 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 6282cf4fb..152585347 100644 --- a/src/bytes.rs +++ b/src/bytes.rs @@ -2,12 +2,12 @@ use crate::{Buf, BufMut}; 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 @@ -527,7 +527,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(); @@ -857,7 +857,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() } } @@ -1031,7 +1031,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() @@ -1539,7 +1539,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() } } @@ -1780,7 +1780,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 114de41a5..024ddfe94 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}; From 2f3a5b0982bb0a29abe61942585d4bda6c5cb0a4 Mon Sep 17 00:00:00 2001 From: Douman Date: Sat, 31 Aug 2019 08:00:27 +0200 Subject: [PATCH 2/5] Adjust alloc usage and add cargo check to CI --- ci/azure-test-stable.yml | 4 ++++ src/buf/buf_impl.rs | 5 ++++- src/buf/buf_mut.rs | 12 ++++++++---- src/buf/vec_deque.rs | 3 +++ src/bytes.rs | 6 +++++- src/hex.rs | 2 +- src/lib.rs | 1 + 7 files changed, 26 insertions(+), 7 deletions(-) diff --git a/ci/azure-test-stable.yml b/ci/azure-test-stable.yml index dd1561639..b402696a3 100644 --- a/ci/azure-test-stable.yml +++ b/ci/azure-test-stable.yml @@ -40,3 +40,7 @@ jobs: - ${{ if parameters.benches }}: - script: cargo check --benches displayName: Check benchmarks + + # Run with no default defaults + - script: cargo ${{ parameters.cmd }} + displayName: cargo ${{ parameters.cmd }} --no-default-features diff --git a/src/buf/buf_impl.rs b/src/buf/buf_impl.rs index e590b7802..a65aaa59f 100644 --- a/src/buf/buf_impl.rs +++ b/src/buf/buf_impl.rs @@ -1,4 +1,4 @@ -use super::{Take, Reader, Chain}; +use super::{Take, Chain}; #[cfg(feature = "std")] use super::Reader; @@ -8,6 +8,9 @@ use core::{cmp, ptr, mem}; #[cfg(feature = "std")] use std::io::IoSlice; +#[cfg(not(feature = "std"))] +use alloc::{boxed::Box}; + macro_rules! buf_get_impl { ($this:ident, $typ:tt::$conv:tt) => ({ const SIZE: usize = mem::size_of::<$typ>(); diff --git a/src/buf/buf_mut.rs b/src/buf/buf_mut.rs index 2bec1e324..ef4e01bff 100644 --- a/src/buf/buf_mut.rs +++ b/src/buf/buf_mut.rs @@ -1,5 +1,3 @@ -use super::{Writer}; - #[cfg(feature = "std")] use super::Writer; @@ -8,6 +6,9 @@ use core::{mem, cmp, ptr, usize}; #[cfg(feature = "std")] use std::io::IoSliceMut; +#[cfg(not(feature = "std"))] +use alloc::{vec::Vec, boxed::Box}; + /// A trait for values that provide sequential write access to bytes. /// /// Write bytes to a buffer @@ -191,6 +192,7 @@ pub trait BufMut { /// with `dst` being a zero length slice. /// /// [`readv`]: http://man7.org/linux/man-pages/man2/readv.2.html + #[cfg(feature = "std")] unsafe fn bytes_vectored_mut<'a>(&'a mut self, dst: &mut [IoSliceMut<'a>]) -> usize { if dst.is_empty() { return 0; @@ -934,6 +936,7 @@ impl BufMut for &mut T { (**self).bytes_mut() } + #[cfg(feature = "std")] unsafe fn bytes_vectored_mut<'b>(&'b mut self, dst: &mut [IoSliceMut<'b>]) -> usize { (**self).bytes_vectored_mut(dst) } @@ -952,6 +955,7 @@ impl BufMut for Box { (**self).bytes_mut() } + #[cfg(feature = "std")] unsafe fn bytes_vectored_mut<'b>(&'b mut self, dst: &mut [IoSliceMut<'b>]) -> usize { (**self).bytes_vectored_mut(dst) } @@ -975,7 +979,7 @@ impl BufMut for &mut [u8] { #[inline] unsafe fn advance_mut(&mut self, cnt: usize) { // Lifetime dance taken from `impl Write for &mut [u8]`. - let (_, b) = std::mem::replace(self, &mut []).split_at_mut(cnt); + let (_, b) = core::mem::replace(self, &mut []).split_at_mut(cnt); *self = b; } } @@ -1001,7 +1005,7 @@ impl BufMut for Vec { #[inline] unsafe fn bytes_mut(&mut self) -> &mut [u8] { - use std::slice; + use core::slice; if self.capacity() == self.len() { self.reserve(64); // Grow the vec diff --git a/src/buf/vec_deque.rs b/src/buf/vec_deque.rs index 0b48b0ab8..26328a909 100644 --- a/src/buf/vec_deque.rs +++ b/src/buf/vec_deque.rs @@ -1,4 +1,7 @@ +#[cfg(not(feature = "std"))] use alloc::collections::VecDeque; +#[cfg(feature = "std")] +use std::collections::VecDeque; use super::Buf; diff --git a/src/bytes.rs b/src/bytes.rs index 152585347..a19631170 100644 --- a/src/bytes.rs +++ b/src/bytes.rs @@ -3,12 +3,16 @@ use crate::buf::IntoIter; use crate::debug; 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}; +#[cfg(not(feature = "std"))] +use alloc::{vec::Vec, string::String, boxed::Box, borrow::{Borrow, BorrowMut}}; +#[cfg(feature = "std")] +use std::borrow::{Borrow, BorrowMut}; + /// A reference counted contiguous slice of memory. /// /// `Bytes` is an efficient container for storing and operating on contiguous diff --git a/src/hex.rs b/src/hex.rs index d3fdafbb5..48ae6a42c 100644 --- a/src/hex.rs +++ b/src/hex.rs @@ -1,5 +1,5 @@ use crate::{Bytes, BytesMut}; -use std::fmt::{Formatter, LowerHex, Result, UpperHex}; +use core::fmt::{Formatter, LowerHex, Result, UpperHex}; struct BytesRef<'a>(&'a [u8]); diff --git a/src/lib.rs b/src/lib.rs index 024ddfe94..242abc62e 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -73,6 +73,7 @@ #![cfg_attr(not(feature = "std"), no_std)] +#[cfg(not(feature = "std"))] extern crate alloc; pub mod buf; From ab9423b8bab1b4f054de1effbc73df4c20b543bf Mon Sep 17 00:00:00 2001 From: Chris Beck Date: Tue, 3 Sep 2019 11:30:08 -0700 Subject: [PATCH 3/5] change no_std condition per @tarcieri request --- src/lib.rs | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/src/lib.rs b/src/lib.rs index 242abc62e..0ed25c988 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -71,7 +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)] +#![no_std] + +#[cfg(feature = "std")] +extern crate std; #[cfg(not(feature = "std"))] extern crate alloc; From f14e87da44438c938d2b3612b2a83e0335d5a21f Mon Sep 17 00:00:00 2001 From: Chris Beck Date: Tue, 3 Sep 2019 11:37:50 -0700 Subject: [PATCH 4/5] fixup previous --- src/buf/buf_impl.rs | 3 +++ src/buf/buf_mut.rs | 2 ++ src/bytes.rs | 2 +- 3 files changed, 6 insertions(+), 1 deletion(-) diff --git a/src/buf/buf_impl.rs b/src/buf/buf_impl.rs index a65aaa59f..58489c258 100644 --- a/src/buf/buf_impl.rs +++ b/src/buf/buf_impl.rs @@ -8,6 +8,9 @@ use core::{cmp, ptr, mem}; #[cfg(feature = "std")] use std::io::IoSlice; +#[cfg(feature = "std")] +use std::{boxed::Box}; + #[cfg(not(feature = "std"))] use alloc::{boxed::Box}; diff --git a/src/buf/buf_mut.rs b/src/buf/buf_mut.rs index ef4e01bff..22c86bb29 100644 --- a/src/buf/buf_mut.rs +++ b/src/buf/buf_mut.rs @@ -8,6 +8,8 @@ use std::io::IoSliceMut; #[cfg(not(feature = "std"))] use alloc::{vec::Vec, boxed::Box}; +#[cfg(feature = "std")] +use std::{vec::Vec, boxed::Box}; /// A trait for values that provide sequential write access to bytes. /// diff --git a/src/bytes.rs b/src/bytes.rs index a19631170..0d93079a0 100644 --- a/src/bytes.rs +++ b/src/bytes.rs @@ -11,7 +11,7 @@ use core::iter::{FromIterator, Iterator}; #[cfg(not(feature = "std"))] use alloc::{vec::Vec, string::String, boxed::Box, borrow::{Borrow, BorrowMut}}; #[cfg(feature = "std")] -use std::borrow::{Borrow, BorrowMut}; +use std::{vec::Vec, string::String, boxed::Box, borrow::{Borrow, BorrowMut}}; /// A reference counted contiguous slice of memory. /// From 3fd7fa82cb6a5eaae4e90a28531584246195f741 Mon Sep 17 00:00:00 2001 From: Chris Beck Date: Wed, 4 Sep 2019 12:19:52 -0700 Subject: [PATCH 5/5] fixups to std vs. alloc imports per PR discussion --- src/buf/buf_impl.rs | 4 ---- src/buf/buf_mut.rs | 3 --- src/buf/vec_deque.rs | 3 --- src/bytes.rs | 3 --- src/lib.rs | 5 ++--- 5 files changed, 2 insertions(+), 16 deletions(-) diff --git a/src/buf/buf_impl.rs b/src/buf/buf_impl.rs index 58489c258..b9e9141f7 100644 --- a/src/buf/buf_impl.rs +++ b/src/buf/buf_impl.rs @@ -8,10 +8,6 @@ use core::{cmp, ptr, mem}; #[cfg(feature = "std")] use std::io::IoSlice; -#[cfg(feature = "std")] -use std::{boxed::Box}; - -#[cfg(not(feature = "std"))] use alloc::{boxed::Box}; macro_rules! buf_get_impl { diff --git a/src/buf/buf_mut.rs b/src/buf/buf_mut.rs index 22c86bb29..1571580ed 100644 --- a/src/buf/buf_mut.rs +++ b/src/buf/buf_mut.rs @@ -6,10 +6,7 @@ use core::{mem, cmp, ptr, usize}; #[cfg(feature = "std")] use std::io::IoSliceMut; -#[cfg(not(feature = "std"))] use alloc::{vec::Vec, boxed::Box}; -#[cfg(feature = "std")] -use std::{vec::Vec, boxed::Box}; /// A trait for values that provide sequential write access to bytes. /// diff --git a/src/buf/vec_deque.rs b/src/buf/vec_deque.rs index 26328a909..0b48b0ab8 100644 --- a/src/buf/vec_deque.rs +++ b/src/buf/vec_deque.rs @@ -1,7 +1,4 @@ -#[cfg(not(feature = "std"))] use alloc::collections::VecDeque; -#[cfg(feature = "std")] -use std::collections::VecDeque; use super::Buf; diff --git a/src/bytes.rs b/src/bytes.rs index 0d93079a0..edbd03072 100644 --- a/src/bytes.rs +++ b/src/bytes.rs @@ -8,10 +8,7 @@ use core::sync::atomic::{self, AtomicUsize, AtomicPtr}; use core::sync::atomic::Ordering::{Relaxed, Acquire, Release, AcqRel}; use core::iter::{FromIterator, Iterator}; -#[cfg(not(feature = "std"))] use alloc::{vec::Vec, string::String, boxed::Box, borrow::{Borrow, BorrowMut}}; -#[cfg(feature = "std")] -use std::{vec::Vec, string::String, boxed::Box, borrow::{Borrow, BorrowMut}}; /// A reference counted contiguous slice of memory. /// diff --git a/src/lib.rs b/src/lib.rs index 0ed25c988..af4dfeecb 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -73,12 +73,11 @@ #![no_std] +extern crate alloc; + #[cfg(feature = "std")] extern crate std; -#[cfg(not(feature = "std"))] -extern crate alloc; - pub mod buf; pub use crate::buf::{ Buf,