Skip to content

Commit

Permalink
Add support for no-std usages of capnp crate.
Browse files Browse the repository at this point in the history
  • Loading branch information
dwrensha committed May 24, 2020
1 parent 1f99e45 commit 022ca7c
Show file tree
Hide file tree
Showing 33 changed files with 386 additions and 192 deletions.
7 changes: 5 additions & 2 deletions .travis.yml
Expand Up @@ -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"
Expand All @@ -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
Expand Down
4 changes: 4 additions & 0 deletions capnp/Cargo.toml
Expand Up @@ -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
Expand Up @@ -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};
Expand Down
2 changes: 1 addition & 1 deletion capnp/src/any_pointer_list.rs
Expand Up @@ -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>;

Expand Down
29 changes: 14 additions & 15 deletions capnp/src/capability.rs
Expand Up @@ -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"]
Expand All @@ -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,
}

Expand All @@ -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!(),
}
Expand Down Expand Up @@ -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
Expand Up @@ -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;
Expand Down Expand Up @@ -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>;
Expand Down
2 changes: 1 addition & 1 deletion capnp/src/constant.rs
Expand Up @@ -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;
Expand Down
4 changes: 2 additions & 2 deletions capnp/src/data.rs
Expand Up @@ -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> {
Expand All @@ -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> {
Expand Down
2 changes: 1 addition & 1 deletion capnp/src/data_list.rs
Expand Up @@ -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>;

Expand Down
16 changes: 8 additions & 8 deletions capnp/src/enum_list.rs
Expand Up @@ -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> {
Expand All @@ -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)
}
Expand All @@ -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)
Expand Down Expand Up @@ -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)
Expand All @@ -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 {
Expand Down
115 changes: 115 additions & 0 deletions capnp/src/io.rs
@@ -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)
}
}
}

0 comments on commit 022ca7c

Please sign in to comment.