Skip to content

Commit

Permalink
Add no_std support, by adding an std feature
Browse files Browse the repository at this point in the history
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.
  • Loading branch information
cbeck88 committed Aug 13, 2019
1 parent 234d814 commit 4dca055
Show file tree
Hide file tree
Showing 12 changed files with 61 additions and 22 deletions.
4 changes: 4 additions & 0 deletions Cargo.toml
Expand Up @@ -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 }
Expand Down
14 changes: 12 additions & 2 deletions 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) => ({
Expand Down Expand Up @@ -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;
Expand Down Expand Up @@ -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<Self> where Self: Sized {
super::reader::new(self)
}
Expand All @@ -923,6 +931,7 @@ impl<T: Buf + ?Sized> Buf for &mut T {
(**self).bytes()
}

#[cfg(feature = "std")]
fn bytes_vectored<'b>(&'b self, dst: &mut [IoSlice<'b>]) -> usize {
(**self).bytes_vectored(dst)
}
Expand All @@ -941,6 +950,7 @@ impl<T: Buf + ?Sized> Buf for Box<T> {
(**self).bytes()
}

#[cfg(feature = "std")]
fn bytes_vectored<'b>(&'b self, dst: &mut [IoSlice<'b>]) -> usize {
(**self).bytes_vectored(dst)
}
Expand Down
11 changes: 9 additions & 2 deletions 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.
///
Expand Down Expand Up @@ -917,6 +923,7 @@ pub trait BufMut {
///
/// assert_eq!(*buf, b"hello world"[..]);
/// ```
#[cfg(feature = "std")]
fn writer(self) -> Writer<Self> where Self: Sized {
super::writer::new(self)
}
Expand Down
4 changes: 4 additions & 0 deletions 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.
Expand Down Expand Up @@ -178,6 +180,7 @@ impl<T, U> Buf for Chain<T, U>
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..]);
Expand Down Expand Up @@ -219,6 +222,7 @@ impl<T, U> BufMut for Chain<T, U>
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..]);
Expand Down
8 changes: 7 additions & 1 deletion src/buf/mod.rs
Expand Up @@ -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;
Expand All @@ -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;
2 changes: 1 addition & 1 deletion 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.
///
Expand Down
2 changes: 1 addition & 1 deletion src/buf/vec_deque.rs
@@ -1,4 +1,4 @@
use std::collections::VecDeque;
use alloc::collections::VecDeque;

use super::Buf;

Expand Down
26 changes: 13 additions & 13 deletions src/bytes.rs
Expand Up @@ -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.
///
Expand Down Expand Up @@ -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
Expand Down Expand Up @@ -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<usize>) -> Bytes {
use std::ops::Bound;
use core::ops::Bound;

let len = self.len();

Expand Down Expand Up @@ -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()
}
}
Expand Down Expand Up @@ -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()
Expand Down Expand Up @@ -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()
}
}
Expand Down Expand Up @@ -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()
Expand Down
2 changes: 1 addition & 1 deletion src/debug.rs
@@ -1,4 +1,4 @@
use std::fmt;
use core::fmt;

/// Alternative implementation of `fmt::Debug` for byte slice.
///
Expand Down
4 changes: 4 additions & 0 deletions src/either.rs
Expand Up @@ -2,6 +2,8 @@ use crate::{Buf, BufMut};

use either::Either;
use either::Either::*;

#[cfg(feature = "std")]
use std::io::{IoSlice, IoSliceMut};

impl<L, R> Buf for Either<L, R>
Expand All @@ -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),
Expand Down Expand Up @@ -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),
Expand Down
4 changes: 4 additions & 0 deletions src/lib.rs
Expand Up @@ -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,
Expand Down
2 changes: 1 addition & 1 deletion 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};

Expand Down

0 comments on commit 4dca055

Please sign in to comment.