1//! Octets Builders
2//!
3//! Octets builders, i.e., anything that implements the [`OctetsBuilder`]
4//! trait, represent a buffer to which octets can be appended.
5//! Whether the buffer can grow to accommodate appended data depends on the
6//! underlying type.
7//!
8//! The [`OctetsBuilder`] trait only provides methods to append data to the
9//! builder. Implementations may, however, provide more functionality. They
10//! do so by implementing additional traits. Conversely, if additional
11//! functionality is needed from a builder, this can be expressed by
12//! adding trait bounds.
13//!
14//! Some examples are:
15//!
16//! * creating an empty octets builder from scratch is provided by the
17//! [`EmptyBuilder`] trait,
18//! * looking at already assembled octets is done via `AsRef<[u8]>`,
19//! * manipulation of already assembled octets requires `AsMut<[u8]>`, and
20//! * truncating the sequence of assembled octets happens through
21//! [`Truncate`].
2223use core::fmt;
24use core::convert::Infallible;
25#[cfg(feature = "bytes")] use bytes::{Bytes, BytesMut};
26#[cfg(feature = "std")] use std::borrow::Cow;
27#[cfg(feature = "std")] use std::vec::Vec;
282930//------------ OctetsBuilder -------------------------------------------------
3132/// A buffer to construct an octet sequence.
33///
34/// Octet builders represent a buffer of space available for building an
35/// octets sequence by appending the contents of octet slices. The buffers
36/// may consist of a predefined amount of space or grow as needed.
37///
38/// Octet builders provide access to the already assembled data through
39/// octet slices via their implementations of `AsRef<[u8]>` and
40/// `AsMut<[u8]>`.
41pub trait OctetsBuilder {
42/// The error type when appending data fails.
43 ///
44 /// There are exactly two options for this type: Builders where appending
45 /// never fails use `Infallible`. Builders with a limited buffer which
46 /// may have insufficient space for appending use [`ShortBuf`].
47 ///
48 /// The trait bound on the type allows upgrading the error to [`ShortBuf`]
49 /// even for builders with unlimited space. This way, an error type for
50 /// operations that use a builder doesn’t need to be generic over the
51 /// append error type and can simply use a variant for anything
52 /// `Into<ShortBuf>` instead.
53type AppendError: Into<ShortBuf>;
5455/// Appends the content of a slice to the builder.
56 ///
57 /// If there isn’t enough space available for appending the slice,
58 /// returns an error and leaves the builder alone.
59fn append_slice(
60&mut self, slice: &[u8]
61 ) -> Result<(), Self::AppendError>;
62}
6364impl<'a, T: OctetsBuilder> OctetsBuilder for &'a mut T {
65type AppendError = T::AppendError;
6667fn append_slice(
68&mut self, slice: &[u8]
69 ) -> Result<(), Self::AppendError> {
70 (*self).append_slice(slice)
71 }
72}
7374#[cfg(feature = "std")]
75impl OctetsBuilder for Vec<u8> {
76type AppendError = Infallible;
7778fn append_slice(
79&mut self, slice: &[u8]
80 ) -> Result<(), Self::AppendError> {
81self.extend_from_slice(slice);
82Ok(())
83 }
84}
8586#[cfg(feature = "std")]
87impl<'a> OctetsBuilder for Cow<'a, [u8]> {
88type AppendError = Infallible;
8990fn append_slice(
91&mut self, slice: &[u8]
92 ) -> Result<(), Self::AppendError> {
93if let Cow::Owned(ref mut vec) = *self {
94 vec.extend_from_slice(slice);
95 } else {
96let mut vec = std::mem::replace(
97self, Cow::Borrowed(b"")
98 ).into_owned();
99 vec.extend_from_slice(slice);
100*self = Cow::Owned(vec);
101 }
102Ok(())
103 }
104}
105106#[cfg(feature = "bytes")]
107impl OctetsBuilder for BytesMut {
108type AppendError = Infallible;
109110fn append_slice(
111&mut self, slice: &[u8]
112 ) -> Result<(), Self::AppendError> {
113self.extend_from_slice(slice);
114Ok(())
115 }
116}
117118#[cfg(feature = "smallvec")]
119impl<A: smallvec::Array<Item = u8>> OctetsBuilder for smallvec::SmallVec<A> {
120type AppendError = Infallible;
121122fn append_slice(
123&mut self, slice: &[u8]
124 ) -> Result<(), Self::AppendError> {
125self.extend_from_slice(slice);
126Ok(())
127 }
128}
129130#[cfg(feature = "heapless")]
131impl<const N: usize> OctetsBuilder for heapless::Vec<u8, N> {
132type AppendError = ShortBuf;
133134fn append_slice(
135&mut self, slice: &[u8]
136 ) -> Result<(), Self::AppendError> {
137self.extend_from_slice(slice).map_err(|_| ShortBuf)
138 }
139}
140141142//------------ Truncate ------------------------------------------------------
143144/// An octet sequence that can be shortened.
145pub trait Truncate {
146/// Truncate the sequence to `len` octets.
147 ///
148 /// If `len` is larger than the length of the sequence, nothing happens.
149fn truncate(&mut self, len: usize);
150}
151152impl<'a, T: Truncate> Truncate for &'a mut T {
153fn truncate(&mut self, len: usize) {
154 (*self).truncate(len)
155 }
156}
157158impl<'a> Truncate for &'a [u8] {
159fn truncate(&mut self, len: usize) {
160if len < self.len() {
161*self = &self[..len]
162 }
163 }
164}
165166#[cfg(feature = "std")]
167impl<'a> Truncate for Cow<'a, [u8]> {
168fn truncate(&mut self, len: usize) {
169match *self {
170 Cow::Borrowed(ref mut slice) => *slice = &slice[..len],
171 Cow::Owned(ref mut vec) => vec.truncate(len),
172 }
173 }
174}
175176#[cfg(feature = "std")]
177impl Truncate for Vec<u8> {
178fn truncate(&mut self, len: usize) {
179self.truncate(len)
180 }
181}
182183#[cfg(feature = "bytes")]
184impl Truncate for Bytes {
185fn truncate(&mut self, len: usize) {
186self.truncate(len)
187 }
188}
189190#[cfg(feature = "bytes")]
191impl Truncate for BytesMut {
192fn truncate(&mut self, len: usize) {
193self.truncate(len)
194 }
195}
196197#[cfg(feature = "smallvec")]
198impl<A: smallvec::Array<Item = u8>> Truncate for smallvec::SmallVec<A> {
199fn truncate(&mut self, len: usize) {
200self.truncate(len)
201 }
202}
203204#[cfg(feature = "heapless")]
205impl<const N: usize> Truncate for heapless::Vec<u8, N> {
206fn truncate(&mut self, len: usize) {
207self.truncate(len)
208 }
209}
210211212//------------ EmptyBuilder --------------------------------------------------
213214/// An octets builder that can be newly created empty.
215pub trait EmptyBuilder {
216/// Creates a new empty octets builder with a default size.
217fn empty() -> Self;
218219/// Creates a new empty octets builder with a suggested initial size.
220 ///
221 /// The builder may or may not use the size provided by `capacity` as the
222 /// initial size of the buffer. It may very well be possibly that the
223 /// builder is never able to grow to this capacity at all. Therefore,
224 /// even if you create a builder for your data size via this function,
225 /// appending may still fail.
226fn with_capacity(capacity: usize) -> Self;
227}
228229#[cfg(feature = "std")]
230impl EmptyBuilder for Vec<u8> {
231fn empty() -> Self {
232 Vec::new()
233 }
234235fn with_capacity(capacity: usize) -> Self {
236 Vec::with_capacity(capacity)
237 }
238}
239240#[cfg(feature = "bytes")]
241impl EmptyBuilder for BytesMut {
242fn empty() -> Self {
243 BytesMut::new()
244 }
245246fn with_capacity(capacity: usize) -> Self {
247 BytesMut::with_capacity(capacity)
248 }
249}
250251#[cfg(feature = "smallvec")]
252impl<A: smallvec::Array<Item = u8>> EmptyBuilder for smallvec::SmallVec<A> {
253fn empty() -> Self {
254 smallvec::SmallVec::new()
255 }
256257fn with_capacity(capacity: usize) -> Self {
258 smallvec::SmallVec::with_capacity(capacity)
259 }
260}
261262#[cfg(feature = "heapless")]
263impl<const N: usize> EmptyBuilder for heapless::Vec<u8, N> {
264fn empty() -> Self {
265Self::new()
266 }
267268fn with_capacity(capacity: usize) -> Self {
269debug_assert!(capacity <= N);
270Self::with_capacity(capacity)
271 }
272}
273274275//------------ FreezeBuilder -------------------------------------------------
276277/// An octets builder that can be frozen into a imutable octets sequence.
278pub trait FreezeBuilder {
279/// The type of octets sequence to builder will be frozen into.
280type Octets;
281282/// Converts the octets builder into an imutable octets sequence.
283fn freeze(self) -> Self::Octets;
284}
285286#[cfg(feature = "std")]
287impl FreezeBuilder for Vec<u8> {
288type Octets = Self;
289290fn freeze(self) -> Self::Octets {
291self
292}
293}
294295#[cfg(feature = "std")]
296impl<'a> FreezeBuilder for Cow<'a, [u8]> {
297type Octets = Self;
298299fn freeze(self) -> Self::Octets {
300self
301}
302}
303304#[cfg(feature = "bytes")]
305impl FreezeBuilder for BytesMut {
306type Octets = Bytes;
307308fn freeze(self) -> Self::Octets {
309 BytesMut::freeze(self)
310 }
311}
312313#[cfg(feature = "smallvec")]
314impl<A: smallvec::Array<Item = u8>> FreezeBuilder for smallvec::SmallVec<A> {
315type Octets = Self;
316317fn freeze(self) -> Self::Octets {
318self
319}
320}
321322#[cfg(feature = "heapless")]
323impl<const N: usize> FreezeBuilder for heapless::Vec<u8, N> {
324type Octets = Self;
325326fn freeze(self) -> Self::Octets {
327self
328}
329}
330331332//------------ IntoBuilder ---------------------------------------------------
333334/// An octets type that can be converted into an octets builder.
335pub trait IntoBuilder {
336/// The type of octets builder this octets type can be converted into.
337type Builder: OctetsBuilder;
338339/// Converts an octets value into an octets builder.
340fn into_builder(self) -> Self::Builder;
341}
342343#[cfg(feature = "std")]
344impl IntoBuilder for Vec<u8> {
345type Builder = Self;
346347fn into_builder(self) -> Self::Builder {
348self
349}
350}
351352#[cfg(feature = "std")]
353impl<'a> IntoBuilder for &'a [u8] {
354type Builder = Vec<u8>;
355356fn into_builder(self) -> Self::Builder {
357self.into()
358 }
359}
360361#[cfg(feature = "std")]
362impl<'a> IntoBuilder for Cow<'a, [u8]> {
363type Builder = Self;
364365fn into_builder(self) -> Self::Builder {
366self
367}
368}
369370#[cfg(feature = "bytes")]
371impl IntoBuilder for Bytes {
372type Builder = BytesMut;
373374fn into_builder(self) -> Self::Builder {
375// XXX Currently, we need to copy to do this. If bytes gains a way
376 // to convert from Bytes to BytesMut for non-shared data without
377 // copying, we should change this.
378BytesMut::from(self.as_ref())
379 }
380}
381382#[cfg(feature = "smallvec")]
383impl<A: smallvec::Array<Item = u8>> IntoBuilder for smallvec::SmallVec<A> {
384type Builder = Self;
385386fn into_builder(self) -> Self::Builder {
387self
388}
389}
390391#[cfg(feature = "heapless")]
392impl<const N: usize> IntoBuilder for heapless::Vec<u8, N> {
393type Builder = Self;
394395fn into_builder(self) -> Self::Builder {
396self
397}
398}
399400401//------------ FromBuilder ---------------------------------------------------
402403/// An octets type that can be created from an octets builder.
404pub trait FromBuilder: AsRef<[u8]> + Sized {
405/// The type of builder this octets type can be created from.
406type Builder: OctetsBuilder + FreezeBuilder<Octets = Self>;
407408/// Creates an octets value from an octets builder.
409fn from_builder(builder: Self::Builder) -> Self;
410}
411412#[cfg(feature = "std")]
413impl FromBuilder for Vec<u8> {
414type Builder = Self;
415416fn from_builder(builder: Self::Builder) -> Self {
417 builder
418 }
419}
420421#[cfg(feature = "std")]
422impl<'a> FromBuilder for Cow<'a, [u8]> {
423type Builder = Self;
424425fn from_builder(builder: Self::Builder) -> Self {
426 builder
427 }
428}
429430#[cfg(feature = "bytes")]
431impl FromBuilder for Bytes {
432type Builder = BytesMut;
433434fn from_builder(builder: Self::Builder) -> Self {
435 builder.freeze()
436 }
437}
438439#[cfg(feature = "smallvec")]
440impl<A: smallvec::Array<Item = u8>> FromBuilder for smallvec::SmallVec<A> {
441type Builder = Self;
442443fn from_builder(builder: Self::Builder) -> Self {
444 builder
445 }
446}
447448#[cfg(feature = "heapless")]
449impl<const N: usize> FromBuilder for heapless::Vec<u8, N> {
450type Builder = Self;
451452fn from_builder(builder: Self::Builder) -> Self {
453 builder
454 }
455}
456457458//------------ BuilderAppendError --------------------------------------------
459460/// A type alias resolving into the `AppendError` of an octets type’s builder.
461///
462/// This alias can be used rather than spelling out the complete litany in
463/// result types.
464pub type BuilderAppendError<Octets>
465 = <<Octets as FromBuilder>::Builder as OctetsBuilder>::AppendError;
466467468//============ Error Handling ================================================
469470//------------ ShortBuf ------------------------------------------------------
471472/// An attempt was made to write beyond the end of a buffer.
473///
474/// This type is returned as an error by all functions and methods that append
475/// data to an [octets builder] when the buffer size of the builder is not
476/// sufficient to append the data.
477///
478/// [octets builder]: trait.OctetsBuilder.html
479#[derive(Clone, Debug, Eq, PartialEq)]
480pub struct ShortBuf;
481482483//--- From
484485impl From<Infallible> for ShortBuf {
486fn from(_: Infallible) -> ShortBuf {
487unreachable!()
488 }
489}
490491492//--- Display and Error
493494impl fmt::Display for ShortBuf {
495fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
496 f.write_str("buffer size exceeded")
497 }
498}
499500#[cfg(feature = "std")]
501impl std::error::Error for ShortBuf {}
502503504//------------ Functions for Infallible --------------------------------------
505506/// Erases an error for infallible results.
507///
508/// This function can be used in place of the still unstable
509/// `Result::into_ok` for operations on infallible octets builders.
510///
511/// If you perform multiple operations, [`with_infallible`] allows you to
512/// use the question mark operator on them before erasing the error.
513pub fn infallible<T, E: Into<Infallible>>(src: Result<T, E>) -> T {
514match src {
515Ok(ok) => ok,
516Err(_) => unreachable!(),
517 }
518}
519520/// Erases an error for a closure returning an infallible results.
521///
522/// This function can be used for a sequence of operations on an infallible
523/// octets builder. By wrapping these operations in a closure, you can still
524/// use the question mark operator rather than having to wrap each individual
525/// operation in [`infallible`].
526pub fn with_infallible<F, T, E>(op: F) -> T
527where
528F: FnOnce() -> Result<T, E>,
529 E: Into<Infallible>,
530{
531 infallible(op())
532}
533