Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

add support for no-std #184

Merged
merged 1 commit into from
May 24, 2020
Merged
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
7 changes: 5 additions & 2 deletions .travis.yml
Original file line number Diff line number Diff line change
@@ -3,10 +3,10 @@ sudo: false
language: rust
matrix:
include:
- rust: stable
#- rust: stable
- rust: beta
- rust: nightly
- rust: 1.40.0
#- rust: 1.44.0
env:
global:
- export PATH="$PATH:$HOME/bin"
@@ -26,6 +26,9 @@ install:
- cd ../

script:
- cd capnp
- cargo test --no-default-features
- cd ../
- cargo build --all
- cargo test --all
- ./target/debug/addressbook write | ./target/debug/addressbook read
4 changes: 4 additions & 0 deletions capnp/Cargo.toml
Original file line number Diff line number Diff line change
@@ -25,9 +25,13 @@ quickcheck = { version = "0.9", optional = true }
quickcheck = "0.9"

[features]
default = ["std"]

rpc_try = []

# If enabled, relaxes alignment requirements on segments.
# This has a performance cost on some targets (e.g. ARMv6).
unaligned = []

std = []

3 changes: 3 additions & 0 deletions capnp/src/any_pointer.rs
Original file line number Diff line number Diff line change
@@ -21,6 +21,9 @@

//! Dynamically typed value.

use alloc::boxed::Box;
use alloc::vec::Vec;

use crate::capability::FromClientHook;
use crate::private::capability::{ClientHook, PipelineHook, PipelineOp};
use crate::private::layout::{PointerReader, PointerBuilder};
2 changes: 1 addition & 1 deletion capnp/src/any_pointer_list.rs
Original file line number Diff line number Diff line change
@@ -124,7 +124,7 @@ impl <'a> crate::traits::SetPointerBuilder<Builder<'a>> for Reader<'a> {
}
}

impl <'a> ::std::iter::IntoIterator for Reader<'a> {
impl <'a> core::iter::IntoIterator for Reader<'a> {
type Item = Result<crate::any_pointer::Reader<'a>>;
type IntoIter = ListIter<Reader<'a>, Self::Item>;

29 changes: 14 additions & 15 deletions capnp/src/capability.rs
Original file line number Diff line number Diff line change
@@ -23,19 +23,18 @@
//!
//! Roughly corresponds to capability.h in the C++ implementation.

use alloc::boxed::Box;
use core::future::{Future};
use core::pin::{Pin};
use core::marker::{PhantomData, Unpin};
use core::task::Poll;
#[cfg(feature = "rpc_try")]
use core::ops::Try;

use crate::{any_pointer, Error, MessageSize};
use crate::traits::{Pipelined, Owned};
use crate::private::capability::{ClientHook, ParamsHook, RequestHook, ResponseHook, ResultsHook};

use std::future::{Future};
use std::pin::{Pin};
use std::marker::Unpin;
use std::task::Poll;
#[cfg(feature = "rpc_try")]
use std::ops::Try;

use std::marker::PhantomData;

/// A computation that might eventually resolve to a value of type `T` or to an error
/// of type `E`. Dropping the promise cancels the computation.
#[must_use = "futures do nothing unless polled"]
@@ -45,7 +44,7 @@ pub struct Promise<T, E> {

enum PromiseInner<T, E> {
Immediate(Result<T,E>),
Deferred(Pin<Box<dyn Future<Output=std::result::Result<T,E>> + 'static>>),
Deferred(Pin<Box<dyn Future<Output=core::result::Result<T,E>> + 'static>>),
Empty,
}

@@ -62,21 +61,21 @@ impl <T, E> Promise<T, E> {
}

pub fn from_future<F>(f: F) -> Promise<T, E>
where F: Future<Output=std::result::Result<T,E>> + 'static
where F: Future<Output=core::result::Result<T,E>> + 'static
{
Promise { inner: PromiseInner::Deferred(Box::pin(f)) }
}
}

impl <T, E> Future for Promise<T, E>
{
type Output = std::result::Result<T,E>;
type Output = core::result::Result<T,E>;

fn poll(self: Pin<&mut Self>, cx: &mut ::std::task::Context) -> Poll<Self::Output> {
fn poll(self: Pin<&mut Self>, cx: &mut ::core::task::Context) -> Poll<Self::Output> {
match self.get_mut().inner {
PromiseInner::Empty => panic!("Promise polled after done."),
ref mut imm @ PromiseInner::Immediate(_) => {
match std::mem::replace(imm, PromiseInner::Empty) {
match core::mem::replace(imm, PromiseInner::Empty) {
PromiseInner::Immediate(r) => Poll::Ready(r),
_ => unreachable!(),
}
@@ -254,7 +253,7 @@ pub trait Server {
/// Trait to track the relationship between generated Server traits and Client structs.
pub trait FromServer<S> : FromClientHook {
// Implemented by the generated ServerDispatch struct.
type Dispatch: Server + 'static + std::ops::DerefMut<Target=S>;
type Dispatch: Server + 'static + core::ops::DerefMut<Target=S>;

fn from_server(s: S) -> Self::Dispatch;
}
5 changes: 3 additions & 2 deletions capnp/src/capability_list.rs
Original file line number Diff line number Diff line change
@@ -20,7 +20,8 @@

//! List of capabilities.

use std::marker::PhantomData;
use alloc::boxed::Box;
use core::marker::PhantomData;

use crate::capability::{FromClientHook};
use crate::private::capability::ClientHook;
@@ -152,7 +153,7 @@ impl <'a, T> crate::traits::SetPointerBuilder<Builder<'a, T>> for Reader<'a, T>
}
}

impl <'a, T> ::std::iter::IntoIterator for Reader<'a, T>
impl <'a, T> ::core::iter::IntoIterator for Reader<'a, T>
where T: FromClientHook
{
type Item = Result<T>;
2 changes: 1 addition & 1 deletion capnp/src/constant.rs
Original file line number Diff line number Diff line change
@@ -23,7 +23,7 @@
//! `constant::Reader` does not do bounds-checking, so it is unsafe to
//! manually construct one of these.

use std::marker::PhantomData;
use core::marker::PhantomData;

use crate::any_pointer;
use crate::private::layout::PointerReader;
4 changes: 2 additions & 2 deletions capnp/src/data.rs
Original file line number Diff line number Diff line change
@@ -35,7 +35,7 @@ impl<'a> crate::traits::Owned<'a> for Owned {
pub type Reader<'a> = &'a [u8];

pub fn new_reader<'a>(p : *const u8, len : u32) -> Reader<'a> {
unsafe { ::std::slice::from_raw_parts(p, len as usize) }
unsafe { ::core::slice::from_raw_parts(p, len as usize) }
}

impl <'a> crate::traits::FromPointerReader<'a> for Reader<'a> {
@@ -47,7 +47,7 @@ impl <'a> crate::traits::FromPointerReader<'a> for Reader<'a> {
pub type Builder<'a> = &'a mut [u8];

pub fn new_builder<'a>(p : *mut u8, len : u32) -> Builder<'a> {
unsafe { ::std::slice::from_raw_parts_mut(p, len as usize) }
unsafe { ::core::slice::from_raw_parts_mut(p, len as usize) }
}

impl <'a> crate::traits::FromPointerBuilder<'a> for Builder<'a> {
2 changes: 1 addition & 1 deletion capnp/src/data_list.rs
Original file line number Diff line number Diff line change
@@ -133,7 +133,7 @@ impl <'a> crate::traits::SetPointerBuilder<Builder<'a>> for Reader<'a> {
}
}

impl <'a> ::std::iter::IntoIterator for Reader<'a> {
impl <'a> ::core::iter::IntoIterator for Reader<'a> {
type Item = Result<crate::data::Reader<'a>>;
type IntoIter = ListIter<Reader<'a>, Self::Item>;

16 changes: 8 additions & 8 deletions capnp/src/enum_list.rs
Original file line number Diff line number Diff line change
@@ -27,7 +27,7 @@ use crate::private::layout::{ListReader, ListBuilder, PointerReader, PointerBuil
TwoBytes, PrimitiveElement};
use crate::{NotInSchema, Result};

use std::marker::PhantomData;
use core::marker::PhantomData;

#[derive(Clone, Copy)]
pub struct Owned<T> {
@@ -52,7 +52,7 @@ impl <'a, T: FromU16> Reader<'a, T> {

pub fn len(&self) -> u32 { self.reader.len() }

pub fn iter(self) -> ListIter<Reader<'a, T>, ::std::result::Result<T, NotInSchema>>{
pub fn iter(self) -> ListIter<Reader<'a, T>, ::core::result::Result<T, NotInSchema>>{
let l = self.len();
ListIter::new(self, l)
}
@@ -65,14 +65,14 @@ impl <'a, T : FromU16> FromPointerReader<'a> for Reader<'a, T> {
}
}

impl <'a, T: FromU16> IndexMove<u32, ::std::result::Result<T, NotInSchema>> for Reader<'a, T>{
fn index_move(&self, index: u32) -> ::std::result::Result<T, NotInSchema> {
impl <'a, T: FromU16> IndexMove<u32, ::core::result::Result<T, NotInSchema>> for Reader<'a, T>{
fn index_move(&self, index: u32) -> ::core::result::Result<T, NotInSchema> {
self.get(index)
}
}

impl <'a, T : FromU16> Reader<'a, T> {
pub fn get(&self, index: u32) -> ::std::result::Result<T, NotInSchema> {
pub fn get(&self, index: u32) -> ::core::result::Result<T, NotInSchema> {
assert!(index < self.len());
let result: u16 = PrimitiveElement::get(&self.reader, index);
FromU16::from_u16(result)
@@ -119,7 +119,7 @@ impl <'a, T : FromU16> FromPointerBuilder<'a> for Builder<'a, T> {
}

impl <'a, T : ToU16 + FromU16> Builder<'a, T> {
pub fn get(&self, index: u32) -> ::std::result::Result<T, NotInSchema> {
pub fn get(&self, index: u32) -> ::core::result::Result<T, NotInSchema> {
assert!(index < self.len());
let result: u16 = PrimitiveElement::get_from_builder(&self.builder, index);
FromU16::from_u16(result)
@@ -138,8 +138,8 @@ impl <'a, T> crate::traits::SetPointerBuilder<Builder<'a, T>> for Reader<'a, T>
}
}

impl <'a, T: FromU16> ::std::iter::IntoIterator for Reader<'a, T> {
type Item = ::std::result::Result<T, NotInSchema>;
impl <'a, T: FromU16> ::core::iter::IntoIterator for Reader<'a, T> {
type Item = ::core::result::Result<T, NotInSchema>;
type IntoIter = ListIter<Reader<'a, T>, Self::Item>;

fn into_iter(self) -> Self::IntoIter {
115 changes: 115 additions & 0 deletions capnp/src/io.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,115 @@
//! Custom I/O traits that roughly mirror `std::io::{Read, BufRead, Write}`.
//! This extra layer of indirection enables support of no-std environments.

use crate::Result;

pub trait Read {
fn read_exact(&mut self, buf: &mut [u8]) -> Result<()>;
}

pub trait BufRead : Read {
fn fill_buf(&mut self) -> Result<&[u8]>;
fn consume(&mut self, amt: usize);
}

pub trait Write {
fn write_all(&mut self, buf: &[u8]) -> Result<()>;
}

#[cfg(feature="std")]
mod std_impls {
use crate::{Result};
use crate::io::{Read, BufRead, Write};

impl <R> Read for R where R: std::io::Read {
fn read_exact(&mut self, buf: &mut [u8]) -> Result<()> {
std::io::Read::read_exact(self, buf)?;
Ok(())
}
}

impl <R> BufRead for R where R: std::io::BufRead {
fn fill_buf(&mut self) -> Result<&[u8]> {
Ok(std::io::BufRead::fill_buf(self)?)
}
fn consume(&mut self, amt: usize) {
std::io::BufRead::consume(self, amt)
}
}

impl <W> Write for W where W: std::io::Write {
fn write_all(&mut self, buf: &[u8]) -> Result<()> {
std::io::Write::write_all(self, buf)?;
Ok(())
}
}
}

#[cfg(not(feature="std"))]
mod no_std_impls {
use alloc::string::ToString;
use crate::{Error, Result};
use crate::io::{Read, BufRead, Write};

impl <'a> Write for &'a mut [u8] {
fn write_all(&mut self, buf: &[u8]) -> Result<()> {
if buf.len() > self.len() {
return Err(Error::failed("buffer is not large enough".to_string()));
}
let amt = buf.len();
let (a, b) = core::mem::replace(self, &mut []).split_at_mut(amt);
a.copy_from_slice(buf);
*self = b;
Ok(())
}
}

impl Write for alloc::vec::Vec<u8> {
fn write_all(&mut self, buf: &[u8]) -> Result<()> {
self.extend_from_slice(buf);
Ok(())
}
}

impl <W: ?Sized> Write for &mut W where W: Write {
fn write_all(&mut self, buf: &[u8]) -> Result<()> {
(**self).write_all(buf)
}
}

impl <'a> Read for &'a [u8] {
fn read_exact(&mut self, buf: &mut [u8]) -> Result<()> {
if buf.len() > self.len() {
return Err(Error::failed("buffer is not large enough".to_string()));
}
let (a, b) = self.split_at(buf.len());
buf.copy_from_slice(a);
*self = b;
Ok(())
}
}

impl <R: ?Sized> Read for &mut R where R: Read {
fn read_exact(&mut self, buf: &mut [u8]) -> Result<()> {
(**self).read_exact(buf)
}
}

impl <'a> BufRead for &'a [u8] {
fn fill_buf(&mut self) -> Result<&[u8]> {
Ok(*self)
}
fn consume(&mut self, amt: usize) {
*self = &self[amt..]
}
}

impl <R: ?Sized> BufRead for &mut R where R: BufRead {
fn fill_buf(&mut self) -> Result<&[u8]> {
(**self).fill_buf()
}
fn consume(&mut self, amt: usize) {
(**self).consume(amt)
}
}
}
Loading