Skip to content

Commit

Permalink
Support no_std w\ enabled-by-default "use_std" feature
Browse files Browse the repository at this point in the history
- Changes all references to libcore features from ::std to ::core
- Feature gates anything dependent on std::io on the "use_std" feature
- Obtains Box, String, and Vec from liballoc in no_std environments
- Vendors a tiny bit of std::io::cursor for use in no_std environments
  • Loading branch information
tonychain committed Jun 19, 2017
1 parent 3240fb9 commit 6871b20
Show file tree
Hide file tree
Showing 15 changed files with 153 additions and 27 deletions.
4 changes: 4 additions & 0 deletions .travis.yml
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,10 @@ matrix:
# Serde implementation
- env: EXTRA_ARGS="--features serde"

# Ensure crate compiles without default features (i.e. for no_std)
- script: cargo build --no-default-features
rust: nightly

before_install: set -e

install:
Expand Down
9 changes: 8 additions & 1 deletion Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -21,8 +21,15 @@ categories = ["network-programming", "data-structures"]

[dependencies]
byteorder = "1.0.0"
iovec = "0.1"
serde = { version = "1.0", optional = true }

[dependencies.iovec]
version = "0.1"
optional = true

[dev-dependencies]
serde_test = "1.0"

[features]
default = ["use_std"]
use_std = ["iovec"]
14 changes: 12 additions & 2 deletions src/buf/buf.rs
Original file line number Diff line number Diff line change
@@ -1,8 +1,15 @@
use super::{IntoBuf, Take, Reader, Iter, FromBuf, Chain};
use byteorder::ByteOrder;
#[cfg(feature = "use_std")]
use iovec::IoVec;

use std::{cmp, io, ptr};
#[cfg(not(feature = "use_std"))]
use alloc::boxed::Box;
use core::{cmp, ptr};
#[cfg(not(feature = "use_std"))]
use buf::Cursor;
#[cfg(feature = "use_std")]
use std::io::Cursor;

/// Read bytes from a buffer.
///
Expand Down Expand Up @@ -113,6 +120,7 @@ pub trait Buf {
/// with `dst` being a zero length slice.
///
/// [`writev`]: http://man7.org/linux/man-pages/man2/readv.2.html
#[cfg(feature = "use_std")]
fn bytes_vec<'a>(&'a self, dst: &mut [&'a IoVec]) -> usize {
if dst.is_empty() {
return 0;
Expand Down Expand Up @@ -662,6 +670,7 @@ impl<'a, T: Buf + ?Sized> Buf for &'a mut T {
(**self).bytes()
}

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

#[cfg(feature = "use_std")]
fn bytes_vec<'b>(&'b self, dst: &mut [&'b IoVec]) -> usize {
(**self).bytes_vec(dst)
}
Expand All @@ -689,7 +699,7 @@ impl<T: Buf + ?Sized> Buf for Box<T> {
}
}

impl<T: AsRef<[u8]>> Buf for io::Cursor<T> {
impl<T: AsRef<[u8]>> Buf for Cursor<T> {
fn remaining(&self) -> usize {
let len = self.get_ref().as_ref().len();
let pos = self.position();
Expand Down
18 changes: 15 additions & 3 deletions src/buf/buf_mut.rs
Original file line number Diff line number Diff line change
@@ -1,8 +1,17 @@
use super::{IntoBuf, Writer};
use byteorder::ByteOrder;
#[cfg(feature = "use_std")]
use iovec::IoVec;

use std::{cmp, io, ptr, usize};
#[cfg(not(feature = "use_std"))]
use alloc::boxed::Box;
#[cfg(not(feature = "use_std"))]
use alloc::vec::Vec;
use core::{cmp, ptr, usize};
#[cfg(not(feature = "use_std"))]
use buf::Cursor;
#[cfg(feature = "use_std")]
use std::io::Cursor;

/// A trait for values that provide sequential write access to bytes.
///
Expand Down Expand Up @@ -188,6 +197,7 @@ pub trait BufMut {
/// with `dst` being a zero length slice.
///
/// [`readv`]: http://man7.org/linux/man-pages/man2/readv.2.html
#[cfg(feature = "use_std")]
unsafe fn bytes_vec_mut<'a>(&'a mut self, dst: &mut [&'a mut IoVec]) -> usize {
if dst.is_empty() {
return 0;
Expand Down Expand Up @@ -645,6 +655,7 @@ impl<'a, T: BufMut + ?Sized> BufMut for &'a mut T {
(**self).bytes_mut()
}

#[cfg(feature = "use_std")]
unsafe fn bytes_vec_mut<'b>(&'b mut self, dst: &mut [&'b mut IoVec]) -> usize {
(**self).bytes_vec_mut(dst)
}
Expand All @@ -663,6 +674,7 @@ impl<T: BufMut + ?Sized> BufMut for Box<T> {
(**self).bytes_mut()
}

#[cfg(feature = "use_std")]
unsafe fn bytes_vec_mut<'b>(&'b mut self, dst: &mut [&'b mut IoVec]) -> usize {
(**self).bytes_vec_mut(dst)
}
Expand All @@ -672,7 +684,7 @@ impl<T: BufMut + ?Sized> BufMut for Box<T> {
}
}

impl<T: AsMut<[u8]> + AsRef<[u8]>> BufMut for io::Cursor<T> {
impl<T: AsMut<[u8]> + AsRef<[u8]>> BufMut for Cursor<T> {
fn remaining_mut(&self) -> usize {
use Buf;
self.remaining()
Expand Down Expand Up @@ -721,7 +733,7 @@ impl BufMut for Vec<u8> {

#[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
Expand Down
3 changes: 3 additions & 0 deletions src/buf/chain.rs
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
use {Buf, BufMut};
#[cfg(feature = "use_std")]
use iovec::IoVec;

/// A `Chain` sequences two buffers.
Expand Down Expand Up @@ -177,6 +178,7 @@ impl<T, U> Buf for Chain<T, U>
self.b.advance(cnt);
}

#[cfg(feature = "use_std")]
fn bytes_vec<'a>(&'a self, dst: &mut [&'a IoVec]) -> usize {
let mut n = self.a.bytes_vec(dst);
n += self.b.bytes_vec(&mut dst[n..]);
Expand Down Expand Up @@ -218,6 +220,7 @@ impl<T, U> BufMut for Chain<T, U>
self.b.advance_mut(cnt);
}

#[cfg(feature = "use_std")]
unsafe fn bytes_vec_mut<'a>(&'a mut self, dst: &mut [&'a mut IoVec]) -> usize {
let mut n = self.a.bytes_vec_mut(dst);
n += self.b.bytes_vec_mut(&mut dst[n..]);
Expand Down
54 changes: 54 additions & 0 deletions src/buf/cursor.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,54 @@
// Copyright 2015 The Rust Project Developers. See the COPYRIGHT
// file at the top-level directory of this distribution and at
// http://rust-lang.org/COPYRIGHT.
//
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
// option. This file may not be copied, modified, or distributed
// except according to those terms.

/// A `Cursor` wraps another type and provides it with a
/// [`Seek`] implementation.
///
/// `Cursor`s are typically used with in-memory buffers to allow them to
/// implement [`Read`] and/or [`Write`], allowing these buffers to be used
/// anywhere you might use a reader or writer that does actual I/O.
///
/// The standard library implements some I/O traits on various types which
/// are commonly used as a buffer, like `Cursor<`[`Vec`]`<u8>>` and
/// `Cursor<`[`&[u8]`][bytes]`>`.
#[derive(Clone, Debug)]
pub struct Cursor<T> {
inner: T,
pos: u64,
}

impl<T> Cursor<T> {
/// Creates a new cursor wrapping the provided underlying I/O object.
///
/// Cursor initial position is `0` even if underlying object (e.
/// g. `Vec`) is not empty. So writing to cursor starts with
/// overwriting `Vec` content, not with appending to it.
pub fn new(inner: T) -> Cursor<T> {
Cursor { pos: 0, inner: inner }
}

/// Consumes this cursor, returning the underlying value.
pub fn into_inner(self) -> T { self.inner }

/// Gets a reference to the underlying value in this cursor.
pub fn get_ref(&self) -> &T { &self.inner }

/// Gets a mutable reference to the underlying value in this cursor.
///
/// Care should be taken to avoid modifying the internal I/O state of the
/// underlying value as it may corrupt this cursor's position.
pub fn get_mut(&mut self) -> &mut T { &mut self.inner }

/// Returns the current position of this cursor.
pub fn position(&self) -> u64 { self.pos }

/// Sets the position of this cursor.
pub fn set_position(&mut self, pos: u64) { self.pos = pos; }
}
3 changes: 3 additions & 0 deletions src/buf/from_buf.rs
Original file line number Diff line number Diff line change
@@ -1,5 +1,8 @@
use {Buf, BufMut, IntoBuf, Bytes, BytesMut};

#[cfg(not(feature = "use_std"))]
use alloc::vec::Vec;

/// Conversion from a [`Buf`]
///
/// Implementing `FromBuf` for a type defines how it is created from a buffer.
Expand Down
33 changes: 20 additions & 13 deletions src/buf/into_buf.rs
Original file line number Diff line number Diff line change
@@ -1,6 +1,13 @@
use super::{Buf};

use std::io;
#[cfg(not(feature = "use_std"))]
use buf::Cursor;
#[cfg(not(feature = "use_std"))]
use alloc::string::String;
#[cfg(not(feature = "use_std"))]
use alloc::vec::Vec;
#[cfg(feature = "use_std")]
use std::io::Cursor;

/// Conversion into a `Buf`
///
Expand Down Expand Up @@ -56,65 +63,65 @@ impl<T: Buf> IntoBuf for T {
}

impl<'a> IntoBuf for &'a [u8] {
type Buf = io::Cursor<&'a [u8]>;
type Buf = Cursor<&'a [u8]>;

fn into_buf(self) -> Self::Buf {
io::Cursor::new(self)
Cursor::new(self)
}
}

impl<'a> IntoBuf for &'a str {
type Buf = io::Cursor<&'a [u8]>;
type Buf = Cursor<&'a [u8]>;

fn into_buf(self) -> Self::Buf {
self.as_bytes().into_buf()
}
}

impl IntoBuf for Vec<u8> {
type Buf = io::Cursor<Vec<u8>>;
type Buf = Cursor<Vec<u8>>;

fn into_buf(self) -> Self::Buf {
io::Cursor::new(self)
Cursor::new(self)
}
}

impl<'a> IntoBuf for &'a Vec<u8> {
type Buf = io::Cursor<&'a [u8]>;
type Buf = Cursor<&'a [u8]>;

fn into_buf(self) -> Self::Buf {
io::Cursor::new(&self[..])
Cursor::new(&self[..])
}
}

// Kind of annoying... but this impl is required to allow passing `&'static
// [u8]` where for<'a> &'a T: IntoBuf is required.
impl<'a> IntoBuf for &'a &'static [u8] {
type Buf = io::Cursor<&'static [u8]>;
type Buf = Cursor<&'static [u8]>;

fn into_buf(self) -> Self::Buf {
io::Cursor::new(self)
Cursor::new(self)
}
}

impl<'a> IntoBuf for &'a &'static str {
type Buf = io::Cursor<&'static [u8]>;
type Buf = Cursor<&'static [u8]>;

fn into_buf(self) -> Self::Buf {
self.as_bytes().into_buf()
}
}

impl IntoBuf for String {
type Buf = io::Cursor<Vec<u8>>;
type Buf = Cursor<Vec<u8>>;

fn into_buf(self) -> Self::Buf {
self.into_bytes().into_buf()
}
}

impl<'a> IntoBuf for &'a String {
type Buf = io::Cursor<&'a [u8]>;
type Buf = Cursor<&'a [u8]>;

fn into_buf(self) -> Self::Buf {
self.as_bytes().into_buf()
Expand Down
4 changes: 4 additions & 0 deletions src/buf/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,8 @@ mod buf;
mod buf_mut;
mod from_buf;
mod chain;
#[cfg(not(feature = "use_std"))]
mod cursor;
mod into_buf;
mod iter;
mod reader;
Expand All @@ -30,6 +32,8 @@ pub use self::buf::Buf;
pub use self::buf_mut::BufMut;
pub use self::from_buf::FromBuf;
pub use self::chain::Chain;
#[cfg(not(feature = "use_std"))]
pub use self::cursor::Cursor;
pub use self::into_buf::IntoBuf;
pub use self::iter::Iter;
pub use self::reader::Reader;
Expand Down
2 changes: 2 additions & 0 deletions src/buf/reader.rs
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
use {Buf};

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

/// A `Buf` adapter which implements `io::Read` for the inner value.
Expand Down Expand Up @@ -78,6 +79,7 @@ impl<B: Buf> Reader<B> {
}
}

#[cfg(feature = "use_std")]
impl<B: Buf + Sized> io::Read for Reader<B> {
fn read(&mut self, dst: &mut [u8]) -> io::Result<usize> {
let len = cmp::min(self.buf.remaining(), dst.len());
Expand Down
2 changes: 1 addition & 1 deletion src/buf/take.rs
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
use {Buf};

use std::cmp;
use core::cmp;

/// A `Buf` adapter which limits the bytes read from an underlying buffer.
///
Expand Down
2 changes: 2 additions & 0 deletions src/buf/writer.rs
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
use BufMut;

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

/// A `BufMut` adapter which implements `io::Write` for the inner value.
Expand Down Expand Up @@ -74,6 +75,7 @@ impl<B: BufMut> Writer<B> {
}
}

#[cfg(feature = "use_std")]
impl<B: BufMut + Sized> io::Write for Writer<B> {
fn write(&mut self, src: &[u8]) -> io::Result<usize> {
let n = cmp::min(self.buf.remaining_mut(), src.len());
Expand Down
Loading

0 comments on commit 6871b20

Please sign in to comment.