octseq/
builder.rs

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`].
22
23use 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;
28
29
30//------------ OctetsBuilder -------------------------------------------------
31
32/// 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.
53    type AppendError: Into<ShortBuf>;
54
55    /// 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.
59    fn append_slice(
60        &mut self, slice: &[u8]
61    ) -> Result<(), Self::AppendError>;
62}
63
64impl<'a, T: OctetsBuilder> OctetsBuilder for &'a mut T {
65    type AppendError = T::AppendError;
66
67    fn append_slice(
68        &mut self, slice: &[u8]
69    ) -> Result<(), Self::AppendError> {
70        (*self).append_slice(slice)
71    }
72}
73
74#[cfg(feature = "std")]
75impl OctetsBuilder for Vec<u8> {
76    type AppendError = Infallible;
77
78    fn append_slice(
79        &mut self, slice: &[u8]
80    ) -> Result<(), Self::AppendError> {
81        self.extend_from_slice(slice);
82        Ok(())
83    }
84}
85
86#[cfg(feature = "std")]
87impl<'a> OctetsBuilder for Cow<'a, [u8]> {
88    type AppendError = Infallible;
89
90    fn append_slice(
91        &mut self, slice: &[u8]
92    ) -> Result<(), Self::AppendError> {
93        if let Cow::Owned(ref mut vec) = *self {
94            vec.extend_from_slice(slice);
95        } else {
96            let mut vec = std::mem::replace(
97                self, Cow::Borrowed(b"")
98            ).into_owned();
99            vec.extend_from_slice(slice);
100            *self = Cow::Owned(vec);
101        }
102        Ok(())
103    }
104}
105
106#[cfg(feature = "bytes")]
107impl OctetsBuilder for BytesMut {
108    type AppendError = Infallible;
109
110    fn append_slice(
111        &mut self, slice: &[u8]
112    ) -> Result<(), Self::AppendError> {
113        self.extend_from_slice(slice);
114        Ok(())
115    }
116}
117
118#[cfg(feature = "smallvec")]
119impl<A: smallvec::Array<Item = u8>> OctetsBuilder for smallvec::SmallVec<A> {
120    type AppendError = Infallible;
121
122    fn append_slice(
123        &mut self, slice: &[u8]
124    ) -> Result<(), Self::AppendError> {
125        self.extend_from_slice(slice);
126        Ok(())
127    }
128}
129
130#[cfg(feature = "heapless")]
131impl<const N: usize> OctetsBuilder for heapless::Vec<u8, N> {
132    type AppendError = ShortBuf;
133
134    fn append_slice(
135        &mut self, slice: &[u8]
136    ) -> Result<(), Self::AppendError> {
137        self.extend_from_slice(slice).map_err(|_| ShortBuf)
138    }
139}
140
141
142//------------ Truncate ------------------------------------------------------
143
144/// 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.
149    fn truncate(&mut self, len: usize);
150}
151
152impl<'a, T: Truncate> Truncate for &'a mut T {
153    fn truncate(&mut self, len: usize) {
154        (*self).truncate(len)
155    }
156}
157
158impl<'a> Truncate for &'a [u8] {
159    fn truncate(&mut self, len: usize) {
160        if len < self.len() {
161            *self = &self[..len]
162        }
163    }
164}
165
166#[cfg(feature = "std")]
167impl<'a> Truncate for Cow<'a, [u8]> {
168    fn truncate(&mut self, len: usize) {
169        match *self {
170            Cow::Borrowed(ref mut slice) => *slice = &slice[..len],
171            Cow::Owned(ref mut vec) => vec.truncate(len),
172        }
173    }
174}
175
176#[cfg(feature = "std")]
177impl Truncate for Vec<u8> {
178    fn truncate(&mut self, len: usize) {
179        self.truncate(len)
180    }
181}
182
183#[cfg(feature = "bytes")]
184impl Truncate for Bytes {
185    fn truncate(&mut self, len: usize) {
186        self.truncate(len)
187    }
188}
189
190#[cfg(feature = "bytes")]
191impl Truncate for BytesMut {
192    fn truncate(&mut self, len: usize) {
193        self.truncate(len)
194    }
195}
196
197#[cfg(feature = "smallvec")]
198impl<A: smallvec::Array<Item = u8>> Truncate for smallvec::SmallVec<A> {
199    fn truncate(&mut self, len: usize) {
200        self.truncate(len)
201    }
202}
203
204#[cfg(feature = "heapless")]
205impl<const N: usize> Truncate for heapless::Vec<u8, N> {
206    fn truncate(&mut self, len: usize) {
207        self.truncate(len)
208    }
209}
210
211
212//------------ EmptyBuilder --------------------------------------------------
213
214/// An octets builder that can be newly created empty.
215pub trait EmptyBuilder {
216    /// Creates a new empty octets builder with a default size.
217    fn empty() -> Self;
218
219    /// 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.
226    fn with_capacity(capacity: usize) -> Self;
227}
228
229#[cfg(feature = "std")]
230impl EmptyBuilder for Vec<u8> {
231    fn empty() -> Self {
232        Vec::new()
233    }
234
235    fn with_capacity(capacity: usize) -> Self {
236        Vec::with_capacity(capacity)
237    }
238}
239
240#[cfg(feature = "bytes")]
241impl EmptyBuilder for BytesMut {
242    fn empty() -> Self {
243        BytesMut::new()
244    }
245
246    fn with_capacity(capacity: usize) -> Self {
247        BytesMut::with_capacity(capacity)
248    }
249}
250
251#[cfg(feature = "smallvec")]
252impl<A: smallvec::Array<Item = u8>> EmptyBuilder for smallvec::SmallVec<A> {
253    fn empty() -> Self {
254        smallvec::SmallVec::new()
255    }
256
257    fn with_capacity(capacity: usize) -> Self {
258        smallvec::SmallVec::with_capacity(capacity)
259    }
260}
261
262#[cfg(feature = "heapless")]
263impl<const N: usize> EmptyBuilder for heapless::Vec<u8, N> {
264    fn empty() -> Self {
265        Self::new()
266    }
267
268    fn with_capacity(capacity: usize) -> Self {
269        debug_assert!(capacity <= N);
270        Self::with_capacity(capacity)
271    }
272}
273
274
275//------------ FreezeBuilder -------------------------------------------------
276
277/// 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.
280    type Octets;
281
282    /// Converts the octets builder into an imutable octets sequence.
283    fn freeze(self) -> Self::Octets;
284}
285
286#[cfg(feature = "std")]
287impl FreezeBuilder for Vec<u8> {
288    type Octets = Self;
289
290    fn freeze(self) -> Self::Octets {
291        self
292    }
293}
294
295#[cfg(feature = "std")]
296impl<'a> FreezeBuilder for Cow<'a, [u8]> {
297    type Octets = Self;
298
299    fn freeze(self) -> Self::Octets {
300        self
301    }
302}
303
304#[cfg(feature = "bytes")]
305impl FreezeBuilder for BytesMut {
306    type Octets = Bytes;
307
308    fn freeze(self) -> Self::Octets {
309        BytesMut::freeze(self)
310    }
311}
312
313#[cfg(feature = "smallvec")]
314impl<A: smallvec::Array<Item = u8>> FreezeBuilder for smallvec::SmallVec<A> {
315    type Octets = Self;
316
317    fn freeze(self) -> Self::Octets {
318        self
319    }
320}
321
322#[cfg(feature = "heapless")]
323impl<const N: usize> FreezeBuilder for heapless::Vec<u8, N> {
324    type Octets = Self;
325
326    fn freeze(self) -> Self::Octets {
327        self
328    }
329}
330
331
332//------------ IntoBuilder ---------------------------------------------------
333
334/// 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.
337    type Builder: OctetsBuilder;
338
339    /// Converts an octets value into an octets builder.
340    fn into_builder(self) -> Self::Builder;
341}
342
343#[cfg(feature = "std")]
344impl IntoBuilder for Vec<u8> {
345    type Builder = Self;
346
347    fn into_builder(self) -> Self::Builder {
348        self
349    }
350}
351
352#[cfg(feature = "std")]
353impl<'a> IntoBuilder for &'a [u8] {
354    type Builder = Vec<u8>;
355
356    fn into_builder(self) -> Self::Builder {
357        self.into()
358    }
359}
360
361#[cfg(feature = "std")]
362impl<'a> IntoBuilder for Cow<'a, [u8]> {
363    type Builder = Self;
364
365    fn into_builder(self) -> Self::Builder {
366        self
367    }
368}
369
370#[cfg(feature = "bytes")]
371impl IntoBuilder for Bytes {
372    type Builder = BytesMut;
373
374    fn 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.
378        BytesMut::from(self.as_ref())
379    }
380}
381
382#[cfg(feature = "smallvec")]
383impl<A: smallvec::Array<Item = u8>> IntoBuilder for smallvec::SmallVec<A> {
384    type Builder = Self;
385
386    fn into_builder(self) -> Self::Builder {
387        self
388    }
389}
390
391#[cfg(feature = "heapless")]
392impl<const N: usize> IntoBuilder for heapless::Vec<u8, N> {
393    type Builder = Self;
394
395    fn into_builder(self) -> Self::Builder {
396        self
397    }
398}
399
400
401//------------ FromBuilder ---------------------------------------------------
402
403/// 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.
406    type Builder: OctetsBuilder + FreezeBuilder<Octets = Self>;
407
408    /// Creates an octets value from an octets builder.
409    fn from_builder(builder: Self::Builder) -> Self;
410}
411
412#[cfg(feature = "std")]
413impl FromBuilder for Vec<u8> {
414    type Builder = Self;
415
416    fn from_builder(builder: Self::Builder) -> Self {
417        builder
418    }
419}
420
421#[cfg(feature = "std")]
422impl<'a> FromBuilder for Cow<'a, [u8]> {
423    type Builder = Self;
424
425    fn from_builder(builder: Self::Builder) -> Self {
426        builder
427    }
428}
429
430#[cfg(feature = "bytes")]
431impl FromBuilder for Bytes {
432    type Builder = BytesMut;
433
434    fn from_builder(builder: Self::Builder) -> Self {
435        builder.freeze()
436    }
437}
438
439#[cfg(feature = "smallvec")]
440impl<A: smallvec::Array<Item = u8>> FromBuilder for smallvec::SmallVec<A> {
441    type Builder = Self;
442
443    fn from_builder(builder: Self::Builder) -> Self {
444        builder
445    }
446}
447
448#[cfg(feature = "heapless")]
449impl<const N: usize> FromBuilder for heapless::Vec<u8, N> {
450    type Builder = Self;
451
452    fn from_builder(builder: Self::Builder) -> Self {
453        builder
454    }
455}
456
457
458//------------ BuilderAppendError --------------------------------------------
459
460/// 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;
466
467
468//============ Error Handling ================================================
469
470//------------ ShortBuf ------------------------------------------------------
471
472/// 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;
481
482
483//--- From
484
485impl From<Infallible> for ShortBuf {
486    fn from(_: Infallible) -> ShortBuf {
487        unreachable!()
488    }
489}
490
491
492//--- Display and Error
493
494impl fmt::Display for ShortBuf {
495    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
496        f.write_str("buffer size exceeded")
497    }
498}
499
500#[cfg(feature = "std")]
501impl std::error::Error for ShortBuf {}
502
503
504//------------ Functions for Infallible --------------------------------------
505
506/// 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 {
514    match src {
515        Ok(ok) => ok,
516        Err(_) => unreachable!(),
517    }
518}
519
520/// 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
528    F: FnOnce() -> Result<T, E>,
529    E: Into<Infallible>,
530{
531    infallible(op())
532}
533