diff --git a/.travis.yml b/.travis.yml index e332ce1f3..96c582ec4 100644 --- a/.travis.yml +++ b/.travis.yml @@ -37,6 +37,10 @@ matrix: - env: EXTRA_ARGS="--no-default-features" script: cargo build $EXTRA_ARGS + # `alloc` crate-based implementation + - env: EXTRA_ARGS="--no-default-features --features=alloc --lib --tests" + rust: nightly # TODO: test 'alloc' on stable rust when it is fully stabilized + # Serde implementation - env: EXTRA_ARGS="--features serde" diff --git a/Cargo.toml b/Cargo.toml index 3dc10d857..0fdf22e4f 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -38,5 +38,6 @@ serde_test = "1.0" [features] default = ["std"] +alloc = [] i128 = ["byteorder/i128"] -std = ["iovec"] +std = ["alloc", "iovec"] diff --git a/src/buf/buf.rs b/src/buf/buf.rs index 06738d668..888f6f4a9 100644 --- a/src/buf/buf.rs +++ b/src/buf/buf.rs @@ -2,7 +2,7 @@ use super::{IntoBuf, Take, Reader, Iter, FromBuf, Chain}; use byteorder::{BigEndian, ByteOrder, LittleEndian}; #[cfg(feature = "iovec")] use iovec::IoVec; -#[cfg(feature = "std")] +#[cfg(feature = "alloc")] use prelude::*; use core::{cmp, ptr}; @@ -1077,7 +1077,7 @@ impl<'a, T: Buf + ?Sized> Buf for &'a mut T { } } -#[cfg(feature = "std")] +#[cfg(feature = "alloc")] impl Buf for Box { fn remaining(&self) -> usize { (**self).remaining() diff --git a/src/buf/buf_mut.rs b/src/buf/buf_mut.rs index 265b66668..bef36bd87 100644 --- a/src/buf/buf_mut.rs +++ b/src/buf/buf_mut.rs @@ -2,7 +2,7 @@ use super::{IntoBuf, Writer}; use byteorder::{LittleEndian, ByteOrder, BigEndian}; #[cfg(feature = "iovec")] use iovec::IoVec; -#[cfg(feature = "std")] +#[cfg(feature = "alloc")] use prelude::*; use core::{cmp, ptr, usize}; @@ -1088,7 +1088,7 @@ impl<'a, T: BufMut + ?Sized> BufMut for &'a mut T { } } -#[cfg(feature = "std")] +#[cfg(feature = "alloc")] impl BufMut for Box { fn remaining_mut(&self) -> usize { (**self).remaining_mut() @@ -1098,6 +1098,7 @@ impl BufMut for Box { (**self).bytes_mut() } + #[cfg(feature = "iovec")] unsafe fn bytes_vec_mut<'b>(&'b mut self, dst: &mut [&'b mut IoVec]) -> usize { (**self).bytes_vec_mut(dst) } @@ -1136,7 +1137,7 @@ impl + AsRef<[u8]>> BufMut for io::Cursor { } } -#[cfg(feature = "std")] +#[cfg(feature = "alloc")] impl BufMut for Vec { #[inline] fn remaining_mut(&self) -> usize { diff --git a/src/buf/from_buf.rs b/src/buf/from_buf.rs index 58e8d2374..7d4accca8 100644 --- a/src/buf/from_buf.rs +++ b/src/buf/from_buf.rs @@ -1,7 +1,7 @@ use {IntoBuf}; -#[cfg(feature = "std")] +#[cfg(feature = "alloc")] use prelude::*; -#[cfg(feature = "std")] +#[cfg(feature = "alloc")] use {Buf, BufMut, Bytes, BytesMut}; /// Conversion from a [`Buf`] @@ -90,7 +90,7 @@ pub trait FromBuf { fn from_buf(buf: T) -> Self where T: IntoBuf; } -#[cfg(feature = "std")] +#[cfg(feature = "alloc")] impl FromBuf for Vec { fn from_buf(buf: T) -> Self where T: IntoBuf @@ -102,7 +102,7 @@ impl FromBuf for Vec { } } -#[cfg(feature = "std")] +#[cfg(feature = "alloc")] impl FromBuf for Bytes { fn from_buf(buf: T) -> Self where T: IntoBuf @@ -111,7 +111,7 @@ impl FromBuf for Bytes { } } -#[cfg(feature = "std")] +#[cfg(feature = "alloc")] impl FromBuf for BytesMut { fn from_buf(buf: T) -> Self where T: IntoBuf diff --git a/src/buf/mod.rs b/src/buf/mod.rs index efa7d0b2d..f2792de2f 100644 --- a/src/buf/mod.rs +++ b/src/buf/mod.rs @@ -24,7 +24,7 @@ mod into_buf; mod iter; mod reader; mod take; -#[cfg(feature = "std")] +#[cfg(feature = "alloc")] mod vec_deque; mod writer; diff --git a/src/buf/vec_deque.rs b/src/buf/vec_deque.rs index ad8f31342..0669bf3c4 100644 --- a/src/buf/vec_deque.rs +++ b/src/buf/vec_deque.rs @@ -1,3 +1,6 @@ +#[cfg(all(feature = "alloc", not(feature = "std")))] +use alloc::collections::vec_deque::VecDeque; +#[cfg(feature = "std")] use std::collections::VecDeque; use super::Buf; diff --git a/src/bytes.rs b/src/bytes.rs index a3e4632c1..1c7357251 100644 --- a/src/bytes.rs +++ b/src/bytes.rs @@ -1,14 +1,19 @@ -use {IntoBuf, Buf, BufMut}; +use {BufMut}; +#[cfg(feature = "std")] +use {Buf, IntoBuf}; +#[cfg(feature = "std")] use buf::Iter; use debug; use prelude::*; -use std::{cmp, fmt, mem, hash, ops, slice, ptr, usize}; -use std::borrow::{Borrow, BorrowMut}; +use core::{cmp, fmt, mem, hash, ops, slice, ptr, usize}; +use core::borrow::{Borrow, BorrowMut}; +use core::sync::atomic::{self, AtomicUsize, AtomicPtr}; +use core::sync::atomic::Ordering::{Relaxed, Acquire, Release, AcqRel}; +use core::iter::{FromIterator, Iterator}; + +#[cfg(feature = "std")] use std::io::Cursor; -use std::sync::atomic::{self, AtomicUsize, AtomicPtr}; -use std::sync::atomic::Ordering::{Relaxed, Acquire, Release, AcqRel}; -use std::iter::{FromIterator, Iterator}; /// A reference counted contiguous slice of memory. /// @@ -835,6 +840,7 @@ impl Bytes { } } +#[cfg(feature = "std")] impl IntoBuf for Bytes { type Buf = Cursor; @@ -843,6 +849,7 @@ impl IntoBuf for Bytes { } } +#[cfg(feature = "std")] impl<'a> IntoBuf for &'a Bytes { type Buf = Cursor; @@ -986,6 +993,7 @@ impl Borrow<[u8]> for Bytes { } } +#[cfg(feature = "std")] impl IntoIterator for Bytes { type Item = u8; type IntoIter = Iter>; @@ -995,6 +1003,7 @@ impl IntoIterator for Bytes { } } +#[cfg(feature = "std")] impl<'a> IntoIterator for &'a Bytes { type Item = u8; type IntoIter = Iter>; @@ -1563,6 +1572,7 @@ impl BufMut for BytesMut { } } +#[cfg(feature = "std")] impl IntoBuf for BytesMut { type Buf = Cursor; @@ -1571,6 +1581,7 @@ impl IntoBuf for BytesMut { } } +#[cfg(feature = "std")] impl<'a> IntoBuf for &'a BytesMut { type Buf = Cursor<&'a BytesMut>; @@ -1736,6 +1747,7 @@ impl Clone for BytesMut { } } +#[cfg(feature = "std")] impl IntoIterator for BytesMut { type Item = u8; type IntoIter = Iter>; @@ -1745,6 +1757,7 @@ impl IntoIterator for BytesMut { } } +#[cfg(feature = "std")] impl<'a> IntoIterator for &'a BytesMut { type Item = u8; type IntoIter = Iter>; diff --git a/src/debug.rs b/src/debug.rs index f8b830a24..08ee4d9dc 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/lib.rs b/src/lib.rs index 164acfac4..34720863d 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -71,7 +71,10 @@ #![deny(warnings, missing_docs, missing_debug_implementations)] #![doc(html_root_url = "https://docs.rs/bytes/0.4.12")] #![no_std] +#![cfg_attr(feature = "alloc", feature(alloc))] +#[cfg(feature = "alloc")] +extern crate alloc; extern crate byteorder; #[cfg(feature = "iovec")] extern crate iovec; @@ -92,13 +95,12 @@ pub use buf::{ Take, }; -#[cfg(feature = "std")] +#[cfg(feature = "alloc")] mod bytes; -#[cfg(feature = "std")] mod debug; -#[cfg(feature = "std")] -pub use bytes::{Bytes, BytesMut}; mod prelude; +#[cfg(feature = "alloc")] +pub use bytes::{Bytes, BytesMut}; #[deprecated] pub use byteorder::{ByteOrder, BigEndian, LittleEndian}; diff --git a/src/prelude.rs b/src/prelude.rs index 1ea00b8fb..7635d3df3 100644 --- a/src/prelude.rs +++ b/src/prelude.rs @@ -1,5 +1,15 @@ //! Crate-local import prelude, primarily intended as a facade for accessing //! heap-allocated data structures. +#[cfg(all(feature = "alloc", not(feature = "std")))] +mod alloc_prelude { + pub use alloc::boxed::Box; + pub use alloc::string::String; + pub use alloc::vec::Vec; +} + +#[cfg(all(feature = "alloc", not(feature = "std")))] +pub use self::alloc_prelude::*; + #[cfg(feature = "std")] pub use std::prelude::v1::*; diff --git a/tests/test_buf.rs b/tests/test_buf.rs index f25c25f2b..16d3c1f19 100644 --- a/tests/test_buf.rs +++ b/tests/test_buf.rs @@ -1,12 +1,17 @@ extern crate bytes; extern crate byteorder; +#[cfg(feature = "iovec")] extern crate iovec; +#[cfg(feature = "std")] use bytes::Buf; +#[cfg(feature = "iovec")] use iovec::IoVec; +#[cfg(feature = "std")] use std::io::Cursor; #[test] +#[cfg(feature = "std")] fn test_fresh_cursor_vec() { let mut buf = Cursor::new(b"hello".to_vec()); @@ -25,12 +30,14 @@ fn test_fresh_cursor_vec() { } #[test] +#[cfg(feature = "std")] fn test_get_u8() { let mut buf = Cursor::new(b"\x21zomg"); assert_eq!(0x21, buf.get_u8()); } #[test] +#[cfg(feature = "std")] fn test_get_u16() { let buf = b"\x21\x54zomg"; assert_eq!(0x2154, Cursor::new(buf).get_u16_be()); @@ -39,12 +46,14 @@ fn test_get_u16() { #[test] #[should_panic] +#[cfg(feature = "std")] fn test_get_u16_buffer_underflow() { let mut buf = Cursor::new(b"\x21"); buf.get_u16_be(); } #[test] +#[cfg(all(feature = "iovec", feature = "std"))] fn test_bufs_vec() { let buf = Cursor::new(b"hello world"); diff --git a/tests/test_buf_mut.rs b/tests/test_buf_mut.rs index 2c8faa104..e985e546d 100644 --- a/tests/test_buf_mut.rs +++ b/tests/test_buf_mut.rs @@ -1,13 +1,20 @@ extern crate bytes; extern crate byteorder; +#[cfg(feature = "iovec")] extern crate iovec; -use bytes::{BufMut, BytesMut}; +use bytes::BufMut; +#[cfg(feature = "std")] +use bytes::BytesMut; +#[cfg(feature = "iovec")] use iovec::IoVec; +#[cfg(feature = "std")] use std::usize; +#[cfg(feature = "std")] use std::fmt::Write; #[test] +#[cfg(feature = "std")] fn test_vec_as_mut_buf() { let mut buf = Vec::with_capacity(64); @@ -61,6 +68,7 @@ fn test_vec_advance_mut() { } #[test] +#[cfg(feature = "std")] fn test_clone() { let mut buf = BytesMut::with_capacity(100); buf.write_str("this is a test").unwrap(); @@ -71,6 +79,7 @@ fn test_clone() { } #[test] +#[cfg(feature = "iovec")] fn test_bufs_vec_mut() { use std::mem; diff --git a/tests/test_bytes.rs b/tests/test_bytes.rs index e1883543f..935e8c9f7 100644 --- a/tests/test_bytes.rs +++ b/tests/test_bytes.rs @@ -1,6 +1,8 @@ extern crate bytes; -use bytes::{Bytes, BytesMut, BufMut, IntoBuf}; +use bytes::{Bytes, BytesMut, BufMut}; +#[cfg(feature = "std")] +use bytes::IntoBuf; const LONG: &'static [u8] = b"mary had a little lamb, little lamb, little lamb"; const SHORT: &'static [u8] = b"hello world"; @@ -166,6 +168,7 @@ fn split_off_uninitialized() { } #[test] +#[cfg(feature = "std")] fn split_off_to_loop() { let s = b"abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ"; @@ -299,6 +302,7 @@ fn fns_defined_for_bytes_mut() { } #[test] +#[cfg(feature = "std")] fn mut_into_buf() { let mut v = vec![0, 0, 0, 0]; let s = &mut v[..]; @@ -306,6 +310,7 @@ fn mut_into_buf() { } #[test] +#[cfg(feature = "std")] fn reserve_convert() { // Inline -> Vec let mut bytes = BytesMut::with_capacity(8); @@ -341,6 +346,7 @@ fn reserve_convert() { } #[test] +#[cfg(feature = "std")] fn reserve_growth() { let mut bytes = BytesMut::with_capacity(64); bytes.put("hello world"); @@ -385,6 +391,7 @@ fn reserve_max_original_capacity_value() { // within the program that this actually recycles memory. Instead, just exercise // the code path to ensure that the results are correct. #[test] +#[cfg(feature = "std")] fn reserve_vec_recycling() { let mut bytes = BytesMut::from(Vec::with_capacity(16)); assert_eq!(bytes.capacity(), 16); @@ -432,6 +439,7 @@ fn reserve_in_arc_nonunique_does_not_overallocate() { } #[test] +#[cfg(feature = "std")] fn inline_storage() { let mut bytes = BytesMut::with_capacity(inline_cap()); let zero = [0u8; 64]; @@ -524,7 +532,7 @@ fn advance_past_len() { #[test] // Only run these tests on little endian systems. CI uses qemu for testing // little endian... and qemu doesn't really support threading all that well. -#[cfg(target_endian = "little")] +#[cfg(all(target_endian = "little", feature = "std"))] fn stress() { // Tests promoting a buffer from a vec -> shared in a concurrent situation use std::sync::{Arc, Barrier}; diff --git a/tests/test_chain.rs b/tests/test_chain.rs index 2789e7c06..279940f28 100644 --- a/tests/test_chain.rs +++ b/tests/test_chain.rs @@ -1,12 +1,18 @@ extern crate bytes; +#[cfg(feature = "iovec")] extern crate iovec; -use bytes::{Buf, BufMut, Bytes, BytesMut}; +use bytes::{BufMut, BytesMut}; +#[cfg(feature = "std")] +use bytes::{Buf, Bytes}; use bytes::buf::Chain; +#[cfg(feature = "iovec")] use iovec::IoVec; +#[cfg(feature = "std")] use std::io::Cursor; #[test] +#[cfg(feature = "std")] fn collect_two_bufs() { let a = Cursor::new(Bytes::from(&b"hello"[..])); let b = Cursor::new(Bytes::from(&b"world"[..])); @@ -39,6 +45,7 @@ fn writing_chained() { } #[test] +#[cfg(feature = "std")] fn iterating_two_bufs() { let a = Cursor::new(Bytes::from(&b"hello"[..])); let b = Cursor::new(Bytes::from(&b"world"[..])); @@ -48,6 +55,7 @@ fn iterating_two_bufs() { } #[test] +#[cfg(feature = "std")] fn vectored_read() { let a = Cursor::new(Bytes::from(&b"hello"[..])); let b = Cursor::new(Bytes::from(&b"world"[..])); diff --git a/tests/test_from_buf.rs b/tests/test_from_buf.rs index 216bf1232..0b73456ea 100644 --- a/tests/test_from_buf.rs +++ b/tests/test_from_buf.rs @@ -1,12 +1,17 @@ extern crate bytes; +#[cfg(feature = "std")] use bytes::{Buf, Bytes, BytesMut}; +#[cfg(feature = "std")] use std::io::Cursor; +#[cfg(feature = "std")] const LONG: &'static [u8] = b"mary had a little lamb, little lamb, little lamb"; +#[cfg(feature = "std")] const SHORT: &'static [u8] = b"hello world"; #[test] +#[cfg(feature = "std")] fn collect_to_vec() { let buf: Vec = Cursor::new(SHORT).collect(); assert_eq!(buf, SHORT); @@ -16,6 +21,7 @@ fn collect_to_vec() { } #[test] +#[cfg(feature = "std")] fn collect_to_bytes() { let buf: Bytes = Cursor::new(SHORT).collect(); assert_eq!(buf, SHORT); @@ -25,6 +31,7 @@ fn collect_to_bytes() { } #[test] +#[cfg(feature = "std")] fn collect_to_bytes_mut() { let buf: BytesMut = Cursor::new(SHORT).collect(); assert_eq!(buf, SHORT); diff --git a/tests/test_iter.rs b/tests/test_iter.rs index c16dbf694..3243c2fd5 100644 --- a/tests/test_iter.rs +++ b/tests/test_iter.rs @@ -1,8 +1,10 @@ extern crate bytes; +#[cfg(feature = "std")] use bytes::{Buf, IntoBuf, Bytes}; #[test] +#[cfg(feature = "std")] fn iter_len() { let buf = Bytes::from(&b"hello world"[..]).into_buf(); let iter = buf.iter(); @@ -13,6 +15,7 @@ fn iter_len() { #[test] +#[cfg(feature = "std")] fn empty_iter_len() { let buf = Bytes::from(&b""[..]).into_buf(); let iter = buf.iter(); diff --git a/tests/test_reader.rs b/tests/test_reader.rs index 7103f3592..4247c629c 100644 --- a/tests/test_reader.rs +++ b/tests/test_reader.rs @@ -1,10 +1,12 @@ extern crate bytes; +#[cfg(feature = "std")] use std::io::{BufRead, Cursor, Read}; - +#[cfg(feature = "std")] use bytes::Buf; #[test] +#[cfg(feature = "std")] fn read() { let buf1 = Cursor::new(b"hello "); let buf2 = Cursor::new(b"world"); @@ -15,6 +17,7 @@ fn read() { } #[test] +#[cfg(feature = "std")] fn buf_read() { let buf1 = Cursor::new(b"hell"); let buf2 = Cursor::new(b"o\nworld"); diff --git a/tests/test_take.rs b/tests/test_take.rs index 93e0c6c5a..bbc197a9c 100644 --- a/tests/test_take.rs +++ b/tests/test_take.rs @@ -1,9 +1,12 @@ extern crate bytes; +#[cfg(feature = "std")] use bytes::Buf; +#[cfg(feature = "std")] use std::io::Cursor; #[test] +#[cfg(feature = "std")] fn long_take() { // Tests that take with a size greater than the buffer length will not // overrun the buffer. Regression test for #138.