| // Copyright 2018 The Fuchsia Authors. All rights reserved. |
| // 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, |
| 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. |
| /// |
| /// A `Buf` wraps a byte slice (a type which implements `AsRef<[u8]>` or |
| /// `AsMut<[u8]>`) and implements `Buffer` and `BufferMut` by keeping track of |
| /// prefix, body, and suffix offsets within the byte slice. |
| pub struct Buf<B> { |
| buf: B, |
| range: Range<usize>, |
| } |
| |
| impl<B: AsRef<[u8]>> Buf<B> { |
| /// Constructs a new `Buf`. |
| /// |
| /// `new` constructs a new `Buf` from a buffer and a range. The bytes within |
| /// the range will be the body, the bytes before the range will be the |
| /// prefix, and the bytes after the range will be the suffix. |
| /// |
| /// # Panics |
| /// |
| /// `new` panics if `range` is out of bounds of `buf`, or if it is |
| /// nonsensical (the end precedes the start). |
| pub fn new<R: RangeBounds<usize>>(buf: B, range: R) -> Buf<B> { |
| let len = buf.as_ref().len(); |
| Buf { |
| buf, |
| range: canonicalize_range(len, &range), |
| } |
| } |
| |
| // in a separate method so it can be used in testing |
| pub(crate) fn buffer_view(&mut self) -> BufView { |
| BufView { |
| buf: self.buf.as_ref(), |
| range: &mut self.range, |
| } |
| } |
| } |
| |
| impl<B: AsRef<[u8]>> ParseBuffer for Buf<B> { |
| fn shrink<R: RangeBounds<usize>>(&mut self, range: R) { |
| let len = self.len(); |
| let mut range = canonicalize_range(len, &range); |
| range.start += self.range.start; |
| range.end += self.range.start; |
| self.range = range; |
| } |
| |
| fn len(&self) -> usize { |
| self.range.end - self.range.start |
| } |
| fn shrink_front(&mut self, n: usize) { |
| assert!(n <= self.len()); |
| self.range.start += n; |
| } |
| fn shrink_back(&mut self, n: usize) { |
| assert!(n <= self.len()); |
| self.range.end -= n; |
| } |
| fn parse_with<'a, ParseArgs, P: ParsablePacket<&'a [u8], ParseArgs>>( |
| &'a mut self, args: ParseArgs, |
| ) -> Result<P, P::Error> { |
| P::parse(self.buffer_view(), args) |
| } |
| fn as_buf(&self) -> Buf<&[u8]> { |
| // TODO(joshlf): Once we have impl specialization, can we specialize this at all? |
| Buf::new(self.buf.as_ref(), self.range.clone()) |
| } |
| } |
| |
| impl<B: AsRef<[u8]> + AsMut<[u8]>> ParseBufferMut for Buf<B> { |
| fn parse_with_mut<'a, ParseArgs, P: ParsablePacket<&'a mut [u8], ParseArgs>>( |
| &'a mut self, args: ParseArgs, |
| ) -> Result<P, P::Error> { |
| P::parse( |
| BufViewMut { |
| buf: self.buf.as_mut(), |
| range: &mut self.range, |
| }, |
| args, |
| ) |
| } |
| fn as_buf_mut(&mut self) -> Buf<&mut [u8]> { |
| Buf::new(self.buf.as_mut(), self.range.clone()) |
| } |
| } |
| |
| impl<B: AsRef<[u8]>> Buffer for Buf<B> { |
| fn capacity(&self) -> usize { |
| self.buf.as_ref().len() |
| } |
| fn prefix_len(&self) -> usize { |
| self.range.start |
| } |
| fn suffix_len(&self) -> usize { |
| self.buf.as_ref().len() - self.range.end |
| } |
| fn grow_front(&mut self, n: usize) { |
| assert!(n <= self.range.start); |
| self.range.start -= n; |
| } |
| fn grow_back(&mut self, n: usize) { |
| assert!(n <= self.buf.as_ref().len() - self.range.end); |
| self.range.end += n; |
| } |
| } |
| |
| impl<B: AsRef<[u8]> + AsMut<[u8]>> BufferMut for Buf<B> {} |
| |
| impl<B: AsRef<[u8]>> AsRef<[u8]> for Buf<B> { |
| fn as_ref(&self) -> &[u8] { |
| &self.buf.as_ref()[self.range.clone()] |
| } |
| } |
| |
| impl<B: AsMut<[u8]>> AsMut<[u8]> for Buf<B> { |
| fn as_mut(&mut self) -> &mut [u8] { |
| &mut self.buf.as_mut()[self.range.clone()] |
| } |
| } |
| |
| // used in testing in a different module |
| pub(crate) struct BufView<'a> { |
| buf: &'a [u8], |
| range: &'a mut Range<usize>, |
| } |
| |
| impl<'a> BufferView<&'a [u8]> for BufView<'a> { |
| fn take_front(&mut self, n: usize) -> Option<&'a [u8]> { |
| if self.len() < n { |
| return None; |
| } |
| self.range.start += n; |
| Some(take_front(&mut self.buf, n)) |
| } |
| |
| fn take_back(&mut self, n: usize) -> Option<&'a [u8]> { |
| if self.len() < n { |
| return None; |
| } |
| self.range.end -= n; |
| Some(take_back(&mut self.buf, n)) |
| } |
| |
| fn into_rest(self) -> &'a [u8] { |
| self.buf |
| } |
| } |
| |
| impl<'a> AsRef<[u8]> for BufView<'a> { |
| fn as_ref(&self) -> &[u8] { |
| self.buf |
| } |
| } |
| |
| struct BufViewMut<'a> { |
| buf: &'a mut [u8], |
| range: &'a mut Range<usize>, |
| } |
| |
| impl<'a> BufferView<&'a mut [u8]> for BufViewMut<'a> { |
| fn take_front(&mut self, n: usize) -> Option<&'a mut [u8]> { |
| if self.len() < n { |
| return None; |
| } |
| self.range.start += n; |
| Some(take_front_mut(&mut self.buf, n)) |
| } |
| |
| fn take_back(&mut self, n: usize) -> Option<&'a mut [u8]> { |
| if self.len() < n { |
| return None; |
| } |
| self.range.end -= n; |
| Some(take_back_mut(&mut self.buf, n)) |
| } |
| |
| fn into_rest(self) -> &'a mut [u8] { |
| self.buf |
| } |
| } |
| |
| impl<'a> BufferViewMut<&'a mut [u8]> for BufViewMut<'a> {} |
| |
| impl<'a> AsRef<[u8]> for BufViewMut<'a> { |
| fn as_ref(&self) -> &[u8] { |
| self.buf |
| } |
| } |
| |
| impl<'a> AsMut<[u8]> for BufViewMut<'a> { |
| fn as_mut(&mut self) -> &mut [u8] { |
| 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, |
| ); |
| } |
| } |
| } |
| } |
| } |
| } |
| } |
| } |