pub trait NestedPacketBuilder {
    // Required methods
    fn try_constraints(&self) -> Option<PacketConstraints>;
    fn serialize_into<B: TargetBuffer>(&self, buffer: &mut B);

    // Provided methods
    fn encapsulate<O: NestedPacketBuilder>(self, outer: O) -> Nested<Self, O>
       where Self: Sized { ... }
    fn with_size_limit(self, limit: usize) -> LimitedSizePacketBuilder<Self>
       where Self: Sized { ... }
Expand description

One or more nested PacketBuilders.

A NestedPacketBuilder represents one or more PacketBuilders nested inside of each other. Two NestedPacketBuilders, a and b, can be composed by calling a.encapsulate(b). The resulting NestedPacketBuilder has a header comprising b’s header followed by a’s header, and has a footer comprising a’s footer followed by b’s footer. It also has minimum and maximum body length requirements which are the composition of those of a and b. See encapsulate for more details.

Required Methods§


fn try_constraints(&self) -> Option<PacketConstraints>

Gets the constraints for this NestedPacketBuilder.

If constraints returns None, it means that a valid PacketConstraints cannot be constructed. Since NestedPacketBuilders can be nested, multiple valid NestedPacketBuilders can nest to create an invalid NestedPacketBuilder. This can happen if an inner NestedPacketBuilder’s headers and footers take up more space than an outer NestedPacketBuilder’s maximum body length, so the maximum body length of this NestedPacketBuilder is technically negative. It can also happen if the header and footer lengths, when summed, overflow usize. In either case, the PacketConstraints type cannot represent the constraints, and no body exists which would satisfy those constraints (a satisfying body would need to have negative length). Thus, the correct behavior is to interpret a None value as implying that constraints are violated.

If constraints returns None, the caller must not call serialize_into, or risk unspecified behavior (including possibly a panic).


fn serialize_into<B: TargetBuffer>(&self, buffer: &mut B)

Serializes this NestedPacketBuilder into a buffer.

serialize_into takes a buffer containing a body, and serializes this NestedPacketBuilder’s headers and footers before and after that body respectively. When serialize_into returns, the buffer’s body has been expanded to include the newly-serialized headers and footers.

If the provided body is smaller than this NestedPacketBuilder’s minimum body length requirement, serialize_into will add padding after the body in order to meet that requriement. If this NestedPacketBuilder comprises multiple other NestedPacketBuilders with their own minimum body length requirements, then internal padding may be added between footers in order to meet those requirements. In particular, padding is always added after the body of the packet with that requirement (as opposed to after the body of an encapsulated packet).

Callers should not add their own post-body padding! The minimum body length requirement might come from a NestedPacketBuilder which is not the innermost one, in which case padding belongs after at least one of the footers, and adding padding directly after the body would be incorrect. As described in the previous paragraph, serialize_into will take care of putting padding in the right place.


Any added padding will be zeroed in order to ensure that the contents of another packet previously stored in the same buffer do not leak.


May panic if buffer doesn’t have enough prefix and suffix space to hold the headers and footers. In particular, if this NestedPacketBuilder has PacketConstraints c, then buffer must satisfy the following requirements:

  • buffer.prefix_len() >= c.header_len()
  • buffer.suffix_len() >= c.footer_len()
  • buffer.len() <= c.max_body_len()
  • If padding = c.min_body_len().saturating_sub(buffer.len()), then buffer.suffix_len() >= padding + c.footer_len()

Note that the PacketConstraints type has certain invariants that make it easier for implementers to satisfy these preconditions.

serialize_into may exhibit unspecified behavior (including possibly panicking) if self.try_constraints() returns None. In order to avoid a panic, the caller must call that method first, and only call serialize_into if it returns Some.

Provided Methods§


fn encapsulate<O: NestedPacketBuilder>(self, outer: O) -> Nested<Self, O>where Self: Sized,

Encapsulates this NestedPacketBuilder inside of another one.

If a and b are NestedPacketBuilders with PacketConstraints ac and bc, then a.encapsulate(b) produces a NestedPacketBuilder with the following properties:

  • Its header is equivalent to b’s header followed by a’s header, and has length bc.header_len() + ac.header_len()
  • Its footer is equivalent to a’s footer followed by b’s footer, and has length ac.footer_len() + bc.footer_len()
  • Its minimum body length requirement is core::cmp::max(ac.min_body_len(), bc.min_body_len() - (ac.header_len() + ac.footer_len()))
  • Its maximum body length requirement is core::cmp::min(ac.max_body_len(), bc.max_body_len() - (ac.header_len() + ac.footer_len()))

Note that a and b having valid PacketConstraints does not imply that a.encapsulate(b) will as well. This could be for one of the following reasons:

  • b has a maximum body length requirement which is exceeded by a’s headers and footers alone (without considering further space occupied by a body)
  • b has a maximum body length requirement which is exceeded by the sum of a’s header and footers and a’s minimum body length requirement
  • The PacketConstraints would have values that overflow usize, such as b’s header length plus a’s header length

fn with_size_limit(self, limit: usize) -> LimitedSizePacketBuilder<Self>where Self: Sized,

Constructs a new NestedPacketBuilder with an additional size limit constraint

The returned NestedPacketBuilder will have a maximum body length constraint equal to the minimum of its original maximum body length constraint and limit.