Skip to content

Commit

Permalink
Add (de)serialization based on Vec, slice, Read and Write (#18)
Browse files Browse the repository at this point in the history
  • Loading branch information
ModProg authored Nov 16, 2023
1 parent 71b5685 commit f780e70
Show file tree
Hide file tree
Showing 3 changed files with 109 additions and 4 deletions.
34 changes: 33 additions & 1 deletion src/de.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ use alloc::string::{String, ToString};
use core::fmt::Display;
use core::ops::Range;

use serde::de::{EnumAccess, MapAccess, SeqAccess, VariantAccess};
use serde::de::{DeserializeOwned, EnumAccess, MapAccess, SeqAccess, VariantAccess};

Check warning on line 6 in src/de.rs

View workflow job for this annotation

GitHub Actions / test

unused import: `DeserializeOwned`
use serde::Deserialize;

use crate::parser::{self, Config, Event, EventKind, Name, Nested, Parser, Primitive};
Expand Down Expand Up @@ -1350,6 +1350,38 @@ impl Config {
deserializer.ensure_eof()?;
Ok(result)
}

pub fn deserialize_from_slice<'de, T: Deserialize<'de>>(
self,
source: &'de [u8],
) -> Result<T, Error> {
let source = match alloc::str::from_utf8(source) {
Ok(source) => source,
Err(error) => {
let end = error
.error_len()
.map(|l| l + error.valid_up_to())
.unwrap_or(source.len());
return Err(Error::new(
(error.valid_up_to() + 1)..end,
ErrorKind::InvalidUtf8,
));
}
};
self.deserialize(source)
}

#[cfg(feature = "std")]
pub fn deserialize_from_reader<T: DeserializeOwned, R: std::io::Read>(
self,
mut reader: R,
) -> Result<T, Error> {
let mut source = alloc::vec::Vec::new();
reader
.read_to_end(&mut source)
.map_err(|e| Error::new(0..0, ErrorKind::Message(e.to_string())))?;
self.deserialize_from_slice(&source)
}
}

struct BetterPeekable<T>
Expand Down
29 changes: 26 additions & 3 deletions src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -19,11 +19,34 @@ pub fn from_str<'de, D: serde::Deserialize<'de>>(source: &'de str) -> Result<D,
parser::Config::default().deserialize(source)
}

#[cfg(feature = "serde")]
pub fn from_slice<'de, D: serde::Deserialize<'de>>(source: &'de [u8]) -> Result<D, de::Error> {
parser::Config::default().deserialize_from_slice(source)
}

#[cfg(all(feature = "serde", feature = "std"))]
pub fn from_reader<D: serde::de::DeserializeOwned, R: std::io::Read>(
reader: R,
) -> Result<D, de::Error> {
parser::Config::default().deserialize_from_reader(reader)
}

#[cfg(feature = "serde")]
pub fn to_string<S: serde::Serialize>(value: &S) -> alloc::string::String {
let mut serializer = ser::Serializer::default();
value.serialize(&mut serializer).expect("infallible");
serializer.finish()
ser::Config::default().serialize(value)
}

#[cfg(feature = "serde")]
pub fn to_vec<S: serde::Serialize>(value: &S) -> alloc::vec::Vec<u8> {
ser::Config::default().serialize_to_vec(value)
}

#[cfg(all(feature = "serde", feature = "std"))]
pub fn to_writer<S: serde::Serialize, W: std::io::Write>(
value: &S,
writer: W,
) -> std::io::Result<usize> {
ser::Config::default().serialize_to_writer(value, writer)
}

#[cfg(feature = "serde")]
Expand Down
50 changes: 50 additions & 0 deletions src/ser.rs
Original file line number Diff line number Diff line change
Expand Up @@ -469,6 +469,56 @@ impl Config {
value.serialize(&mut serializer).expect("core::fmt::Error");
serializer.finish()
}

pub fn serialize_to_vec<S: Serialize>(&self, value: &S) -> alloc::vec::Vec<u8> {
self.serialize(value).into_bytes()
}
}

#[cfg(feature = "std")]
mod serialize_writer {
use super::*;
struct Writer<T> {
writer: T,
written: usize,
error: Option<std::io::Error>,
}
impl<T: std::io::Write> Write for Writer<T> {
fn write_str(&mut self, s: &str) -> core::fmt::Result {
match self.writer.write(s.as_bytes()) {
Ok(written) => {
self.written += written;
Ok(())
}
Err(error) => {
assert!(
self.error.is_none(),
"should not have continued on write error"
);
self.error = Some(error);
Err(core::fmt::Error)
}
}
}
}
impl Config {
pub fn serialize_to_writer<S: Serialize, W: std::io::Write>(
&self,
value: &S,
writer: W,
) -> std::io::Result<usize> {
let mut writer = Writer {
writer,
written: 0,
error: None,
};
let mut serializer = Serializer::new(&mut writer, self);
value
.serialize(&mut serializer)
.map_err(|_| writer.error.expect("should store error on error"))?;
Ok(writer.written)
}
}
}

#[test]
Expand Down

0 comments on commit f780e70

Please sign in to comment.