Skip to content

Commit

Permalink
Support multiple versions of heapless and heapless bytes
Browse files Browse the repository at this point in the history
This allows better backwards compatibility and serializing to heapless directly.

Given #11 I went with a breaking change update
(the `Serializer` field was public and existing implementations are put behind a breaking change)
  • Loading branch information
sosthene-nitrokey committed Oct 7, 2024
1 parent 2ba6ee3 commit 4bf2788
Show file tree
Hide file tree
Showing 5 changed files with 179 additions and 84 deletions.
14 changes: 11 additions & 3 deletions Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -15,16 +15,24 @@ categories = ["development-tools", "embedded"]

[dependencies]
delog = "0.1.0-alpha.3"
heapless = "0.7"
heapless-bytes = "0.3"
heapless-bytes-v0-3 = { package = "heapless-bytes", version = "0.3", optional = true }
heapless-bytes-v0-4 = { package = "heapless-bytes", version = "0.4", optional = true }
heapless-v0-7 = { package = "heapless", version = "0.7", optional = true }
heapless-v0-8 = { package = "heapless", version = "0.8", optional = true }
serde = { version = "1", default-features = false }

[dev-dependencies]
heapless = { version = "0.7", features = ["serde"] }
heapless-v0-8 = { package = "heapless", version = "0.8", features = ["serde"] }
heapless-bytes-v0-4 = { package = "heapless-bytes", version = "0.4" }
serde = { version = "1", default-features = false, features = ["derive"] }
serde_bytes = "0.11.12"

[features]
heapless-bytes-v0-3 = ["dep:heapless-bytes-v0-3"]
heapless-bytes-v0-4 = ["dep:heapless-bytes-v0-4"]
heapless-v0-7 = ["dep:heapless-v0-7"]
heapless-v0-8 = ["dep:heapless-v0-8"]

bytes-from-array = []
log-all = []
log-none = []
Expand Down
36 changes: 24 additions & 12 deletions src/de.rs
Original file line number Diff line number Diff line change
Expand Up @@ -814,7 +814,8 @@ impl<'de, 'a> de::Deserializer<'de> for &'a mut Deserializer<'de> {
// strings to fields (and the mapping from bytes to fields can be optimized out).
let length = self.raw_deserialize_u32(major)? as usize;
let bytes: &'de [u8] = self.try_take_n(length)?;
let string_slice = core::str::from_utf8(bytes).map_err(|_| Error::DeserializeBadUtf8)?;
let string_slice =
core::str::from_utf8(bytes).map_err(|_| Error::DeserializeBadUtf8)?;
visitor.visit_borrowed_str(string_slice)
}
MAJOR_POSINT => self.deserialize_u64(visitor),
Expand Down Expand Up @@ -1056,28 +1057,39 @@ mod tests {
}
}

#[cfg_attr(
not(feature = "heapless-bytes-v0-4"),
ignore = "Enable heapless-bytes-v0-4 feature"
)]
#[test]
fn de_bytes() {
let mut buf = [0u8; 64];

let slice = b"thank you postcard!";
let bytes = crate::Bytes::<64>::from_slice(slice).unwrap();
let ser = cbor_serialize(&bytes, &mut buf).unwrap();
println!("serialized bytes = {:?}", ser);
let de: crate::Bytes<64> = from_bytes(&buf).unwrap();
println!("deserialized bytes = {:?}", &de);
assert_eq!(&de, slice);
#[cfg(feature = "heapless-bytes-v0-4")]
{
let mut buf = [0u8; 64];

let slice = b"thank you postcard!";
let bytes = heapless_bytes_v0_4::Bytes::<64>::try_from(slice).unwrap();
let ser = cbor_serialize(&bytes, &mut buf).unwrap();
println!("serialized bytes = {:?}", ser);
let de: heapless_bytes_v0_4::Bytes<64> = from_bytes(&buf).unwrap();
println!("deserialized bytes = {:?}", &de);
assert_eq!(&de, slice);
}
#[cfg(not(feature = "heapless-bytes-v0-4"))]
{
panic!("This test must be run with the heapless-v0-4 feature")
}
}

#[test]
fn de_str() {
let mut buf = [0u8; 64];

let string_slice = "thank you postcard, for blazing the path 🐝";
let mut string = heapless::String::<64>::new();
let mut string = heapless_v0_8::String::<64>::new();
string.push_str(string_slice).unwrap();
let _n = cbor_serialize(&string, &mut buf);
let de: heapless::String<64> = from_bytes(&buf).unwrap();
let de: heapless_v0_8::String<64> = from_bytes(&buf).unwrap();
assert_eq!(de, string_slice);
}

Expand Down
2 changes: 1 addition & 1 deletion src/error.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@
use core::fmt::{Display, Formatter};

/// This is the Result type used by cbor-smol.
pub type Result<T> = core::result::Result<T, Error>;
pub type Result<T, Err = Error> = core::result::Result<T, Err>;

/// This is the error type used by cbor-smol
#[derive(Clone, Copy, Debug, Eq, PartialEq)]
Expand Down
36 changes: 20 additions & 16 deletions src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -4,38 +4,41 @@
extern crate delog;
generate_macros!();

pub use heapless_bytes::Bytes;

pub(crate) mod consts;
pub mod de;
pub mod error;
pub mod ser;

pub use error::{Error, Result};
use ser::Writer;

// pub use de::from_bytes;
// pub use de::take_from_bytes;
/// Serialize an object to a `Writer`
///
/// Returns the amount of bytes written to the writer
pub fn cbor_serialize_to<'a, T: ?Sized + serde::Serialize, W: Writer>(
object: &T,
writer: W,
) -> Result<usize> {
let mut serializer = ser::Serializer::new(writer);
object.serialize(&mut serializer)?;
Ok(serializer.written())
}

// kudos to postcard, this is much nicer than returning size
pub fn cbor_serialize<'a, T: ?Sized + serde::Serialize>(
object: &T,
buffer: &'a mut [u8],
) -> Result<&'a [u8]> {
let writer = ser::SliceWriter::new(buffer);
let mut ser = ser::Serializer::new(writer);

object.serialize(&mut ser)?;

let writer = ser.into_inner();
let size = writer.bytes_written();

Ok(&buffer[..size])
let mut buf = &mut *buffer;
let written = cbor_serialize_to(object, &mut buf)?;
Ok(&buffer[..written])
}

#[cfg(feature = "heapless-bytes-v0-3")]
/// Append serialization of object to existing bytes, returning length of serialized object.
pub fn cbor_serialize_extending_bytes<T: ?Sized + serde::Serialize, const N: usize>(
object: &T,
bytes: &mut Bytes<N>,
bytes: &mut heapless_bytes_v0_3::Bytes<N>,
) -> Result<usize> {
let len_before = bytes.len();
let mut ser = ser::Serializer::new(bytes);
Expand All @@ -45,11 +48,12 @@ pub fn cbor_serialize_extending_bytes<T: ?Sized + serde::Serialize, const N: usi
Ok(ser.into_inner().len() - len_before)
}

#[cfg(feature = "heapless-bytes-v0-3")]
/// Serialize object into newly allocated Bytes.
pub fn cbor_serialize_bytes<T: ?Sized + serde::Serialize, const N: usize>(
object: &T,
) -> Result<Bytes<N>> {
let mut data = Bytes::<N>::new();
) -> Result<heapless_bytes_v0_3::Bytes<N>> {
let mut data = heapless_bytes_v0_3::Bytes::<N>::new();
cbor_serialize_extending_bytes(object, &mut data)?;
Ok(data)
}
Expand Down
Loading

0 comments on commit 4bf2788

Please sign in to comment.