diff --git a/Cargo.toml b/Cargo.toml index 6124b95..1da3582 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -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 = [] diff --git a/src/de.rs b/src/de.rs index 59e05ab..008138b 100644 --- a/src/de.rs +++ b/src/de.rs @@ -811,7 +811,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), @@ -1053,17 +1054,28 @@ 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] @@ -1071,10 +1083,10 @@ mod tests { 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); } diff --git a/src/error.rs b/src/error.rs index c3ffdba..69dc0d9 100644 --- a/src/error.rs +++ b/src/error.rs @@ -3,7 +3,7 @@ use core::fmt::{Display, Formatter}; /// This is the Result type used by cbor-smol. -pub type Result = core::result::Result; +pub type Result = core::result::Result; /// This is the error type used by cbor-smol #[derive(Clone, Copy, Debug, Eq, PartialEq)] diff --git a/src/lib.rs b/src/lib.rs index aa7495e..d269473 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -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 { + 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( object: &T, - bytes: &mut Bytes, + bytes: &mut heapless_bytes_v0_3::Bytes, ) -> Result { let len_before = bytes.len(); let mut ser = ser::Serializer::new(bytes); @@ -45,11 +48,12 @@ pub fn cbor_serialize_extending_bytes( object: &T, -) -> Result> { - let mut data = Bytes::::new(); +) -> Result> { + let mut data = heapless_bytes_v0_3::Bytes::::new(); cbor_serialize_extending_bytes(object, &mut data)?; Ok(data) } diff --git a/src/ser.rs b/src/ser.rs index 1411c16..7f86ebd 100644 --- a/src/ser.rs +++ b/src/ser.rs @@ -2,6 +2,8 @@ use super::error::{Error, Result}; use serde::ser; use serde::Serialize; +use core::mem; + use crate::consts::*; // pub fn to_slice<'a, 'b, T>(value: &'a T, buf: &'b mut [u8]) -> Result<&'b mut [u8]> @@ -16,86 +18,157 @@ pub trait Writer { type Error: Into; /// Attempts to write an entire buffer into this write. - fn write_all(&mut self, buf: &[u8]) -> core::result::Result<(), Self::Error>; -} - -#[derive(Debug)] -pub struct SliceWriter<'a> { - slice: &'a mut [u8], - index: usize, + fn write_all(&mut self, buf: &[u8]) -> Result<(), Self::Error>; } -impl<'a> SliceWriter<'a> { - /// Wraps a mutable slice so it can be used as a `Writer`. - pub fn new(slice: &'a mut [u8]) -> SliceWriter<'a> { - SliceWriter { slice, index: 0 } +impl<'a> Writer for &'a mut [u8] { + type Error = Error; + fn write_all<'b>(&'b mut self, buf: &[u8]) -> Result<()> { + let l = buf.len(); + if self.len() < l { + // This buffer will not fit in our slice + return Err(Error::SerializeBufferFull(0)); + } + let (current, rem) = mem::take(self).split_at_mut(l); + current.copy_from_slice(buf); + *self = rem; + Ok(()) } +} - /// Returns the number of bytes written to the underlying slice. - pub fn bytes_written(&self) -> usize { - self.index +#[cfg(feature = "heapless-bytes-v0-3")] +impl Writer for heapless_bytes_v0_3::Bytes { + type Error = Error; + fn write_all(&mut self, buf: &[u8]) -> Result<()> { + self.extend_from_slice(buf) + .or(Err(Error::SerializeBufferFull(self.len()))) } +} - /// Returns the underlying slice. - pub fn into_inner(self) -> &'a mut [u8] { - self.slice +#[cfg(feature = "heapless-bytes-v0-4")] +impl Writer for heapless_bytes_v0_4::Bytes { + type Error = Error; + fn write_all(&mut self, buf: &[u8]) -> Result<()> { + self.extend_from_slice(buf) + .or(Err(Error::SerializeBufferFull(self.len()))) } } -impl<'a> Writer for SliceWriter<'a> { +#[cfg(feature = "heapless-v0-7")] +impl Writer for heapless_v0_7::Vec { type Error = Error; - fn write_all(&mut self, buf: &[u8]) -> Result<()> { - let l = buf.len(); - if self.slice.len() - self.index < l { - // This buffer will not fit in our slice - return Err(Error::SerializeBufferFull(self.index)); - } - self.slice[self.index..][..l].copy_from_slice(buf); - self.index += l; - Ok(()) + self.extend_from_slice(buf) + .or(Err(Error::SerializeBufferFull(self.len()))) } } -impl<'a, const N: usize> Writer for &'a mut crate::Bytes { +#[cfg(feature = "heapless-v0-8")] +impl Writer for heapless_v0_8::Vec { type Error = Error; - fn write_all(&mut self, buf: &[u8]) -> Result<()> { self.extend_from_slice(buf) - .map_err(|_| Error::SerializeBufferFull(buf.len())) + .or(Err(Error::SerializeBufferFull(self.len()))) } } -pub struct Serializer -// where -// W: Writer, -{ - pub writer: W, +impl<'a, T: Writer> Writer for &'a mut T { + type Error = T::Error; + fn write_all(&mut self, buf: &[u8]) -> Result<(), Self::Error> { + (**self).write_all(buf) + } +} + +// #[derive(Debug)] +// pub struct SliceWriter<'a> { +// slice: &'a mut [u8], +// index: usize, +// } + +// impl<'a> SliceWriter<'a> { +// /// Wraps a mutable slice so it can be used as a `Writer`. +// pub fn new(slice: &'a mut [u8]) -> SliceWriter<'a> { +// SliceWriter { slice, index: 0 } +// } + +// /// Returns the number of bytes written to the underlying slice. +// pub fn bytes_written(&self) -> usize { +// self.index +// } + +// /// Returns the underlying slice. +// pub fn into_inner(self) -> &'a mut [u8] { +// self.slice +// } +// } + +// impl<'a> Writer for SliceWriter<'a> { +// type Error = Error; + +// fn write_all(&mut self, buf: &[u8]) -> Result<()> { +// let l = buf.len(); +// if self.slice.len() - self.index < l { +// // This buffer will not fit in our slice +// return Err(Error::SerializeBufferFull(self.index)); +// } +// self.slice[self.index..][..l].copy_from_slice(buf); +// self.index += l; +// Ok(()) +// } +// } + +// impl<'a, const N: usize> Writer for &'a mut crate::Bytes { +// type Error = Error; + +// fn write_all(&mut self, buf: &[u8]) -> Result<()> { +// self.extend_from_slice(buf) +// .map_err(|_| Error::SerializeBufferFull(buf.len())) +// } +// } + +struct WrittenWriter { + writer: W, + written: usize, +} + +impl Writer for WrittenWriter { + type Error = W::Error; + + fn write_all(&mut self, buf: &[u8]) -> core::result::Result<(), Self::Error> { + self.written += buf.len(); + self.writer.write_all(buf) + } +} + +pub struct Serializer { + inner: WrittenWriter, } impl Serializer { #[inline] pub fn new(writer: W) -> Self { Serializer { - writer, - // packed: false, - // enum_as_map: true, + inner: WrittenWriter { writer, written: 0 }, } } + pub fn written(&self) -> usize { + self.inner.written + } + /// Unwrap the `Writer` from the `Serializer`. #[inline] pub fn into_inner(self) -> W { - self.writer + self.inner.writer } #[inline] fn write_u8(&mut self, major: u8, value: u8) -> Result<()> { if value <= 0x17 { - self.writer.write_all(&[major << MAJOR_OFFSET | value]) + self.inner.write_all(&[major << MAJOR_OFFSET | value]) } else { let buf = [major << MAJOR_OFFSET | 24, value]; - self.writer.write_all(&buf) + self.inner.write_all(&buf) } .map_err(|e| e.into()) } @@ -107,7 +180,7 @@ impl Serializer { } else { let mut buf = [major << MAJOR_OFFSET | 25, 0, 0]; buf[1..].copy_from_slice(&value.to_be_bytes()); - self.writer.write_all(&buf).map_err(|e| e.into()) + self.inner.write_all(&buf).map_err(|e| e.into()) } } @@ -118,7 +191,7 @@ impl Serializer { } else { let mut buf = [major << MAJOR_OFFSET | 26, 0, 0, 0, 0]; buf[1..].copy_from_slice(&value.to_be_bytes()); - self.writer.write_all(&buf).map_err(|e| e.into()) + self.inner.write_all(&buf).map_err(|e| e.into()) } } @@ -129,7 +202,7 @@ impl Serializer { } else { let mut buf = [major << MAJOR_OFFSET | 27, 0, 0, 0, 0, 0, 0, 0, 0]; buf[1..].copy_from_slice(&value.to_be_bytes()); - self.writer.write_all(&buf).map_err(|e| e.into()) + self.inner.write_all(&buf).map_err(|e| e.into()) } } @@ -145,7 +218,7 @@ impl Serializer { false } None => { - self.writer + self.inner .write_all(&[major << MAJOR_OFFSET | 31]) .map_err(|e| e.into())?; true @@ -186,7 +259,7 @@ where #[inline] fn serialize_bool(self, value: bool) -> Result<()> { let value = if value { VALUE_TRUE } else { VALUE_FALSE }; - self.writer.write_all(&[value]).map_err(|e| e.into()) + self.inner.write_all(&[value]).map_err(|e| e.into()) } #[inline] @@ -259,20 +332,18 @@ where #[inline] fn serialize_str(self, value: &str) -> Result<()> { self.write_u64(MAJOR_STR, value.len() as u64)?; - self.writer - .write_all(value.as_bytes()) - .map_err(|e| e.into()) + self.inner.write_all(value.as_bytes()).map_err(|e| e.into()) } #[inline] fn serialize_bytes(self, value: &[u8]) -> Result<()> { self.write_u64(MAJOR_BYTES, value.len() as u64)?; - self.writer.write_all(value).map_err(|e| e.into()) + self.inner.write_all(value).map_err(|e| e.into()) } #[inline] fn serialize_none(self) -> Result<()> { - self.writer.write_all(&[VALUE_NULL]).map_err(|e| e.into()) + self.inner.write_all(&[VALUE_NULL]).map_err(|e| e.into()) } #[inline] @@ -587,7 +658,7 @@ where #[inline] fn end_inner(self) -> Result<()> { if self.needs_eof { - self.ser.writer.write_all(&[0xff]).map_err(|e| e.into()) + self.ser.inner.write_all(&[0xff]).map_err(|e| e.into()) } else { Ok(()) }