diff --git a/src/lib.rs b/src/lib.rs index a56b4435c..492caf4d6 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -74,7 +74,7 @@ pub mod ser; #[doc(inline)] pub use self::de::{from_slice, from_str}; #[doc(inline)] -pub use self::ser::{to_string, to_vec}; +pub use self::ser::{to_string, to_vec, to_slice}; #[allow(deprecated)] unsafe fn uninitialized() -> T { diff --git a/src/ser/map.rs b/src/ser/map.rs index dd1bfde79..227bf866d 100644 --- a/src/ser/map.rs +++ b/src/ser/map.rs @@ -1,12 +1,10 @@ use serde::ser; -use heapless::ArrayLength; - -use crate::ser::{Error, Result, Serializer}; +use crate::{ser::slice::MutSlice, ser::{Error, Result, Serializer}}; pub struct SerializeMap<'a, B> where - B: ArrayLength, + B: MutSlice, { ser: &'a mut Serializer, first: bool, @@ -14,7 +12,7 @@ where impl<'a, B> SerializeMap<'a, B> where - B: ArrayLength, + B: MutSlice, { pub(crate) fn new(ser: &'a mut Serializer) -> Self { SerializeMap { ser, first: true } @@ -23,7 +21,7 @@ where impl<'a, B> ser::SerializeMap for SerializeMap<'a, B> where - B: ArrayLength, + B: MutSlice, { type Ok = (); type Error = Error; diff --git a/src/ser/mod.rs b/src/ser/mod.rs index bd4556608..a25f491c9 100644 --- a/src/ser/mod.rs +++ b/src/ser/mod.rs @@ -9,6 +9,8 @@ use heapless::{consts::*, String, Vec}; use self::map::SerializeMap; use self::seq::SerializeSeq; use self::struct_::SerializeStruct; +use self::slice::{Slice, MutSlice, VecSlice}; +mod slice; mod map; mod seq; @@ -53,17 +55,17 @@ impl fmt::Display for Error { pub(crate) struct Serializer where - B: heapless::ArrayLength, + B: MutSlice, { - buf: Vec, + buf: B, } impl Serializer where - B: heapless::ArrayLength, + B: MutSlice, { - fn new() -> Self { - Serializer { buf: Vec::new() } + fn new(buf: B) -> Self { + Serializer { buf } } } @@ -136,7 +138,7 @@ macro_rules! serialize_fmt { impl<'a, B> ser::Serializer for &'a mut Serializer where - B: heapless::ArrayLength, + B: MutSlice, { type Ok = (); type Error = Error; @@ -338,9 +340,9 @@ where B: heapless::ArrayLength, T: ser::Serialize + ?Sized, { - let mut ser = Serializer::new(); + let mut ser = Serializer::new(VecSlice::new()); value.serialize(&mut ser)?; - Ok(unsafe { String::from_utf8_unchecked(ser.buf) }) + Ok(unsafe { String::from_utf8_unchecked(ser.buf.release()) }) } /// Serializes the given data structure as a JSON byte vector @@ -349,9 +351,19 @@ where B: heapless::ArrayLength, T: ser::Serialize + ?Sized, { - let mut ser = Serializer::new(); + let mut ser = Serializer::new(VecSlice::new()); + value.serialize(&mut ser)?; + Ok(ser.buf.release()) +} + +/// Serializes the given data structure as a JSON byte slice +pub fn to_slice<'a, T>(slice: &'a mut [u8], value: &T) -> Result<&'a mut [u8]> +where + T: ser::Serialize + ?Sized, +{ + let mut ser = Serializer::new(Slice::new(slice)); value.serialize(&mut ser)?; - Ok(ser.buf) + Ok(ser.buf.release()) } impl ser::Error for Error { diff --git a/src/ser/seq.rs b/src/ser/seq.rs index d260edddf..943d2a9e6 100644 --- a/src/ser/seq.rs +++ b/src/ser/seq.rs @@ -1,12 +1,10 @@ use serde::ser; -use heapless::ArrayLength; - -use crate::ser::{Error, Result, Serializer}; +use crate::{ser::slice::MutSlice, ser::{Error, Result, Serializer}}; pub struct SerializeSeq<'a, B> where - B: ArrayLength, + B: MutSlice, { de: &'a mut Serializer, first: bool, @@ -14,7 +12,7 @@ where impl<'a, B> SerializeSeq<'a, B> where - B: ArrayLength, + B: MutSlice, { pub(crate) fn new(de: &'a mut Serializer) -> Self { SerializeSeq { de, first: true } @@ -23,7 +21,7 @@ where impl<'a, B> ser::SerializeSeq for SerializeSeq<'a, B> where - B: ArrayLength, + B: MutSlice, { type Ok = (); type Error = Error; @@ -49,7 +47,7 @@ where impl<'a, B> ser::SerializeTuple for SerializeSeq<'a, B> where - B: ArrayLength, + B: MutSlice, { type Ok = (); type Error = Error; diff --git a/src/ser/slice.rs b/src/ser/slice.rs new file mode 100644 index 000000000..35c98f665 --- /dev/null +++ b/src/ser/slice.rs @@ -0,0 +1,73 @@ +pub trait MutSlice { + type Output; + + fn push(&mut self, b: u8) -> Result<(), u8>; + fn extend_from_slice(&mut self, slice: &[u8]) -> Result<(), ()>; + fn release(self) -> Self::Output; +} + +pub struct Slice<'a> { + buf: &'a mut [u8], + index: usize, +} + +impl<'a> Slice<'a> { + pub fn new(buf: &'a mut [u8]) -> Self { + Slice { buf, index: 0 } + } +} + +impl<'a> MutSlice for Slice<'a> { + type Output = &'a mut [u8]; + fn push(&mut self, b: u8) -> Result<(), u8> { + if self.index >= self.buf.len() { + return Err(b); + } + + self.buf[self.index] = b; + self.index += 1; + Ok(()) + } + + fn extend_from_slice(&mut self, slice: &[u8]) -> Result<(), ()> { + if self.index + slice.len() >= self.buf.len() { + return Err(()); + } + self.buf[self.index..self.index + slice.len()].copy_from_slice(slice); + self.index += slice.len(); + Ok(()) + } + + fn release(self) -> Self::Output { + let (used, _unused) = self.buf.split_at_mut(self.index); + + used + } +} + +use heapless::Vec; + +pub struct VecSlice>(pub Vec); + +impl VecSlice +where + B: heapless::ArrayLength, +{ + pub fn new() -> Self { + VecSlice(Vec::new()) + } +} + +impl> MutSlice for VecSlice { + type Output = Vec; + fn push(&mut self, b: u8) -> Result<(), u8> { + self.0.push(b) + } + + fn extend_from_slice(&mut self, slice: &[u8]) -> Result<(), ()> { + self.0.extend_from_slice(slice) + } + fn release(self) -> Self::Output { + self.0 + } +} diff --git a/src/ser/struct_.rs b/src/ser/struct_.rs index b76826766..b9481b644 100644 --- a/src/ser/struct_.rs +++ b/src/ser/struct_.rs @@ -1,12 +1,10 @@ use serde::ser; -use heapless::ArrayLength; - -use crate::ser::{Error, Result, Serializer}; +use crate::{ser::slice::MutSlice, ser::{Error, Result, Serializer}}; pub struct SerializeStruct<'a, B> where - B: ArrayLength, + B: MutSlice, { ser: &'a mut Serializer, first: bool, @@ -14,7 +12,7 @@ where impl<'a, B> SerializeStruct<'a, B> where - B: ArrayLength, + B: MutSlice, { pub(crate) fn new(ser: &'a mut Serializer) -> Self { SerializeStruct { ser, first: true } @@ -23,7 +21,7 @@ where impl<'a, B> ser::SerializeStruct for SerializeStruct<'a, B> where - B: ArrayLength, + B: MutSlice, { type Ok = (); type Error = Error;