Skip to main content

capnp/
message.rs

1// Copyright (c) 2013-2015 Sandstorm Development Group, Inc. and contributors
2// Licensed under the MIT License:
3//
4// Permission is hereby granted, free of charge, to any person obtaining a copy
5// of this software and associated documentation files (the "Software"), to deal
6// in the Software without restriction, including without limitation the rights
7// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
8// copies of the Software, and to permit persons to whom the Software is
9// furnished to do so, subject to the following conditions:
10//
11// The above copyright notice and this permission notice shall be included in
12// all copies or substantial portions of the Software.
13//
14// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
15// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
16// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
17// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
18// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
19// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
20// THE SOFTWARE.
21
22//! Untyped root container for a Cap'n Proto value.
23//!
24//! ## Notes about type specialization
25//! This module provides [TypedReader] and [TypedBuilder] structs which are strongly-typed variants
26//! of [Reader] and [Builder].
27//!
28//! Code autogenerated by capnpc will have an individual module for each structure and each of these
29//! modules will have `Owned` struct which implements [Owned] trait.
30//!
31//! Example from a real auto-generated file:
32//!
33//! ```ignore
34//! pub mod simple_struct {
35//!     #[derive(Copy, Clone)]
36//!     pub struct Owned(());
37//!     impl <'a> ::capnp::traits::Owned<'a> for Owned { type Reader = Reader<'a>; type Builder = Builder<'a>; }
38//!     ....
39//! }
40//! ```
41//!
42//! [TypedReader] and [TypedBuilder] accept generic type parameter `T`. This parameter must be
43//! a corresponding `Owned` type which was auto-generated inside the corresponding module.
44//!
45//! For example, for auto-generated module `crate::test_data::simple_struct` you'd supply
46//! `crate::test_data::simple_struct::Owned` type into [TypedReader]/[TypedBuilder]
47//!
48//! ```ignore
49//! capnp::generated_code!(mod simple_struct_capnp);
50//!
51//! use capnp::message::{self, TypedBuilder, TypedReader};
52//! use simple_struct_capnp::simple_struct;
53//!
54//! fn main() {
55//!     let mut builder = TypedBuilder::<simple_struct::Owned>::new_default();
56//!     let mut builder_root = builder.init_root();
57//!     builder_root.set_x(10);
58//!     builder_root.set_y(20);
59//!
60//!     let mut buffer = vec![];
61//!     capnp::serialize_packed::write_message(&mut buffer, builder.borrow_inner()).unwrap();
62//!
63//!     let reader = capnp::serialize_packed::read_message(buffer.as_slice(), ReaderOptions::new()).unwrap();
64//!     let typed_reader = TypedReader::<_, simple_struct::Owned>::new(reader);
65//!
66//!     let reader_root = typed_reader.get().unwrap();
67//!     assert_eq!(reader_root.get_x(), 10);
68//!     assert_eq!(reader_root.get_y(), 20);
69//! }
70//!
71//! ```
72
73use crate::any_pointer;
74use crate::private::arena::{BuilderArena, BuilderArenaImpl};
75use crate::private::arena::{ReaderArena, ReaderArenaImpl};
76use crate::private::layout;
77use crate::private::units::BYTES_PER_WORD;
78use crate::traits::{FromPointerBuilder, SetterInput};
79use crate::traits::{FromPointerReader, Owned};
80use crate::OutputSegments;
81use crate::Result;
82
83/// Options controlling how data is read.
84#[derive(Clone, Copy, Debug)]
85pub struct ReaderOptions {
86    /// Limits how many total (8-byte) words of data are allowed to be traversed. Traversal is counted
87    /// when a new struct or list builder is obtained, e.g. from a get() accessor. This means that
88    /// calling the getter for the same sub-struct multiple times will cause it to be double-counted.
89    /// Once the traversal limit is reached, an error will be reported.
90    ///
91    /// This limit exists for security reasons. It is possible for an attacker to construct a message
92    /// in which multiple pointers point at the same location. This is technically invalid, but hard
93    /// to detect. Using such a message, an attacker could cause a message which is small on the wire
94    /// to appear much larger when actually traversed, possibly exhausting server resources leading to
95    /// denial-of-service.
96    ///
97    /// It makes sense to set a traversal limit that is much larger than the underlying message.
98    /// Together with sensible coding practices (e.g. trying to avoid calling sub-object getters
99    /// multiple times, which is expensive anyway), this should provide adequate protection without
100    /// inconvenience.
101    ///
102    /// A traversal limit of `None` means that no limit is enforced.
103    pub traversal_limit_in_words: Option<usize>,
104
105    /// Limits how deeply nested a message structure can be, e.g. structs containing other structs or
106    /// lists of structs.
107    ///
108    /// Like the traversal limit, this limit exists for security reasons. Since it is common to use
109    /// recursive code to traverse recursive data structures, an attacker could easily cause a stack
110    /// overflow by sending a very-deeply-nested (or even cyclic) message, without the message even
111    /// being very large. The default limit of 64 is probably low enough to prevent any chance of
112    /// stack overflow, yet high enough that it is never a problem in practice.
113    pub nesting_limit: i32,
114}
115
116#[cfg(not(target_pointer_width = "16"))]
117pub const DEFAULT_READER_OPTIONS: ReaderOptions = ReaderOptions {
118    traversal_limit_in_words: Some(8 * 1024 * 1024),
119    nesting_limit: 64,
120};
121
122#[cfg(target_pointer_width = "16")]
123pub const DEFAULT_READER_OPTIONS: ReaderOptions = ReaderOptions {
124    traversal_limit_in_words: Some(8 * 1024),
125    nesting_limit: 64,
126};
127
128impl Default for ReaderOptions {
129    fn default() -> Self {
130        DEFAULT_READER_OPTIONS
131    }
132}
133
134impl ReaderOptions {
135    pub const fn new() -> Self {
136        DEFAULT_READER_OPTIONS
137    }
138
139    pub fn nesting_limit(&mut self, value: i32) -> &mut Self {
140        self.nesting_limit = value;
141        self
142    }
143
144    pub fn traversal_limit_in_words(&mut self, value: Option<usize>) -> &mut Self {
145        self.traversal_limit_in_words = value;
146        self
147    }
148}
149
150/// An object that manages the buffers underlying a Cap'n Proto message reader.
151pub trait ReaderSegments {
152    /// Gets the segment with index `idx`. Returns `None` if `idx` is out of range.
153    ///
154    /// The segment must be 8-byte aligned or the "unaligned" feature must
155    /// be enabled in the capnp crate. (Otherwise reading the segment will return an error.)
156    ///
157    /// The returned slice is required to point to memory that remains valid until the ReaderSegments
158    /// object is dropped. In safe Rust, it should not be possible to violate this requirement.
159    fn get_segment(&self, idx: u32) -> Option<&[u8]>;
160
161    /// Gets the number of segments.
162    fn len(&self) -> usize {
163        for i in 0u32.. {
164            if self.get_segment(i).is_none() {
165                return i as usize;
166            }
167        }
168        unreachable!()
169    }
170
171    fn is_empty(&self) -> bool {
172        self.len() == 0
173    }
174}
175
176/// Allows stacking of references to a `ReaderSegments`.
177///
178/// This is especially useful with the implementation for slices, as it allows treating
179/// `&[&[u8]]` as `ReaderSegments`, e.g., to construct a `Reader`:
180/// ```
181/// # use capnp::message::ReaderSegments;
182/// use capnp::message::Reader;
183/// let slice_of_slices: &[&[u8]] = &[&*b"some data", &*b"more data"];
184/// let _ = Reader::new(slice_of_slices, Default::default());
185/// ```
186impl<S> ReaderSegments for &S
187where
188    S: ReaderSegments + ?Sized,
189{
190    fn get_segment(&self, idx: u32) -> Option<&[u8]> {
191        (**self).get_segment(idx)
192    }
193
194    fn len(&self) -> usize {
195        (**self).len()
196    }
197
198    fn is_empty(&self) -> bool {
199        (**self).is_empty()
200    }
201}
202
203/// An array of segments.
204pub struct SegmentArray<'a> {
205    segments: &'a [&'a [u8]],
206}
207
208impl<'a> SegmentArray<'a> {
209    pub fn new(segments: &'a [&'a [u8]]) -> SegmentArray<'a> {
210        SegmentArray { segments }
211    }
212}
213
214impl ReaderSegments for SegmentArray<'_> {
215    fn get_segment(&self, id: u32) -> Option<&[u8]> {
216        self.segments.get(id as usize).copied()
217    }
218
219    fn len(&self) -> usize {
220        self.segments.len()
221    }
222}
223
224impl<I> ReaderSegments for [I]
225where
226    I: AsRef<[u8]>,
227{
228    fn get_segment(&self, id: u32) -> Option<&[u8]> {
229        self.get(id as usize).map(|i| i.as_ref())
230    }
231
232    fn len(&self) -> usize {
233        self.len()
234    }
235
236    fn is_empty(&self) -> bool {
237        self.is_empty()
238    }
239}
240
241#[cfg(feature = "alloc")]
242impl<I> ReaderSegments for alloc::vec::Vec<I>
243where
244    I: AsRef<[u8]>,
245{
246    fn get_segment(&self, id: u32) -> Option<&[u8]> {
247        self.get(id as usize).map(|i| i.as_ref())
248    }
249
250    fn len(&self) -> usize {
251        self.len()
252    }
253
254    fn is_empty(&self) -> bool {
255        self.is_empty()
256    }
257}
258
259/// A container used to read a message.
260pub struct Reader<S>
261where
262    S: ReaderSegments,
263{
264    arena: ReaderArenaImpl<S>,
265}
266
267impl<S> Reader<S>
268where
269    S: ReaderSegments,
270{
271    pub fn new(segments: S, options: ReaderOptions) -> Self {
272        Self {
273            arena: ReaderArenaImpl::new(segments, options),
274        }
275    }
276
277    fn get_root_internal(&self) -> Result<any_pointer::Reader<'_>> {
278        let (segment_start, _seg_len) = self.arena.get_segment(0)?;
279        let pointer_reader = unsafe {
280            layout::PointerReader::get_root(
281                &self.arena,
282                0,
283                segment_start,
284                self.arena.nesting_limit(),
285            )
286        }?;
287        Ok(any_pointer::Reader::new(pointer_reader))
288    }
289
290    /// Gets the root of the message, interpreting it as the given type.
291    pub fn get_root<'a, T: FromPointerReader<'a>>(&'a self) -> Result<T> {
292        self.get_root_internal()?.get_as()
293    }
294
295    pub fn into_segments(self) -> S {
296        self.arena.into_segments()
297    }
298
299    /// Checks whether the message is [canonical](https://capnproto.org/encoding.html#canonicalization).
300    pub fn is_canonical(&self) -> Result<bool> {
301        let (segment_start, seg_len) = self.arena.get_segment(0)?;
302
303        if self.arena.get_segment(1).is_ok() {
304            // TODO(cleanup, apibump): should there be a nicer way to ask the arena how many
305            // segments there are?
306
307            // There is more than one segment, so the message cannot be canonical.
308            return Ok(false);
309        }
310
311        let pointer_reader = unsafe {
312            layout::PointerReader::get_root(
313                &self.arena,
314                0,
315                segment_start,
316                self.arena.nesting_limit(),
317            )
318        }?;
319        let read_head = ::core::cell::Cell::new(unsafe { segment_start.add(BYTES_PER_WORD) });
320        let root_is_canonical = pointer_reader.is_canonical(&read_head)?;
321        let all_words_consumed = (read_head.get() as usize - segment_start as usize)
322            / BYTES_PER_WORD
323            == seg_len as usize;
324        Ok(root_is_canonical && all_words_consumed)
325    }
326
327    /// Gets the [canonical](https://capnproto.org/encoding.html#canonicalization) form
328    /// of this message. Works by copying the message twice. For a canonicalization
329    /// method that only requires one copy, see `message::Builder::set_root_canonical()`.
330    #[cfg(feature = "alloc")]
331    pub fn canonicalize(&self) -> Result<alloc::vec::Vec<crate::Word>> {
332        let root = self.get_root_internal()?;
333        let size = root.target_size()?.word_count + 1;
334        let mut message =
335            Builder::new(HeapAllocator::new().first_segment_words(u32::try_from(size).unwrap()));
336        message.set_root_canonical(root)?;
337        let output_segments = message.get_segments_for_output();
338        assert_eq!(1, output_segments.len());
339        let output = output_segments[0];
340        assert!((output.len() / BYTES_PER_WORD) as u64 <= size);
341        let mut result = crate::Word::allocate_zeroed_vec(output.len() / BYTES_PER_WORD);
342        crate::Word::words_to_bytes_mut(&mut result[..]).copy_from_slice(output);
343        Ok(result)
344    }
345
346    pub fn into_typed<T: Owned>(self) -> TypedReader<S, T> {
347        TypedReader::new(self)
348    }
349
350    pub fn size_in_words(&self) -> usize {
351        self.arena.size_in_words()
352    }
353
354    /// Retrieves the underlying [`ReaderSegments`] object.
355    pub fn get_segments(&self) -> &S {
356        self.arena.get_segments()
357    }
358}
359
360/// A message reader whose value is known to be of type `T`.
361/// Please see [module documentation](self) for more info about reader type specialization.
362pub struct TypedReader<S, T>
363where
364    S: ReaderSegments,
365    T: Owned,
366{
367    marker: ::core::marker::PhantomData<T>,
368    message: Reader<S>,
369}
370
371impl<S, T> TypedReader<S, T>
372where
373    S: ReaderSegments,
374    T: Owned,
375{
376    pub fn new(message: Reader<S>) -> Self {
377        Self {
378            marker: ::core::marker::PhantomData,
379            message,
380        }
381    }
382
383    pub fn get(&self) -> Result<T::Reader<'_>> {
384        self.message.get_root()
385    }
386
387    pub fn into_inner(self) -> Reader<S> {
388        self.message
389    }
390
391    /// Retrieves the underlying [`ReaderSegments`] object.
392    pub fn get_segments(&self) -> &S {
393        self.message.get_segments()
394    }
395}
396
397impl<S, T> From<Reader<S>> for TypedReader<S, T>
398where
399    S: ReaderSegments,
400    T: Owned,
401{
402    fn from(message: Reader<S>) -> Self {
403        Self::new(message)
404    }
405}
406
407impl<A, T> From<Builder<A>> for TypedReader<Builder<A>, T>
408where
409    A: Allocator,
410    T: Owned,
411{
412    fn from(message: Builder<A>) -> Self {
413        let reader = message.into_reader();
414        reader.into_typed()
415    }
416}
417
418impl<A, T> From<TypedBuilder<T, A>> for TypedReader<Builder<A>, T>
419where
420    A: Allocator,
421    T: Owned,
422{
423    fn from(builder: TypedBuilder<T, A>) -> Self {
424        builder.into_reader()
425    }
426}
427
428/// An object that allocates memory for a Cap'n Proto message as it is being built.
429///
430/// Users of capnproto-rust who wish to provide memory in non-standard ways should
431/// implement this trait. Objects implementing this trait are intended to be wrapped
432/// by `capnp::private::BuilderArena`, which handles calling the methods at the appropriate
433/// times, including calling `deallocate_segment()` on drop.
434///
435/// # Safety
436/// Implementations must ensure all of the following:
437///   1. The memory returned by `allocate_segment` is initialized to all zeroes.
438///   2. The memory returned by `allocate_segment` is valid until `deallocate_segment()`
439///      is called on it.
440///   3. The allocated memory does not overlap with other allocated memory.
441///   4. The allocated memory is 8-byte aligned (or the "unaligned" feature is enabled
442///      for the capnp crate).
443pub unsafe trait Allocator {
444    /// Allocates zeroed memory for a new segment, returning a pointer to the start of the segment
445    /// and a u32 indicating the length of the segment in words. The allocated segment must be
446    /// at least `minimum_size` words long (`minimum_size * 8` bytes long). Allocator implementations
447    /// commonly allocate much more than the minimum, to reduce the total number of segments needed.
448    /// A reasonable strategy is to allocate the maximum of `minimum_size` and twice the size of the
449    /// previous segment.
450    fn allocate_segment(&mut self, minimum_size: u32) -> (core::ptr::NonNull<u8>, u32);
451
452    /// Indicates that a segment, previously allocated via allocate_segment(), is no longer in use.
453    /// `word_size` is the length of the segment in words, as returned from `allocate_segment()`.
454    /// `words_used` is always less than or equal to `word_size`, and indicates how many
455    /// words (contiguous from the start of the segment) were possibly written with non-zero values.
456    ///
457    /// # Safety
458    /// Callers must only call this method on a pointer that has previously been returned
459    /// from `allocate_segment()`, and only once on each such segment. `word_size` must
460    /// equal the word size returned from `allocate_segment()`, and `words_used` must be at
461    /// most `word_size`.
462    unsafe fn deallocate_segment(
463        &mut self,
464        ptr: core::ptr::NonNull<u8>,
465        word_size: u32,
466        words_used: u32,
467    );
468}
469
470/// A container used to build a message.
471pub struct Builder<A>
472where
473    A: Allocator,
474{
475    arena: BuilderArenaImpl<A>,
476}
477
478fn _assert_kinds() {
479    fn _assert_send<T: Send>() {}
480    fn _assert_sync<T: Sync>() {}
481    fn _assert_reader<S: ReaderSegments + Send>() {
482        _assert_send::<Reader<S>>();
483    }
484    fn _assert_builder_send<A: Allocator + Send>() {
485        _assert_send::<Builder<A>>();
486    }
487    fn _assert_builder_sync<A: Allocator + Sync>() {
488        _assert_sync::<Builder<A>>();
489    }
490}
491
492impl<A> Builder<A>
493where
494    A: Allocator,
495{
496    pub fn new(allocator: A) -> Self {
497        Self {
498            arena: BuilderArenaImpl::new(allocator),
499        }
500    }
501
502    fn get_root_internal(&mut self) -> any_pointer::Builder<'_> {
503        if self.arena.is_empty() {
504            self.arena
505                .allocate_segment(1)
506                .expect("allocate root pointer");
507            self.arena.allocate(0, 1).expect("allocate root pointer");
508        }
509        let (seg_start, _seg_len) = self.arena.get_segment_mut(0);
510        let location: *mut u8 = seg_start;
511        let Self { arena } = self;
512
513        any_pointer::Builder::new(layout::PointerBuilder::get_root(arena, 0, location))
514    }
515
516    /// Initializes the root as a value of the given type.
517    pub fn init_root<'a, T: FromPointerBuilder<'a>>(&'a mut self) -> T {
518        let root = self.get_root_internal();
519        root.init_as()
520    }
521
522    /// Initializes the root as a value of the given list type, with the given length.
523    pub fn initn_root<'a, T: FromPointerBuilder<'a>>(&'a mut self, length: u32) -> T {
524        let root = self.get_root_internal();
525        root.initn_as(length)
526    }
527
528    /// Gets the root, interpreting it as the given type.
529    pub fn get_root<'a, T: FromPointerBuilder<'a>>(&'a mut self) -> Result<T> {
530        let root = self.get_root_internal();
531        root.get_as()
532    }
533
534    pub fn get_root_as_reader<'a, T: FromPointerReader<'a>>(&'a self) -> Result<T> {
535        if self.arena.is_empty() {
536            any_pointer::Reader::new(layout::PointerReader::new_default()).get_as()
537        } else {
538            let (segment_start, _segment_len) = self.arena.get_segment(0)?;
539            let pointer_reader = unsafe {
540                layout::PointerReader::get_root(
541                    self.arena.as_reader(),
542                    0,
543                    segment_start,
544                    0x7fffffff,
545                )
546            }?;
547            let root = any_pointer::Reader::new(pointer_reader);
548            root.get_as()
549        }
550    }
551
552    /// Sets the root to a deep copy of the given value.
553    pub fn set_root<T: Owned>(&mut self, value: impl SetterInput<T>) -> Result<()> {
554        let mut root = self.get_root_internal();
555        root.set_as(value)
556    }
557
558    /// Sets the root to a canonicalized version of `value`. If this was the first action taken
559    /// on this `Builder`, then a subsequent call to `get_segments_for_output()` should return
560    /// a single segment, containing the full canonicalized message.
561    pub fn set_root_canonical<T: Owned>(&mut self, value: impl SetterInput<T>) -> Result<()> {
562        if self.arena.is_empty() {
563            self.arena
564                .allocate_segment(1)
565                .expect("allocate root pointer");
566            self.arena.allocate(0, 1).expect("allocate root pointer");
567        }
568        let (seg_start, _seg_len) = self.arena.get_segment_mut(0);
569        let pointer = layout::PointerBuilder::get_root(&mut self.arena, 0, seg_start);
570        SetterInput::set_pointer_builder(pointer, value, true)?;
571        assert_eq!(self.get_segments_for_output().len(), 1);
572        Ok(())
573    }
574
575    pub fn get_segments_for_output(&self) -> OutputSegments<'_> {
576        self.arena.get_segments_for_output()
577    }
578
579    pub fn into_reader(self) -> Reader<Self> {
580        Reader::new(
581            self,
582            ReaderOptions {
583                traversal_limit_in_words: None,
584                nesting_limit: i32::MAX,
585            },
586        )
587    }
588
589    pub fn into_typed<T: Owned>(self) -> TypedBuilder<T, A> {
590        TypedBuilder::new(self)
591    }
592
593    /// Retrieves the underlying `Allocator`, deallocating all currently-allocated
594    /// segments.
595    pub fn into_allocator(self) -> A {
596        self.arena.into_allocator()
597    }
598
599    pub fn size_in_words(&self) -> usize {
600        self.arena.size_in_words()
601    }
602}
603
604impl<A> ReaderSegments for Builder<A>
605where
606    A: Allocator,
607{
608    fn get_segment(&self, id: u32) -> Option<&[u8]> {
609        self.get_segments_for_output().get(id as usize).copied()
610    }
611
612    fn len(&self) -> usize {
613        self.get_segments_for_output().len()
614    }
615}
616
617/// Strongly typed variant of the [Builder]
618///
619/// Generic type parameters:
620/// - `T` - type of the capnp message which this builder is specialized on. Please see
621///   [module documentation](self) for more info about builder type specialization.
622/// - `A` - type of allocator
623#[cfg(feature = "alloc")]
624pub struct TypedBuilder<T, A = HeapAllocator>
625where
626    T: Owned,
627    A: Allocator,
628{
629    marker: ::core::marker::PhantomData<T>,
630    message: Builder<A>,
631}
632
633// Defined separately because the A=HeapAllocator default type
634// argument is not allowed in no-alloc mode.
635// TODO(apibump): remove the A=HeapAllocator thing above?
636#[cfg(not(feature = "alloc"))]
637pub struct TypedBuilder<T, A>
638where
639    T: Owned,
640    A: Allocator,
641{
642    marker: ::core::marker::PhantomData<T>,
643    message: Builder<A>,
644}
645
646#[cfg(feature = "alloc")]
647impl<T> TypedBuilder<T, HeapAllocator>
648where
649    T: Owned,
650{
651    pub fn new_default() -> Self {
652        Default::default()
653    }
654}
655
656#[cfg(feature = "alloc")]
657impl<T> Default for TypedBuilder<T, HeapAllocator>
658where
659    T: Owned,
660{
661    fn default() -> Self {
662        Self::new(Builder::default())
663    }
664}
665
666impl<T, A> TypedBuilder<T, A>
667where
668    T: Owned,
669    A: Allocator,
670{
671    pub fn new(message: Builder<A>) -> Self {
672        Self {
673            marker: ::core::marker::PhantomData,
674            message,
675        }
676    }
677
678    pub fn init_root(&mut self) -> T::Builder<'_> {
679        self.message.init_root()
680    }
681
682    pub fn initn_root(&mut self, length: u32) -> T::Builder<'_> {
683        self.message.initn_root(length)
684    }
685
686    pub fn get_root(&mut self) -> Result<T::Builder<'_>> {
687        self.message.get_root()
688    }
689
690    pub fn get_root_as_reader(&self) -> Result<T::Reader<'_>> {
691        self.message.get_root_as_reader()
692    }
693
694    pub fn set_root(&mut self, value: T::Reader<'_>) -> Result<()> {
695        self.message.set_root(value)
696    }
697
698    pub fn into_inner(self) -> Builder<A> {
699        self.message
700    }
701
702    pub fn borrow_inner(&self) -> &Builder<A> {
703        &self.message
704    }
705
706    pub fn borrow_inner_mut(&mut self) -> &mut Builder<A> {
707        &mut self.message
708    }
709
710    pub fn into_reader(self) -> TypedReader<Builder<A>, T> {
711        TypedReader::new(self.message.into_reader())
712    }
713}
714
715impl<T, A> From<Builder<A>> for TypedBuilder<T, A>
716where
717    T: Owned,
718    A: Allocator,
719{
720    fn from(builder: Builder<A>) -> Self {
721        Self::new(builder)
722    }
723}
724
725/// Standard segment allocator. Allocates each segment via `alloc::alloc::alloc_zeroed()`.
726#[derive(Debug)]
727#[cfg(feature = "alloc")]
728pub struct HeapAllocator {
729    // Minimum number of words in the next allocation.
730    next_size: u32,
731
732    // How to update next_size after an allocation.
733    allocation_strategy: AllocationStrategy,
734
735    // Maximum number of words to allocate.
736    max_segment_words: u32,
737}
738
739#[derive(Clone, Copy, Debug)]
740pub enum AllocationStrategy {
741    /// Allocates the same number of words for each segment, to the extent possible.
742    /// This strategy is primarily useful for testing cross-segment pointers.
743    FixedSize,
744
745    /// Increases segment size by a multiplicative factor for each subsequent segment.
746    GrowHeuristically,
747}
748
749pub const SUGGESTED_FIRST_SEGMENT_WORDS: u32 = 1024;
750pub const SUGGESTED_ALLOCATION_STRATEGY: AllocationStrategy = AllocationStrategy::GrowHeuristically;
751
752#[cfg(feature = "alloc")]
753impl Default for HeapAllocator {
754    fn default() -> Self {
755        Self {
756            next_size: SUGGESTED_FIRST_SEGMENT_WORDS,
757            allocation_strategy: SUGGESTED_ALLOCATION_STRATEGY,
758            max_segment_words: 1 << 29,
759        }
760    }
761}
762
763#[cfg(feature = "alloc")]
764impl HeapAllocator {
765    pub fn new() -> Self {
766        Self::default()
767    }
768
769    /// Sets the size of the initial segment in words, where 1 word = 8 bytes.
770    pub fn first_segment_words(mut self, value: u32) -> Self {
771        assert!(value <= self.max_segment_words);
772        self.next_size = value;
773        self
774    }
775
776    /// Sets the allocation strategy for segments after the first one.
777    pub fn allocation_strategy(mut self, value: AllocationStrategy) -> Self {
778        self.allocation_strategy = value;
779        self
780    }
781
782    /// Sets the maximum number of words allowed in a single allocation.
783    pub fn max_segment_words(mut self, value: u32) -> Self {
784        assert!(self.next_size <= value);
785        self.max_segment_words = value;
786        self
787    }
788}
789
790#[cfg(feature = "alloc")]
791unsafe impl Allocator for HeapAllocator {
792    fn allocate_segment(&mut self, minimum_size: u32) -> (core::ptr::NonNull<u8>, u32) {
793        let size = core::cmp::max(minimum_size, self.next_size);
794        if size == 0 {
795            // passing a zero-sized layout to alloc_zeroed() leads to undefined behavior
796            return (core::ptr::NonNull::dangling(), 0);
797        }
798        let layout =
799            alloc::alloc::Layout::from_size_align(size as usize * BYTES_PER_WORD, 8).unwrap();
800        let ptr = unsafe { alloc::alloc::alloc_zeroed(layout) };
801        let Some(ptr) = core::ptr::NonNull::new(ptr) else {
802            alloc::alloc::handle_alloc_error(layout);
803        };
804        match self.allocation_strategy {
805            AllocationStrategy::GrowHeuristically => {
806                if size < self.max_segment_words - self.next_size {
807                    self.next_size += size;
808                } else {
809                    self.next_size = self.max_segment_words;
810                }
811            }
812            AllocationStrategy::FixedSize => {}
813        }
814        (ptr, size)
815    }
816
817    unsafe fn deallocate_segment(
818        &mut self,
819        ptr: core::ptr::NonNull<u8>,
820        word_size: u32,
821        _words_used: u32,
822    ) {
823        unsafe {
824            alloc::alloc::dealloc(
825                ptr.as_ptr(),
826                alloc::alloc::Layout::from_size_align(word_size as usize * BYTES_PER_WORD, 8)
827                    .unwrap(),
828            );
829        }
830        self.next_size = SUGGESTED_FIRST_SEGMENT_WORDS;
831    }
832}
833
834#[cfg(feature = "alloc")]
835#[test]
836fn test_allocate_max() {
837    let allocation_size = 1 << 24;
838    let mut allocator = HeapAllocator::new()
839        .max_segment_words((1 << 25) - 1)
840        .first_segment_words(allocation_size);
841
842    let (a1, s1) = allocator.allocate_segment(allocation_size);
843    let (a2, s2) = allocator.allocate_segment(allocation_size);
844    let (a3, s3) = allocator.allocate_segment(allocation_size);
845
846    assert_eq!(s1, allocation_size);
847
848    // Allocation size tops out at max_segment_words.
849    assert_eq!(s2, allocator.max_segment_words);
850    assert_eq!(s3, allocator.max_segment_words);
851
852    unsafe {
853        allocator.deallocate_segment(a1, s1, 0);
854        allocator.deallocate_segment(a2, s2, 0);
855        allocator.deallocate_segment(a3, s3, 0);
856    }
857}
858
859#[cfg(feature = "alloc")]
860impl Builder<HeapAllocator> {
861    /// Constructs a new `message::Builder<HeapAllocator>` whose first segment has length
862    /// `SUGGESTED_FIRST_SEGMENT_WORDS`.
863    pub fn new_default() -> Self {
864        Default::default()
865    }
866}
867
868#[cfg(feature = "alloc")]
869impl Default for Builder<HeapAllocator> {
870    /// Constructs a new `message::Builder<HeapAllocator>` whose first segment has length
871    /// `SUGGESTED_FIRST_SEGMENT_WORDS`.
872    fn default() -> Self {
873        Self::new(HeapAllocator::new())
874    }
875}
876
877/// An Allocator whose first segment is backed by a user-provided buffer.
878///
879/// Recall that an `Allocator` implementation must ensure that allocated segments are
880/// initially *zeroed*. `ScratchSpaceHeapAllocator` ensures that is the case by zeroing
881/// the entire buffer upon initial construction, and then zeroing any *potentially used*
882/// part of the buffer upon `deallocate_segment()`.
883///
884/// You can reuse a `ScratchSpaceHeapAllocator` by calling `message::Builder::into_allocator()`,
885/// or by initially passing it to `message::Builder::new()` as a `&mut ScratchSpaceHeapAllocator`.
886/// Such reuse can save significant amounts of zeroing.
887#[cfg(feature = "alloc")]
888pub struct ScratchSpaceHeapAllocator<'a> {
889    scratch_space: &'a mut [u8],
890    scratch_space_allocated: bool,
891    allocator: HeapAllocator,
892}
893
894#[cfg(feature = "alloc")]
895impl<'a> ScratchSpaceHeapAllocator<'a> {
896    /// Writes zeroes into the entire buffer and constructs a new allocator from it.
897    ///
898    /// If the buffer is large, this operation could be relatively expensive. If you want to reuse
899    /// the same scratch space in a later message, you should reuse the entire
900    /// `ScratchSpaceHeapAllocator`, to avoid paying this full cost again.
901    pub fn new(scratch_space: &'a mut [u8]) -> ScratchSpaceHeapAllocator<'a> {
902        #[cfg(not(feature = "unaligned"))]
903        {
904            if scratch_space.as_ptr() as usize % BYTES_PER_WORD != 0 {
905                panic!(
906                    "Scratch space must be 8-byte aligned, or you must enable the \"unaligned\" \
907                        feature in the capnp crate"
908                );
909            }
910        }
911
912        // We need to ensure that the buffer is zeroed.
913        for b in &mut scratch_space[..] {
914            *b = 0;
915        }
916        ScratchSpaceHeapAllocator {
917            scratch_space,
918            scratch_space_allocated: false,
919            allocator: HeapAllocator::new(),
920        }
921    }
922
923    /// Sets the size of the second segment in words, where 1 word = 8 bytes.
924    /// (The first segment is the scratch space passed to `ScratchSpaceHeapAllocator::new()`.
925    pub fn second_segment_words(self, value: u32) -> ScratchSpaceHeapAllocator<'a> {
926        ScratchSpaceHeapAllocator {
927            allocator: self.allocator.first_segment_words(value),
928            ..self
929        }
930    }
931
932    /// Sets the allocation strategy for segments after the second one.
933    pub fn allocation_strategy(self, value: AllocationStrategy) -> ScratchSpaceHeapAllocator<'a> {
934        ScratchSpaceHeapAllocator {
935            allocator: self.allocator.allocation_strategy(value),
936            ..self
937        }
938    }
939}
940
941#[cfg(feature = "alloc")]
942unsafe impl Allocator for ScratchSpaceHeapAllocator<'_> {
943    fn allocate_segment(&mut self, minimum_size: u32) -> (core::ptr::NonNull<u8>, u32) {
944        if (minimum_size as usize) <= (self.scratch_space.len() / BYTES_PER_WORD)
945            && !self.scratch_space_allocated
946        {
947            self.scratch_space_allocated = true;
948            (
949                core::ptr::NonNull::new(self.scratch_space.as_mut_ptr()).unwrap(),
950                u32::try_from(self.scratch_space.len() / BYTES_PER_WORD).unwrap(),
951            )
952        } else {
953            self.allocator.allocate_segment(minimum_size)
954        }
955    }
956
957    unsafe fn deallocate_segment(
958        &mut self,
959        ptr: core::ptr::NonNull<u8>,
960        word_size: u32,
961        words_used: u32,
962    ) {
963        let seg_ptr = self.scratch_space.as_mut_ptr();
964        if ptr.as_ptr() == seg_ptr {
965            // Rezero the slice to allow reuse of the allocator. We only need to write
966            // words that we know might contain nonzero values.
967            unsafe {
968                core::ptr::write_bytes(
969                    seg_ptr, // miri isn't happy if we use ptr instead
970                    0u8,
971                    (words_used as usize) * BYTES_PER_WORD,
972                );
973            }
974            self.scratch_space_allocated = false;
975        } else {
976            self.allocator
977                .deallocate_segment(ptr, word_size, words_used);
978        }
979    }
980}
981
982/// An Allocator whose first and only segment is backed by a user-provided buffer.
983/// If the segment fills up, subsequent allocations trigger panics.
984///
985/// The main purpose of this struct is to be used in situations where heap allocation
986/// is not available.
987///
988/// Recall that an `Allocator` implementation must ensure that allocated segments are
989/// initially *zeroed*. `SingleSegmentAllocator` ensures that is the case by zeroing
990/// the entire buffer upon initial construction, and then zeroing any *potentially used*
991/// part of the buffer upon `deallocate_segment()`.
992///
993/// You can reuse a `SingleSegmentAllocator` by calling `message::Builder::into_allocator()`,
994/// or by initially passing it to `message::Builder::new()` as a `&mut SingleSegmentAllocator`.
995/// Such reuse can save significant amounts of zeroing.
996pub struct SingleSegmentAllocator<'a> {
997    segment: &'a mut [u8],
998    segment_allocated: bool,
999}
1000
1001impl<'a> SingleSegmentAllocator<'a> {
1002    /// Writes zeroes into the entire buffer and constructs a new allocator from it.
1003    ///
1004    /// If the buffer is large, this operation could be relatively expensive. If you want to reuse
1005    /// the same scratch space in a later message, you should reuse the entire
1006    /// `SingleSegmentAllocator`, to avoid paying this full cost again.
1007    pub fn new(segment: &'a mut [u8]) -> SingleSegmentAllocator<'a> {
1008        #[cfg(not(feature = "unaligned"))]
1009        {
1010            if segment.as_ptr() as usize % BYTES_PER_WORD != 0 {
1011                panic!(
1012                    "Segment must be 8-byte aligned, or you must enable the \"unaligned\" \
1013                        feature in the capnp crate"
1014                );
1015            }
1016        }
1017
1018        // We need to ensure that the buffer is zeroed.
1019        for b in &mut segment[..] {
1020            *b = 0;
1021        }
1022        SingleSegmentAllocator {
1023            segment,
1024            segment_allocated: false,
1025        }
1026    }
1027}
1028
1029unsafe impl Allocator for SingleSegmentAllocator<'_> {
1030    fn allocate_segment(&mut self, minimum_size: u32) -> (core::ptr::NonNull<u8>, u32) {
1031        let available_word_count = self.segment.len() / BYTES_PER_WORD;
1032        if (minimum_size as usize) > available_word_count {
1033            panic!(
1034                "Allocation too large: asked for {minimum_size} words, \
1035                    but only {available_word_count} are available."
1036            )
1037        } else if self.segment_allocated {
1038            panic!("Tried to allocated two segments in a SingleSegmentAllocator.")
1039        } else {
1040            self.segment_allocated = true;
1041            (
1042                core::ptr::NonNull::new(self.segment.as_mut_ptr()).unwrap(),
1043                u32::try_from(self.segment.len() / BYTES_PER_WORD).unwrap(),
1044            )
1045        }
1046    }
1047
1048    unsafe fn deallocate_segment(
1049        &mut self,
1050        ptr: core::ptr::NonNull<u8>,
1051        _word_size: u32,
1052        words_used: u32,
1053    ) {
1054        let seg_ptr = self.segment.as_mut_ptr();
1055        if ptr.as_ptr() == seg_ptr {
1056            // Rezero the slice to allow reuse of the allocator. We only need to write
1057            // words that we know might contain nonzero values.
1058            unsafe {
1059                core::ptr::write_bytes(
1060                    seg_ptr, // miri isn't happy if we use ptr instead
1061                    0u8,
1062                    (words_used as usize) * BYTES_PER_WORD,
1063                );
1064            }
1065            self.segment_allocated = false;
1066        }
1067    }
1068}
1069
1070unsafe impl<A> Allocator for &'_ mut A
1071where
1072    A: Allocator,
1073{
1074    fn allocate_segment(&mut self, minimum_size: u32) -> (core::ptr::NonNull<u8>, u32) {
1075        (*self).allocate_segment(minimum_size)
1076    }
1077
1078    unsafe fn deallocate_segment(
1079        &mut self,
1080        ptr: core::ptr::NonNull<u8>,
1081        word_size: u32,
1082        words_used: u32,
1083    ) {
1084        (*self).deallocate_segment(ptr, word_size, words_used)
1085    }
1086}