Skip to content

Commit 56e878a

Browse files
authored
Add support for heapless. (#19)
1 parent ab4c6c5 commit 56e878a

File tree

5 files changed

+227
-69
lines changed

5 files changed

+227
-69
lines changed

Cargo.toml

+1
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,7 @@ license = "BSD-3-Clause"
1313

1414
[dependencies]
1515
bytes = { version = "1", optional = true }
16+
heapless = { version = "0.7", optional = true }
1617
serde = { version = "1", optional = true }
1718
smallvec = { version = "1", optional = true }
1819

src/array.rs

+2-57
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,8 @@
22
use core::{cmp, fmt};
33
use core::convert::Infallible;
44
use crate::builder::{
5-
CollapseResult, EmptyBuilder, FromBuilder, IntoBuilder, OctetsBuilder,
5+
EmptyBuilder, FromBuilder, IntoBuilder, OctetsBuilder, ShortBuf,
6+
ShortBuild,
67
};
78
use crate::octets::{OctetsFrom, Truncate};
89

@@ -270,59 +271,3 @@ impl<'de, const N: usize> crate::serde::DeserializeOctets<'de> for Array<N> {
270271
}
271272
}
272273

273-
274-
//============ Error Types ===================================================
275-
276-
//------------ ShortBuf ------------------------------------------------------
277-
278-
/// An attempt was made to write beyond the end of a buffer.
279-
///
280-
/// This type is returned as an error by all functions and methods that append
281-
/// data to an [octets builder] when the buffer size of the builder is not
282-
/// sufficient to append the data.
283-
///
284-
/// [octets builder]: trait.OctetsBuilder.html
285-
#[derive(Clone, Debug, Eq, PartialEq)]
286-
pub struct ShortBuf;
287-
288-
//--- From and CollapseResult
289-
290-
impl From<Infallible> for ShortBuf {
291-
fn from(_: Infallible) -> ShortBuf {
292-
unreachable!()
293-
}
294-
}
295-
296-
impl<T> CollapseResult<T, ShortBuild<Infallible>> for Result<T, ShortBuf> {
297-
fn collapse_result(src: Result<T, ShortBuild<Infallible>>) -> Self {
298-
src.map_err(|err| match err {
299-
ShortBuild::ShortBuf => ShortBuf,
300-
ShortBuild::Build(_) => unreachable!()
301-
})
302-
}
303-
}
304-
//--- Display and Error
305-
306-
impl fmt::Display for ShortBuf {
307-
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
308-
f.write_str("buffer size exceeded")
309-
}
310-
}
311-
312-
#[cfg(feature = "std")]
313-
impl std::error::Error for ShortBuf {}
314-
315-
316-
//------------ ShortBuild ----------------------------------------------------
317-
318-
pub enum ShortBuild<T> {
319-
Build(T),
320-
ShortBuf,
321-
}
322-
323-
impl<T> From<T> for ShortBuild<T> {
324-
fn from(t: T) -> Self {
325-
ShortBuild::Build(t)
326-
}
327-
}
328-

src/builder.rs

+128
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,7 @@
2020
//! * truncating the sequence of assembled octets happens through
2121
//! [`Truncate`].
2222
23+
use core::fmt;
2324
use core::convert::Infallible;
2425
#[cfg(feature = "bytes")] use bytes::{Bytes, BytesMut};
2526
#[cfg(feature = "std")] use std::borrow::Cow;
@@ -212,6 +213,31 @@ impl<A: smallvec::Array<Item = u8>> OctetsBuilder for smallvec::SmallVec<A> {
212213
}
213214
}
214215

216+
#[cfg(feature = "heapless")]
217+
impl<const N: usize> OctetsBuilder for heapless::Vec<u8, N> {
218+
type Octets = Self;
219+
type BuildError<E> = ShortBuild<E>;
220+
type AppendResult<T> = Result<T, ShortBuf>;
221+
222+
fn try_append_slice(
223+
&mut self, slice: &[u8]
224+
) -> Result<(), Self::BuildError<Infallible>> {
225+
self.extend_from_slice(slice).map_err(|_| ShortBuild::ShortBuf)
226+
}
227+
228+
fn len(&self) -> usize {
229+
self.as_slice().len()
230+
}
231+
232+
fn is_empty(&self) -> bool {
233+
self.len() == 0
234+
}
235+
236+
fn freeze(self) -> Self::Octets {
237+
self
238+
}
239+
}
240+
215241
//------------ EmptyBuilder --------------------------------------------------
216242

217243
/// An octets builder that can be newly created empty.
@@ -262,6 +288,18 @@ impl<A: smallvec::Array<Item = u8>> EmptyBuilder for smallvec::SmallVec<A> {
262288
}
263289
}
264290

291+
#[cfg(feature = "heapless")]
292+
impl<const N: usize> EmptyBuilder for heapless::Vec<u8, N> {
293+
fn empty() -> Self {
294+
Self::new()
295+
}
296+
297+
fn with_capacity(capacity: usize) -> Self {
298+
debug_assert!(capacity <= N);
299+
Self::with_capacity(capacity)
300+
}
301+
}
302+
265303
//------------ IntoBuilder ---------------------------------------------------
266304

267305
/// An octets type that can be converted into an octets builder.
@@ -321,6 +359,15 @@ impl<A: smallvec::Array<Item = u8>> IntoBuilder for smallvec::SmallVec<A> {
321359
}
322360
}
323361

362+
#[cfg(feature = "heapless")]
363+
impl<const N: usize> IntoBuilder for heapless::Vec<u8, N> {
364+
type Builder = Self;
365+
366+
fn into_builder(self) -> Self::Builder {
367+
self
368+
}
369+
}
370+
324371

325372
//------------ FromBuilder ---------------------------------------------------
326373

@@ -369,6 +416,15 @@ impl<A: smallvec::Array<Item = u8>> FromBuilder for smallvec::SmallVec<A> {
369416
}
370417
}
371418

419+
#[cfg(feature = "heapless")]
420+
impl<const N: usize> FromBuilder for heapless::Vec<u8, N> {
421+
type Builder = Self;
422+
423+
fn from_builder(builder: Self::Builder) -> Self {
424+
builder
425+
}
426+
}
427+
372428

373429
//============ Error Handling ================================================
374430

@@ -413,3 +469,75 @@ impl<T, E, U: CollapseResult<T, E>> Collapse<U> for Result<T, E> {
413469
}
414470
}
415471

472+
473+
//------------ ShortBuf ------------------------------------------------------
474+
475+
/// An attempt was made to write beyond the end of a buffer.
476+
///
477+
/// This type is returned as an error by all functions and methods that append
478+
/// data to an [octets builder] when the buffer size of the builder is not
479+
/// sufficient to append the data.
480+
///
481+
/// [octets builder]: trait.OctetsBuilder.html
482+
#[derive(Clone, Debug, Eq, PartialEq)]
483+
pub struct ShortBuf;
484+
485+
486+
//--- From and CollapseResult
487+
488+
impl From<Infallible> for ShortBuf {
489+
fn from(_: Infallible) -> ShortBuf {
490+
unreachable!()
491+
}
492+
}
493+
494+
impl<T> CollapseResult<T, ShortBuild<Infallible>> for Result<T, ShortBuf> {
495+
fn collapse_result(src: Result<T, ShortBuild<Infallible>>) -> Self {
496+
src.map_err(|err| match err {
497+
ShortBuild::ShortBuf => ShortBuf,
498+
ShortBuild::Build(_) => unreachable!()
499+
})
500+
}
501+
}
502+
503+
504+
//--- Display and Error
505+
506+
impl fmt::Display for ShortBuf {
507+
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
508+
f.write_str("buffer size exceeded")
509+
}
510+
}
511+
512+
#[cfg(feature = "std")]
513+
impl std::error::Error for ShortBuf {}
514+
515+
516+
//------------ ShortBuild ----------------------------------------------------
517+
518+
#[derive(Clone, Debug)]
519+
pub enum ShortBuild<T> {
520+
Build(T),
521+
ShortBuf,
522+
}
523+
524+
impl<T> From<T> for ShortBuild<T> {
525+
fn from(t: T) -> Self {
526+
ShortBuild::Build(t)
527+
}
528+
}
529+
530+
//--- Display and Error
531+
532+
impl<T: fmt::Display> fmt::Display for ShortBuild<T> {
533+
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
534+
match self {
535+
ShortBuild::Build(t) => t.fmt(f),
536+
ShortBuild::ShortBuf => ShortBuf.fmt(f)
537+
}
538+
}
539+
}
540+
541+
#[cfg(feature = "std")]
542+
impl<T: fmt::Debug + fmt::Display> std::error::Error for ShortBuild<T> {}
543+

src/octets.rs

+31
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,7 @@ use core::ops::{Index, RangeBounds};
1818
#[cfg(feature = "bytes")] use bytes::{Bytes, BytesMut};
1919
#[cfg(feature = "std")] use std::borrow::Cow;
2020
#[cfg(feature = "std")] use std::vec::Vec;
21+
#[cfg(feature = "heapless")] use crate::builder::ShortBuf;
2122

2223

2324
//------------ Octets --------------------------------------------------------
@@ -95,6 +96,17 @@ impl<A: smallvec::Array<Item = u8>> Octets for smallvec::SmallVec<A> {
9596
}
9697
}
9798

99+
#[cfg(feature = "heapless")]
100+
impl<const N: usize> Octets for heapless::Vec<u8, N> {
101+
type Range<'a> = &'a [u8] where Self: 'a;
102+
103+
fn range(&self, range: impl RangeBounds<usize>) -> Self::Range<'_> {
104+
self.index(
105+
(range.start_bound().cloned(), range.end_bound().cloned())
106+
)
107+
}
108+
}
109+
98110

99111
//------------ Truncate ------------------------------------------------------
100112

@@ -152,6 +164,13 @@ impl<A: smallvec::Array<Item = u8>> Truncate for smallvec::SmallVec<A> {
152164
}
153165
}
154166

167+
#[cfg(feature = "heapless")]
168+
impl<const N: usize> Truncate for heapless::Vec<u8, N> {
169+
fn truncate(&mut self, len: usize) {
170+
self.truncate(len)
171+
}
172+
}
173+
155174
//------------ OctetsFrom ----------------------------------------------------
156175

157176
/// Convert a type from one octets type to another.
@@ -236,6 +255,18 @@ where
236255
}
237256
}
238257

258+
#[cfg(feature = "heapless")]
259+
impl<Source, const N: usize> OctetsFrom<Source> for heapless::Vec<u8, N>
260+
where
261+
Source: AsRef<[u8]>,
262+
{
263+
type Error = ShortBuf;
264+
265+
fn try_octets_from(source: Source) -> Result<Self, ShortBuf> {
266+
heapless::Vec::from_slice(source.as_ref()).map_err(|_| ShortBuf)
267+
}
268+
}
269+
239270

240271
//------------ OctetsInto ----------------------------------------------------
241272

0 commit comments

Comments
 (0)