Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Never inline map value deserialization #14

Closed
wants to merge 4 commits into from
Closed
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
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
50 changes: 38 additions & 12 deletions src/de.rs
Original file line number Diff line number Diff line change
Expand Up @@ -342,6 +342,7 @@ impl<'a, 'b: 'a> serde::de::MapAccess<'b> for MapAccess<'a, 'b> {
}
}

#[inline(never)]
fn next_value_seed<V>(&mut self, seed: V) -> Result<V::Value>
where
V: de::DeserializeSeed<'b>,
Expand Down Expand Up @@ -803,7 +804,21 @@ impl<'de, 'a> de::Deserializer<'de> for &'a mut Deserializer<'de> {
where
V: Visitor<'de>,
{
self.deserialize_str(visitor)
let major = self.peek_major()?;
match major {
MAJOR_BYTES | MAJOR_STR => {
// Rust identifiers are always valid UTF-8 so we can assume that bytes are
// UTF-8-encoded strings. This has the benefit that we only need a mapping from
// 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)?;
visitor.visit_borrowed_str(string_slice)
}
MAJOR_POSINT => self.deserialize_u64(visitor),
_ => Err(Error::DeserializeBadMajor),
}
}

fn deserialize_ignored_any<V>(self, visitor: V) -> Result<V::Value>
Expand Down Expand Up @@ -1040,28 +1055,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