Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 4 additions & 1 deletion source/postcard/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -65,7 +65,10 @@ pub use de::flavors as de_flavors;
pub use de::{from_bytes, from_bytes_cobs, take_from_bytes, take_from_bytes_cobs};
pub use error::{Error, Result};
pub use ser::flavors as ser_flavors;
pub use ser::{serialize_with_flavor, serializer::Serializer, to_extend, to_slice, to_slice_cobs};
pub use ser::{
serialize_with_flavor, serializer::Serializer, to_extend, to_extend_ref, to_slice,
to_slice_cobs,
};

#[cfg(feature = "heapless")]
pub use ser::{to_vec, to_vec_cobs};
Expand Down
41 changes: 41 additions & 0 deletions source/postcard/src/ser/flavors.rs
Original file line number Diff line number Diff line change
Expand Up @@ -250,6 +250,47 @@ where
}
}

/// Wrapper over a [`core::iter::Extend<u8>`] that implements the flavor trait
///
/// This is like [`ExtendFlavor`], but it takes the writer by reference instead of
/// by value. This allows you to remain in control of the writer.
pub struct ExtendRefFlavor<'a, T> {
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Maybe use the word "mut" instead? When I see "ref", I usually expect &.

Suggested change
pub struct ExtendRefFlavor<'a, T> {
pub struct ExtendMutFlavor<'a, T> {

iter: &'a mut T,
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Maybe call it bytes? Extend is not a trait for iterator, it represent a collection that can accept an iterator to extend itself.

Suggested change
iter: &'a mut T,
bytes: &'a mut T,

}

impl<'a, T> ExtendRefFlavor<'a, T>
where
T: core::iter::Extend<u8>,
{
/// Create a new [`Self`] flavor from a given [`core::iter::Extend<u8>`]
pub fn new(iter: &'a mut T) -> Self {
Self { iter }
}
}

impl<T> Flavor for ExtendRefFlavor<'_, T>
where
T: core::iter::Extend<u8>,
{
type Output = ();
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Maybe return used size for convenience?


#[inline(always)]
fn try_push(&mut self, data: u8) -> Result<()> {
self.iter.extend([data]);
Ok(())
}

#[inline(always)]
fn try_extend(&mut self, b: &[u8]) -> Result<()> {
self.iter.extend(b.iter().copied());
Ok(())
}

fn finalize(self) -> Result<Self::Output> {
Ok(())
}
}

/// Support for the [`embedded-io`](crate::eio::embedded_io) traits
#[cfg(any(feature = "embedded-io-04", feature = "embedded-io-06"))]
pub mod eio {
Expand Down
23 changes: 23 additions & 0 deletions source/postcard/src/ser/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -274,6 +274,29 @@ where
serialize_with_flavor::<T, _, _>(value, flavors::ExtendFlavor::new(writer))
}

/// Serialize a `T` to a [`core::iter::Extend`],
///
/// This is like [`to_extend`], but it takes the writer by reference instead of
/// by value. This allows you to remain in control of the writer.
///
/// ## Example
///
/// ```rust
/// use postcard::to_extend_ref;
/// let mut vec = Vec::new();
///
/// to_extend_ref(&true, &mut vec).unwrap();
/// to_extend_ref("Hi!", &mut vec).unwrap();
/// assert_eq!(&vec[0..5], &[0x01, 0x03, b'H', b'i', b'!']);
/// ```
pub fn to_extend_ref<T, W>(value: &T, writer: &mut W) -> Result<()>
where
T: Serialize + ?Sized,
W: core::iter::Extend<u8>,
{
serialize_with_flavor::<T, _, _>(value, flavors::ExtendRefFlavor::new(writer))
}

/// Serialize a `T` to an [`embedded_io Write`](crate::eio::Write),
/// ## Example
///
Expand Down