1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176
// Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.
// SPDX-License-Identifier: Apache-2.0
use crate::{Encoder, EncoderBuffer};
pub struct Buffer<'a> {
inner: EncoderBuffer<'a>,
#[cfg(feature = "bytes")]
extra: Option<bytes::Bytes>,
}
impl<'a> Buffer<'a> {
/// Ensures an extra bytes are written into the main EncoderBuffer.
#[inline]
pub fn flatten(&mut self) -> &mut EncoderBuffer<'a> {
self.flush();
&mut self.inner
}
}
/// Implement a version with `bytes` enabled
#[cfg(feature = "bytes")]
impl<'a> Buffer<'a> {
/// Initializes a buffer without any extra bytes at the end
#[inline]
pub fn new(inner: EncoderBuffer<'a>) -> Self {
Self { inner, extra: None }
}
/// Initializes the buffer with extra bytes
///
/// NOTE the EncoderBuffer position should not include the extra bytes. This ensures the bytes
/// can be "flushed" into the EncoderBuffer if another write happens or `flatten` is called.
#[inline]
pub fn new_with_extra(inner: EncoderBuffer<'a>, extra: Option<bytes::Bytes>) -> Self {
Self { inner, extra }
}
/// Converts the buffer into its inner parts
///
/// NOTE: the EncoderBuffer position will not include the extra bytes. The caller will need to
/// account for this data.
#[inline]
pub fn into_inner(self) -> (EncoderBuffer<'a>, Option<bytes::Bytes>) {
(self.inner, self.extra)
}
/// Returns the inner EncoderBuffer, along with the current extra bytes
#[inline]
pub fn inner_mut(&mut self) -> (&mut EncoderBuffer<'a>, &Option<bytes::Bytes>) {
(&mut self.inner, &self.extra)
}
/// Resets the encoder to its initial state while also dropping any extra bytes at the end
#[inline]
pub fn clear(&mut self) {
self.inner.set_position(0);
self.extra = None;
}
#[inline]
fn flush(&mut self) {
// move the extra bytes into the main buffer
if let Some(extra) = self.extra.take() {
self.inner.write_slice(&extra);
}
}
}
/// Include a functional implementation when `bytes` is not available
#[cfg(not(feature = "bytes"))]
impl<'a> Buffer<'a> {
#[inline]
pub fn new(inner: EncoderBuffer<'a>) -> Self {
Self { inner }
}
#[inline]
pub fn new_with_extra(inner: EncoderBuffer<'a>, extra: Option<&'static [u8]>) -> Self {
debug_assert!(extra.is_none());
Self { inner }
}
#[inline]
pub fn into_inner(self) -> (EncoderBuffer<'a>, Option<&'static [u8]>) {
(self.inner, None)
}
#[inline]
pub fn inner_mut(&mut self) -> (&mut EncoderBuffer<'a>, &Option<&'static [u8]>) {
(&mut self.inner, &None)
}
#[inline]
pub fn clear(&mut self) {
self.inner.set_position(0);
}
#[inline(always)]
fn flush(&mut self) {}
}
impl<'a> Encoder for Buffer<'a> {
/// We have special handling for writes that include `Bytes` so signal that
#[cfg(feature = "bytes")]
const SPECIALIZES_BYTES: bool = true;
#[inline]
fn write_sized<F: FnOnce(&mut [u8])>(&mut self, len: usize, write: F) {
// we need to flush the extra bytes if we have them
self.flush();
self.inner.write_sized(len, write)
}
#[inline]
fn write_slice(&mut self, slice: &[u8]) {
// we need to flush the extra bytes if we have them
self.flush();
self.inner.write_slice(slice);
}
#[inline]
#[cfg(feature = "bytes")]
fn write_bytes(&mut self, bytes: bytes::Bytes) {
// we need to flush the extra bytes if we have them and replace them with the new one
self.flush();
// ensure the underlying buffer is big enough for the write
self.inner.assert_capacity(bytes.len());
// store the extra bytes and defer the copy
self.extra = Some(bytes);
}
#[inline]
fn write_zerocopy<
T: zerocopy::AsBytes + zerocopy::FromBytes + zerocopy::Unaligned,
F: FnOnce(&mut T),
>(
&mut self,
write: F,
) {
// we need to flush the extra bytes if we have them
self.flush();
self.inner.write_zerocopy(write);
}
#[inline]
fn write_repeated(&mut self, count: usize, value: u8) {
// we need to flush the extra bytes if we have them
self.flush();
self.inner.write_repeated(count, value)
}
#[inline]
fn capacity(&self) -> usize {
self.inner.capacity()
}
#[inline]
#[cfg(feature = "bytes")]
fn len(&self) -> usize {
let mut len = self.inner.len();
// make sure our len includes the extra bytes if we have them
if let Some(extra) = self.extra.as_ref() {
len += extra.len();
}
len
}
#[inline]
#[cfg(not(feature = "bytes"))]
fn len(&self) -> usize {
self.inner.len()
}
}