Skip to content

Commit 7f98a95

Browse files
author
Artem Kryvokrysenko
committed
capnp: adding capnp::serialize::NoAllocSliceSegments and capnp::serialize::read_message_from_flat_slice_no_alloc
1 parent b3a51fe commit 7f98a95

File tree

3 files changed

+650
-1
lines changed

3 files changed

+650
-1
lines changed

capnp/src/serialize.rs

+21-1
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,9 @@
2323
//! [standard stream framing](https://capnproto.org/encoding.html#serialization-over-a-stream),
2424
//! where each message is preceded by a segment table indicating the size of its segments.
2525
26+
mod no_alloc_slice_segments;
27+
pub use no_alloc_slice_segments::NoAllocSliceSegments;
28+
2629
use alloc::string::ToString;
2730
use alloc::vec::Vec;
2831
use core::convert::TryInto;
@@ -33,6 +36,7 @@ use crate::message;
3336
use crate::private::units::BYTES_PER_WORD;
3437
use crate::{Error, Result};
3538

39+
pub const SEGMENTS_COUNT_LIMIT : usize = 512;
3640

3741
/// Segments read from a single flat slice of words.
3842
pub struct SliceSegments<'a> {
@@ -88,6 +92,22 @@ pub fn read_message_from_flat_slice<'a>(slice: &mut &'a [u8],
8892
}
8993
}
9094

95+
/// Reads a serialized message (including a segment table) from a flat slice of bytes, without copying.
96+
/// The slice is allowed to extend beyond the end of the message. On success, updates `slice` to point
97+
/// to the remaining bytes beyond the end of the message.
98+
///
99+
/// Unlike read_message_from_flat_slice_no_alloc it does not do heap allocation (except for error message)
100+
///
101+
/// ALIGNMENT: If the "unaligned" feature is enabled, then there are no alignment requirements on `slice`.
102+
/// Otherwise, `slice` must be 8-byte aligned (attempts to read the message will trigger errors).
103+
pub fn read_message_from_flat_slice_no_alloc<'a>(slice: &mut &'a [u8],
104+
options: message::ReaderOptions)
105+
-> Result<message::Reader<NoAllocSliceSegments<'a>>> {
106+
let segments = NoAllocSliceSegments::try_new(slice, options)?;
107+
108+
Ok(message::Reader::new(segments, options))
109+
}
110+
91111
/// Segments read from a buffer, useful for when you have the message in a buffer and don't want the extra
92112
/// copy of `read_message`.
93113
pub struct BufferSegments<T> {
@@ -291,7 +311,7 @@ fn read_segment_table<R>(read: &mut R,
291311

292312
let segment_count = u32::from_le_bytes(buf[0..4].try_into().unwrap()).wrapping_add(1) as usize;
293313

294-
if segment_count >= 512 {
314+
if segment_count >= SEGMENTS_COUNT_LIMIT {
295315
return Err(Error::failed(format!("Too many segments: {}", segment_count)))
296316
} else if segment_count == 0 {
297317
return Err(Error::failed(format!("Too few segments: {}", segment_count)))

0 commit comments

Comments
 (0)