diff --git a/src/ser/mod.rs b/src/ser/mod.rs index 0674aa15..30b1062c 100644 --- a/src/ser/mod.rs +++ b/src/ser/mod.rs @@ -11,11 +11,13 @@ use heapless::{String, Vec}; use self::map::SerializeMap; use self::seq::SerializeSeq; +use self::ser_backend::{SerializerBackend, SliceSerializer}; use self::struct_::{SerializeStruct, SerializeStructVariant}; mod map; mod seq; mod struct_; +mod ser_backend; /// Serialization result pub type Result = ::core::result::Result; @@ -49,50 +51,31 @@ impl fmt::Display for Error { } } + /// A structure that serializes Rust values as JSON into a buffer. pub struct Serializer<'a> { - buf: &'a mut [u8], - current_length: usize, + backend: &'a mut dyn SerializerBackend } impl<'a> Serializer<'a> { /// Create a new `Serializer` - pub fn new(buf: &'a mut [u8]) -> Self { - Serializer { - buf, - current_length: 0, + pub fn new(backend: &'a mut dyn SerializerBackend) -> Self { + Self { + backend } } /// Return the current amount of serialized data in the buffer pub fn end(&self) -> usize { - self.current_length + self.backend.end() } fn push(&mut self, c: u8) -> Result<()> { - if self.current_length < self.buf.len() { - unsafe { self.push_unchecked(c) }; - Ok(()) - } else { - Err(Error::BufferFull) - } - } - - unsafe fn push_unchecked(&mut self, c: u8) { - self.buf[self.current_length] = c; - self.current_length += 1; + self.backend.push(c) } fn extend_from_slice(&mut self, other: &[u8]) -> Result<()> { - if self.current_length + other.len() > self.buf.len() { - // won't fit in the buf; don't modify anything and return an error - Err(Error::BufferFull) - } else { - for c in other { - unsafe { self.push_unchecked(*c) }; - } - Ok(()) - } + self.backend.extend_from_slice(other) } } @@ -469,9 +452,10 @@ pub fn to_slice(value: &T, buf: &mut [u8]) -> Result where T: ser::Serialize + ?Sized, { - let mut ser = Serializer::new(buf); + let mut backend = SliceSerializer::new(buf); + let mut ser = Serializer::new(&mut backend); value.serialize(&mut ser)?; - Ok(ser.current_length) + Ok(backend.current_length) } impl ser::Error for Error { diff --git a/src/ser/ser_backend.rs b/src/ser/ser_backend.rs new file mode 100644 index 00000000..5cecbed9 --- /dev/null +++ b/src/ser/ser_backend.rs @@ -0,0 +1,55 @@ +use super::{Result, Error}; + +pub trait SerializerBackend { + /// Return the current amount of serialized data in the buffer + fn end(&self) -> usize; + fn push(&mut self, c: u8) -> Result<()>; + fn extend_from_slice(&mut self, other: &[u8]) -> Result<()>; +} + +pub struct SliceSerializer<'a> { + buf: &'a mut [u8], + pub(crate) current_length: usize, +} + +impl<'a> SliceSerializer<'a> { + /// Create a new `Serializer` + pub fn new(buf: &'a mut [u8]) -> Self { + Self { + buf, + current_length: 0, + } + } + + unsafe fn push_unchecked(&mut self, c: u8) { + self.buf[self.current_length] = c; + self.current_length += 1; + } +} + +impl<'a> SerializerBackend for SliceSerializer<'a> { + fn end(&self) -> usize { + self.current_length + } + + fn push(&mut self, c: u8) -> Result<()> { + if self.current_length < self.buf.len() { + unsafe { self.push_unchecked(c) }; + Ok(()) + } else { + Err(Error::BufferFull) + } + } + + fn extend_from_slice(&mut self, other: &[u8]) -> Result<()> { + if self.current_length + other.len() > self.buf.len() { + // won't fit in the buf; don't modify anything and return an error + Err(Error::BufferFull) + } else { + for c in other { + unsafe { self.push_unchecked(*c) }; + } + Ok(()) + } + } +}