[packet] Add serialization

Test: serialize::tests module

Change-Id: I44d2e73302907d929a318baccb9c4ebbe05c1f77
diff --git a/public/rust/packet/src/lib.rs b/public/rust/packet/src/lib.rs
index 66bb7d4..982424b 100644
--- a/public/rust/packet/src/lib.rs
+++ b/public/rust/packet/src/lib.rs
@@ -121,7 +121,7 @@
 //!                          Ipv4Packet { header, body }
 //!
 //! |-------------------------------------|--------------------|-----|
-//!              Buffer prefix                    Buffer body    Buffer suffix
+//!              Buffer prefix                 Buffer body       Buffer suffix
 //! ```
 //!
 //! We can continue this process as long as we like, repeatedly parsing
@@ -135,6 +135,216 @@
 //! section of this documentation), they are limited to doing so in a smaller
 //! buffer, making it more likely that a new buffer will need to be allocated.
 //!
+//! ## Serialization
+//!
+//! In this section, we will illustrate serialization using the same packet
+//! structure that was used to illustrate parsing - a TCP segment in an IPv4
+//! packet in an Ethernet frame.
+//!
+//! Serialization comprises two tasks:
+//! - First, given a buffer with sufficient capacity, and part of the packet
+//!   already serialized, serialize the next layer of the packet. For example,
+//!   given a buffer with a TCP segment already serialized in it, serialize the
+//!   IPv4 header, resulting in an IPv4 packet containing a TCP segment.
+//! - Second, given a description of a nested sequence of packets, figure out
+//!   the constraints that a buffer must satisfy in order to be able to fit the
+//!   entire sequence, and allocate a buffer which satisfies those constraints.
+//!   This buffer is then used to serialize one layer at a time, as described in
+//!   the previous bullet.
+//!
+//! ### Serializing into a buffer
+//!
+//! The `PacketBuilder` trait is implemented by types which are capable of
+//! serializing a new layer of a packet into an existing buffer. For example, we
+//! might define an `Ipv4PacketBuilder` type, which describes the source IP
+//! address, destination IP address, and any other metadata required to generate
+//! the header of an IPv4 packet. Importantly, a `PacketBuilder` does *not*
+//! define any encapsulated packets. In order to construct a TCP segment in an
+//! IPv4 packet, we would need a separate `TcpSegmentBuilder` to describe the
+//! TCP segment.
+//!
+//! A `PacketBuilder` exposes the number of bytes it requires for headers,
+//! footers, and minimum body lengths via the `header_len`, `footer_len`, and
+//! `min_body_len` methods. It serializes via the `serialize` method.
+//!
+//! In order to serialize a `PacketBuilder`, a `SerializeBuffer` must first be
+//! constructed. A `SerializeBuffer` is a view into a `Buffer` used for
+//! serialization, and it is initialized with the proper number of bytes for the
+//! header, footer, and body. The number of bytes required for these is
+//! discovered through calls to the `PacketBuilder`'s `header_len`,
+//! `footer_len`, and `min_body_len` methods.
+//!
+//! The `PacketBuilder`'s `serialize` method consumes the `PacketBuilder` itself
+//! and the `SerializeBuffer` by value, and serializes the headers and footers
+//! of the packet into the buffer. It expects that the `SerializeBuffer` is
+//! intialized with a body equal to the body which will be encapsulated. For
+//! example, imagine that we are trying to serialize a TCP segment in an IPv4
+//! packet in an Ethernet frame, and that, so far, we have only serialized the
+//! TCP segment:
+//!
+//! ```text
+//! |-------------------------------------|++++++++++++++++++++|-----| TCP segment
+//! |-----------------|++++++++++++++++++++++++++++++++++++++++|-----| IPv4 packet
+//! |++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++| Ethernet frame
+//!
+//! |-------------------------------------|--------------------|-----|
+//!                                             TCP segment
+//!
+//! |-------------------------------------|--------------------|-----|
+//!              Buffer prefix                 Buffer body       Buffer suffix
+//! ```
+//!
+//! Note that the buffer's body is currently equal to the TCP segment, and the
+//! contents of the body are already initialized to the segment's contents.
+//!
+//! Given an `Ipv4PacketBuilder`, we call the appropriate methods to discover
+//! that it requires 20 bytes for its header. Thus, we modify the buffer by
+//! extending the body by 20 bytes, and constructing a `SerializeBuffer` whose
+//! header references the newly-added 20 bytes, and whose body references the
+//! old contents of the body, corresponding to the TCP segment.
+//!
+//! ```text
+//! |-------------------------------------|++++++++++++++++++++|-----| TCP segment
+//! |-----------------|++++++++++++++++++++++++++++++++++++++++|-----| IPv4 packet
+//! |++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++| Ethernet frame
+//!
+//! |-----------------|-------------------|--------------------|-----|
+//!                        IPv4 header          IPv4 body
+//!                             |                   |
+//!                             +-----------+       |
+//!                                         |       |
+//!                      SerializeBuffer { header, body }
+//!
+//! |-----------------|----------------------------------------|-----|
+//!    Buffer prefix                 Buffer body                 Buffer suffix
+//! ```
+//!
+//! We then pass the `SerializeBuffer` to a call to the `Ipv4PacketBuilder`'s
+//! `serialize` method, and it serializes the IPv4 header in the space provided.
+//! When the call to `serialize` returns, the `SerializeBuffer` and
+//! `Ipv4PacketBuilder` have been discarded, and the buffer's body is now equal
+//! to the bytes of the IPv4 packet.
+//!
+//! ```text
+//! |-------------------------------------|++++++++++++++++++++|-----| TCP segment
+//! |-----------------|++++++++++++++++++++++++++++++++++++++++|-----| IPv4 packet
+//! |++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++| Ethernet frame
+//!
+//! |-----------------|----------------------------------------|-----|
+//!                                  IPv4 packet
+//!
+//! |-----------------|----------------------------------------|-----|
+//!    Buffer prefix                 Buffer body                 Buffer suffix
+//! ```
+//!
+//! Now, we area ready to repeat the same process with the Ethernet layer of the
+//! packet.
+//!
+//! ### Constructing a buffer for serialization
+//!
+//! Now that we know how, given a buffer with a subset of a packet serialized
+//! into it, we can serialize the next layer of the packet, we need to figure
+//! out how to construct such a buffer in the first place.
+//!
+//! The primary challenge here is that we need to be able to commit to what
+//! we're going to serialize before we actually serialize it. For example,
+//! consider sending a TCP segment to the network. From the perspective of the
+//! TCP module of our code, we don't know how large the buffer needs to be
+//! because don't know what packet layers our TCP segment will be encapsulated
+//! inside of. If the IP layer decides to route our segment over an Ethernet
+//! link, then we'll need to have a buffer large enough for a TCP segment in an
+//! IPv4 packet in an Ethernet segment. If, on the other hand, the IP layer
+//! decides to route our segment through a GRE tunnel, then we'll need to have a
+//! buffer large enough for a TCP segment in an IPv4 packet in a GRE packet in
+//! an IP packet in an Ethernet segment.
+//!
+//! We accomplish this commit-before-serializing via the `Serializer` trait. A
+//! `Serializer` describes a packet which can be serialized in the future, but
+//! which has not yet been serialized. Unlike a `PacketBuilder`, a `Serializer`
+//! describes all layers of a packet up to a certain point. For example, a
+//! `Serializer` might describe a TCP segment, or it might describe a TCP
+//! segment in an IP packet, or it might describe a TCP segment in an IP packet
+//! in an Ethernet frame, etc.
+//!
+//! #### Constructing a `Serializer`
+//!
+//! `Serializer`s are recursive - a `Serializer` combined with a `PacketBuilder`
+//! yields a new `Serializer` which describes encapsulating the original
+//! `Serializer` in a new packet layer. For example, a `Serializer` describing a
+//! TCP segment combined with an `Ipv4PacketBuilder` yields a `Serializer` which
+//! describes a TCP segment in an IPv4 packet. Concretely, given a `Serializer`,
+//! `s`, and a `PacketBuilder`, `b`, a new `Serializer` can be constructed by
+//! calling `s.encapsulate(b)`. The [`Serializer::encapsulate`] method consumes
+//! both the `Serializer` and the `PacketBuilder` by value, and returns a new
+//! `Serializer`.
+//!
+//! Note that, while `Serializer`s are passed around by value, they are only as
+//! large in memory as the `PacketBuilder`s they're constructed from, and those
+//! should, in most cases, be quite small. If size is a concern, the
+//! `PacketBuilder` trait can be implemented for a reference type (e.g.,
+//! `&Ipv4PacketBuilder`), and references passed around instead of values.
+//!
+//! #### Constructing a buffer from a `Serializer`
+//!
+//! If `Serializer`s are constructed by starting at the innermost packet layer
+//! and working outwards, adding packet layers, then in order to turn a
+//! `Serializer` into a buffer, they are consumed by starting at the outermost
+//! packet layer and working inwards.
+//!
+//! In order to construct a buffer, the [`Serializer::serialize`] method is
+//! provided. It takes a `Bar`, which describes the constraints built up by any
+//! encapsulating layers. For example, when serializing a TCP segment in an IP
+//! packet in an Ethernet frame, the `serialize` call on the IP packet
+//! `Serializer` would be given a `Bar` describing the Ethernet frame's
+//! requirement of 18 prefix bytes for its header. This call would then compute
+//! a new `Bar` describing the combined requirement of 38 prefix bytes for the
+//! IP and Ethernet headers combined, and would pass this to a call to
+//! `serialize` on the TCP segment `Serializer`.
+//!
+//! When the innermost call to `serialize` is reached, it is that call's
+//! responsibility to produce a buffer which satisfies the constraints passed to
+//! it, and to intialize that buffer's body with the contents of its packet. For
+//! example, the TCP segment `Serializer` from the preceding example would need
+//! to produce a buffer with 38 bytes of prefix, and whose body was initialized
+//! to the bytes of the TCP segment.
+//!
+//! We can now see how `Serializer`s and `PacketBuilder`s compose - the buffer
+//! returned from a call to `serialize` satisfies the requirements of the
+//! `PacketBuilder::serialize` method - its body is initialized to the packet to
+//! be encapsulated, and enough prefix and suffix space exist to serialize this
+//! layer's header and footer. For example, the call to `Serializer::serialize`
+//! on the TCP segment serializer would return a buffer with 38 bytes of prefix
+//! and a body initialized to the bytes of the TCP segment. The call to
+//! `Serializer::serialize` on the IP packet would then pass this buffer to a
+//! call to `PacketBuilder::serialize` on its `Ipv4PacketBuilder`, resulting in
+//! a buffer with 18 bytes of prefix and a body initialized to the bytes of the
+//! entire IP packet. This buffer would then be suitable to return from the call
+//! to `Serializer::serialize`, allowing the Ethernet layer to continue
+//! operating on the buffer, and so on.
+//!
+//! Note in particular that, throughout this entire process of constructing
+//! `Serializer`s and `PacketBuilder`s and then consuming them, a buffer is only
+//! allocated once, and each byte of the packet is only serialized once. No
+//! temporary buffers or copying between buffers is required.
+//!
+//! #### Reusing buffers
+//!
+//! Another important property of the `Serializer` trait is that it can be
+//! implemented by buffers. Since buffers contain prefixes, bodies, and
+//! suffixes, and since the `Serializer::serialize` method consumes the
+//! `Serializer` by value and returns a buffer by value, a buffer is itself a
+//! valid `Serializer`. When `serialize` is called, so long as it already
+//! satisfies the constraints requested, it can simply return itself by value.
+//! If the constraints are not satisfied, it may need to produce a different
+//! buffer through some user-defined mechanism. The [`BufferSerializer`] type
+//! wraps an existing buffer and implements the `Serializer` trait as described
+//! here.
+//!
+//! This allows existing buffers to be reused in many cases. For example,
+//! consider receiving a packet in a buffer, and then responding to that packet
+//! with a new packet. The buffer that the original packet was stored in can be
+//! used to serialize the new packet, avoiding any unnecessary allocation.
+//!
 //! # Monomorphization Overflow
 //!
 //! Because this crate's APIs make heavy use of static type parameters,
@@ -323,7 +533,7 @@
 pub trait ParseBufferMut: ParseBuffer + AsMut<[u8]> {
     /// Parses a mutable packet from the body.
     ///
-    /// `parse_mut` is like [`Buffer::parse`], but instead of calling
+    /// `parse_mut` is like [`ParseBuffer::parse`], but instead of calling
     /// [`P::parse`] on a [`BufferView`], it calls [`P::parse_mut`] on a
     /// [`BufferViewMut`]. The effect is that the parsed packet can contain
     /// mutable references to the buffer. This can be useful if you want to
@@ -365,7 +575,7 @@
 /// `AsRef<[u8]>` implementation provides acecss to the body.
 ///
 /// A `Buffer` guarantees never to discard bytes from the prefix or suffix,
-/// which is an important requirement for serialization. [1] For parsing, this
+/// which is an important requirement for serialization. \[1\] For parsing, this
 /// guarantee is not needed. The subset of methods which do not require this
 /// guarantee are defined in the `ParseBuffer` trait, which does not have this
 /// requirement. `Buffer` extends `ParseBuffer`.
@@ -501,6 +711,75 @@
         self.grow_front_zero(prefix);
         self.grow_back_zero(suffix);
     }
+
+    /// Serializes a packet in the buffer.
+    ///
+    /// `serialize` serializes the packet described in `builder` into the
+    /// buffer. The body of the buffer is used as the body of the packet, and
+    /// the prefix and suffix of the buffer are used to serialize the packet's
+    /// header and footer. This is a low-level function: you probably want the
+    /// [`Serializer`] trait instead.
+    ///
+    /// If `builder` has a minimum body size which is larger than the current
+    /// body, the body is first grown to the right (towards the end of the
+    /// buffer) with padding bytes in order to meet the minimum body size. This
+    /// is transparent to the `builder` - it always just sees a body which meets
+    /// the minimum body size requirement.
+    ///
+    /// The added padding is zeroed in order to avoid leaking the contents of
+    /// packets previously stored in the buffer.
+    ///
+    /// # Panics
+    ///
+    /// `serialize` panics if there are not enough prefix or suffix bytes to
+    /// serialize the packet. In particular, `b.serialize(buffer)` panics if
+    /// either of the following hold:
+    /// - `b.prefix_len() < buffer.header_bytes()`
+    /// - `b.len() + b.suffix_len() < buffer.min_body_bytes() +
+    ///   buffer.footer_bytes()`
+    fn serialize<B: PacketBuilder>(&mut self, builder: B) {
+        if self.len() < builder.min_body_len() {
+            // The body isn't large enough to satisfy the minimum body length
+            // requirement, so we add padding.
+
+            // SECURITY: Use _zero to ensure we zero padding bytes to prevent
+            // leaking information from packets previously stored in this
+            // buffer.
+            let len = self.len();
+            self.grow_back_zero(builder.min_body_len() - len);
+        }
+
+        let body_len = self.len();
+        // These aren't necessary for correctness (grow_xxx_zero will panic
+        // under the same conditions that these assertions will fail), but they
+        // provide nicer error messages for debugging.
+        debug_assert!(
+            self.prefix_len() >= builder.header_len(),
+            "prefix ({} bytes) too small to serialize header ({} bytes)",
+            self.prefix_len(),
+            builder.header_len()
+        );
+        debug_assert!(
+            self.suffix_len() >= builder.footer_len(),
+            "suffix ({} bytes) too small to serialize footer ({} bytes)",
+            self.suffix_len(),
+            builder.footer_len()
+        );
+        // SECURITY: _zero here is technically unncessary since it's
+        // PacketBuilder::serialize's responsibility to zero/initialize the
+        // header and footer, but we do it anyway to hedge against non-compliant
+        // PacketBuilder::serialize implementations. If this becomes a
+        // performance issue, we can revisit it, but the optimizer will probably
+        // take care of it for us.
+        self.grow_front_zero(builder.header_len());
+        self.grow_back_zero(builder.footer_len());
+
+        let body = builder.header_len()..(builder.header_len() + body_len);
+        builder.serialize(SerializeBuffer {
+            buf: self.as_mut(),
+            body,
+        });
+    }
 }
 
 /// A view into a `Buffer`.
@@ -757,11 +1036,6 @@
 /// buffer. It is recommended that as much of the packet object as possible be
 /// references into the buffer in order to avoid copying for performance
 /// reasons.
-///
-/// # Inner Packets
-///
-/// Inner packets - which do not encapsulate other packets - should implement
-/// [`ParsableInnerPacket`] instead.
 pub trait ParsablePacket<B: ByteSlice, ParseArgs>: Sized {
     /// The type of errors returned from `parse` and `parse_mut`.
     type Error;
@@ -813,6 +1087,84 @@
     fn parse_metadata(&self) -> ParseMetadata;
 }
 
+/// A view into a `BufferMut` used for serializing new packets.
+///
+/// A `SerializeBuffer` is a view into a `BufferMut` which is used by the
+/// [`PacketBuilder::serialize`] method to serialize a new packet. It is
+/// constructed by the [`BufferMut::serialize`] method.
+///
+/// A `SerializeBuffer` provides separate access to the bytes which will store
+/// the header, body, and footer of the new packet. The body is initialized to
+/// contain the bytes of the packet to be encapsulated (including any padding),
+/// and it is the caller's responsibility to serialize the header and footer.
+///
+/// `SerializeBuffer` implements `AsRef<[u8]>` and `AsMut<[u8]>`, providing a
+/// reference to the entire buffer (header, body, and footer) at once.
+pub struct SerializeBuffer<'a> {
+    buf: &'a mut [u8],
+    body: Range<usize>,
+}
+
+impl<'a> SerializeBuffer<'a> {
+    /// Constructs a new `SerializeBuffer`.
+    ///
+    /// `new` constructs a new `SerializeBuffer`. The entire buffer is
+    /// initialized to `buf`. The body is set to the subset of `buf` identified
+    /// by the range `body`. The header is set to the subset of `buf` preceding
+    /// the body, and the footer is set to the subset of `buf` following the
+    /// body.
+    ///
+    /// # Panics
+    ///
+    /// `new` panics if `body` is out of range of `buf`, or if the range is
+    /// nonsensical (the end precedes the start).
+    pub fn new<R: RangeBounds<usize>>(buf: &'a mut [u8], body: R) -> SerializeBuffer<'a> {
+        let body = canonicalize_range(buf.len(), &body);
+        SerializeBuffer { buf, body }
+    }
+
+    /// Gets the bytes of the header.
+    pub fn header(&mut self) -> &mut [u8] {
+        &mut self.buf[..self.body.start]
+    }
+
+    /// Gets the bytes of the body.
+    pub fn body(&mut self) -> &mut [u8] {
+        &mut self.buf[self.body.clone()]
+    }
+
+    /// Gets the bytes of the footer.
+    pub fn footer(&mut self) -> &mut [u8] {
+        &mut self.buf[self.body.end..]
+    }
+
+    /// Gets the bytes of the header, body, and footer.
+    ///
+    /// `parts` gets references to the header, body, and footer all at once.
+    /// Because of lifetime rules and the fact that the `header`, `body`, and
+    /// `footer` methods borrow this `SerializeBuffer`, this is the only way to
+    /// construct and operate on references to more than one section of the
+    /// buffer at a time.
+    pub fn parts(&mut self) -> (&mut [u8], &mut [u8], &mut [u8]) {
+        let buf = &mut self.buf;
+        let (prefix, rest) = buf.split_at_mut(self.body.start);
+        let (body, suffix) = rest.split_at_mut(self.body.end - self.body.start);
+        (prefix, body, suffix)
+    }
+}
+
+impl<'a> AsRef<[u8]> for SerializeBuffer<'a> {
+    fn as_ref(&self) -> &[u8] {
+        self.buf
+    }
+}
+
+impl<'a> AsMut<[u8]> for SerializeBuffer<'a> {
+    fn as_mut(&mut self) -> &mut [u8] {
+        self.buf
+    }
+}
+
 fn zero(bytes: &mut [u8]) {
     for byte in bytes.iter_mut() {
         *byte = 0;
@@ -1043,6 +1395,27 @@
     }
 
     #[test]
+    fn test_either_impl_buffer() {
+        macro_rules! test_either {
+            ($variant:ident) => {
+                test_buffer::<Either<Buf<Vec<u8>>, Buf<Vec<u8>>>, _>(|len| {
+                    Either::$variant(Buf::new(ascending(len), ..))
+                });
+                let mut buf: Either<Buf<Vec<u8>>, Buf<Vec<u8>>> =
+                    Either::$variant(Buf::new(ascending(10), ..));
+                test_buffer_view(match &mut buf {
+                    Either::$variant(buf) => buf.buffer_view(),
+                    _ => unreachable!(),
+                });
+                test_buffer_view_post(&buf, true);
+            };
+        }
+
+        test_either!(A);
+        test_either!(B);
+    }
+
+    #[test]
     fn test_buf_impl_buffer() {
         test_buffer(|len| Buf::new(ascending(len), ..));
         let mut buf = Buf::new(ascending(10), ..);
@@ -1193,7 +1566,7 @@
     // Each panic test case needs to be in its own function, which results in an
     // explosion of test functions. These macros generates the appropriate
     // function definitions automatically for a given type, reducing the amount
-    // of code by a factor of ~3.
+    // of code by a factor of ~4.
     macro_rules! make_parse_buffer_panic_tests {
         (
             $new_empty_buffer:expr,
@@ -1250,6 +1623,13 @@
         test_byte_slice_mut_nonsense_shrink_panics,
     );
     make_panic_tests!(
+        Either::A::<Buf<&[u8]>, Buf<&[u8]>>(Buf::new(&[][..], ..)),
+        test_either_slice_panics,
+        test_either_nonsense_slice_panics,
+        test_either_grow_front_panics,
+        test_either_grow_back_panics,
+    );
+    make_panic_tests!(
         Buf::new(&[][..], ..),
         test_buf_shrink_panics,
         test_buf_nonsense_shrink_panics,
diff --git a/public/rust/packet/src/serialize.rs b/public/rust/packet/src/serialize.rs
index 1343271..c63b72c 100644
--- a/public/rust/packet/src/serialize.rs
+++ b/public/rust/packet/src/serialize.rs
@@ -2,10 +2,155 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
+///! Serialization.
+
+use std::cmp;
 use std::ops::{Range, RangeBounds};
 
 use crate::{canonicalize_range, take_back, take_back_mut, take_front, take_front_mut, Buffer,
-            BufferMut, BufferView, BufferViewMut, ParsablePacket, ParseBuffer, ParseBufferMut};
+            BufferMut, BufferView, BufferViewMut, ParsablePacket, ParseBuffer, ParseBufferMut,
+            SerializeBuffer};
+
+/// Either of two buffers.
+///
+/// An `Either` wraps one of two different buffer types. It implements all of
+/// the relevant traits by calling the corresponding methods on the wrapped
+/// buffer.
+pub enum Either<A, B> {
+    A(A),
+    B(B),
+}
+
+macro_rules! call_method_on_either {
+    ($val:expr, $method:ident, $($args:expr),*) => {
+        match $val {
+            Either::A(a) => a.$method($($args),*),
+            Either::B(b) => b.$method($($args),*),
+        }
+    };
+    ($val:expr, $method:ident) => {
+        call_method_on_either!($val, $method,)
+    };
+}
+
+// NOTE(joshlf): We override the default implementations of all methods for
+// Either. Many of the default implementations make multiple calls to other
+// Buffer methods, each of which performs a match statement to figure out which
+// Either variant is present. We assume that doing this match once is more
+// performant than doing it multiple times.
+
+impl<A, B> ParseBuffer for Either<A, B>
+where
+    A: ParseBuffer,
+    B: ParseBuffer,
+{
+    fn shrink<R: RangeBounds<usize>>(&mut self, range: R) {
+        call_method_on_either!(self, shrink, range)
+    }
+    fn len(&self) -> usize {
+        call_method_on_either!(self, len)
+    }
+    fn is_empty(&self) -> bool {
+        call_method_on_either!(self, is_empty)
+    }
+    fn shrink_front(&mut self, n: usize) {
+        call_method_on_either!(self, shrink_front, n)
+    }
+    fn shrink_back(&mut self, n: usize) {
+        call_method_on_either!(self, shrink_back, n)
+    }
+    fn parse<'a, P: ParsablePacket<&'a [u8], ()>>(&'a mut self) -> Result<P, P::Error> {
+        call_method_on_either!(self, parse)
+    }
+    fn parse_with<'a, ParseArgs, P: ParsablePacket<&'a [u8], ParseArgs>>(
+        &'a mut self, args: ParseArgs,
+    ) -> Result<P, P::Error> {
+        call_method_on_either!(self, parse_with, args)
+    }
+    fn as_buf(&self) -> Buf<&[u8]> {
+        call_method_on_either!(self, as_buf)
+    }
+}
+
+impl<A, B> ParseBufferMut for Either<A, B>
+where
+    A: ParseBufferMut,
+    B: ParseBufferMut,
+{
+    fn parse_mut<'a, P: ParsablePacket<&'a mut [u8], ()>>(&'a mut self) -> Result<P, P::Error> {
+        call_method_on_either!(self, parse_mut)
+    }
+    fn parse_with_mut<'a, ParseArgs, P: ParsablePacket<&'a mut [u8], ParseArgs>>(
+        &'a mut self, args: ParseArgs,
+    ) -> Result<P, P::Error> {
+        call_method_on_either!(self, parse_with_mut, args)
+    }
+    fn as_buf_mut(&mut self) -> Buf<&mut [u8]> {
+        call_method_on_either!(self, as_buf_mut)
+    }
+}
+
+impl<A, B> Buffer for Either<A, B>
+where
+    A: Buffer,
+    B: Buffer,
+{
+    fn capacity(&self) -> usize {
+        call_method_on_either!(self, capacity)
+    }
+    fn prefix_len(&self) -> usize {
+        call_method_on_either!(self, prefix_len)
+    }
+    fn suffix_len(&self) -> usize {
+        call_method_on_either!(self, suffix_len)
+    }
+    fn grow_front(&mut self, n: usize) {
+        call_method_on_either!(self, grow_front, n)
+    }
+    fn grow_back(&mut self, n: usize) {
+        call_method_on_either!(self, grow_back, n)
+    }
+    fn reset(&mut self) {
+        call_method_on_either!(self, reset)
+    }
+}
+
+impl<A, B> BufferMut for Either<A, B>
+where
+    A: BufferMut,
+    B: BufferMut,
+{
+    fn reset_zero(&mut self) {
+        call_method_on_either!(self, reset_zero)
+    }
+    fn serialize<BB: PacketBuilder>(&mut self, builder: BB) {
+        call_method_on_either!(self, serialize, builder)
+    }
+}
+
+impl<A: AsRef<[u8]>, B: AsRef<[u8]>> AsRef<[u8]> for Either<A, B> {
+    fn as_ref(&self) -> &[u8] {
+        call_method_on_either!(self, as_ref)
+    }
+}
+
+impl<A: AsMut<[u8]>, B: AsMut<[u8]>> AsMut<[u8]> for Either<A, B> {
+    fn as_mut(&mut self) -> &mut [u8] {
+        call_method_on_either!(self, as_mut)
+    }
+}
+
+impl<A, B> AsRef<Either<A, B>> for Either<A, B> {
+    fn as_ref(&self) -> &Either<A, B> {
+        self
+    }
+}
+
+impl<A, B> AsMut<Either<A, B>> for Either<A, B> {
+    fn as_mut(&mut self) -> &mut Either<A, B> {
+        self
+    }
+}
 
 /// A byte slice wrapper providing [`Buffer`] functionality.
 ///
@@ -201,3 +346,524 @@
         self.buf
     }
 }
+
+/// A builder capable of serializing packets into an existing
+/// buffer, and which encapsulate other packets.
+///
+/// A `PacketBuilder` describes a packet, and is capable of serializing that
+/// packet into an existing buffer via the `serialize` method.
+///
+/// Note that `PacketBuilder` does not describe an entire nested sequence of
+/// packets - such as a TCP segment encapsulated in an IP packet - but instead
+/// describes only a single packet - such as the IP packet in the previous
+/// example. Given a buffer with a packet already serialized in its body, the
+/// `PacketBuilder` is responsible for encapsulating that packet by serializing
+/// its header and footer before and after the existing packet.
+pub trait PacketBuilder {
+    /// The number of bytes in this packet's header.
+    fn header_len(&self) -> usize;
+    /// The minimum size of body required by this packet.
+    fn min_body_len(&self) -> usize;
+    /// The number of bytes in this packet's footer.
+    fn footer_len(&self) -> usize;
+
+    /// Serializes this packet into an existing buffer.
+    ///
+    /// `serialize` is called with a [`SerializeBuffer`] which provides access
+    /// to the parts of a buffer corresponding to the header, body, and footer
+    /// of this packet. The header and footer bytes will be uninitialized, and
+    /// will have the number of bytes specified by the `header_len` and
+    /// `footer_len` methods. The body will be initialized with the contents of
+    /// the packet to be encapsulated, and will have at least `min_body_len`
+    /// bytes (padding may have been added in order to satisfy this minimum).
+    /// `serialize` is responsible for serializing the header and footer into
+    /// the appropriate sections of the buffer.
+    ///
+    /// # Security
+    ///
+    /// All of the bytes of the header and footer should be initialized, even if
+    /// only to zero, in order to avoid leaking the contents of packets
+    /// previously stored in the same buffer.
+    fn serialize(self, buffer: SerializeBuffer);
+}
+
+/// A builder capable of serializing packets into an existing buffer, and which
+/// do not encapsulate other packets.
+///
+/// An `InnerPacketBuilder` describes a packet, and is capable of serializing
+/// that packet into an existing buffer via the `serialize` method. Unlike the
+/// [`PacketBuilder`] trait, it describes a packet which does not encapsulate
+/// other packets.
+///
+/// # Notable implementations
+///
+/// `InnerPacketBuilder` is implemented for `&[u8]`, `&mut [u8]`, and `Vec<u8>`
+/// by treating the contents of the slice/`Vec` as the contents of the packet to
+/// be serialized.
+pub trait InnerPacketBuilder {
+    /// The number of bytes consumed by this packet.
+    fn bytes(&self) -> usize;
+
+    /// Serializes this packet into an existing buffer.
+    ///
+    /// `serialize` is called with a buffer of length `self.bytes()`, and is
+    /// responsible for serializing the packet into the buffer.
+    ///
+    /// # Security
+    ///
+    /// All of the bytes of the buffer should be initialized, even if only to
+    /// zero, in order to avoid leaking the contents of packets previously
+    /// stored in the same buffer.
+    fn serialize(self, buffer: &mut [u8]);
+}
+
+impl<'a> InnerPacketBuilder for &'a [u8] {
+    fn bytes(&self) -> usize {
+        self.len()
+    }
+    fn serialize(self, buffer: &mut [u8]) {
+        buffer.copy_from_slice(self);
+    }
+}
+impl<'a> InnerPacketBuilder for &'a mut [u8] {
+    fn bytes(&self) -> usize {
+        self.len()
+    }
+    fn serialize(self, buffer: &mut [u8]) {
+        buffer.copy_from_slice(self);
+    }
+}
+impl<'a> InnerPacketBuilder for Vec<u8> {
+    fn bytes(&self) -> usize {
+        self.len()
+    }
+    fn serialize(self, buffer: &mut [u8]) {
+        buffer.copy_from_slice(self.as_slice());
+    }
+}
+
+/// Constraints passed to [`Serializer::serialize`].
+///
+/// `SerializeConstraints` describes the prefix length, minimum body length, and
+/// suffix length required of the buffer returned from a call to `serialize`.
+pub struct SerializeConstraints {
+    pub prefix_len: usize,
+    pub min_body_len: usize,
+    pub suffix_len: usize,
+}
+
+pub trait Serializer: Sized {
+    /// The type of buffers returned from a call to `serialize`.
+    type Buffer: BufferMut;
+
+    /// Serialize this `Serializer`, producing a buffer.
+    ///
+    /// `serialize` accepts a set of constraints, and produces a buffer which
+    /// satisfies them. In particular, the returned buffer must:
+    /// - Have at least `c.prefix_len` bytes of prefix
+    /// - Have at least `c.min_body_len` bytes of body, initialized to the
+    ///   contents of the packet described by this `Serializer`
+    /// - Have at least `c.suffix_len` bytes of suffix
+    fn serialize(self, c: SerializeConstraints) -> Self::Buffer;
+
+    /// Serialize this `Serializer` as the outmost packet.
+    ///
+    /// `serialize_outer` is like `serialize`, except that it is called when
+    /// this `Serializer` describes the outmost packet, not encapsulated in any
+    /// other packets. It is equivalent to calling `serialize` with a
+    /// `SerializationConstraints` of all zeros.
+    fn serialize_outer(self) -> Self::Buffer {
+        self.serialize(SerializeConstraints {
+            prefix_len: 0,
+            min_body_len: 0,
+            suffix_len: 0,
+        })
+    }
+
+    /// Encapsulate this `Serializer` in another packet, producing a new
+    /// `Serializer`.
+    ///
+    /// `encapsulate` consumes this `Serializer` and a [`PacketBuilder`], and
+    /// produces a new `Serializer` which describes encapsulating this one in
+    /// the packet described by `builder`. Calling `serialize` on the returned
+    /// `Serializer` will do the following:
+    /// - Call `serialize` on this `Serializer`, producing a buffer
+    /// - Serialize `builder` into the buffer as the next layer of the packet
+    /// - Return the buffer
+    fn encapsulate<B: PacketBuilder>(self, builder: B) -> EncapsulatingSerializer<B, Self> {
+        EncapsulatingSerializer {
+            builder,
+            inner: self,
+        }
+    }
+}
+
+// TODO(joshlf): Once impl specialization is stable, make this a default impl,
+// and add a specializing impl for 'B: Buffer'.
+
+impl<B: InnerPacketBuilder> Serializer for B {
+    type Buffer = Buf<Vec<u8>>;
+
+    fn serialize(self, c: SerializeConstraints) -> Buf<Vec<u8>> {
+        let body_bytes = cmp::max(c.min_body_len, self.bytes());
+        let total_len = c.prefix_len + body_bytes + c.suffix_len;
+        let body_range = c.prefix_len..(c.prefix_len + self.bytes());
+
+        let mut buf = vec![0; total_len];
+        <Self as InnerPacketBuilder>::serialize(self, &mut buf[body_range.clone()]);
+        Buf::new(buf, body_range)
+    }
+}
+
+/// A [`Serializer`] for inner packets, wrapping an [`InnerPacketBuilder`] and a
+/// buffer.
+///
+/// An `InnerSerializer` implements `Serializer` for an `InnerPacketBuilder`. It
+/// stores a buffer for the fast path and, in case that buffer does not satisfy
+/// the constraints passed to [`Serializer::serialize`], it stores a function
+/// capable of producing a buffer which does.
+pub struct InnerSerializer<B, Buf, F> {
+    builder: B,
+    buf: Buf,
+    get_buf: F,
+}
+
+impl<B, Buf, F> InnerSerializer<B, Buf, F> {
+    /// Constructs a new `InnerSerializer`.
+    ///
+    /// `new` accepts an [`InnerPacketBuilder`], a buffer, and a function. When
+    /// `serialize` is called, two things happen:
+    /// - A buffer is produced. If the existing buffer satisfies the constraints
+    ///   passed to `serialize`, it is used. Otherwise, `get_buf` is used to
+    ///   produce a buffer which satisfies the constraints.
+    /// - Once a buffer has been produced, the `InnerPacketBuilder` is
+    ///   serialized into it, and it is returned.
+    ///
+    /// `get_buf` is a function which accepts a `usize` and produces a buffer of
+    /// that length.
+    pub fn new(builder: B, buffer: Buf, get_buf: F) -> InnerSerializer<B, Buf, F> {
+        InnerSerializer {
+            builder,
+            buf: buffer,
+            get_buf,
+        }
+    }
+}
+
+// NOTE(joshlf): This impl block may look a bit confusing. What's happening is
+// that we can't write down the type of the closure that we're passing to
+// InnerSerializer::new, so we have to have new_vec return an 'impl FnOnce...'.
+// However, we can't write 'impl<B, Buf> InnerSerializer<B, Buf, impl
+// FnOnce...>' because that's not valid syntax. Instead, we pick a dummy
+// variable for the third type parameter. Note that it doesn't have to be the
+// same type as the return value from new_vec. Thus, when you write something
+// like:
+//
+// let x = InnerSerializer::new_vec();
+//
+// It's equivalent to:
+//
+// let x: InnerSerializer<_, _, _> = InnerSerializer::<_, _, ()>::new_vec();
+//
+// The type on the left is different from the type on the right.
+
+impl<B, Buf> InnerSerializer<B, Buf, ()> {
+    /// Constructs a new `InnerSerializer` which allocates a new `Vec` as a
+    /// fallback path.
+    ///
+    /// `new_vec` is like `new`, except that its `get_buf` function is
+    /// automatically set to allocate a new `Vec` on the heap.
+    pub fn new_vec(
+        builder: B, buffer: Buf,
+    ) -> InnerSerializer<B, Buf, impl FnOnce(usize) -> crate::Buf<Vec<u8>>> {
+        InnerSerializer {
+            builder,
+            buf: buffer,
+            get_buf: |n| crate::Buf::new(vec![0; n], ..),
+        }
+    }
+}
+
+impl<B, Buf, O, F> Serializer for InnerSerializer<B, Buf, F>
+where
+    B: InnerPacketBuilder,
+    Buf: BufferMut,
+    O: BufferMut,
+    F: FnOnce(usize) -> O,
+{
+    type Buffer = Either<Buf, O>;
+
+    fn serialize(self, c: SerializeConstraints) -> Either<Buf, O> {
+        let InnerSerializer {
+            builder,
+            mut buf,
+            get_buf,
+        } = self;
+        let total_len =
+            c.prefix_len + cmp::max(c.min_body_len, builder.bytes()) + c.suffix_len;
+
+        let mut buf = if buf.capacity() >= total_len {
+            buf.reset();
+            Either::A(buf)
+        } else {
+            Either::B(get_buf(total_len))
+        };
+        buf.shrink(c.prefix_len..(c.prefix_len + builder.bytes()));
+        builder.serialize(buf.as_mut());
+        buf
+    }
+}
+
+/// A [`Serializer`] for inner packets, wrapping an `InnerPacketBuilder`.
+///
+/// An `FnSerializer` implements `Serializer` for an [`InnerPacketBuilder`]. It
+/// stores a function which is called to produce a buffer. This function is used
+/// to implement [`Serializer::serialize`].
+pub struct FnSerializer<B, F> {
+    builder: B,
+    get_buf: F,
+}
+
+impl<B, F> FnSerializer<B, F> {
+    /// Constructs a new `FnSerializer`.
+    ///
+    /// `new` takes an [`InnerPacketBuider`] and a function, and produces a
+    /// `FnSerializer`. The function accepts a `usize`, and produces a buffer of
+    /// that length.
+    ///
+    /// When `serialize` is called, `get_buf` is called in order to produce a
+    /// buffer, `builder` is serialized into the buffer, and it is returned.
+    pub fn new(builder: B, get_buf: F) -> FnSerializer<B, F> {
+        FnSerializer { builder, get_buf }
+    }
+}
+
+// See comment on InnerSerializer for why we have this impl block.
+
+impl<B> FnSerializer<B, ()> {
+    /// Constructs a new `FnSerializer` which allocates a new `Vec`.
+    ///
+    /// `new_vec` is like `new`, except that its `get_buf` function is
+    /// automatically set to allocate a new `Vec` on the heap.
+    pub fn new_vec(builder: B) -> FnSerializer<B, impl FnOnce(usize) -> Buf<Vec<u8>>> {
+        FnSerializer::new(builder, |n| Buf::new(vec![0; n], ..))
+    }
+}
+
+impl<B, O, F> Serializer for FnSerializer<B, F>
+where
+    B: InnerPacketBuilder,
+    O: BufferMut,
+    F: FnOnce(usize) -> O,
+{
+    type Buffer = O;
+
+    fn serialize(self, c: SerializeConstraints) -> O {
+        let FnSerializer { builder, get_buf } = self;
+        let total_len =
+            c.prefix_len + cmp::max(c.min_body_len, builder.bytes()) + c.suffix_len;
+
+        let mut buf = get_buf(total_len);
+        buf.shrink(c.prefix_len..(c.prefix_len + builder.bytes()));
+        builder.serialize(buf.as_mut());
+        buf
+    }
+}
+
+/// A [`Serializer`] which returns a packet already serialized into an existing
+/// buffer.
+///
+/// A `BufferSerializer` wraps an existing buffer, and implements the
+/// `Serializer` trait, treating the body of the buffer as the packet to be
+/// serialized. In the fast path, when the buffer already satisfies the
+/// constraints passed to [`Serializer::serialize`], the buffer itself is
+/// returned. In the slow path, a function is used to produce a buffer which
+/// satisfies the constraints, and the body is copied from the original buffer
+/// to the new one.
+///
+/// `BufferSerializer`s are useful as performance optimization in order to avoid
+/// unnecessary allocation when a buffer already exists during serialization.
+/// This can happen, for example, when a buffer is used to store an incoming
+/// packet, and then that buffer can be reused to serialize an outgoing packet
+/// sent in response.
+pub struct BufferSerializer<B, F> {
+    buf: B,
+    get_buf: F,
+}
+
+impl<B, F> BufferSerializer<B, F> {
+    /// Constructs a new `BufferSerializer`.
+    ///
+    /// `new` accepts a buffer and a `get_buf` function, which produces a
+    /// buffer. When `serialize` is called, if the existing buffer satisfies the
+    /// constraints, it is returned. Otherwise, `get_buf` is used to produce a
+    /// buffer which satisfies the constraints, and the body is copied from the
+    /// original buffer into the new one before it is returned.
+    ///
+    /// `get_buf` accepts a `usize`, and produces a buffer of that length.
+    pub fn new(buffer: B, get_buf: F) -> BufferSerializer<B, F> {
+        BufferSerializer {
+            buf: buffer,
+            get_buf,
+        }
+    }
+}
+
+// See comment on InnerSerializer for why we have this impl block.
+
+impl<B> BufferSerializer<B, ()> {
+    /// Constructs a new `BufferSerializer` which allocates a new `Vec` in the
+    /// fallback path.
+    ///
+    /// `new_vec` is like `new`, except that its `get_buf` function is
+    /// automatically set to allocate a new `Vec` on the heap.
+    pub fn new_vec(buffer: B) -> BufferSerializer<B, impl FnOnce(usize) -> Buf<Vec<u8>>> {
+        BufferSerializer::new(buffer, |n| Buf::new(vec![0; n], ..))
+    }
+}
+
+impl<B: BufferMut, O: BufferMut, F: FnOnce(usize) -> O> Serializer for BufferSerializer<B, F> {
+    type Buffer = Either<B, O>;
+
+    fn serialize(self, c: SerializeConstraints) -> Either<B, O> {
+        let BufferSerializer { buf, get_buf } = self;
+        let body_and_padding = cmp::max(c.min_body_len, buf.len());
+        let total_len = c.prefix_len + body_and_padding + c.suffix_len;
+
+        if buf.prefix_len() >= c.prefix_len
+            && buf.len() + buf.suffix_len() >= body_and_padding + c.suffix_len
+        {
+            // The buffer satisfies the requirements, so there's no work to do.
+            Either::A(buf)
+        // } else if buf.cap() >= total_len {
+        //     // The buffer is large enough, but the body is currently too far
+        //     // forward or too far backwards to satisfy the prefix or suffix
+        //     // requirements, so we need to move the body within the buffer.
+        //     unimplemented!()
+        } else {
+            // The buffer is too small, so we need to allocate a new one.
+            let mut new_buf = get_buf(total_len);
+            new_buf.shrink(c.prefix_len..(c.prefix_len + buf.len()));
+            new_buf.as_mut().copy_from_slice(buf.as_ref());
+            Either::B(new_buf)
+        }
+    }
+}
+
+/// A [`Serializer`] which encapsulates another `Serializer` in a new packet
+/// layer described by a [`PacketBuilder`].
+///
+/// An `EncapsulatingSerializer` takes a `Serializer` - which describes a
+/// complete packet - and a `PacketBuilder` - which describes a new layer of a
+/// packet - and produces a `Serializer` which describes the encapsulation of
+/// the former in the latter.
+///
+/// `EncapsulatingSerializer`s are produced by the [`Serializer::encapsulate`]
+/// method.
+pub struct EncapsulatingSerializer<B: PacketBuilder, S: Serializer> {
+    builder: B,
+    inner: S,
+}
+
+impl<B: PacketBuilder, S: Serializer> Serializer for EncapsulatingSerializer<B, S> {
+    type Buffer = S::Buffer;
+
+    fn serialize(self, mut c: SerializeConstraints) -> Self::Buffer {
+        c.prefix_len += self.builder.header_len();
+        c.suffix_len += self.builder.footer_len();
+
+        // The number required by this layer.
+        let this_min_body = self.builder.min_body_len();
+        // The number required by the next outer layer, taking into account
+        // that header_len + footer_len will be consumed by this layer.
+        let next_min_body = c
+            .min_body_len
+            .checked_sub(self.builder.header_len() + self.builder.footer_len())
+            .unwrap_or(0);
+        c.min_body_len = cmp::max(this_min_body, next_min_body);
+
+        let EncapsulatingSerializer { builder, inner } = self;
+        let mut buffer = inner.serialize(c);
+        buffer.serialize(builder);
+        buffer
+    }
+}
+
+#[cfg(test)]
+mod tests {
+    use super::*;
+
+    #[test]
+    fn test_buffer_serializer_and_inner_serializer() {
+        fn verify_buffer_serializer<B: BufferMut>(
+            buffer: B, prefix_len: usize, suffix_len: usize, min_body_len: usize,
+        ) {
+            let old_len = buffer.len();
+            let mut old_body = Vec::with_capacity(old_len);
+            old_body.extend_from_slice(buffer.as_ref());
+
+            let buffer = BufferSerializer::new_vec(buffer).serialize(SerializeConstraints {
+                prefix_len,
+                suffix_len,
+                min_body_len,
+            });
+            verify(buffer, &old_body, prefix_len, suffix_len, min_body_len);
+        }
+
+        fn verify_inner_serializer(
+            body: &[u8], buf_len: usize, prefix_len: usize, suffix_len: usize, min_body_len: usize,
+        ) {
+            let buffer =
+                InnerSerializer::new_vec(body, Buf::new(vec![0; buf_len], ..)).serialize(SerializeConstraints {
+                    prefix_len,
+                    suffix_len,
+                    min_body_len,
+                });
+            verify(buffer, body, prefix_len, suffix_len, min_body_len);
+        }
+
+        fn verify<B: Buffer>(
+            buffer: B, body: &[u8], prefix_len: usize, suffix_len: usize, min_body_len: usize,
+        ) {
+            assert_eq!(buffer.as_ref(), body);
+            assert!(buffer.prefix_len() >= prefix_len);
+            assert!(buffer.suffix_len() >= suffix_len);
+            assert!(buffer.len() + buffer.suffix_len() >= (min_body_len + suffix_len));
+        }
+        // Test for every valid combination of buf_len, range_start, range_end,
+        // prefix, suffix, and min_body within [0, 8).
+        for buf_len in 0..8 {
+            for range_start in 0..buf_len {
+                for range_end in range_start..buf_len {
+                    for prefix in 0..8 {
+                        for suffix in 0..8 {
+                            for min_body in 0..8 {
+                                let mut vec = vec![0; buf_len];
+                                // Initialize the vector with values 0, 1, 2,
+                                // ... so that we can check to make sure that
+                                // the range bytes have been properly copied if
+                                // the buffer is reallocated.
+                                for i in 0..vec.len() {
+                                    vec[i] = i as u8;
+                                }
+                                verify_buffer_serializer(
+                                    Buf::new(vec.as_mut_slice(), range_start..range_end),
+                                    prefix,
+                                    suffix,
+                                    min_body,
+                                );
+                                verify_inner_serializer(
+                                    &vec.as_slice()[range_start..range_end],
+                                    buf_len,
+                                    prefix,
+                                    suffix,
+                                    min_body,
+                                );
+                            }
+                        }
+                    }
+                }
+            }
+        }
+    }
+}