Skip to content

Commit

Permalink
ser: Add to_writer function to write to impl of embedded_io::Write
Browse files Browse the repository at this point in the history
  • Loading branch information
elrafoon committed Jan 20, 2024
1 parent 985541e commit bb199dc
Show file tree
Hide file tree
Showing 5 changed files with 120 additions and 0 deletions.
6 changes: 6 additions & 0 deletions Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -28,10 +28,16 @@ version = "0.3.5"
default-features = false
optional = true

[dependencies.embedded-io]
default-features = false
version = "0.6"
optional = true

[dev-dependencies]
serde_derive = "1.0.100"

[features]
default = ["heapless"]
embedded-io = ["dep:embedded-io"]
custom-error-messages = ["heapless"]
std = ["serde/std"]
3 changes: 3 additions & 0 deletions src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -70,6 +70,9 @@ pub use self::de::{from_slice, from_str};
pub use self::ser::to_slice;
#[cfg(feature = "heapless")]
pub use self::ser::{to_string, to_vec};
#[doc(inline)]
#[cfg(feature = "embedded-io")]
pub use self::ser::to_writer;

#[cfg(feature = "heapless")]
pub use heapless;
44 changes: 44 additions & 0 deletions src/ser/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,9 @@ mod seq;
mod struct_;
mod ser_backend;

#[cfg(feature = "embedded-io")]
mod write_backend;

/// Serialization result
pub type Result<T> = ::core::result::Result<T, Error>;

Expand All @@ -29,6 +32,9 @@ pub type Result<T> = ::core::result::Result<T, Error>;
pub enum Error {
/// Buffer is full
BufferFull,
/// Some IO error occurred
#[cfg(feature = "embedded-io")]
IOError
}

impl From<()> for Error {
Expand Down Expand Up @@ -458,6 +464,19 @@ where
Ok(backend.current_length)
}

/// Serializes the given data structure as a JSON byte vector into the provided writer
#[cfg(feature = "embedded-io")]
pub fn to_writer<T, W>(value: &T, writer: &mut W) -> Result<()>
where
T: ser::Serialize + ?Sized,
W: embedded_io::Write
{
let mut backend = write_backend::WriteSerializer::new(writer);
let mut ser = Serializer::new(&mut backend);
value.serialize(&mut ser)?;
Ok(())
}

impl ser::Error for Error {
fn custom<T>(_msg: T) -> Self
where
Expand Down Expand Up @@ -832,4 +851,29 @@ mod tests {
let sd3 = SimpleDecimal(22222.777777);
assert_eq!(&*crate::to_string::<_, N>(&sd3).unwrap(), r#"22222.78"#);
}

#[cfg(feature = "embedded-io")]
mod my_writer;

#[cfg(feature = "embedded-io")]
#[test]
fn to_writer() {
#[derive(Serialize)]
struct Dog<'a> {
name: &'a str,
age: u8
}

let dog = Dog { name: "Punto", age: 10 };
let json1 = crate::to_string::<_, 128>(&dog).unwrap();

let mut my_writer = my_writer::MyWriter { buffer: [0; 128], pos: 0, fail: false };
crate::to_writer(&dog, &mut my_writer).unwrap();
let json2 = &my_writer.buffer[..my_writer.pos];

assert_eq!(
json1.as_bytes(),
json2
);
}
}
32 changes: 32 additions & 0 deletions src/ser/tests/my_writer.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
pub struct MyWriter {
pub buffer: [u8; 128],
pub pos: usize,
pub fail: bool
}

#[derive(Debug)]
pub struct MyWriterError { }

impl embedded_io::Error for MyWriterError {
fn kind(&self) -> embedded_io::ErrorKind {
embedded_io::ErrorKind::OutOfMemory
}
}

impl embedded_io::ErrorType for MyWriter {
type Error = MyWriterError;
}

impl embedded_io::Write for MyWriter {
fn write(&mut self, buf: &[u8]) -> Result<usize, Self::Error> {
let av = self.buffer.len() - self.pos;
let wr = core::cmp::min(av, buf.len());
self.buffer[self.pos..(self.pos + wr)].copy_from_slice(&buf[..wr]);
self.pos = self.pos + wr;
Ok(wr)
}

fn flush(&mut self) -> Result<(), Self::Error> {
Ok(())
}
}
35 changes: 35 additions & 0 deletions src/ser/write_backend.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
use super::{Result, Error, ser_backend::SerializerBackend};
use embedded_io::{Write, self};

pub struct WriteSerializer<'a, W: Write> {
writer: &'a mut W,
current_length: usize,
}

impl<'a, W: Write> WriteSerializer<'a, W> {
/// Create a new `Serializer`
pub fn new(writer: &'a mut W) -> Self {
Self {
writer,
current_length: 0
}
}
}

impl<'a, W: Write> SerializerBackend for WriteSerializer<'a, W> {
fn end(&self) -> usize {
self.current_length
}

fn push(&mut self, c: u8) -> Result<()> {
self.writer.write_all(&[c; 1]).map_err(|_err| Error::IOError)?;
self.current_length = self.current_length + 1;
Ok(())
}

fn extend_from_slice(&mut self, other: &[u8]) -> Result<()> {
self.writer.write_all(other).map_err(|_err| Error::IOError)?;
self.current_length = self.current_length + other.len();
Ok(())
}
}

0 comments on commit bb199dc

Please sign in to comment.