From 873a1b745106ca627982b90ed1337391f3f7b066 Mon Sep 17 00:00:00 2001 From: Ariel Miculas Date: Thu, 29 Jun 2023 17:11:23 +0300 Subject: [PATCH] Add cfg(feature=alloc) guards This allows us to compile capnproto in no-alloc environments. --- capnp/src/any_pointer.rs | 18 ++- capnp/src/any_pointer_list.rs | 2 + capnp/src/capability.rs | 1 + capnp/src/capability_list.rs | 1 + capnp/src/data.rs | 2 + capnp/src/data_list.rs | 2 + capnp/src/dynamic_list.rs | 1 + capnp/src/dynamic_struct.rs | 1 + capnp/src/dynamic_value.rs | 1 + capnp/src/enum_list.rs | 2 + capnp/src/introspect.rs | 2 + capnp/src/io.rs | 1 + capnp/src/lib.rs | 8 + capnp/src/list_list.rs | 2 + capnp/src/message.rs | 35 +++- capnp/src/primitive_list.rs | 2 + capnp/src/private/arena.rs | 18 ++- capnp/src/private/capability.rs | 1 + capnp/src/private/layout.rs | 150 +++++++++++++++--- capnp/src/schema.rs | 1 + capnp/src/serialize.rs | 36 ++++- .../src/serialize/no_alloc_slice_segments.rs | 17 +- capnp/src/serialize_packed.rs | 6 + capnp/src/stringify.rs | 1 + capnp/src/struct_list.rs | 2 + capnp/src/text.rs | 2 + capnp/src/text_list.rs | 2 + capnp/src/traits.rs | 6 +- capnp/tests/canonicalize.rs | 11 ++ 29 files changed, 302 insertions(+), 32 deletions(-) diff --git a/capnp/src/any_pointer.rs b/capnp/src/any_pointer.rs index c75228246..d93462d64 100644 --- a/capnp/src/any_pointer.rs +++ b/capnp/src/any_pointer.rs @@ -21,10 +21,12 @@ //! Untyped pointer that can be cast to any struct, list, or capability type. -use alloc::boxed::Box; -use alloc::vec::Vec; +#[cfg(feature = "alloc")] +use alloc::{boxed::Box, vec::Vec}; +#[cfg(feature = "alloc")] use crate::capability::FromClientHook; +#[cfg(feature = "alloc")] use crate::private::capability::{ClientHook, PipelineHook, PipelineOp}; use crate::private::layout::{PointerBuilder, PointerReader}; use crate::traits::{FromPointerBuilder, FromPointerReader, SetPointerBuilder}; @@ -44,6 +46,7 @@ impl crate::introspect::Introspect for Owned { } } +#[cfg(feature = "alloc")] impl crate::traits::Pipelined for Owned { type Pipeline = Pipeline; } @@ -73,12 +76,14 @@ impl<'a> Reader<'a> { FromPointerReader::get_from_pointer(&self.reader, None) } + #[cfg(feature = "alloc")] pub fn get_as_capability(&self) -> Result { Ok(FromClientHook::new(self.reader.get_capability()?)) } //# Used by RPC system to implement pipelining. Applications //# generally shouldn't use this directly. + #[cfg(feature = "alloc")] pub fn get_pipelined_cap(&self, ops: &[PipelineOp]) -> Result> { let mut pointer = self.reader; @@ -117,6 +122,7 @@ impl<'a> crate::traits::SetPointerBuilder for Reader<'a> { } } +#[cfg(feature = "alloc")] impl<'a> crate::traits::Imbue<'a> for Reader<'a> { fn imbue(&mut self, cap_table: &'a crate::private::layout::CapTable) { self.reader @@ -165,6 +171,7 @@ impl<'a> Builder<'a> { } // XXX value should be a user client. + #[cfg(feature = "alloc")] pub fn set_as_capability(&mut self, value: Box) { self.builder.set_capability(value); } @@ -199,6 +206,7 @@ impl<'a> FromPointerBuilder<'a> for Builder<'a> { } } +#[cfg(feature = "alloc")] impl<'a> crate::traits::ImbueMut<'a> for Builder<'a> { fn imbue_mut(&mut self, cap_table: &'a mut crate::private::layout::CapTable) { self.builder @@ -206,6 +214,7 @@ impl<'a> crate::traits::ImbueMut<'a> for Builder<'a> { } } +#[cfg(feature = "alloc")] pub struct Pipeline { // XXX this should not be public pub hook: Box, @@ -213,6 +222,7 @@ pub struct Pipeline { ops: Vec, } +#[cfg(feature = "alloc")] impl Pipeline { pub fn new(hook: Box) -> Self { Self { @@ -245,24 +255,28 @@ impl Pipeline { } } +#[cfg(feature = "alloc")] impl crate::capability::FromTypelessPipeline for Pipeline { fn new(typeless: Pipeline) -> Self { typeless } } +#[cfg(feature = "alloc")] impl<'a> From> for crate::dynamic_value::Reader<'a> { fn from(a: Reader<'a>) -> crate::dynamic_value::Reader<'a> { crate::dynamic_value::Reader::AnyPointer(a) } } +#[cfg(feature = "alloc")] impl<'a> From> for crate::dynamic_value::Builder<'a> { fn from(a: Builder<'a>) -> crate::dynamic_value::Builder<'a> { crate::dynamic_value::Builder::AnyPointer(a) } } +#[cfg(feature = "alloc")] #[test] fn init_clears_value() { let mut message = crate::message::Builder::new_default(); diff --git a/capnp/src/any_pointer_list.rs b/capnp/src/any_pointer_list.rs index 1c4e9e40c..9c2c63adf 100644 --- a/capnp/src/any_pointer_list.rs +++ b/capnp/src/any_pointer_list.rs @@ -189,6 +189,7 @@ impl<'a> core::iter::IntoIterator for Reader<'a> { } } +#[cfg(feature = "alloc")] impl<'a> From> for crate::dynamic_value::Reader<'a> { fn from(t: Reader<'a>) -> crate::dynamic_value::Reader<'a> { crate::dynamic_value::Reader::List(crate::dynamic_list::Reader::new( @@ -198,6 +199,7 @@ impl<'a> From> for crate::dynamic_value::Reader<'a> { } } +#[cfg(feature = "alloc")] impl<'a> From> for crate::dynamic_value::Builder<'a> { fn from(t: Builder<'a>) -> crate::dynamic_value::Builder<'a> { crate::dynamic_value::Builder::List(crate::dynamic_list::Builder::new( diff --git a/capnp/src/capability.rs b/capnp/src/capability.rs index 9d72aafe5..7c6d2b072 100644 --- a/capnp/src/capability.rs +++ b/capnp/src/capability.rs @@ -22,6 +22,7 @@ //! Hooks for for the RPC system. //! //! Roughly corresponds to capability.h in the C++ implementation. +#![cfg(feature = "alloc")] use alloc::boxed::Box; use core::future::Future; diff --git a/capnp/src/capability_list.rs b/capnp/src/capability_list.rs index 740d21ebb..bca9d2380 100644 --- a/capnp/src/capability_list.rs +++ b/capnp/src/capability_list.rs @@ -19,6 +19,7 @@ // THE SOFTWARE. //! List of capabilities. +#![cfg(feature = "alloc")] use alloc::boxed::Box; use core::marker::PhantomData; diff --git a/capnp/src/data.rs b/capnp/src/data.rs index 89e0c6c19..4e8c49d96 100644 --- a/capnp/src/data.rs +++ b/capnp/src/data.rs @@ -82,12 +82,14 @@ impl<'a> crate::traits::SetPointerBuilder for Reader<'a> { } } +#[cfg(feature = "alloc")] impl<'a> From> for crate::dynamic_value::Reader<'a> { fn from(d: Reader<'a>) -> crate::dynamic_value::Reader<'a> { crate::dynamic_value::Reader::Data(d) } } +#[cfg(feature = "alloc")] impl<'a> From> for crate::dynamic_value::Builder<'a> { fn from(d: Builder<'a>) -> crate::dynamic_value::Builder<'a> { crate::dynamic_value::Builder::Data(d) diff --git a/capnp/src/data_list.rs b/capnp/src/data_list.rs index f5fee2575..042e4e895 100644 --- a/capnp/src/data_list.rs +++ b/capnp/src/data_list.rs @@ -199,6 +199,7 @@ impl<'a> ::core::iter::IntoIterator for Reader<'a> { } } +#[cfg(feature = "alloc")] impl<'a> From> for crate::dynamic_value::Reader<'a> { fn from(t: Reader<'a>) -> crate::dynamic_value::Reader<'a> { crate::dynamic_value::Reader::List(crate::dynamic_list::Reader { @@ -208,6 +209,7 @@ impl<'a> From> for crate::dynamic_value::Reader<'a> { } } +#[cfg(feature = "alloc")] impl<'a> From> for crate::dynamic_value::Builder<'a> { fn from(t: Builder<'a>) -> crate::dynamic_value::Builder<'a> { crate::dynamic_value::Builder::List(crate::dynamic_list::Builder { diff --git a/capnp/src/dynamic_list.rs b/capnp/src/dynamic_list.rs index 4a17e3503..bfc83ae25 100644 --- a/capnp/src/dynamic_list.rs +++ b/capnp/src/dynamic_list.rs @@ -1,5 +1,6 @@ //! Dynamically-typed lists. +#![cfg(feature = "alloc")] use crate::dynamic_value; use crate::introspect::{Type, TypeVariant}; use crate::private::layout::{self, PrimitiveElement}; diff --git a/capnp/src/dynamic_struct.rs b/capnp/src/dynamic_struct.rs index 76995cf97..6db952f01 100644 --- a/capnp/src/dynamic_struct.rs +++ b/capnp/src/dynamic_struct.rs @@ -1,5 +1,6 @@ //! Dynamically-typed structs. +#![cfg(feature = "alloc")] use crate::introspect::TypeVariant; use crate::private::layout; use crate::schema::{Field, StructSchema}; diff --git a/capnp/src/dynamic_value.rs b/capnp/src/dynamic_value.rs index 7cf5201ba..17fba9fab 100644 --- a/capnp/src/dynamic_value.rs +++ b/capnp/src/dynamic_value.rs @@ -1,5 +1,6 @@ //! Dynamically typed values. +#![cfg(feature = "alloc")] use crate::introspect::{self, TypeVariant}; use crate::schema_capnp::value; use crate::Result; diff --git a/capnp/src/enum_list.rs b/capnp/src/enum_list.rs index 8fa713029..1c8faeab2 100644 --- a/capnp/src/enum_list.rs +++ b/capnp/src/enum_list.rs @@ -214,6 +214,7 @@ impl<'a, T: TryFrom> ::core::iter::IntoIterator for Re } } +#[cfg(feature = "alloc")] impl<'a, T: TryFrom + crate::introspect::Introspect> From> for crate::dynamic_value::Reader<'a> { @@ -225,6 +226,7 @@ impl<'a, T: TryFrom + crate::introspect::Introspect> F } } +#[cfg(feature = "alloc")] impl<'a, T: TryFrom + crate::introspect::Introspect> From> for crate::dynamic_value::Builder<'a> { diff --git a/capnp/src/introspect.rs b/capnp/src/introspect.rs index b8b51e124..463b581bb 100644 --- a/capnp/src/introspect.rs +++ b/capnp/src/introspect.rs @@ -1,5 +1,6 @@ //! Traits and types to support run-time type introspection, i.e. reflection. +#[cfg(feature = "alloc")] use crate::private::layout::ElementSize; /// A type that supports reflection. All types that can appear in a Cap'n Proto message @@ -70,6 +71,7 @@ impl Type { /// If this type T appears as List(T), then what is the expected /// element size of the list? + #[cfg(feature = "alloc")] pub(crate) fn expected_element_size(&self) -> ElementSize { if self.list_count > 0 { ElementSize::Pointer diff --git a/capnp/src/io.rs b/capnp/src/io.rs index f9a81dd26..1698d08ae 100644 --- a/capnp/src/io.rs +++ b/capnp/src/io.rs @@ -105,6 +105,7 @@ mod no_std_impls { } } + #[cfg(feature = "alloc")] impl Write for alloc::vec::Vec { fn write_all(&mut self, buf: &[u8]) -> Result<()> { self.extend_from_slice(buf); diff --git a/capnp/src/lib.rs b/capnp/src/lib.rs index 1a42fa384..d7d3acee3 100644 --- a/capnp/src/lib.rs +++ b/capnp/src/lib.rs @@ -29,11 +29,13 @@ #![cfg_attr(feature = "rpc_try", feature(try_trait_v2))] #![cfg_attr(not(feature = "std"), no_std)] +#[cfg(feature = "alloc")] #[macro_use] extern crate alloc; /// Code generated from /// [schema.capnp](https://github.com/capnproto/capnproto/blob/master/c%2B%2B/src/capnp/schema.capnp). +#[cfg(feature = "alloc")] pub mod schema_capnp; pub mod any_pointer; @@ -65,6 +67,7 @@ pub mod traits; #[cfg(feature = "alloc")] use alloc::string::String; +#[cfg(feature = "alloc")] use alloc::vec::Vec; /// @@ -81,6 +84,7 @@ pub struct Word { /// /// Constructs a word with the given bytes. /// +#[allow(clippy::too_many_arguments)] pub const fn word(b0: u8, b1: u8, b2: u8, b3: u8, b4: u8, b5: u8, b6: u8, b7: u8) -> Word { Word { raw_content: [b0, b1, b2, b3, b4, b5, b6, b7], @@ -89,6 +93,7 @@ pub const fn word(b0: u8, b1: u8, b2: u8, b3: u8, b4: u8, b5: u8, b6: u8, b7: u8 impl Word { /// Allocates a vec of `length` words, all set to zero. + #[cfg(feature = "alloc")] pub fn allocate_zeroed_vec(length: usize) -> Vec { vec![word(0, 0, 0, 0, 0, 0, 0, 0); length] } @@ -589,11 +594,13 @@ impl ::std::error::Error for Error { /// Helper struct that allows `MessageBuilder::get_segments_for_output()` to avoid heap allocations /// in the single-segment case. +#[cfg(feature = "alloc")] pub enum OutputSegments<'a> { SingleSegment([&'a [u8]; 1]), MultiSegment(Vec<&'a [u8]>), } +#[cfg(feature = "alloc")] impl<'a> core::ops::Deref for OutputSegments<'a> { type Target = [&'a [u8]]; fn deref(&self) -> &[&'a [u8]] { @@ -604,6 +611,7 @@ impl<'a> core::ops::Deref for OutputSegments<'a> { } } +#[cfg(feature = "alloc")] impl<'s> message::ReaderSegments for OutputSegments<'s> { fn get_segment(&self, id: u32) -> Option<&[u8]> { match self { diff --git a/capnp/src/list_list.rs b/capnp/src/list_list.rs index 9c7349637..c55f921de 100644 --- a/capnp/src/list_list.rs +++ b/capnp/src/list_list.rs @@ -280,6 +280,7 @@ where } } +#[cfg(feature = "alloc")] impl<'a, T: crate::traits::Owned> From> for crate::dynamic_value::Reader<'a> { fn from(t: Reader<'a, T>) -> crate::dynamic_value::Reader<'a> { crate::dynamic_value::Reader::List(crate::dynamic_list::Reader::new( @@ -289,6 +290,7 @@ impl<'a, T: crate::traits::Owned> From> for crate::dynamic_value:: } } +#[cfg(feature = "alloc")] impl<'a, T: crate::traits::Owned> From> for crate::dynamic_value::Builder<'a> { fn from(t: Builder<'a, T>) -> crate::dynamic_value::Builder<'a> { crate::dynamic_value::Builder::List(crate::dynamic_list::Builder::new( diff --git a/capnp/src/message.rs b/capnp/src/message.rs index 7445b4e30..fe40e0a7c 100644 --- a/capnp/src/message.rs +++ b/capnp/src/message.rs @@ -68,15 +68,22 @@ //! } //! //! ``` +#[cfg(feature = "alloc")] use alloc::vec::Vec; use core::convert::From; use crate::any_pointer; -use crate::private::arena::{BuilderArena, BuilderArenaImpl, ReaderArena, ReaderArenaImpl}; +#[cfg(feature = "alloc")] +use crate::private::arena::{BuilderArena, BuilderArenaImpl}; +use crate::private::arena::{ReaderArena, ReaderArenaImpl}; use crate::private::layout; use crate::private::units::BYTES_PER_WORD; -use crate::traits::{FromPointerBuilder, FromPointerReader, Owned, SetPointerBuilder}; -use crate::{OutputSegments, Result}; +#[cfg(feature = "alloc")] +use crate::traits::{FromPointerBuilder, SetPointerBuilder}; +use crate::traits::{FromPointerReader, Owned}; +#[cfg(feature = "alloc")] +use crate::OutputSegments; +use crate::Result; /// Options controlling how data is read. #[derive(Clone, Copy, Debug)] @@ -275,6 +282,7 @@ where /// Gets the [canonical](https://capnproto.org/encoding.html#canonicalization) form /// of this message. Works by copying the message twice. For a canonicalization /// method that only requires one copy, see `message::Builder::set_root_canonical()`. + #[cfg(feature = "alloc")] pub fn canonicalize(&self) -> Result> { let root = self.get_root_internal()?; let size = root.target_size()?.word_count + 1; @@ -336,6 +344,7 @@ where } } +#[cfg(feature = "alloc")] impl From> for TypedReader, T> where A: Allocator, @@ -347,6 +356,7 @@ where } } +#[cfg(feature = "alloc")] impl From> for TypedReader, T> where A: Allocator, @@ -394,6 +404,7 @@ pub unsafe trait Allocator { } /// A container used to build a message. +#[cfg(feature = "alloc")] pub struct Builder where A: Allocator, @@ -401,8 +412,10 @@ where arena: BuilderArenaImpl, } +#[cfg(feature = "alloc")] unsafe impl Send for Builder where A: Send + Allocator {} +#[cfg(feature = "alloc")] fn _assert_kinds() { fn _assert_send() {} fn _assert_reader() { @@ -413,6 +426,7 @@ fn _assert_kinds() { } } +#[cfg(feature = "alloc")] impl Builder where A: Allocator, @@ -519,6 +533,7 @@ where } } +#[cfg(feature = "alloc")] impl ReaderSegments for Builder where A: Allocator, @@ -538,6 +553,7 @@ where /// - `T` - type of the capnp message which this builder is specialized on. Please see /// [module documentation](self) for more info about builder type specialization. /// - `A` - type of allocator +#[cfg(feature = "alloc")] pub struct TypedBuilder where T: Owned, @@ -547,6 +563,7 @@ where message: Builder, } +#[cfg(feature = "alloc")] impl TypedBuilder where T: Owned, @@ -556,6 +573,7 @@ where } } +#[cfg(feature = "alloc")] impl TypedBuilder where T: Owned, @@ -605,6 +623,7 @@ where } } +#[cfg(feature = "alloc")] impl From> for TypedBuilder where T: Owned, @@ -617,6 +636,7 @@ where /// Standard segment allocator. Allocates each segment via `alloc::alloc::alloc_zeroed()`. #[derive(Debug)] +#[cfg(feature = "alloc")] pub struct HeapAllocator { // Minimum number of words in the next allocation. next_size: u32, @@ -641,6 +661,7 @@ pub enum AllocationStrategy { pub const SUGGESTED_FIRST_SEGMENT_WORDS: u32 = 1024; pub const SUGGESTED_ALLOCATION_STRATEGY: AllocationStrategy = AllocationStrategy::GrowHeuristically; +#[cfg(feature = "alloc")] impl Default for HeapAllocator { fn default() -> Self { Self { @@ -651,6 +672,7 @@ impl Default for HeapAllocator { } } +#[cfg(feature = "alloc")] impl HeapAllocator { pub fn new() -> Self { Self::default() @@ -677,6 +699,7 @@ impl HeapAllocator { } } +#[cfg(feature = "alloc")] unsafe impl Allocator for HeapAllocator { fn allocate_segment(&mut self, minimum_size: u32) -> (*mut u8, u32) { let size = core::cmp::max(minimum_size, self.next_size); @@ -711,6 +734,7 @@ unsafe impl Allocator for HeapAllocator { } } +#[cfg(feature = "alloc")] #[test] fn test_allocate_max() { let allocation_size = 1 << 24; @@ -735,6 +759,7 @@ fn test_allocate_max() { } } +#[cfg(feature = "alloc")] impl Builder { /// Constructs a new `message::Builder` whose first segment has length /// `SUGGESTED_FIRST_SEGMENT_WORDS`. @@ -753,12 +778,14 @@ impl Builder { /// You can reuse a `ScratchSpaceHeapAllocator` by calling `message::Builder::into_allocator()`, /// or by initally passing it to `message::Builder::new()` as a `&mut ScratchSpaceHeapAllocator`. /// Such reuse can save significant amounts of zeroing. +#[cfg(feature = "alloc")] pub struct ScratchSpaceHeapAllocator<'a> { scratch_space: &'a mut [u8], scratch_space_allocated: bool, allocator: HeapAllocator, } +#[cfg(feature = "alloc")] impl<'a> ScratchSpaceHeapAllocator<'a> { /// Writes zeroes into the entire buffer and constructs a new allocator from it. /// @@ -805,6 +832,7 @@ impl<'a> ScratchSpaceHeapAllocator<'a> { } } +#[cfg(feature = "alloc")] unsafe impl<'a> Allocator for ScratchSpaceHeapAllocator<'a> { fn allocate_segment(&mut self, minimum_size: u32) -> (*mut u8, u32) { if (minimum_size as usize) < (self.scratch_space.len() / BYTES_PER_WORD) @@ -835,6 +863,7 @@ unsafe impl<'a> Allocator for ScratchSpaceHeapAllocator<'a> { } } +#[cfg(feature = "alloc")] unsafe impl<'a, A> Allocator for &'a mut A where A: Allocator, diff --git a/capnp/src/primitive_list.rs b/capnp/src/primitive_list.rs index 9468c05b5..a304b90c2 100644 --- a/capnp/src/primitive_list.rs +++ b/capnp/src/primitive_list.rs @@ -256,6 +256,7 @@ where } } +#[cfg(feature = "alloc")] impl<'a, T: PrimitiveElement + crate::introspect::Introspect> From> for crate::dynamic_value::Reader<'a> { @@ -267,6 +268,7 @@ impl<'a, T: PrimitiveElement + crate::introspect::Introspect> From } } +#[cfg(feature = "alloc")] impl<'a, T: PrimitiveElement + crate::introspect::Introspect> From> for crate::dynamic_value::Builder<'a> { diff --git a/capnp/src/private/arena.rs b/capnp/src/private/arena.rs index ce4071df5..46626c1f0 100644 --- a/capnp/src/private/arena.rs +++ b/capnp/src/private/arena.rs @@ -18,15 +18,21 @@ // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN // THE SOFTWARE. +#[cfg(feature = "alloc")] use alloc::vec::Vec; +#[cfg(feature = "alloc")] use core::slice; use core::u64; use crate::message; -use crate::message::{Allocator, ReaderSegments}; +#[cfg(feature = "alloc")] +use crate::message::Allocator; +use crate::message::ReaderSegments; use crate::private::read_limiter::ReadLimiter; use crate::private::units::*; -use crate::{Error, ErrorKind, OutputSegments, Result}; +#[cfg(feature = "alloc")] +use crate::OutputSegments; +use crate::{Error, ErrorKind, Result}; pub type SegmentId = u32; @@ -157,6 +163,7 @@ pub trait BuilderArena: ReaderArena { } /// A wrapper around a memory segment used in building a message. +#[cfg(feature = "alloc")] struct BuilderSegment { /// Pointer to the start of the segment. ptr: *mut u8, @@ -169,6 +176,7 @@ struct BuilderSegment { allocated: u32, } +#[cfg(feature = "alloc")] pub struct BuilderArenaImplInner where A: Allocator, @@ -179,6 +187,7 @@ where segments: Vec, } +#[cfg(feature = "alloc")] pub struct BuilderArenaImpl where A: Allocator, @@ -186,6 +195,7 @@ where inner: BuilderArenaImplInner, } +#[cfg(feature = "alloc")] impl BuilderArenaImpl where A: Allocator, @@ -248,6 +258,7 @@ where } } +#[cfg(feature = "alloc")] impl ReaderArena for BuilderArenaImpl where A: Allocator, @@ -279,6 +290,7 @@ where } } +#[cfg(feature = "alloc")] impl BuilderArenaImplInner where A: Allocator, @@ -343,6 +355,7 @@ where } } +#[cfg(feature = "alloc")] impl BuilderArena for BuilderArenaImpl where A: Allocator, @@ -364,6 +377,7 @@ where } } +#[cfg(feature = "alloc")] impl Drop for BuilderArenaImplInner where A: Allocator, diff --git a/capnp/src/private/capability.rs b/capnp/src/private/capability.rs index da40c77bd..ba725fb60 100644 --- a/capnp/src/private/capability.rs +++ b/capnp/src/private/capability.rs @@ -19,6 +19,7 @@ // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN // THE SOFTWARE. +#![cfg(feature = "alloc")] use alloc::boxed::Box; use alloc::vec::Vec; diff --git a/capnp/src/private/layout.rs b/capnp/src/private/layout.rs index b57774a8e..e071871f6 100644 --- a/capnp/src/private/layout.rs +++ b/capnp/src/private/layout.rs @@ -19,14 +19,15 @@ // 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; +#[cfg(feature = "alloc")] +use alloc::{boxed::Box, vec::Vec}; use core::cell::Cell; use core::mem; use core::ptr; use crate::data; use crate::private::arena::{BuilderArena, NullArena, ReaderArena, SegmentId}; +#[cfg(feature = "alloc")] use crate::private::capability::ClientHook; use crate::private::mask::Mask; use crate::private::primitive::{Primitive, WireValue}; @@ -344,17 +345,21 @@ impl WirePointer { } mod wire_helpers { + #[cfg(feature = "alloc")] use alloc::boxed::Box; use core::{ptr, slice}; use crate::data; use crate::private::arena::*; + #[cfg(feature = "alloc")] use crate::private::capability::ClientHook; use crate::private::layout::ElementSize::*; use crate::private::layout::{data_bits_per_element, pointers_per_element}; + #[cfg(feature = "alloc")] + use crate::private::layout::{CapTableBuilder, CapTableReader}; use crate::private::layout::{ - CapTableBuilder, CapTableReader, ElementSize, ListBuilder, ListReader, StructBuilder, - StructReader, StructSize, WirePointer, WirePointerKind, + ElementSize, ListBuilder, ListReader, StructBuilder, StructReader, StructSize, WirePointer, + WirePointerKind, }; use crate::private::units::*; use crate::text; @@ -834,7 +839,7 @@ mod wire_helpers { unsafe fn copy_struct( arena: &mut dyn BuilderArena, segment_id: u32, - cap_table: CapTableBuilder, + #[cfg(feature = "alloc")] cap_table: CapTableBuilder, dst: *mut u8, src: *const u8, data_size: isize, @@ -849,6 +854,7 @@ mod wire_helpers { copy_message( arena, segment_id, + #[cfg(feature = "alloc")] cap_table, dst_refs.offset(ii), src_refs.offset(ii), @@ -861,7 +867,7 @@ mod wire_helpers { pub unsafe fn copy_message( arena: &mut dyn BuilderArena, segment_id: u32, - cap_table: CapTableBuilder, + #[cfg(feature = "alloc")] cap_table: CapTableBuilder, dst: *mut WirePointer, src: *const WirePointer, ) -> (*mut u8, *mut WirePointer, u32) { @@ -882,6 +888,7 @@ mod wire_helpers { copy_struct( arena, segment_id, + #[cfg(feature = "alloc")] cap_table, dst_ptr, src_ptr, @@ -934,6 +941,7 @@ mod wire_helpers { copy_message( arena, segment_id, + #[cfg(feature = "alloc")] cap_table, dst_refs.offset(ii * BYTES_PER_WORD as isize) as *mut WirePointer, src_refs.offset(ii), @@ -968,6 +976,7 @@ mod wire_helpers { copy_struct( arena, segment_id, + #[cfg(feature = "alloc")] cap_table, dst_element, src_element, @@ -1107,7 +1116,7 @@ mod wire_helpers { arena: &mut dyn BuilderArena, reff: *mut WirePointer, segment_id: u32, - cap_table: CapTableBuilder, + #[cfg(feature = "alloc")] cap_table: CapTableBuilder, size: StructSize, ) -> StructBuilder<'_> { let (ptr, reff, segment_id) = allocate( @@ -1122,6 +1131,7 @@ mod wire_helpers { StructBuilder { arena, segment_id, + #[cfg(feature = "alloc")] cap_table, data: ptr as *mut _, pointers: ptr.offset((size.data as usize) as isize * BYTES_PER_WORD as isize) as *mut _, @@ -1135,7 +1145,7 @@ mod wire_helpers { arena: &'a mut dyn BuilderArena, mut reff: *mut WirePointer, mut segment_id: u32, - cap_table: CapTableBuilder, + #[cfg(feature = "alloc")] cap_table: CapTableBuilder, size: StructSize, default: Option<&'a [crate::Word]>, ) -> Result> { @@ -1145,18 +1155,29 @@ mod wire_helpers { match default { None => { return Ok(init_struct_pointer( - arena, reff, segment_id, cap_table, size, + arena, + reff, + segment_id, + #[cfg(feature = "alloc")] + cap_table, + size, )) } Some(d) if (*(d.as_ptr() as *const WirePointer)).is_null() => { return Ok(init_struct_pointer( - arena, reff, segment_id, cap_table, size, + arena, + reff, + segment_id, + #[cfg(feature = "alloc")] + cap_table, + size, )) } Some(d) => { let (new_ref_target, new_reff, new_segment_id) = copy_message( arena, segment_id, + #[cfg(feature = "alloc")] cap_table, reff, d.as_ptr() as *const WirePointer, @@ -1226,6 +1247,7 @@ mod wire_helpers { Ok(StructBuilder { arena, segment_id, + #[cfg(feature = "alloc")] cap_table, data: ptr as *mut _, pointers: new_pointer_section, @@ -1236,6 +1258,7 @@ mod wire_helpers { Ok(StructBuilder { arena, segment_id: old_segment_id, + #[cfg(feature = "alloc")] cap_table, data: old_ptr, pointers: old_pointer_section, @@ -1250,7 +1273,7 @@ mod wire_helpers { arena: &mut dyn BuilderArena, reff: *mut WirePointer, segment_id: u32, - cap_table: CapTableBuilder, + #[cfg(feature = "alloc")] cap_table: CapTableBuilder, element_count: ElementCount32, element_size: ElementSize, ) -> ListBuilder<'_> { @@ -1271,6 +1294,7 @@ mod wire_helpers { ListBuilder { arena, segment_id, + #[cfg(feature = "alloc")] cap_table, ptr, step, @@ -1286,7 +1310,7 @@ mod wire_helpers { arena: &mut dyn BuilderArena, reff: *mut WirePointer, segment_id: u32, - cap_table: CapTableBuilder, + #[cfg(feature = "alloc")] cap_table: CapTableBuilder, element_count: ElementCount32, element_size: StructSize, ) -> ListBuilder<'_> { @@ -1316,6 +1340,7 @@ mod wire_helpers { ListBuilder { arena, segment_id, + #[cfg(feature = "alloc")] cap_table, ptr: ptr1 as *mut _, step: words_per_element * BITS_PER_WORD as u32, @@ -1331,7 +1356,7 @@ mod wire_helpers { arena: &mut dyn BuilderArena, mut orig_ref: *mut WirePointer, mut orig_segment_id: u32, - cap_table: CapTableBuilder, + #[cfg(feature = "alloc")] cap_table: CapTableBuilder, element_size: ElementSize, default_value: *const u8, ) -> Result> { @@ -1349,6 +1374,7 @@ mod wire_helpers { let (new_orig_ref_target, new_orig_ref, new_orig_segment_id) = copy_message( arena, orig_segment_id, + #[cfg(feature = "alloc")] cap_table, orig_ref, default_value as *const WirePointer, @@ -1425,6 +1451,7 @@ mod wire_helpers { Ok(ListBuilder { arena, segment_id, + #[cfg(feature = "alloc")] cap_table, ptr: ptr as *mut _, element_count: (*tag).inline_composite_list_element_count(), @@ -1450,6 +1477,7 @@ mod wire_helpers { Ok(ListBuilder { arena, segment_id, + #[cfg(feature = "alloc")] cap_table, ptr: ptr as *mut _, step, @@ -1466,7 +1494,7 @@ mod wire_helpers { arena: &mut dyn BuilderArena, mut orig_ref: *mut WirePointer, mut orig_segment_id: u32, - cap_table: CapTableBuilder, + #[cfg(feature = "alloc")] cap_table: CapTableBuilder, element_size: StructSize, default_value: *const u8, ) -> Result> { @@ -1479,6 +1507,7 @@ mod wire_helpers { let (new_orig_ref_target, new_orig_ref, new_orig_segment_id) = copy_message( arena, orig_segment_id, + #[cfg(feature = "alloc")] cap_table, orig_ref, default_value as *const WirePointer, @@ -1521,6 +1550,7 @@ mod wire_helpers { return Ok(ListBuilder { arena, segment_id: old_segment_id, + #[cfg(feature = "alloc")] cap_table, ptr: old_ptr as *mut _, element_count, @@ -1592,6 +1622,7 @@ mod wire_helpers { Ok(ListBuilder { arena, segment_id: new_segment_id, + #[cfg(feature = "alloc")] cap_table, ptr: new_ptr, element_count, @@ -1614,6 +1645,7 @@ mod wire_helpers { arena, orig_ref, orig_segment_id, + #[cfg(feature = "alloc")] cap_table, element_count, element_size, @@ -1690,6 +1722,7 @@ mod wire_helpers { Ok(ListBuilder { arena, segment_id: new_segment_id, + #[cfg(feature = "alloc")] cap_table, ptr: new_ptr, element_count, @@ -1759,6 +1792,7 @@ mod wire_helpers { let (new_ref_target, new_reff, new_segment_id) = copy_message( arena, segment_id, + #[cfg(feature = "alloc")] CapTableBuilder::Plain(::core::ptr::null_mut()), reff, d.as_ptr() as *const _, @@ -1846,6 +1880,7 @@ mod wire_helpers { let (new_ref_target, new_reff, new_segment_id) = copy_message( arena, segment_id, + #[cfg(feature = "alloc")] CapTableBuilder::Plain(core::ptr::null_mut()), reff, d.as_ptr() as *const _, @@ -1879,7 +1914,7 @@ mod wire_helpers { pub unsafe fn set_struct_pointer( arena: &mut dyn BuilderArena, segment_id: u32, - cap_table: CapTableBuilder, + #[cfg(feature = "alloc")] cap_table: CapTableBuilder, reff: *mut WirePointer, value: StructReader, canonicalize: bool, @@ -1943,10 +1978,12 @@ mod wire_helpers { copy_pointer( arena, segment_id, + #[cfg(feature = "alloc")] cap_table, pointer_section.offset(i), value.arena, value.segment_id, + #[cfg(feature = "alloc")] value.cap_table, value.pointers.offset(i), value.nesting_limit, @@ -1960,6 +1997,7 @@ mod wire_helpers { }) } + #[cfg(feature = "alloc")] pub fn set_capability_pointer( _arena: &mut dyn BuilderArena, _segment_id: u32, @@ -1976,7 +2014,7 @@ mod wire_helpers { pub unsafe fn set_list_pointer( arena: &mut dyn BuilderArena, segment_id: u32, - cap_table: CapTableBuilder, + #[cfg(feature = "alloc")] cap_table: CapTableBuilder, reff: *mut WirePointer, value: ListReader, canonicalize: bool, @@ -1996,10 +2034,12 @@ mod wire_helpers { copy_pointer( arena, segment_id, + #[cfg(feature = "alloc")] cap_table, (ptr as *mut WirePointer).offset(i), value.arena, value.segment_id, + #[cfg(feature = "alloc")] value.cap_table, (value.ptr as *const WirePointer).offset(i), value.nesting_limit, @@ -2119,10 +2159,12 @@ mod wire_helpers { copy_pointer( arena, segment_id, + #[cfg(feature = "alloc")] cap_table, dst as *mut _, value.arena, value.segment_id, + #[cfg(feature = "alloc")] value.cap_table, src as *const WirePointer, value.nesting_limit, @@ -2145,11 +2187,11 @@ mod wire_helpers { pub unsafe fn copy_pointer( dst_arena: &mut dyn BuilderArena, dst_segment_id: u32, - dst_cap_table: CapTableBuilder, + #[cfg(feature = "alloc")] dst_cap_table: CapTableBuilder, dst: *mut WirePointer, src_arena: &dyn ReaderArena, src_segment_id: u32, - src_cap_table: CapTableReader, + #[cfg(feature = "alloc")] src_cap_table: CapTableReader, src: *const WirePointer, nesting_limit: i32, canonicalize: bool, @@ -2183,11 +2225,13 @@ mod wire_helpers { set_struct_pointer( dst_arena, dst_segment_id, + #[cfg(feature = "alloc")] dst_cap_table, dst, StructReader { arena: src_arena, segment_id: src_segment_id, + #[cfg(feature = "alloc")] cap_table: src_cap_table, data: ptr, pointers: ptr @@ -2247,11 +2291,13 @@ mod wire_helpers { set_list_pointer( dst_arena, dst_segment_id, + #[cfg(feature = "alloc")] dst_cap_table, dst, ListReader { arena: src_arena, segment_id: src_segment_id, + #[cfg(feature = "alloc")] cap_table: src_cap_table, ptr: ptr as *const _, element_count, @@ -2289,11 +2335,13 @@ mod wire_helpers { set_list_pointer( dst_arena, dst_segment_id, + #[cfg(feature = "alloc")] dst_cap_table, dst, ListReader { arena: src_arena, segment_id: src_segment_id, + #[cfg(feature = "alloc")] cap_table: src_cap_table, ptr: ptr as *const _, element_count, @@ -2317,6 +2365,7 @@ mod wire_helpers { ErrorKind::CannotCreateACanonicalMessageWithACapability, )); } + #[cfg(feature = "alloc")] match src_cap_table.extract_cap((*src).cap_index() as usize) { Some(cap) => { set_capability_pointer(dst_arena, dst_segment_id, dst_cap_table, dst, cap); @@ -2329,6 +2378,8 @@ mod wire_helpers { ErrorKind::MessageContainsInvalidCapabilityPointer, )), } + #[cfg(not(feature = "alloc"))] + return Err(Error::from_kind(ErrorKind::UnknownPointerType)); } } } @@ -2337,7 +2388,7 @@ mod wire_helpers { pub unsafe fn read_struct_pointer<'a>( mut arena: &'a dyn ReaderArena, mut segment_id: u32, - cap_table: CapTableReader, + #[cfg(feature = "alloc")] cap_table: CapTableReader, mut reff: *const WirePointer, default: Option<&'a [crate::Word]>, nesting_limit: i32, @@ -2383,6 +2434,7 @@ mod wire_helpers { Ok(StructReader { arena, segment_id, + #[cfg(feature = "alloc")] cap_table, data: ptr, pointers: ptr.offset(data_size_words as isize * BYTES_PER_WORD as isize) as *const _, @@ -2393,6 +2445,7 @@ mod wire_helpers { } #[inline] + #[cfg(feature = "alloc")] pub unsafe fn read_capability_pointer( _arena: &dyn ReaderArena, _segment_id: u32, @@ -2423,7 +2476,7 @@ mod wire_helpers { pub unsafe fn read_list_pointer( mut arena: &dyn ReaderArena, mut segment_id: u32, - cap_table: CapTableReader, + #[cfg(feature = "alloc")] cap_table: CapTableReader, mut reff: *const WirePointer, default_value: *const u8, expected_element_size: Option, @@ -2521,6 +2574,7 @@ mod wire_helpers { Ok(ListReader { arena, segment_id, + #[cfg(feature = "alloc")] cap_table, ptr: ptr as *const _, element_count: size, @@ -2584,6 +2638,7 @@ mod wire_helpers { Ok(ListReader { arena, segment_id, + #[cfg(feature = "alloc")] cap_table, ptr: ptr as *const _, element_count, @@ -2708,9 +2763,11 @@ fn zero_pointer() -> *const WirePointer { static NULL_ARENA: NullArena = NullArena; +#[cfg(feature = "alloc")] pub type CapTable = Vec>>; #[derive(Copy, Clone)] +#[cfg(feature = "alloc")] pub enum CapTableReader { // At one point, we had a `Dummy` variant here, but that ended up // making values of this type take 16 bytes of memory. Now we instead @@ -2718,6 +2775,7 @@ pub enum CapTableReader { Plain(*const Vec>>), } +#[cfg(feature = "alloc")] impl CapTableReader { pub fn extract_cap(&self, index: usize) -> Option> { match *self { @@ -2737,6 +2795,7 @@ impl CapTableReader { } #[derive(Copy, Clone)] +#[cfg(feature = "alloc")] pub enum CapTableBuilder { // At one point, we had a `Dummy` variant here, but that ended up // making values of this type take 16 bytes of memory. Now we instead @@ -2744,6 +2803,7 @@ pub enum CapTableBuilder { Plain(*mut Vec>>), } +#[cfg(feature = "alloc")] impl CapTableBuilder { pub fn into_reader(self) -> CapTableReader { match self { @@ -2804,6 +2864,7 @@ impl CapTableBuilder { #[derive(Clone, Copy)] pub struct PointerReader<'a> { arena: &'a dyn ReaderArena, + #[cfg(feature = "alloc")] cap_table: CapTableReader, pointer: *const WirePointer, segment_id: u32, @@ -2815,6 +2876,7 @@ impl<'a> PointerReader<'a> { PointerReader { arena: &NULL_ARENA, segment_id: 0, + #[cfg(feature = "alloc")] cap_table: CapTableReader::Plain(ptr::null()), pointer: ptr::null(), nesting_limit: 0x7fffffff, @@ -2838,6 +2900,7 @@ impl<'a> PointerReader<'a> { Ok(PointerReader { arena, segment_id, + #[cfg(feature = "alloc")] cap_table: CapTableReader::Plain(ptr::null()), pointer: location as *const _, nesting_limit, @@ -2855,12 +2918,14 @@ impl<'a> PointerReader<'a> { PointerReader { arena: &NULL_ARENA, segment_id: 0, + #[cfg(feature = "alloc")] cap_table: CapTableReader::Plain(ptr::null()), pointer: location as *const _, nesting_limit: 0x7fffffff, } } + #[cfg(feature = "alloc")] pub fn imbue(&mut self, cap_table: CapTableReader) { self.cap_table = cap_table; } @@ -2898,6 +2963,7 @@ impl<'a> PointerReader<'a> { wire_helpers::read_struct_pointer( self.arena, self.segment_id, + #[cfg(feature = "alloc")] self.cap_table, reff, default, @@ -2924,6 +2990,7 @@ impl<'a> PointerReader<'a> { wire_helpers::read_list_pointer( self.arena, self.segment_id, + #[cfg(feature = "alloc")] self.cap_table, reff, default_value, @@ -2943,6 +3010,7 @@ impl<'a> PointerReader<'a> { wire_helpers::read_list_pointer( self.arena, self.segment_id, + #[cfg(feature = "alloc")] self.cap_table, reff, default_value, @@ -2970,6 +3038,7 @@ impl<'a> PointerReader<'a> { unsafe { wire_helpers::read_data_pointer(self.arena, self.segment_id, reff, default) } } + #[cfg(feature = "alloc")] pub fn get_capability(&self) -> Result> { let reff: *const WirePointer = if self.pointer.is_null() { zero_pointer() @@ -3040,6 +3109,7 @@ impl<'a> PointerReader<'a> { pub struct PointerBuilder<'a> { arena: &'a mut dyn BuilderArena, segment_id: u32, + #[cfg(feature = "alloc")] cap_table: CapTableBuilder, pointer: *mut WirePointer, } @@ -3049,6 +3119,7 @@ impl<'a> PointerBuilder<'a> { pub fn get_root(arena: &'a mut dyn BuilderArena, segment_id: u32, location: *mut u8) -> Self { PointerBuilder { arena, + #[cfg(feature = "alloc")] cap_table: CapTableBuilder::Plain(ptr::null_mut()), segment_id, pointer: location as *mut _, @@ -3063,6 +3134,7 @@ impl<'a> PointerBuilder<'a> { } } + #[cfg(feature = "alloc")] pub fn imbue(&mut self, cap_table: CapTableBuilder) { self.cap_table = cap_table; } @@ -3082,6 +3154,7 @@ impl<'a> PointerBuilder<'a> { self.arena, self.pointer, self.segment_id, + #[cfg(feature = "alloc")] self.cap_table, size, default, @@ -3103,6 +3176,7 @@ impl<'a> PointerBuilder<'a> { self.arena, self.pointer, self.segment_id, + #[cfg(feature = "alloc")] self.cap_table, element_size, default_value, @@ -3124,6 +3198,7 @@ impl<'a> PointerBuilder<'a> { self.arena, self.pointer, self.segment_id, + #[cfg(feature = "alloc")] self.cap_table, element_size, default_value, @@ -3153,6 +3228,7 @@ impl<'a> PointerBuilder<'a> { } } + #[cfg(feature = "alloc")] pub fn get_capability(&self) -> Result> { unsafe { wire_helpers::read_capability_pointer( @@ -3171,6 +3247,7 @@ impl<'a> PointerBuilder<'a> { self.arena, self.pointer, self.segment_id, + #[cfg(feature = "alloc")] self.cap_table, size, ) @@ -3187,6 +3264,7 @@ impl<'a> PointerBuilder<'a> { self.arena, self.pointer, self.segment_id, + #[cfg(feature = "alloc")] self.cap_table, element_count, element_size, @@ -3204,6 +3282,7 @@ impl<'a> PointerBuilder<'a> { self.arena, self.pointer, self.segment_id, + #[cfg(feature = "alloc")] self.cap_table, element_count, element_size, @@ -3228,6 +3307,7 @@ impl<'a> PointerBuilder<'a> { wire_helpers::set_struct_pointer( self.arena, self.segment_id, + #[cfg(feature = "alloc")] self.cap_table, self.pointer, *value, @@ -3242,6 +3322,7 @@ impl<'a> PointerBuilder<'a> { wire_helpers::set_list_pointer( self.arena, self.segment_id, + #[cfg(feature = "alloc")] self.cap_table, self.pointer, *value, @@ -3263,6 +3344,7 @@ impl<'a> PointerBuilder<'a> { } } + #[cfg(feature = "alloc")] pub fn set_capability(&mut self, cap: Box) { wire_helpers::set_capability_pointer( self.arena, @@ -3286,10 +3368,12 @@ impl<'a> PointerBuilder<'a> { wire_helpers::copy_pointer( self.arena, self.segment_id, + #[cfg(feature = "alloc")] self.cap_table, self.pointer, other.arena, other.segment_id, + #[cfg(feature = "alloc")] other.cap_table, other.pointer, other.nesting_limit, @@ -3311,6 +3395,7 @@ impl<'a> PointerBuilder<'a> { PointerReader { arena: self.arena.as_reader(), segment_id: self.segment_id, + #[cfg(feature = "alloc")] cap_table: self.cap_table.into_reader(), pointer: self.pointer, nesting_limit: 0x7fffffff, @@ -3321,6 +3406,7 @@ impl<'a> PointerBuilder<'a> { PointerReader { arena: self.arena.as_reader(), segment_id: self.segment_id, + #[cfg(feature = "alloc")] cap_table: self.cap_table.into_reader(), pointer: self.pointer, nesting_limit: 0x7fffffff, @@ -3331,6 +3417,7 @@ impl<'a> PointerBuilder<'a> { #[derive(Clone, Copy)] pub struct StructReader<'a> { arena: &'a dyn ReaderArena, + #[cfg(feature = "alloc")] cap_table: CapTableReader, data: *const u8, pointers: *const WirePointer, @@ -3345,6 +3432,7 @@ impl<'a> StructReader<'a> { StructReader { arena: &NULL_ARENA, segment_id: 0, + #[cfg(feature = "alloc")] cap_table: CapTableReader::Plain(ptr::null()), data: ptr::null(), pointers: ptr::null(), @@ -3354,6 +3442,7 @@ impl<'a> StructReader<'a> { } } + #[cfg(feature = "alloc")] pub fn imbue(&mut self, cap_table: CapTableReader) { self.cap_table = cap_table } @@ -3370,6 +3459,7 @@ impl<'a> StructReader<'a> { ListReader { arena: self.arena, segment_id: self.segment_id, + #[cfg(feature = "alloc")] cap_table: self.cap_table, ptr: self.pointers as *const _, element_count: u32::from(self.pointer_count), @@ -3439,6 +3529,7 @@ impl<'a> StructReader<'a> { PointerReader { arena: self.arena, segment_id: self.segment_id, + #[cfg(feature = "alloc")] cap_table: self.cap_table, pointer: unsafe { self.pointers.add(ptr_index) }, nesting_limit: self.nesting_limit, @@ -3539,6 +3630,7 @@ impl<'a> StructReader<'a> { pub struct StructBuilder<'a> { arena: &'a mut dyn BuilderArena, + #[cfg(feature = "alloc")] cap_table: CapTableBuilder, data: *mut u8, pointers: *mut WirePointer, @@ -3559,6 +3651,7 @@ impl<'a> StructBuilder<'a> { pub fn as_reader(&self) -> StructReader<'_> { StructReader { arena: self.arena.as_reader(), + #[cfg(feature = "alloc")] cap_table: self.cap_table.into_reader(), data: self.data, pointers: self.pointers, @@ -3572,6 +3665,7 @@ impl<'a> StructBuilder<'a> { pub fn into_reader(self) -> StructReader<'a> { StructReader { arena: self.arena.as_reader(), + #[cfg(feature = "alloc")] cap_table: self.cap_table.into_reader(), data: self.data, pointers: self.pointers, @@ -3582,6 +3676,7 @@ impl<'a> StructBuilder<'a> { } } + #[cfg(feature = "alloc")] pub fn imbue(&mut self, cap_table: CapTableBuilder) { self.cap_table = cap_table } @@ -3649,6 +3744,7 @@ impl<'a> StructBuilder<'a> { PointerBuilder { arena: self.arena, segment_id: self.segment_id, + #[cfg(feature = "alloc")] cap_table: self.cap_table, pointer: unsafe { self.pointers.add(ptr_index) }, } @@ -3659,6 +3755,7 @@ impl<'a> StructBuilder<'a> { PointerBuilder { arena: self.arena, segment_id: self.segment_id, + #[cfg(feature = "alloc")] cap_table: self.cap_table, pointer: unsafe { self.pointers.add(ptr_index) }, } @@ -3735,10 +3832,12 @@ impl<'a> StructBuilder<'a> { wire_helpers::copy_pointer( self.arena, self.segment_id, + #[cfg(feature = "alloc")] self.cap_table, self.pointers.offset(i), other.arena, other.segment_id, + #[cfg(feature = "alloc")] other.cap_table, other.pointers.offset(i), other.nesting_limit, @@ -3754,6 +3853,7 @@ impl<'a> StructBuilder<'a> { #[derive(Clone, Copy)] pub struct ListReader<'a> { arena: &'a dyn ReaderArena, + #[cfg(feature = "alloc")] cap_table: CapTableReader, ptr: *const u8, segment_id: u32, @@ -3770,6 +3870,7 @@ impl<'a> ListReader<'a> { ListReader { arena: &NULL_ARENA, segment_id: 0, + #[cfg(feature = "alloc")] cap_table: CapTableReader::Plain(ptr::null()), ptr: ptr::null(), element_count: 0, @@ -3781,6 +3882,7 @@ impl<'a> ListReader<'a> { } } + #[cfg(feature = "alloc")] pub fn imbue(&mut self, cap_table: CapTableReader) { self.cap_table = cap_table } @@ -3828,6 +3930,7 @@ impl<'a> ListReader<'a> { StructReader { arena: self.arena, segment_id: self.segment_id, + #[cfg(feature = "alloc")] cap_table: self.cap_table, data: struct_data, pointers: struct_pointers, @@ -3845,6 +3948,7 @@ impl<'a> ListReader<'a> { PointerReader { arena: self.arena, segment_id: self.segment_id, + #[cfg(feature = "alloc")] cap_table: self.cap_table, pointer: unsafe { self.ptr.offset(offset) } as *const _, nesting_limit: self.nesting_limit, @@ -3963,6 +4067,7 @@ impl<'a> ListReader<'a> { pub struct ListBuilder<'a> { arena: &'a mut dyn BuilderArena, + #[cfg(feature = "alloc")] cap_table: CapTableBuilder, ptr: *mut u8, segment_id: u32, @@ -3979,6 +4084,7 @@ impl<'a> ListBuilder<'a> { ListBuilder { arena, segment_id: 0, + #[cfg(feature = "alloc")] cap_table: CapTableBuilder::Plain(ptr::null_mut()), ptr: ptr::null_mut(), element_count: 0, @@ -3993,6 +4099,7 @@ impl<'a> ListBuilder<'a> { ListReader { arena: self.arena.as_reader(), segment_id: self.segment_id, + #[cfg(feature = "alloc")] cap_table: self.cap_table.into_reader(), ptr: self.ptr as *const _, element_count: self.element_count, @@ -4012,6 +4119,7 @@ impl<'a> ListBuilder<'a> { } } + #[cfg(feature = "alloc")] pub fn imbue(&mut self, cap_table: CapTableBuilder) { self.cap_table = cap_table } @@ -4034,6 +4142,7 @@ impl<'a> ListBuilder<'a> { StructBuilder { arena: self.arena, segment_id: self.segment_id, + #[cfg(feature = "alloc")] cap_table: self.cap_table, data: struct_data, pointers: struct_pointers, @@ -4052,6 +4161,7 @@ impl<'a> ListBuilder<'a> { PointerBuilder { arena: self.arena, segment_id: self.segment_id, + #[cfg(feature = "alloc")] cap_table: self.cap_table, pointer: unsafe { self.ptr.offset(offset as isize) } as *mut _, } diff --git a/capnp/src/schema.rs b/capnp/src/schema.rs index d828121be..b24f8f4bc 100644 --- a/capnp/src/schema.rs +++ b/capnp/src/schema.rs @@ -1,5 +1,6 @@ //! Convenience wrappers of the datatypes defined in schema.capnp. +#![cfg(feature = "alloc")] use crate::dynamic_value; use crate::introspect::{self, RawBrandedStructSchema, RawEnumSchema}; use crate::private::layout; diff --git a/capnp/src/serialize.rs b/capnp/src/serialize.rs index 9ea434e72..226950936 100644 --- a/capnp/src/serialize.rs +++ b/capnp/src/serialize.rs @@ -26,18 +26,26 @@ mod no_alloc_slice_segments; pub use no_alloc_slice_segments::NoAllocSliceSegments; +#[cfg(feature = "alloc")] use crate::io::{Read, Write}; +#[cfg(feature = "alloc")] use alloc::vec::Vec; +#[cfg(feature = "alloc")] use core::convert::TryInto; +#[cfg(feature = "alloc")] use core::ops::Deref; use crate::message; +#[cfg(feature = "alloc")] use crate::private::units::BYTES_PER_WORD; -use crate::{Error, ErrorKind, Result}; +use crate::Result; +#[cfg(feature = "alloc")] +use crate::{Error, ErrorKind}; pub const SEGMENTS_COUNT_LIMIT: usize = 512; /// Segments read from a single flat slice of words. +#[cfg(feature = "alloc")] pub struct SliceSegments<'a> { words: &'a [u8], @@ -46,6 +54,7 @@ pub struct SliceSegments<'a> { segment_indices: Vec<(usize, usize)>, } +#[cfg(feature = "alloc")] impl<'a> message::ReaderSegments for SliceSegments<'a> { fn get_segment(&self, id: u32) -> Option<&[u8]> { if id < self.segment_indices.len() as u32 { @@ -67,6 +76,7 @@ impl<'a> message::ReaderSegments for SliceSegments<'a> { /// /// ALIGNMENT: If the "unaligned" feature is enabled, then there are no alignment requirements on `slice`. /// Otherwise, `slice` must be 8-byte aligned (attempts to read the message will trigger errors). +#[cfg(feature = "alloc")] pub fn read_message_from_flat_slice<'a>( slice: &mut &'a [u8], options: message::ReaderOptions, @@ -114,6 +124,7 @@ pub fn read_message_from_flat_slice_no_alloc<'a>( /// Segments read from a buffer, useful for when you have the message in a buffer and don't want the extra /// copy of `read_message`. +#[cfg(feature = "alloc")] pub struct BufferSegments { buffer: T, @@ -125,6 +136,7 @@ pub struct BufferSegments { segment_indices: Vec<(usize, usize)>, } +#[cfg(feature = "alloc")] impl> BufferSegments { /// Reads a serialized message (including a segment table) from a buffer and takes ownership, without copying. /// The buffer is allowed to be longer than the message. Provide this to `Reader::new` with options that make @@ -154,6 +166,7 @@ impl> BufferSegments { } } +#[cfg(feature = "alloc")] impl> message::ReaderSegments for BufferSegments { fn get_segment(&self, id: u32) -> Option<&[u8]> { if id < self.segment_indices.len() as u32 { @@ -174,6 +187,7 @@ impl> message::ReaderSegments for BufferSegments { /// Owned memory containing a message's segments sequentialized in a single contiguous buffer. /// The segments are guaranteed to be 8-byte aligned. +#[cfg(feature = "alloc")] pub struct OwnedSegments { // Each pair represents a segment inside of `owned_space`. // (starting index (in words), ending index (in words)) @@ -182,6 +196,7 @@ pub struct OwnedSegments { owned_space: Vec, } +#[cfg(feature = "alloc")] impl core::ops::Deref for OwnedSegments { type Target = [u8]; fn deref(&self) -> &[u8] { @@ -189,12 +204,14 @@ impl core::ops::Deref for OwnedSegments { } } +#[cfg(feature = "alloc")] impl core::ops::DerefMut for OwnedSegments { fn deref_mut(&mut self) -> &mut [u8] { crate::Word::words_to_bytes_mut(&mut self.owned_space[..]) } } +#[cfg(feature = "alloc")] impl crate::message::ReaderSegments for OwnedSegments { fn get_segment(&self, id: u32) -> Option<&[u8]> { if id < self.segment_indices.len() as u32 { @@ -210,12 +227,14 @@ impl crate::message::ReaderSegments for OwnedSegments { } } +#[cfg(feature = "alloc")] /// Helper object for constructing an `OwnedSegments` or a `SliceSegments`. pub struct SegmentLengthsBuilder { segment_indices: Vec<(usize, usize)>, total_words: usize, } +#[cfg(feature = "alloc")] impl SegmentLengthsBuilder { /// Creates a new `SegmentsLengthsBuilder`, initializing the segment_indices vector with /// `Vec::with_capacitiy(capacity)`. `capacity` should equal the number of times that `push_segment()` @@ -269,6 +288,7 @@ impl SegmentLengthsBuilder { /// Reads a serialized message from a stream with the provided options. /// /// For optimal performance, `read` should be a buffered reader type. +#[cfg(feature = "alloc")] pub fn read_message( mut read: R, options: message::ReaderOptions, @@ -289,6 +309,7 @@ where /// Like `read_message()`, but returns None instead of an error if there are zero bytes left in /// `read`. This is useful for reading a stream containing an unknown number of messages -- you /// call this function until it returns None. +#[cfg(feature = "alloc")] pub fn try_read_message( mut read: R, options: message::ReaderOptions, @@ -309,6 +330,7 @@ where /// /// The segment table format for streams is defined in the Cap'n Proto /// [encoding spec](https://capnproto.org/encoding.html) +#[cfg(feature = "alloc")] fn read_segment_table( read: &mut R, options: message::ReaderOptions, @@ -377,6 +399,7 @@ where Ok(Some(segment_lengths_builder)) } +#[cfg(feature = "alloc")] /// Reads segments from `read`. fn read_segments( read: &mut R, @@ -391,6 +414,7 @@ where } /// Constructs a flat vector containing the entire message, including a segment header. +#[cfg(feature = "alloc")] pub fn write_message_to_words(message: &message::Builder) -> Vec where A: message::Allocator, @@ -400,6 +424,7 @@ where /// Like `write_message_to_words()`, but takes a `ReaderSegments`, allowing it to be /// used on `message::Reader` objects (via `into_segments()`). +#[cfg(feature = "alloc")] pub fn write_message_segments_to_words(message: &R) -> Vec where R: message::ReaderSegments, @@ -407,6 +432,7 @@ where flatten_segments(message) } +#[cfg(feature = "alloc")] fn flatten_segments(segments: &R) -> Vec { let word_count = compute_serialized_size(segments); let segment_count = segments.len(); @@ -431,6 +457,7 @@ fn flatten_segments(segments: &R) -> Vec(mut write: W, message: &message::Builder) -> Result<()> where W: Write, @@ -443,6 +470,7 @@ where /// Like `write_message()`, but takes a `ReaderSegments`, allowing it to be /// used on `message::Reader` objects (via `into_segments()`). +#[cfg(feature = "alloc")] pub fn write_message_segments(mut write: W, segments: &R) -> Result<()> where W: Write, @@ -452,6 +480,7 @@ where write_segments(&mut write, segments) } +#[cfg(feature = "alloc")] fn write_segment_table(write: &mut W, segments: &[&[u8]]) -> Result<()> where W: Write, @@ -462,6 +491,7 @@ where /// Writes a segment table to `write`. /// /// `segments` must contain at least one segment. +#[cfg(feature = "alloc")] fn write_segment_table_internal(write: &mut W, segments: &R) -> Result<()> where W: Write, @@ -512,6 +542,7 @@ where } /// Writes segments to `write`. +#[cfg(feature = "alloc")] fn write_segments(write: &mut W, segments: &R) -> Result<()> where W: Write, @@ -526,6 +557,7 @@ where Ok(()) } +#[cfg(feature = "alloc")] fn compute_serialized_size(segments: &R) -> usize { // Table size let len = segments.len(); @@ -542,6 +574,7 @@ fn compute_serialized_size(segments: &R) -> /// /// Multiply this by 8 (or `std::mem::size_of::()`) to get the number of bytes /// that [`write_message()`](fn.write_message.html) will write. +#[cfg(feature = "alloc")] pub fn compute_serialized_size_in_words(message: &crate::message::Builder) -> usize where A: crate::message::Allocator, @@ -549,6 +582,7 @@ where compute_serialized_size(&message.get_segments_for_output()) } +#[cfg(feature = "alloc")] #[cfg(test)] pub mod test { use alloc::vec::Vec; diff --git a/capnp/src/serialize/no_alloc_slice_segments.rs b/capnp/src/serialize/no_alloc_slice_segments.rs index 563560c84..c777485b7 100644 --- a/capnp/src/serialize/no_alloc_slice_segments.rs +++ b/capnp/src/serialize/no_alloc_slice_segments.rs @@ -289,19 +289,26 @@ fn calculate_data_offset(segments_count: usize) -> Option { #[cfg(test)] mod tests { + #[cfg(feature = "alloc")] use quickcheck::{quickcheck, TestResult}; + use crate::serialize::no_alloc_slice_segments::calculate_data_offset; + #[cfg(feature = "alloc")] use crate::{ message::{ReaderOptions, ReaderSegments}, - serialize::{self, no_alloc_slice_segments::calculate_data_offset}, - word, OutputSegments, Word, + serialize, word, Word, }; + #[cfg(feature = "alloc")] + use crate::OutputSegments; + + #[cfg(feature = "alloc")] + use super::NoAllocSliceSegments; use super::{ read_u32_le, u32_to_segment_length_bytes, u32_to_segments_count, verify_alignment, - NoAllocSliceSegments, }; + #[cfg(feature = "alloc")] use alloc::vec::Vec; #[repr(align(8))] @@ -382,6 +389,7 @@ mod tests { assert_eq!(calculate_data_offset(101), Some(408)); } + #[cfg(feature = "alloc")] quickcheck! { #[cfg_attr(miri, ignore)] // miri takes a long time with quickcheck fn test_no_alloc_buffer_segments_single_segment_optimization( @@ -437,6 +445,7 @@ mod tests { } } + #[cfg(feature = "alloc")] #[test] fn test_no_alloc_buffer_segments_message_postfix() { let output_segments = OutputSegments::SingleSegment([&[1, 2, 3, 4, 5, 6, 7, 8]]); @@ -452,6 +461,7 @@ mod tests { assert_eq!(*remaining, &[11, 12, 13, 14, 15, 16, 0, 0]); } + #[cfg(feature = "alloc")] #[test] fn test_no_alloc_buffer_segments_message_invalid() { let mut buf = vec![]; @@ -475,6 +485,7 @@ mod tests { buf.clear(); } + #[cfg(feature = "alloc")] quickcheck! { #[cfg_attr(miri, ignore)] // miri takes a long time with quickcheck fn test_no_alloc_buffer_segments_message_truncated(segments_vec: Vec>) -> TestResult { diff --git a/capnp/src/serialize_packed.rs b/capnp/src/serialize_packed.rs index c5c42190f..286a36950 100644 --- a/capnp/src/serialize_packed.rs +++ b/capnp/src/serialize_packed.rs @@ -25,7 +25,9 @@ use crate::io::{BufRead, Read, Write}; use core::{mem, ptr, slice}; +#[cfg(feature = "alloc")] use crate::message; +#[cfg(feature = "alloc")] use crate::serialize; use crate::{Error, ErrorKind, Result}; @@ -229,6 +231,7 @@ where } /// Reads a packed message from a stream using the provided options. +#[cfg(feature = "alloc")] pub fn read_message( read: R, options: message::ReaderOptions, @@ -241,6 +244,7 @@ where } /// Like read_message(), but returns None instead of an error if there are zero bytes left in `read`. +#[cfg(feature = "alloc")] pub fn try_read_message( read: R, options: message::ReaderOptions, @@ -404,6 +408,7 @@ where /// /// The only source of errors from this function are `write.write_all()` calls. If you pass in /// a writer that never returns an error, then this function will never return an error. +#[cfg(feature = "alloc")] pub fn write_message(write: W, message: &crate::message::Builder) -> Result<()> where W: Write, @@ -413,6 +418,7 @@ where serialize::write_message(packed_write, message) } +#[cfg(feature = "alloc")] #[cfg(test)] mod tests { use alloc::vec::Vec; diff --git a/capnp/src/stringify.rs b/capnp/src/stringify.rs index a7bb8a7a4..253eaa7fd 100644 --- a/capnp/src/stringify.rs +++ b/capnp/src/stringify.rs @@ -1,3 +1,4 @@ +#![cfg(feature = "alloc")] use crate::dynamic_value; use core::fmt::{self, Formatter}; diff --git a/capnp/src/struct_list.rs b/capnp/src/struct_list.rs index 7c8103e23..dc9fb43a5 100644 --- a/capnp/src/struct_list.rs +++ b/capnp/src/struct_list.rs @@ -284,6 +284,7 @@ where } } +#[cfg(feature = "alloc")] impl<'a, T: crate::traits::OwnedStruct> From> for crate::dynamic_value::Reader<'a> { fn from(t: Reader<'a, T>) -> crate::dynamic_value::Reader<'a> { crate::dynamic_value::Reader::List(crate::dynamic_list::Reader::new( @@ -293,6 +294,7 @@ impl<'a, T: crate::traits::OwnedStruct> From> for crate::dynamic_v } } +#[cfg(feature = "alloc")] impl<'a, T: crate::traits::OwnedStruct> From> for crate::dynamic_value::Builder<'a> { fn from(t: Builder<'a, T>) -> crate::dynamic_value::Builder<'a> { crate::dynamic_value::Builder::List(crate::dynamic_list::Builder::new( diff --git a/capnp/src/text.rs b/capnp/src/text.rs index 50344d7b9..f1184a582 100644 --- a/capnp/src/text.rs +++ b/capnp/src/text.rs @@ -151,12 +151,14 @@ impl<'a> crate::traits::SetPointerBuilder for Reader<'a> { } } +#[cfg(feature = "alloc")] impl<'a> From> for crate::dynamic_value::Reader<'a> { fn from(t: Reader<'a>) -> crate::dynamic_value::Reader<'a> { crate::dynamic_value::Reader::Text(t) } } +#[cfg(feature = "alloc")] impl<'a> From> for crate::dynamic_value::Builder<'a> { fn from(t: Builder<'a>) -> crate::dynamic_value::Builder<'a> { crate::dynamic_value::Builder::Text(t) diff --git a/capnp/src/text_list.rs b/capnp/src/text_list.rs index 72cbd2647..873d73b9d 100644 --- a/capnp/src/text_list.rs +++ b/capnp/src/text_list.rs @@ -197,6 +197,7 @@ impl<'a> ::core::iter::IntoIterator for Reader<'a> { } } +#[cfg(feature = "alloc")] impl<'a> From> for crate::dynamic_value::Reader<'a> { fn from(t: Reader<'a>) -> crate::dynamic_value::Reader<'a> { crate::dynamic_value::Reader::List(crate::dynamic_list::Reader { @@ -206,6 +207,7 @@ impl<'a> From> for crate::dynamic_value::Reader<'a> { } } +#[cfg(feature = "alloc")] impl<'a> From> for crate::dynamic_value::Builder<'a> { fn from(t: Builder<'a>) -> crate::dynamic_value::Builder<'a> { crate::dynamic_value::Builder::List(crate::dynamic_list::Builder { diff --git a/capnp/src/traits.rs b/capnp/src/traits.rs index 1ca28ce19..5b0be701a 100644 --- a/capnp/src/traits.rs +++ b/capnp/src/traits.rs @@ -19,8 +19,10 @@ // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN // THE SOFTWARE. +#[cfg(feature = "alloc")] +use crate::private::layout::CapTable; use crate::private::layout::{ - CapTable, ListReader, PointerBuilder, PointerReader, StructBuilder, StructReader, StructSize, + ListReader, PointerBuilder, PointerReader, StructBuilder, StructReader, StructSize, }; use crate::Result; @@ -87,10 +89,12 @@ pub trait SetPointerBuilder { ) -> Result<()>; } +#[cfg(feature = "alloc")] pub trait Imbue<'a> { fn imbue(&mut self, caps: &'a CapTable); } +#[cfg(feature = "alloc")] pub trait ImbueMut<'a> { fn imbue_mut(&mut self, caps: &'a mut CapTable); } diff --git a/capnp/tests/canonicalize.rs b/capnp/tests/canonicalize.rs index c0404ad44..43631a63f 100644 --- a/capnp/tests/canonicalize.rs +++ b/capnp/tests/canonicalize.rs @@ -21,6 +21,7 @@ use capnp::message; +#[cfg(feature = "alloc")] #[test] fn canonicalize_succeeds_on_null_message() { let segment: &[capnp::Word] = &[capnp::word(0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00)]; @@ -34,6 +35,7 @@ fn canonicalize_succeeds_on_null_message() { assert_eq!(&canonical_bytes[..], segment); } +#[cfg(feature = "alloc")] #[test] fn dont_truncate_struct_too_far() { let segment: &[capnp::Word] = &[ @@ -63,6 +65,7 @@ fn dont_truncate_struct_too_far() { assert_eq!(&canonicalized[..], canonical_segment); } +#[cfg(feature = "alloc")] #[test] fn dont_truncate_struct_list_too_far() { let segment: &[capnp::Word] = &[ @@ -175,6 +178,7 @@ fn is_canonical_requires_dense_packing() { assert!(!message.is_canonical().unwrap()); } +#[cfg(feature = "alloc")] #[test] fn simple_multisegment_message() { let segment0: &[capnp::Word] = &[ @@ -206,6 +210,7 @@ fn simple_multisegment_message() { assert_eq!(&canonicalized[..], canonical_segment); } +#[cfg(feature = "alloc")] #[test] fn multisegment_only_first_segment_used() { // A segment with a canonicalized struct. @@ -265,6 +270,7 @@ fn is_canonical_rejects_unused_trailing_words() { assert!(!message.is_canonical().unwrap()); } +#[cfg(feature = "alloc")] #[test] fn empty_inline_composite_list_of_0_sized_structs() { let segment: &[capnp::Word] = &[ @@ -285,6 +291,7 @@ fn empty_inline_composite_list_of_0_sized_structs() { assert_eq!(segment, &canonical_words[..]); } +#[cfg(feature = "alloc")] #[test] fn inline_composite_list_with_void_list() { let segment: &[capnp::Word] = &[ @@ -330,6 +337,7 @@ fn is_canonical_rejects_inline_composite_list_with_inaccurate_word_length() { assert!(!message.is_canonical().unwrap()); } +#[cfg(feature = "alloc")] #[test] fn truncate_data_section_inline_composite() { let segment: &[capnp::Word] = &[ @@ -354,6 +362,7 @@ fn truncate_data_section_inline_composite() { assert!(canonical_message.is_canonical().unwrap()); } +#[cfg(feature = "alloc")] #[test] fn truncate_pointer_section_inline_composite() { let segment: &[capnp::Word] = &[ @@ -387,6 +396,7 @@ fn truncate_pointer_section_inline_composite() { assert_eq!(expected_canonical_words, &canonical_words[..]); } +#[cfg(feature = "alloc")] #[test] fn list_padding_must_be_zero() { let segment: &[capnp::Word] = &[ @@ -416,6 +426,7 @@ fn list_padding_must_be_zero() { assert_eq!(expected_canonical_words, &canonical_words[..]); } +#[cfg(feature = "alloc")] #[test] fn bit_list_padding_must_be_zero() { let segment: &[capnp::Word] = &[