diff --git a/.travis.yml b/.travis.yml index 0f4e8d15e..423eadb72 100644 --- a/.travis.yml +++ b/.travis.yml @@ -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 diff --git a/capnp/Cargo.toml b/capnp/Cargo.toml index fc61ebcff..4d48b1223 100644 --- a/capnp/Cargo.toml +++ b/capnp/Cargo.toml @@ -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 = [] + diff --git a/capnp/src/any_pointer.rs b/capnp/src/any_pointer.rs index d62b8bad6..238099c1a 100644 --- a/capnp/src/any_pointer.rs +++ b/capnp/src/any_pointer.rs @@ -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}; diff --git a/capnp/src/any_pointer_list.rs b/capnp/src/any_pointer_list.rs index 683494408..2d0ec8e2c 100644 --- a/capnp/src/any_pointer_list.rs +++ b/capnp/src/any_pointer_list.rs @@ -124,7 +124,7 @@ impl <'a> crate::traits::SetPointerBuilder> for Reader<'a> { } } -impl <'a> ::std::iter::IntoIterator for Reader<'a> { +impl <'a> core::iter::IntoIterator for Reader<'a> { type Item = Result>; type IntoIter = ListIter, Self::Item>; diff --git a/capnp/src/capability.rs b/capnp/src/capability.rs index c3976482a..87b9991df 100644 --- a/capnp/src/capability.rs +++ b/capnp/src/capability.rs @@ -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 { enum PromiseInner { Immediate(Result), - Deferred(Pin> + 'static>>), + Deferred(Pin> + 'static>>), Empty, } @@ -62,7 +61,7 @@ impl Promise { } pub fn from_future(f: F) -> Promise - where F: Future> + 'static + where F: Future> + 'static { Promise { inner: PromiseInner::Deferred(Box::pin(f)) } } @@ -70,13 +69,13 @@ impl Promise { impl Future for Promise { - type Output = std::result::Result; + type Output = core::result::Result; - fn poll(self: Pin<&mut Self>, cx: &mut ::std::task::Context) -> Poll { + fn poll(self: Pin<&mut Self>, cx: &mut ::core::task::Context) -> Poll { 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 : FromClientHook { // Implemented by the generated ServerDispatch struct. - type Dispatch: Server + 'static + std::ops::DerefMut; + type Dispatch: Server + 'static + core::ops::DerefMut; fn from_server(s: S) -> Self::Dispatch; } diff --git a/capnp/src/capability_list.rs b/capnp/src/capability_list.rs index e82eed3af..e9845b389 100644 --- a/capnp/src/capability_list.rs +++ b/capnp/src/capability_list.rs @@ -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> 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; diff --git a/capnp/src/constant.rs b/capnp/src/constant.rs index 8de8fdbfd..39a5f9af6 100644 --- a/capnp/src/constant.rs +++ b/capnp/src/constant.rs @@ -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; diff --git a/capnp/src/data.rs b/capnp/src/data.rs index d19f6f490..3a3d07ca6 100644 --- a/capnp/src/data.rs +++ b/capnp/src/data.rs @@ -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> { diff --git a/capnp/src/data_list.rs b/capnp/src/data_list.rs index 785657e0c..20456d2a9 100644 --- a/capnp/src/data_list.rs +++ b/capnp/src/data_list.rs @@ -133,7 +133,7 @@ impl <'a> crate::traits::SetPointerBuilder> for Reader<'a> { } } -impl <'a> ::std::iter::IntoIterator for Reader<'a> { +impl <'a> ::core::iter::IntoIterator for Reader<'a> { type Item = Result>; type IntoIter = ListIter, Self::Item>; diff --git a/capnp/src/enum_list.rs b/capnp/src/enum_list.rs index c5e8f2d85..ed825efbc 100644 --- a/capnp/src/enum_list.rs +++ b/capnp/src/enum_list.rs @@ -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 { @@ -52,7 +52,7 @@ impl <'a, T: FromU16> Reader<'a, T> { pub fn len(&self) -> u32 { self.reader.len() } - pub fn iter(self) -> ListIter, ::std::result::Result>{ + pub fn iter(self) -> ListIter, ::core::result::Result>{ 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> for Reader<'a, T>{ - fn index_move(&self, index: u32) -> ::std::result::Result { +impl <'a, T: FromU16> IndexMove> for Reader<'a, T>{ + fn index_move(&self, index: u32) -> ::core::result::Result { self.get(index) } } impl <'a, T : FromU16> Reader<'a, T> { - pub fn get(&self, index: u32) -> ::std::result::Result { + pub fn get(&self, index: u32) -> ::core::result::Result { 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 { + pub fn get(&self, index: u32) -> ::core::result::Result { 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> for Reader<'a, T> } } -impl <'a, T: FromU16> ::std::iter::IntoIterator for Reader<'a, T> { - type Item = ::std::result::Result; +impl <'a, T: FromU16> ::core::iter::IntoIterator for Reader<'a, T> { + type Item = ::core::result::Result; type IntoIter = ListIter, Self::Item>; fn into_iter(self) -> Self::IntoIter { diff --git a/capnp/src/io.rs b/capnp/src/io.rs new file mode 100644 index 000000000..d1df0ed10 --- /dev/null +++ b/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 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 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 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 { + fn write_all(&mut self, buf: &[u8]) -> Result<()> { + self.extend_from_slice(buf); + Ok(()) + } + } + + impl 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 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 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) + } + } +} diff --git a/capnp/src/lib.rs b/capnp/src/lib.rs index 03065785a..608a6e38b 100644 --- a/capnp/src/lib.rs +++ b/capnp/src/lib.rs @@ -25,8 +25,11 @@ //! [Cap'n Proto](https://capnproto.org) messages in Rust. It is intended to //! be used in conjunction with code generated by the //! [capnpc-rust](https://github.com/capnproto/capnproto-rust/capnpc) crate. + #![cfg_attr(feature = "rpc_try", feature(try_trait))] +#![cfg_attr(not(feature = "std"), no_std)] +#[macro_use] extern crate alloc; pub mod any_pointer; @@ -37,6 +40,7 @@ pub mod constant; pub mod data; pub mod data_list; pub mod enum_list; +pub mod io; pub mod list_list; pub mod message; pub mod primitive_list; @@ -49,6 +53,9 @@ pub mod text; pub mod text_list; pub mod traits; +use alloc::string::String; +use alloc::vec::Vec; + /// /// An 8-byte aligned value. /// @@ -72,20 +79,20 @@ impl Word { unsafe { result.set_len(length); let p: *mut u8 = result.as_mut_ptr() as *mut u8; - std::ptr::write_bytes(p, 0u8, length * std::mem::size_of::()); + core::ptr::write_bytes(p, 0u8, length * core::mem::size_of::()); } result } pub fn words_to_bytes<'a>(words: &'a [Word]) -> &'a [u8] { unsafe { - std::slice::from_raw_parts(words.as_ptr() as *const u8, words.len() * 8) + core::slice::from_raw_parts(words.as_ptr() as *const u8, words.len() * 8) } } pub fn words_to_bytes_mut<'a>(words: &'a mut [Word]) -> &'a mut [u8] { unsafe { - std::slice::from_raw_parts_mut(words.as_mut_ptr() as *mut u8, words.len() * 8) + core::slice::from_raw_parts_mut(words.as_mut_ptr() as *mut u8, words.len() * 8) } } } @@ -124,12 +131,13 @@ impl MessageSize { #[derive(PartialEq, Clone, Copy, Debug)] pub struct NotInSchema(pub u16); -impl ::std::fmt::Display for NotInSchema { - fn fmt(&self, fmt: &mut ::std::fmt::Formatter) -> ::std::result::Result<(), ::std::fmt::Error> { +impl ::core::fmt::Display for NotInSchema { + fn fmt(&self, fmt: &mut ::core::fmt::Formatter) -> ::core::result::Result<(), ::core::fmt::Error> { write!(fmt, "Enum value or union discriminant {} was not present in the schema.", self.0) } } +#[cfg(feature="std")] impl ::std::error::Error for NotInSchema { fn description<'a>(&'a self) -> &'a str { "Enum value or union discriminant was not present in schema." @@ -138,7 +146,7 @@ impl ::std::error::Error for NotInSchema { /// Because messages are lazily validated, the return type of any method that reads a pointer field /// must be wrapped in a Result. -pub type Result = ::std::result::Result; +pub type Result = ::core::result::Result; /// Describes an arbitrary error that prevented an operation from completing. #[derive(Debug, Clone)] @@ -190,7 +198,8 @@ impl Error { } } -impl ::std::convert::From<::std::io::Error> for Error { +#[cfg(feature="std")] +impl core::convert::From<::std::io::Error> for Error { fn from(err: ::std::io::Error) -> Error { use std::io; let kind = match err.kind() { @@ -206,30 +215,31 @@ impl ::std::convert::From<::std::io::Error> for Error { } } -impl ::std::convert::From<::std::string::FromUtf8Error> for Error { - fn from(err: ::std::string::FromUtf8Error) -> Error { +impl core::convert::From for Error { + fn from(err: alloc::string::FromUtf8Error) -> Error { Error::failed(format!("{}", err)) } } -impl ::std::convert::From<::std::str::Utf8Error> for Error { - fn from(err: ::std::str::Utf8Error) -> Error { +impl core::convert::From for Error { + fn from(err: alloc::str::Utf8Error) -> Error { Error::failed(format!("{}", err)) } } -impl ::std::convert::From for Error { +impl core::convert::From for Error { fn from(e: NotInSchema) -> Error { Error::failed(format!("Enum value or union discriminant {} was not present in schema.", e.0)) } } -impl ::std::fmt::Display for Error { - fn fmt(&self, fmt: &mut ::std::fmt::Formatter) -> ::std::result::Result<(), ::std::fmt::Error> { +impl core::fmt::Display for Error { + fn fmt(&self, fmt: &mut core::fmt::Formatter) -> core::result::Result<(), core::fmt::Error> { write!(fmt, "{:?}: {}", self.kind, self.description) } } +#[cfg(feature="std")] impl ::std::error::Error for Error { fn description(&self) -> &str { &self.description @@ -246,7 +256,7 @@ pub enum OutputSegments<'a> { MultiSegment(Vec<&'a [u8]>), } -impl <'a> ::std::ops::Deref for OutputSegments<'a> { +impl <'a> core::ops::Deref for OutputSegments<'a> { type Target = [&'a [u8]]; fn deref<'b>(&'b self) -> &'b [&'a [u8]] { match *self { diff --git a/capnp/src/list_list.rs b/capnp/src/list_list.rs index ff2e435c3..75b084b51 100644 --- a/capnp/src/list_list.rs +++ b/capnp/src/list_list.rs @@ -27,7 +27,7 @@ use crate::Result; #[derive(Clone, Copy)] pub struct Owned where T: for<'a> crate::traits::Owned<'a> { - marker: ::std::marker::PhantomData, + marker: ::core::marker::PhantomData, } impl<'a, T> crate::traits::Owned<'a> for Owned where T: for<'b> crate::traits::Owned<'b> { @@ -36,13 +36,13 @@ impl<'a, T> crate::traits::Owned<'a> for Owned where T: for<'b> crate::traits } pub struct Reader<'a, T> where T: for<'b> crate::traits::Owned<'b> { - marker: ::std::marker::PhantomData<>::Reader>, + marker: ::core::marker::PhantomData<>::Reader>, reader: ListReader<'a> } impl <'a, T> Reader<'a, T> where T: for<'b> crate::traits::Owned<'b> { pub fn new<'b>(reader: ListReader<'b>) -> Reader<'b, T> { - Reader::<'b, T> { reader: reader, marker: ::std::marker::PhantomData } + Reader::<'b, T> { reader: reader, marker: ::core::marker::PhantomData } } pub fn len(&self) -> u32 { self.reader.len() } @@ -69,7 +69,7 @@ where T: for<'b> crate::traits::Owned<'b> { impl <'a, T> FromPointerReader<'a> for Reader<'a, T> where T: for<'b> crate::traits::Owned<'b> { fn get_from_pointer(reader: &PointerReader<'a>, default: Option<&'a [crate::Word]>) -> Result> { Ok(Reader { reader: reader.get_list(Pointer, default)?, - marker: ::std::marker::PhantomData }) + marker: ::core::marker::PhantomData }) } } @@ -81,19 +81,19 @@ impl <'a, T> Reader<'a, T> where T: for<'b> crate::traits::Owned<'b> { } pub struct Builder<'a, T> where T: for<'b> crate::traits::Owned<'b> { - marker: ::std::marker::PhantomData, + marker: ::core::marker::PhantomData, builder: ListBuilder<'a> } impl <'a, T> Builder<'a, T> where T: for<'b> crate::traits::Owned<'b> { pub fn new(builder: ListBuilder<'a>) -> Builder<'a, T> { - Builder { builder: builder, marker: ::std::marker::PhantomData } + Builder { builder: builder, marker: ::core::marker::PhantomData } } pub fn len(&self) -> u32 { self.builder.len() } pub fn into_reader(self) -> Reader<'a, T> { - Reader { reader: self.builder.into_reader(), marker: ::std::marker::PhantomData } + Reader { reader: self.builder.into_reader(), marker: ::core::marker::PhantomData } } } @@ -105,20 +105,20 @@ impl <'a, T> Builder<'a, T> where T: for<'b> crate::traits::Owned<'b> { impl <'a, T> Builder<'a, T> where T: for<'b> crate::traits::Owned<'b> { pub fn reborrow<'b>(&'b mut self) -> Builder<'b, T> { - Builder {builder: self.builder.borrow(), marker: ::std::marker::PhantomData} + Builder {builder: self.builder.borrow(), marker: ::core::marker::PhantomData} } } impl <'a, T> FromPointerBuilder<'a> for Builder<'a, T> where T: for<'b> crate::traits::Owned<'b> { fn init_pointer(builder: PointerBuilder<'a>, size : u32) -> Builder<'a, T> { Builder { - marker: ::std::marker::PhantomData, + marker: ::core::marker::PhantomData, builder: builder.init_list(Pointer, size) } } fn get_from_pointer(builder: PointerBuilder<'a>, default: Option<&'a [crate::Word]>) -> Result> { Ok(Builder { - marker: ::std::marker::PhantomData, + marker: ::core::marker::PhantomData, builder: builder.get_list(Pointer, default)? }) } @@ -141,7 +141,7 @@ impl <'a, T> crate::traits::SetPointerBuilder> 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: for<'b> crate::traits::Owned<'b> { type Item = Result<>::Reader>; diff --git a/capnp/src/message.rs b/capnp/src/message.rs index ba6eb7f24..8b7f554b7 100644 --- a/capnp/src/message.rs +++ b/capnp/src/message.rs @@ -21,7 +21,8 @@ //! Untyped root container for a Cap'n Proto value. -use std::convert::From; +use alloc::vec::Vec; +use core::convert::From; use crate::any_pointer; use crate::private::arena::{BuilderArenaImpl, ReaderArenaImpl, BuilderArena, ReaderArena}; @@ -183,7 +184,7 @@ impl Reader where S: ReaderSegments { let pointer_reader = layout::PointerReader::get_root( &self.arena, 0, segment_start, self.nesting_limit)?; - let read_head = ::std::cell::Cell::new(unsafe {segment_start.offset(BYTES_PER_WORD as isize)}); + let read_head = ::core::cell::Cell::new(unsafe {segment_start.offset(BYTES_PER_WORD as isize)}); let root_is_canonical = pointer_reader.is_canonical(&read_head)?; let all_words_consumed = (read_head.get() as usize - segment_start as usize) / BYTES_PER_WORD == seg_len as usize; @@ -216,7 +217,7 @@ impl Reader where S: ReaderSegments { pub struct TypedReader where S: ReaderSegments, T: for<'a> Owned<'a> { - marker: ::std::marker::PhantomData, + marker: ::core::marker::PhantomData, message: Reader, } @@ -226,7 +227,7 @@ impl TypedReader pub fn new(message: Reader) -> Self { TypedReader { - marker: ::std::marker::PhantomData, + marker: ::core::marker::PhantomData, message: message, } } @@ -419,7 +420,7 @@ impl HeapAllocator { unsafe impl Allocator for HeapAllocator { fn allocate_segment(&mut self, minimum_size: u32) -> (*mut u8, u32) { - let size = ::std::cmp::max(minimum_size, self.next_size); + let size = core::cmp::max(minimum_size, self.next_size); let ptr = unsafe { alloc::alloc::alloc_zeroed(alloc::alloc::Layout::from_size_align(size as usize * BYTES_PER_WORD, 8).unwrap()) }; @@ -494,7 +495,7 @@ unsafe impl <'a> Allocator for ScratchSpaceHeapAllocator<'a> { // Rezero the slice to allow reuse of the allocator. We only need to write // words that we know might contain nonzero values. unsafe { - ::std::ptr::write_bytes(ptr, 0u8, (words_used as usize) * BYTES_PER_WORD); + core::ptr::write_bytes(ptr, 0u8, (words_used as usize) * BYTES_PER_WORD); } self.scratch_space_allocated = false; } else { diff --git a/capnp/src/primitive_list.rs b/capnp/src/primitive_list.rs index 57777d92d..481855cc9 100644 --- a/capnp/src/primitive_list.rs +++ b/capnp/src/primitive_list.rs @@ -21,7 +21,7 @@ //! List of primitives. -use std::{marker}; +use core::{marker}; use crate::traits::{FromPointerReader, FromPointerBuilder, IndexMove, ListIter}; use crate::private::layout::{ListReader, ListBuilder, PointerReader, PointerBuilder, @@ -139,7 +139,7 @@ impl <'a, T> crate::traits::SetPointerBuilder> 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: PrimitiveElement { type Item = T; diff --git a/capnp/src/private/arena.rs b/capnp/src/private/arena.rs index fbc0ae607..29d52c254 100644 --- a/capnp/src/private/arena.rs +++ b/capnp/src/private/arena.rs @@ -18,9 +18,10 @@ // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN // THE SOFTWARE. -use std::cell::{Cell, RefCell}; -use std::slice; -use std::u64; +use alloc::vec::Vec; +use core::cell::{Cell, RefCell}; +use core::slice; +use core::u64; use crate::private::units::*; use crate::message; @@ -340,7 +341,7 @@ impl BuilderArena for NullArena { } fn get_segment_mut(&self, _id: u32) -> (*mut u8, u32) { - (::std::ptr::null_mut(), 0) + (core::ptr::null_mut(), 0) } fn as_reader<'a>(&'a self) -> &'a dyn ReaderArena { diff --git a/capnp/src/private/capability.rs b/capnp/src/private/capability.rs index 42979bac8..627d00798 100644 --- a/capnp/src/private/capability.rs +++ b/capnp/src/private/capability.rs @@ -19,6 +19,9 @@ // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN // THE SOFTWARE. +use alloc::boxed::Box; +use alloc::vec::Vec; + use crate::any_pointer; use crate::MessageSize; use crate::capability::{Params, Promise, Request, RemotePromise, Results}; @@ -87,15 +90,15 @@ pub trait ParamsHook { // Where should this live? pub fn internal_get_typed_params(typeless: Params) -> Params { - Params { hook: typeless.hook, marker: ::std::marker::PhantomData } + Params { hook: typeless.hook, marker: ::core::marker::PhantomData } } pub fn internal_get_typed_results(typeless: Results) -> Results { - Results { hook: typeless.hook, marker: ::std::marker::PhantomData } + Results { hook: typeless.hook, marker: ::core::marker::PhantomData } } pub fn internal_get_untyped_results(typeful: Results) -> Results { - Results { hook: typeful.hook, marker: ::std::marker::PhantomData } + Results { hook: typeful.hook, marker: ::core::marker::PhantomData } } pub trait PipelineHook { diff --git a/capnp/src/private/layout.rs b/capnp/src/private/layout.rs index 18a2ce2cd..fdb80a0fc 100644 --- a/capnp/src/private/layout.rs +++ b/capnp/src/private/layout.rs @@ -19,9 +19,11 @@ // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN // THE SOFTWARE. -use std::mem; -use std::ptr; -use std::cell::Cell; +use alloc::boxed::Box; +use alloc::vec::Vec; +use core::mem; +use core::ptr; +use core::cell::Cell; use crate::data; use crate::text; @@ -136,7 +138,7 @@ pub struct WirePointer { #[cfg(feature = "unaligned")] fn wire_pointer_align() { // We cast *u8 to *WirePointer, so we need to make sure its alignment allows that. - assert_eq!(std::mem::align_of::(), 1); + assert_eq!(core::mem::align_of::(), 1); } impl WirePointer { @@ -317,7 +319,9 @@ impl WirePointer { } mod wire_helpers { - use std::{ptr, slice}; + use alloc::boxed::Box; + use alloc::string::ToString; + use core::{ptr, slice}; use crate::private::capability::ClientHook; use crate::private::arena::*; @@ -1031,8 +1035,8 @@ mod wire_helpers { //# handle writes? Instead, we have to copy the struct to a //# new space now. - let new_data_size = ::std::cmp::max(old_data_size, size.data); - let new_pointer_count = ::std::cmp::max(old_pointer_count, size.pointers); + let new_data_size = ::core::cmp::max(old_data_size, size.data); + let new_pointer_count = ::core::cmp::max(old_pointer_count, size.pointers); let total_size = new_data_size as u32 + new_pointer_count as u32 * WORDS_PER_POINTER as u32; //# Don't let allocate() zero out the object just yet. @@ -1339,8 +1343,8 @@ mod wire_helpers { // The structs in this list are smaller than expected, probably written using an older // version of the protocol. We need to make a copy and expand them. - let new_data_size = ::std::cmp::max(old_data_size, element_size.data); - let new_pointer_count = ::std::cmp::max(old_pointer_count, element_size.pointers); + let new_data_size = ::core::cmp::max(old_data_size, element_size.data); + let new_pointer_count = ::core::cmp::max(old_pointer_count, element_size.pointers); let new_step = new_data_size as u32 + new_pointer_count as u32 * WORDS_PER_POINTER as u32; let total_size = new_step * element_count; @@ -1415,10 +1419,10 @@ mod wire_helpers { let mut new_pointer_count = element_size.pointers; if old_size == ElementSize::Pointer { - new_pointer_count = ::std::cmp::max(new_pointer_count, 1); + new_pointer_count = ::core::cmp::max(new_pointer_count, 1); } else { // Old list contains data elements, so we need at least one word of data. - new_data_size = ::std::cmp::max(new_data_size, 1); + new_data_size = ::core::cmp::max(new_data_size, 1); } let new_step = new_data_size as u32 + new_pointer_count as u32 * WORDS_PER_POINTER as u32; @@ -1525,7 +1529,7 @@ mod wire_helpers { None => return text::Builder::new(&mut [], 0), Some(d) => { let (new_ref_target, new_reff, new_segment_id) = - copy_message(arena, segment_id, CapTableBuilder::Plain(::std::ptr::null_mut()), reff, d.as_ptr() as *const _); + copy_message(arena, segment_id, CapTableBuilder::Plain(::core::ptr::null_mut()), reff, d.as_ptr() as *const _); reff = new_reff; segment_id = new_segment_id; new_ref_target @@ -1598,7 +1602,7 @@ mod wire_helpers { None => return Ok(&mut []), Some(d) => { let (new_ref_target, new_reff, new_segment_id) = - copy_message(arena, segment_id, CapTableBuilder::Plain(std::ptr::null_mut()), reff, d.as_ptr() as *const _); + copy_message(arena, segment_id, CapTableBuilder::Plain(core::ptr::null_mut()), reff, d.as_ptr() as *const _); reff = new_reff; segment_id = new_segment_id; new_ref_target @@ -2489,7 +2493,7 @@ impl <'a> PointerReader<'a> { pub fn get_list(self, expected_element_size: ElementSize, default: Option<&'a [crate::Word]>) -> Result> { - let default_value: *const u8 = match default { None => std::ptr::null(), Some(d) => d.as_ptr() as *const u8}; + let default_value: *const u8 = match default { None => core::ptr::null(), Some(d) => d.as_ptr() as *const u8}; let reff = if self.pointer.is_null() { zero_pointer() } else { self.pointer }; unsafe { wire_helpers::read_list_pointer( @@ -2638,7 +2642,7 @@ impl <'a> PointerBuilder<'a> { pub fn get_list(self, element_size: ElementSize, default: Option<&'a [crate::Word]>) -> Result> { - let default_value: *const u8 = match default { None => std::ptr::null(), Some(d) => d.as_ptr() as *const u8}; + let default_value: *const u8 = match default { None => core::ptr::null(), Some(d) => d.as_ptr() as *const u8}; unsafe { wire_helpers::get_writable_list_pointer( self.arena, self.pointer, self.segment_id, self.cap_table, element_size, default_value) @@ -2648,7 +2652,7 @@ impl <'a> PointerBuilder<'a> { pub fn get_struct_list(self, element_size: StructSize, default: Option<&'a [crate::Word]>) -> Result> { - let default_value: *const u8 = match default { None => std::ptr::null(), Some(d) => d.as_ptr() as *const u8}; + let default_value: *const u8 = match default { None => core::ptr::null(), Some(d) => d.as_ptr() as *const u8}; unsafe { wire_helpers::get_writable_struct_list_pointer( self.arena, self.pointer, self.segment_id, self.cap_table, element_size, default_value) @@ -2677,7 +2681,7 @@ impl <'a> PointerBuilder<'a> { unsafe { wire_helpers::read_capability_pointer( self.arena.as_reader(), - self.segment_id, self.cap_table.into_reader(), self.pointer, ::std::i32::MAX) + self.segment_id, self.cap_table.into_reader(), self.pointer, ::core::i32::MAX) } } @@ -2842,7 +2846,7 @@ impl <'a> StructReader<'a> { &[] } else { unsafe { - ::std::slice::from_raw_parts(self.data, self.data_size as usize / BITS_PER_BYTE) + ::core::slice::from_raw_parts(self.data, self.data_size as usize / BITS_PER_BYTE) } } } @@ -3078,7 +3082,7 @@ impl <'a> StructBuilder<'a> { } pub fn copy_content_from(&mut self, other: &StructReader) -> Result<()> { - use std::cmp::min; + use core::cmp::min; // Determine the amount of data the builders have in common. let shared_data_size = min(self.data_size, other.data_size); let shared_pointer_count = min(self.pointer_count, other.pointer_count); @@ -3193,7 +3197,7 @@ impl <'a> ListReader<'a> { let num_bytes = wire_helpers::round_bits_up_to_bytes( self.step as u64 * self.element_count as u64) as usize; unsafe { - ::std::slice::from_raw_parts(self.ptr, num_bytes) + ::core::slice::from_raw_parts(self.ptr, num_bytes) } } } diff --git a/capnp/src/private/mod.rs b/capnp/src/private/mod.rs index 8d6465031..838077f9f 100644 --- a/capnp/src/private/mod.rs +++ b/capnp/src/private/mod.rs @@ -31,6 +31,12 @@ mod mask; pub mod units; mod zero; +/// Creates a new Box. Generated code uses this function to avoid the +/// need to directly refer to the alloc crate, which requires an `extern crate alloc`. +pub fn new_box(x: T) -> alloc::boxed::Box { + alloc::boxed::Box::new(x) +} + #[cfg(test)] mod layout_test; diff --git a/capnp/src/private/units.rs b/capnp/src/private/units.rs index 14fe33708..3b170139b 100644 --- a/capnp/src/private/units.rs +++ b/capnp/src/private/units.rs @@ -60,9 +60,9 @@ pub const WORDS_PER_POINTER : WordCount = 1; pub const POINTER_SIZE_IN_WORDS : WordCount = 1; pub fn _bytes_per_element() -> ByteCount { - ::std::mem::size_of::() + ::core::mem::size_of::() } pub fn bits_per_element() -> BitCount0 { - 8 * ::std::mem::size_of::() + 8 * ::core::mem::size_of::() } diff --git a/capnp/src/serialize.rs b/capnp/src/serialize.rs index 20687d641..6401afe3d 100644 --- a/capnp/src/serialize.rs +++ b/capnp/src/serialize.rs @@ -23,8 +23,9 @@ //! [standard stream framing](https://capnproto.org/encoding.html#serialization-over-a-stream), //! where each message is preceded by a segment table indicating the size of its segments. -use std::convert::TryInto; -use std::io::{Read, Write}; +use alloc::vec::Vec; +use core::convert::TryInto; +use crate::io::{Read, Write}; use crate::message; use crate::private::units::BYTES_PER_WORD; @@ -91,14 +92,14 @@ pub struct OwnedSegments { owned_space: Vec, } -impl std::ops::Deref for OwnedSegments { +impl core::ops::Deref for OwnedSegments { type Target = [u8]; fn deref(&self) -> &[u8] { crate::Word::words_to_bytes(&self.owned_space[..]) } } -impl std::ops::DerefMut for OwnedSegments { +impl core::ops::DerefMut for OwnedSegments { fn deref_mut(&mut self) -> &mut [u8] { crate::Word::words_to_bytes_mut(&mut self.owned_space[..]) } @@ -286,20 +287,20 @@ fn flatten_segments(segments: &R) -> Vec(write: &mut W, message: &message::Builder) -> ::std::io::Result<()> +pub fn write_message(mut write: W, message: &message::Builder) -> Result<()> where W: Write, A: message::Allocator { let segments = message.get_segments_for_output(); - write_segment_table(write, &segments)?; - write_segments(write, &segments) + write_segment_table(&mut write, &segments)?; + write_segments(&mut write, &segments) } -pub fn write_message_segments(write: &mut W, segments: &R) -> ::std::io::Result<()> +pub fn write_message_segments(mut write: W, segments: &R) -> Result<()> where W: Write, R: message::ReaderSegments { - write_segment_table_internal(write, segments)?; - write_segments(write, segments) + write_segment_table_internal(&mut write, segments)?; + write_segments(&mut write, segments) } -fn write_segment_table(write: &mut W, segments: &[&[u8]]) -> ::std::io::Result<()> +fn write_segment_table(write: &mut W, segments: &[&[u8]]) -> Result<()> where W: Write { write_segment_table_internal(write, segments) } @@ -307,7 +308,7 @@ where W: Write { /// Writes a segment table to `write`. /// /// `segments` must contain at least one segment. -fn write_segment_table_internal(write: &mut W, segments: &R) -> ::std::io::Result<()> +fn write_segment_table_internal(write: &mut W, segments: &R) -> Result<()> where W: Write, R: message::ReaderSegments + ?Sized { let mut buf: [u8; 8] = [0; 8]; let segment_count = segments.len(); @@ -343,7 +344,7 @@ where W: Write, R: message::ReaderSegments + ?Sized { } /// Writes segments to `write`. -fn write_segments(write: &mut W, segments: &R) -> ::std::io::Result<()> +fn write_segments(write: &mut W, segments: &R) -> Result<()> where W: Write { for i in 0.. { if let Some(segment) = segments.get_segment(i) { @@ -375,7 +376,9 @@ pub fn compute_serialized_size_in_words(message: &crate::message::Builder) #[cfg(test)] pub mod test { - use std::io::Write; + use alloc::vec::Vec; + + use crate::io::Write; use quickcheck::{quickcheck, TestResult}; diff --git a/capnp/src/serialize_packed.rs b/capnp/src/serialize_packed.rs index 37ef684b9..2a6f8c8b0 100644 --- a/capnp/src/serialize_packed.rs +++ b/capnp/src/serialize_packed.rs @@ -22,8 +22,9 @@ //! Reading and writing of messages using the //! [packed stream encoding](https://capnproto.org/encoding.html#packing). -use std::{io, mem, ptr, slice}; -use std::io::{Read, BufRead, Write}; +use alloc::string::ToString; +use core::{mem, ptr, slice}; +use crate::io::{Read, BufRead, Write}; use crate::serialize; use crate::Result; @@ -34,8 +35,7 @@ struct PackedRead where R: BufRead { } impl PackedRead where R: BufRead { - - fn get_read_buffer(&mut self) -> io::Result<(*const u8, *const u8)> { + fn get_read_buffer(&mut self) -> Result<(*const u8, *const u8)> { let buf = self.inner.fill_buf()?; Ok((buf.as_ptr(), buf.as_ptr().wrapping_offset(buf.len() as isize))) } @@ -57,19 +57,17 @@ macro_rules! refresh_buffer( $size = ptr_sub($in_end, $in_ptr); $buffer_begin = b; if $size == 0 { - return Err(io::Error::new(io::ErrorKind::Other, - "Premature end of packed input.")); + return Err(crate::Error::failed("Premature end of packed input.".to_string())); } } ); ); impl Read for PackedRead where R: BufRead { - - fn read(&mut self, out_buf: &mut [u8]) -> io::Result { + fn read_exact(&mut self, out_buf: &mut [u8]) -> Result<()> { let len = out_buf.len(); - if len == 0 { return Ok(0); } + if len == 0 { return Ok(()); } assert!(len % 8 == 0, "PackedRead reads must be word-aligned."); @@ -81,7 +79,7 @@ impl Read for PackedRead where R: BufRead { let mut buffer_begin = in_ptr; let mut size = ptr_sub(in_end, in_ptr); if size == 0 { - return Ok(0); + return Ok(()); } loop { @@ -141,8 +139,7 @@ impl Read for PackedRead where R: BufRead { in_ptr = in_ptr.offset(1); if run_length > ptr_sub(out_end, out) { - return Err(io::Error::new(io::ErrorKind::Other, - "Packed input did not end cleanly on a segment boundary.")); + return Err(crate::Error::failed("Packed input did not end cleanly on a segment boundary.".to_string())); } ptr::write_bytes(out, 0, run_length); @@ -156,8 +153,7 @@ impl Read for PackedRead where R: BufRead { in_ptr = in_ptr.offset(1); if run_length > ptr_sub(out_end, out) { - return Err(io::Error::new(io::ErrorKind::Other, - "Packed input did not end cleanly on a segment boundary.")); + return Err(crate::Error::failed("Packed input did not end cleanly on a segment boundary.".to_string())); } let in_remaining = ptr_sub(in_end, in_ptr); @@ -181,7 +177,7 @@ impl Read for PackedRead where R: BufRead { out = out.offset(run_length as isize); if out == out_end { - return Ok(len); + return Ok(()); } else { let (b, e) = self.get_read_buffer()?; in_ptr = b; @@ -195,7 +191,7 @@ impl Read for PackedRead where R: BufRead { if out == out_end { self.inner.consume(ptr_sub(in_ptr, buffer_begin)); - return Ok(len); + return Ok(()); } } } @@ -203,13 +199,13 @@ impl Read for PackedRead where R: BufRead { } /// Reads a packed message from a stream using the provided options. -pub fn read_message(read: &mut R, +pub fn read_message(read: R, options: message::ReaderOptions) -> Result> where R: BufRead { - let mut packed_read = PackedRead { inner: read }; - serialize::read_message(&mut packed_read, options) + let packed_read = PackedRead { inner: read }; + serialize::read_message(packed_read, options) } struct PackedWrite where W: Write { @@ -217,7 +213,7 @@ struct PackedWrite where W: Write { } impl Write for PackedWrite where W: Write { - fn write(&mut self, in_buf: &[u8]) -> io::Result { + fn write_all(&mut self, in_buf: &[u8]) -> Result<()> { unsafe { let mut buf_idx: usize = 0; let mut buf: [u8; 64] = [0; 64]; @@ -343,24 +339,25 @@ impl Write for PackedWrite where W: Write { } self.inner.write_all(&buf[..buf_idx])?; - Ok(in_buf.len()) + Ok(()) } } - - fn flush(&mut self) -> io::Result<()> { self.inner.flush() } } /// Writes a packed message to a stream. -pub fn write_message(write: &mut W, message: &crate::message::Builder) -> io::Result<()> +pub fn write_message(write: W, message: &crate::message::Builder) -> Result<()> where W: Write, A: crate::message::Allocator { - let mut packed_write = PackedWrite { inner: write }; - serialize::write_message(&mut packed_write, message) + let packed_write = PackedWrite { inner: write }; + serialize::write_message(packed_write, message) } #[cfg(test)] mod tests { - use std::io::{Write, Read}; + use alloc::string::ToString; + use alloc::vec::Vec; + + use crate::io::{Write, Read}; use quickcheck::{quickcheck, TestResult}; @@ -375,8 +372,7 @@ mod tests { let mut bytes: Vec = vec![0; unpacked.len()]; packed_read.read_exact(&mut bytes[..]).unwrap(); - let mut buf = [0; 8]; - assert_eq!(packed_read.read(&mut buf).unwrap(), 0); // EOF + assert!(packed_read.inner.is_empty()); // nothing left to read assert_eq!(bytes, unpacked); } @@ -387,7 +383,7 @@ mod tests { let mut bytes: Vec = vec![0; packed.len()]; { let mut packed_write = PackedWrite { inner: &mut bytes[..] }; - packed_write.write(unpacked).unwrap(); + packed_write.write_all(unpacked).unwrap(); } assert_eq!(bytes, packed); @@ -471,7 +467,7 @@ mod tests { Ok(_) => panic!("should have been an error"), Err(e) => { assert_eq!(e.to_string(), - "Packed input did not end cleanly on a segment boundary."); + "Failed: Packed input did not end cleanly on a segment boundary."); } } } @@ -485,7 +481,7 @@ mod tests { match packed_read.read_exact(&mut bytes[..]) { Ok(_) => panic!("should have been an error"), Err(e) => { - assert_eq!(e.to_string(), "Premature end of packed input."); + assert_eq!(e.to_string(), "Failed: Premature end of packed input."); } } } diff --git a/capnp/src/struct_list.rs b/capnp/src/struct_list.rs index 1e9b7f47a..c3d29c007 100644 --- a/capnp/src/struct_list.rs +++ b/capnp/src/struct_list.rs @@ -21,7 +21,7 @@ //! List of structs. -use std::marker::PhantomData; +use core::marker::PhantomData; use crate::private::layout::{ListReader, ListBuilder, PointerReader, PointerBuilder, InlineComposite}; use crate::traits::{FromPointerReader, FromPointerBuilder, @@ -171,7 +171,7 @@ impl <'a, T> crate::traits::SetPointerBuilder> 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: for<'b> crate::traits::OwnedStruct<'b> { type Item = >::Reader; diff --git a/capnp/src/text.rs b/capnp/src/text.rs index a5fdd7198..ce26957f9 100644 --- a/capnp/src/text.rs +++ b/capnp/src/text.rs @@ -21,7 +21,7 @@ //! UTF-8 encoded text. -use std::{convert, str, ops}; +use core::{convert, str, ops}; use crate::{Error, Result}; diff --git a/capnp/src/text_list.rs b/capnp/src/text_list.rs index bddf3079f..fab73385f 100644 --- a/capnp/src/text_list.rs +++ b/capnp/src/text_list.rs @@ -129,7 +129,7 @@ impl <'a> crate::traits::SetPointerBuilder> for Reader<'a> { } } -impl <'a> ::std::iter::IntoIterator for Reader<'a> { +impl <'a> ::core::iter::IntoIterator for Reader<'a> { type Item = Result>; type IntoIter = ListIter, Self::Item>; diff --git a/capnp/src/traits.rs b/capnp/src/traits.rs index aed1fee51..8e478512d 100644 --- a/capnp/src/traits.rs +++ b/capnp/src/traits.rs @@ -23,7 +23,7 @@ use crate::{Result}; use crate::private::layout::{CapTable, ListReader, StructReader, StructBuilder, StructSize, PointerBuilder, PointerReader}; -use std::marker::PhantomData; +use core::marker::PhantomData; pub trait FromStructReader<'a> { fn new(reader: StructReader<'a>) -> Self; @@ -100,7 +100,7 @@ pub trait ToU16 { } pub trait FromU16 : Sized { - fn from_u16(value: u16) -> ::std::result::Result; + fn from_u16(value: u16) -> ::core::result::Result; } pub trait IndexMove { @@ -120,9 +120,9 @@ impl ListIter{ } } -impl > ::std::iter::Iterator for ListIter { +impl > ::core::iter::Iterator for ListIter { type Item = U; - fn next(&mut self) -> ::std::option::Option { + fn next(&mut self) -> ::core::option::Option { if self.index < self.size { let result = self.list.index_move(self.index); self.index += 1; @@ -149,14 +149,14 @@ impl > ::std::iter::Iterator for ListIter { } } -impl > ::std::iter::ExactSizeIterator for ListIter{ +impl > ::core::iter::ExactSizeIterator for ListIter{ fn len(&self) -> usize{ self.size as usize } } -impl > ::std::iter::DoubleEndedIterator for ListIter{ - fn next_back(&mut self) -> ::std::option::Option { +impl > ::core::iter::DoubleEndedIterator for ListIter{ + fn next_back(&mut self) -> ::core::option::Option { if self.size > self.index { self.size -= 1; Some(self.list.index_move(self.size)) diff --git a/capnpc/Cargo.toml b/capnpc/Cargo.toml index f088eb156..de5765e63 100644 --- a/capnpc/Cargo.toml +++ b/capnpc/Cargo.toml @@ -23,6 +23,17 @@ path = "src/lib.rs" name = "capnpc-rust" path = "src/capnpc-rust.rs" -[dependencies] -capnp = { version = "0.13.0-alpha", path = "../capnp" } - +[dependencies.capnp] +version = "0.13.0-alpha" +path = "../capnp" + +# Don't include "std" feature, so that dependent crates can include a build-time +# capnpc dependency still use capnp with no-std. +# +# This might not be necessary in the future, if cargo supports separate feature sets for +# build and main dependencies: https://github.com/rust-lang/cargo/issues/7915 +# +# Doing this forces capnpc to define its own mapping from std::io::Read to capnp::io::Read. +# Fortunately, this is pretty easy, and is just an internal implementation detail. +default-features=false +features=[] diff --git a/capnpc/src/codegen.rs b/capnpc/src/codegen.rs index 02b5a3e2d..fa2abfa66 100644 --- a/capnpc/src/codegen.rs +++ b/capnpc/src/codegen.rs @@ -25,6 +25,7 @@ use std::collections::HashSet; use capnp; use capnp::Error; +use crate::{convert_io_err}; use crate::pointer_constants::generate_pointer_constant; use crate::schema_capnp; use crate::codegen_types::{ Leaf, RustTypeInfo, RustNodeInfo, TypeParameterTexts, do_branding }; @@ -451,7 +452,7 @@ pub fn getter_text(gen: &GeneratorContext, let default_name = format!("DEFAULT_{}", snake_to_upper_case(&camel_to_snake_case(get_field_name(*field)?))); let mut result_type = match raw_type.which()? { - type_::Enum(_) => format!("::std::result::Result<{},::capnp::NotInSchema>", typ), + type_::Enum(_) => format!("::core::result::Result<{},::capnp::NotInSchema>", typ), type_::AnyPointer(_) if !raw_type.is_parameter()? => typ.clone(), type_::Interface(_) => { format!("::capnp::Result<{}>", raw_type.type_string(gen, Leaf::Client)?) @@ -518,7 +519,7 @@ pub fn getter_text(gen: &GeneratorContext, crate::pointer_constants::WordArrayDeclarationOptions {public: true, omit_first_word: false})?); format!("Some(&_private::{}[..])", default_name) } else { - "::std::option::Option::None".to_string() + "::core::option::Option::None".to_string() }; if is_reader { @@ -533,7 +534,7 @@ pub fn getter_text(gen: &GeneratorContext, } (type_::Interface(_), value::Interface(_)) => { - Line(format!("match self.{}.get_pointer_field({}).get_capability() {{ ::std::result::Result::Ok(c) => ::std::result::Result::Ok(::capnp::capability::FromClientHook::new(c)), ::std::result::Result::Err(e) => ::std::result::Result::Err(e)}}", + Line(format!("match self.{}.get_pointer_field({}).get_capability() {{ ::core::result::Result::Ok(c) => ::core::result::Result::Ok(::capnp::capability::FromClientHook::new(c)), ::core::result::Result::Err(e) => ::core::result::Result::Err(e)}}", member, offset)) } (type_::AnyPointer(_), value::AnyPointer(_)) => { @@ -541,9 +542,9 @@ pub fn getter_text(gen: &GeneratorContext, Line(format!("::capnp::any_pointer::{}::new(self.{}.get_pointer_field({}))", module_string, member, offset)) } else { if is_reader { - Line(format!("::capnp::traits::FromPointerReader::get_from_pointer(&self.{}.get_pointer_field({}), ::std::option::Option::None)", member, offset)) + Line(format!("::capnp::traits::FromPointerReader::get_from_pointer(&self.{}.get_pointer_field({}), ::core::option::Option::None)", member, offset)) } else { - Line(format!("::capnp::traits::FromPointerBuilder::get_from_pointer(self.{}.get_pointer_field({}), ::std::option::Option::None)", member, offset)) + Line(format!("::capnp::traits::FromPointerBuilder::get_from_pointer(self.{}.get_pointer_field({}), ::core::option::Option::None)", member, offset)) } } } @@ -865,7 +866,7 @@ fn generate_union(gen: &GeneratorContext, getter_interior.push(Branch(vec![ Line(format!("{} => {{", dvalue)), - Indent(Box::new(Line(format!("::std::result::Result::Ok({}(", enumerant_name.clone())))), + Indent(Box::new(Line(format!("::core::result::Result::Ok({}(", enumerant_name.clone())))), Indent(Box::new(Indent(Box::new(get)))), Indent(Box::new(Line("))".to_string()))), Line("}".to_string()) @@ -901,7 +902,7 @@ fn generate_union(gen: &GeneratorContext, else {"".to_string()} ); - getter_interior.push(Line("x => ::std::result::Result::Err(::capnp::NotInSchema(x))".to_string())); + getter_interior.push(Line("x => ::core::result::Result::Err(::capnp::NotInSchema(x))".to_string())); interior.push( Branch(vec!(Line(format!("pub enum {} {{", enum_name)), @@ -925,7 +926,7 @@ fn generate_union(gen: &GeneratorContext, let getter_result = Branch(vec!(Line("#[inline]".to_string()), - Line(format!("pub fn which(self) -> ::std::result::Result<{}, ::capnp::NotInSchema> {{", + Line(format!("pub fn which(self) -> ::core::result::Result<{}, ::capnp::NotInSchema> {{", concrete_type)), Indent(Box::new(Branch(vec!( Line(format!("match self.{}.get_data_field::({}) {{", field_name, doffset)), @@ -1276,8 +1277,8 @@ fn generate_node(gen: &GeneratorContext, Line(format!("fn init_pointer(builder: ::capnp::private::layout::PointerBuilder<'a>, _size: u32) -> Builder<'a,{}> {{", params.params)), Indent(Box::new(Line("::capnp::traits::FromStructBuilder::new(builder.init_struct(_private::STRUCT_SIZE))".to_string()))), Line("}".to_string()), - Line(format!("fn get_from_pointer(builder: ::capnp::private::layout::PointerBuilder<'a>, default: ::std::option::Option<&'a [capnp::Word]>) -> ::capnp::Result> {{", params.params)), - Indent(Box::new(Line("::std::result::Result::Ok(::capnp::traits::FromStructBuilder::new(builder.get_struct(_private::STRUCT_SIZE, default)?))".to_string()))), + Line(format!("fn get_from_pointer(builder: ::capnp::private::layout::PointerBuilder<'a>, default: ::core::option::Option<&'a [capnp::Word]>) -> ::capnp::Result> {{", params.params)), + Indent(Box::new(Line("::core::result::Result::Ok(::capnp::traits::FromStructBuilder::new(builder.get_struct(_private::STRUCT_SIZE, default)?))".to_string()))), Line("}".to_string()))))), Line("}".to_string()), BlankLine]); @@ -1340,8 +1341,8 @@ fn generate_node(gen: &GeneratorContext, params.params, params.where_clause)), Indent( Box::new(Branch(vec!( - Line(format!("fn get_from_pointer(reader: &::capnp::private::layout::PointerReader<'a>, default: ::std::option::Option<&'a [capnp::Word]>) -> ::capnp::Result> {{",params.params)), - Indent(Box::new(Line("::std::result::Result::Ok(::capnp::traits::FromStructReader::new(reader.get_struct(default)?))".to_string()))), + Line(format!("fn get_from_pointer(reader: &::capnp::private::layout::PointerReader<'a>, default: ::core::option::Option<&'a [capnp::Word]>) -> ::capnp::Result> {{",params.params)), + Indent(Box::new(Line("::core::result::Result::Ok(::capnp::traits::FromStructReader::new(reader.get_struct(default)?))".to_string()))), Line("}".to_string()))))), Line("}".to_string()), BlankLine, @@ -1490,9 +1491,9 @@ fn generate_node(gen: &GeneratorContext, let enumerant = capitalize_first_letter(get_enumerant_name(enumerants.get(ii))?); members.push(Line(format!("{} = {},", enumerant, ii))); match_branches.push( - Line(format!("{} => ::std::result::Result::Ok({}::{}),", ii, last_name, enumerant))); + Line(format!("{} => ::core::result::Result::Ok({}::{}),", ii, last_name, enumerant))); } - match_branches.push(Line("n => ::std::result::Result::Err(::capnp::NotInSchema(n)),".to_string())); + match_branches.push(Line("n => ::core::result::Result::Err(::capnp::NotInSchema(n)),".to_string())); output.push(Branch(vec!( Line("#[repr(u16)]".to_string()), @@ -1508,7 +1509,7 @@ fn generate_node(gen: &GeneratorContext, Indent( Box::new(Branch(vec![ Line(format!( - "fn from_u16(value: u16) -> ::std::result::Result<{}, ::capnp::NotInSchema> {{", + "fn from_u16(value: u16) -> ::core::result::Result<{}, ::capnp::NotInSchema> {{", last_name)), Indent( Box::new(Branch(vec![ @@ -1681,8 +1682,8 @@ fn generate_node(gen: &GeneratorContext, params.params, params.where_clause)), Indent( Box::new(Branch(vec![ - Line(format!("fn get_from_pointer(reader: &::capnp::private::layout::PointerReader<'a>, _default: ::std::option::Option<&'a [capnp::Word]>) -> ::capnp::Result> {{",params.params)), - Indent(Box::new(Line(format!("::std::result::Result::Ok(::capnp::capability::FromClientHook::new(reader.get_capability()?))")))), + Line(format!("fn get_from_pointer(reader: &::capnp::private::layout::PointerReader<'a>, _default: ::core::option::Option<&'a [capnp::Word]>) -> ::capnp::Result> {{",params.params)), + Indent(Box::new(Line(format!("::core::result::Result::Ok(::capnp::capability::FromClientHook::new(reader.get_capability()?))")))), Line("}".to_string())]))), Line("}".to_string())))); @@ -1695,8 +1696,8 @@ fn generate_node(gen: &GeneratorContext, Line(format!("fn init_pointer(_builder: ::capnp::private::layout::PointerBuilder<'a>, _size: u32) -> Client<{}> {{", params.params)), Indent(Box::new(Line("unimplemented!()".to_string()))), Line("}".to_string()), - Line(format!("fn get_from_pointer(builder: ::capnp::private::layout::PointerBuilder<'a>, _default: ::std::option::Option<&'a [capnp::Word]>) -> ::capnp::Result> {{", params.params)), - Indent(Box::new(Line("::std::result::Result::Ok(::capnp::capability::FromClientHook::new(builder.get_capability()?))".to_string()))), + Line(format!("fn get_from_pointer(builder: ::capnp::private::layout::PointerBuilder<'a>, _default: ::core::option::Option<&'a [capnp::Word]>) -> ::capnp::Result> {{", params.params)), + Indent(Box::new(Line("::core::result::Result::Ok(::capnp::capability::FromClientHook::new(builder.get_capability()?))".to_string()))), Line("}".to_string())]))), Line("}".to_string()), BlankLine])); @@ -1713,7 +1714,7 @@ fn generate_node(gen: &GeneratorContext, Indent(Box::new(Line( "pointer.set_capability(from.client.hook);".to_string()))), Indent(Box::new(Line( - "::std::result::Result::Ok(())".to_string()))), + "::core::result::Result::Ok(())".to_string()))), Line("}".to_string())]))), Line("}".to_string())])); @@ -1755,7 +1756,7 @@ fn generate_node(gen: &GeneratorContext, Indent(Box::new(Branch(vec![ Line(format!("type Dispatch = ServerDispatch<_S, {}>;", params.params)), Line(format!("fn from_server(s: _S) -> ServerDispatch<_S, {}> {{", params.params)), - Indent(Box::new(Line(format!("ServerDispatch {{ server: ::std::boxed::Box::new(s), {} }}", params.phantom_data_value)))), + Indent(Box::new(Line(format!("ServerDispatch {{ server: ::capnp::private::new_box(s), {} }}", params.phantom_data_value)))), Line("}".to_string()), ]))), Line("}".to_string()), @@ -1764,9 +1765,9 @@ fn generate_node(gen: &GeneratorContext, mod_interior.push( Branch(vec![ (if is_generic { - Line(format!("impl <{}, _T: Server{}> ::std::ops::Deref for ServerDispatch<_T,{}> {} {{", params.params, bracketed_params, params.params, params.where_clause)) + Line(format!("impl <{}, _T: Server{}> ::core::ops::Deref for ServerDispatch<_T,{}> {} {{", params.params, bracketed_params, params.params, params.where_clause)) } else { - Line("impl <_T: Server> ::std::ops::Deref for ServerDispatch<_T> {".to_string()) + Line("impl <_T: Server> ::core::ops::Deref for ServerDispatch<_T> {".to_string()) }), Indent(Box::new(Line("type Target = _T;".to_string()))), Indent(Box::new(Line("fn deref(&self) -> &_T { &self.server}".to_string()))), @@ -1776,9 +1777,9 @@ fn generate_node(gen: &GeneratorContext, mod_interior.push( Branch(vec![ (if is_generic { - Line(format!("impl <{}, _T: Server{}> ::std::ops::DerefMut for ServerDispatch<_T,{}> {} {{", params.params, bracketed_params, params.params, params.where_clause)) + Line(format!("impl <{}, _T: Server{}> ::core::ops::DerefMut for ServerDispatch<_T,{}> {} {{", params.params, bracketed_params, params.params, params.where_clause)) } else { - Line("impl <_T: Server> ::std::ops::DerefMut for ServerDispatch<_T> {".to_string()) + Line("impl <_T: Server> ::core::ops::DerefMut for ServerDispatch<_T> {".to_string()) }), Indent(Box::new(Line("fn deref_mut(&mut self) -> &mut _T { &mut self.server}".to_string()))), Line("}".to_string()), @@ -1911,14 +1912,26 @@ fn generate_node(gen: &GeneratorContext, Ok(Branch(output)) } +// The capnp crate defines a blanket impl of capnp::Read for R where R: std::io::Read, +// but we can't use that here because it lives behind the "std" feature flag. +struct ReadWrapper where R: std::io::Read { + inner: R, +} + +impl capnp::io::Read for ReadWrapper where R: std::io::Read { + fn read_exact(&mut self, buf: &mut [u8]) -> capnp::Result<()> { + std::io::Read::read_exact(&mut self.inner, buf).map_err(convert_io_err) + } +} + /// Generates Rust code according to a `schema_capnp::code_generator_request` read from `inp`. -pub fn generate_code(mut inp: T, out_dir: &::std::path::Path) -> ::capnp::Result<()> +pub fn generate_code(inp: T, out_dir: &::std::path::Path) -> ::capnp::Result<()> where T: ::std::io::Read { use capnp::serialize; use std::io::Write; - let message = serialize::read_message(&mut inp, capnp::message::ReaderOptions::new())?; + let message = serialize::read_message(ReadWrapper { inner: inp }, capnp::message::ReaderOptions::new())?; let gen = GeneratorContext::new(&message)?; @@ -1928,7 +1941,7 @@ pub fn generate_code(mut inp: T, out_dir: &::std::path::Path) -> ::capnp::Res let requested = ::std::path::PathBuf::from(requested_file.get_filename()?); filepath.push(requested); if let Some(parent) = filepath.parent() { - ::std::fs::create_dir_all(parent)?; + ::std::fs::create_dir_all(parent).map_err(convert_io_err)?; } let root_name = path_to_stem_string(&filepath)?.replace("-", "_"); @@ -1956,12 +1969,12 @@ pub fn generate_code(mut inp: T, out_dir: &::std::path::Path) -> ::capnp::Res // would not include `filepath`. match ::std::fs::File::create(&filepath) { Ok(ref mut writer) => { - writer.write_all(text.as_bytes())?; + writer.write_all(text.as_bytes()).map_err(convert_io_err)?; } Err(e) => { let _ = writeln!(&mut ::std::io::stderr(), "could not open file {:?} for writing: {}", filepath, e); - return Err(e.into()); + return Err(convert_io_err(e)); } } } diff --git a/capnpc/src/codegen_types.rs b/capnpc/src/codegen_types.rs index c0742089e..a6545c668 100644 --- a/capnpc/src/codegen_types.rs +++ b/capnpc/src/codegen_types.rs @@ -116,11 +116,11 @@ impl <'a> RustNodeInfo for node::Reader<'a> { }).collect::>().join(", ") + " "); let phantom_data_type = if params.len() == 1 { // omit parens to avoid linter error - format!("_phantom: ::std::marker::PhantomData<{}>", type_parameters) + format!("_phantom: ::core::marker::PhantomData<{}>", type_parameters) } else { - format!("_phantom: ::std::marker::PhantomData<({})>", type_parameters) + format!("_phantom: ::core::marker::PhantomData<({})>", type_parameters) }; - let phantom_data_value = "_phantom: ::std::marker::PhantomData,".to_string(); + let phantom_data_value = "_phantom: ::core::marker::PhantomData,".to_string(); TypeParameterTexts { expanded_list: params, diff --git a/capnpc/src/lib.rs b/capnpc/src/lib.rs index 85ce43882..1292094cf 100644 --- a/capnpc/src/lib.rs +++ b/capnpc/src/lib.rs @@ -70,10 +70,26 @@ mod pointer_constants; use std::path::{Path, PathBuf}; +// Copied from capnp/src/lib.rs, where this conversion lives behind the "std" feature flag, +// which we don't want to depend on here. +pub(crate) fn convert_io_err(err: std::io::Error) -> capnp::Error { + use std::io; + let kind = match err.kind() { + io::ErrorKind::TimedOut => capnp::ErrorKind::Overloaded, + io::ErrorKind::BrokenPipe | + io::ErrorKind::ConnectionRefused | + io::ErrorKind::ConnectionReset | + io::ErrorKind::ConnectionAborted | + io::ErrorKind::NotConnected => capnp::ErrorKind::Disconnected, + _ => capnp::ErrorKind::Failed, + }; + capnp::Error { description: format!("{}", err), kind: kind } +} + fn run_command(mut command: ::std::process::Command, path: &PathBuf) -> ::capnp::Result<()> { - let mut p = command.spawn()?; + let mut p = command.spawn().map_err(convert_io_err)?; crate::codegen::generate_code(p.stdout.take().unwrap(), path.as_path())?; - let exit_status = p.wait()?; + let exit_status = p.wait().map_err(convert_io_err)?; if !exit_status.success() { Err(::capnp::Error::failed(format!( "Non-success exit status: {}", diff --git a/capnpc/test/test.rs b/capnpc/test/test.rs index 6c9d5f3ab..1aa257559 100644 --- a/capnpc/test/test.rs +++ b/capnpc/test/test.rs @@ -19,6 +19,8 @@ // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN // THE SOFTWARE. +extern crate core; + extern crate capnp; pub mod test_capnp { diff --git a/example/addressbook/addressbook.rs b/example/addressbook/addressbook.rs index 803b93934..c13b0461d 100644 --- a/example/addressbook/addressbook.rs +++ b/example/addressbook/addressbook.rs @@ -20,6 +20,8 @@ // THE SOFTWARE. extern crate capnp; +extern crate core; + pub mod addressbook_capnp { include!(concat!(env!("OUT_DIR"), "/addressbook_capnp.rs")); } @@ -28,7 +30,7 @@ pub mod addressbook { use addressbook_capnp::{address_book, person}; use capnp::serialize_packed; - pub fn write_address_book() -> ::std::io::Result<()> { + pub fn write_address_book() -> ::capnp::Result<()> { let mut message = ::capnp::message::Builder::new_default(); { let address_book = message.init_root::(); @@ -68,7 +70,6 @@ pub mod addressbook { } pub fn print_address_book() -> ::capnp::Result<()> { - let stdin = ::std::io::stdin(); let message_reader = serialize_packed::read_message(&mut stdin.lock(), ::capnp::message::ReaderOptions::new())?; diff --git a/example/addressbook_send/addressbook_send.rs b/example/addressbook_send/addressbook_send.rs index 265100ad6..665e3eb99 100644 --- a/example/addressbook_send/addressbook_send.rs +++ b/example/addressbook_send/addressbook_send.rs @@ -20,6 +20,8 @@ // THE SOFTWARE. extern crate capnp; +extern crate core; + pub mod addressbook_capnp { include!(concat!(env!("OUT_DIR"), "/addressbook_capnp.rs")); }