diff --git a/src/de.rs b/src/de.rs index 64eaea4..a159e51 100644 --- a/src/de.rs +++ b/src/de.rs @@ -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}; use serde::Deserialize; use crate::parser::{self, Config, Event, EventKind, Name, Nested, Parser, Primitive}; @@ -1350,6 +1350,38 @@ impl Config { deserializer.ensure_eof()?; Ok(result) } + + pub fn deserialize_slice<'de, T: Deserialize<'de>>( + self, + source: &'de [u8], + ) -> Result { + 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_reader( + self, + mut reader: R, + ) -> Result { + 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_slice(&source) + } } struct BetterPeekable diff --git a/src/lib.rs b/src/lib.rs index 8b5a6fe..d2e9f44 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -19,11 +19,34 @@ pub fn from_str<'de, D: serde::Deserialize<'de>>(source: &'de str) -> Result>(source: &'de [u8]) -> Result { + parser::Config::default().deserialize_slice(source) +} + +#[cfg(all(feature = "serde", feature = "std"))] +pub fn from_reader( + reader: R, +) -> Result { + parser::Config::default().deserialize_reader(reader) +} + #[cfg(feature = "serde")] pub fn to_string(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(value: &S) -> alloc::vec::Vec { + ser::Config::default().serialize_to_vec(value) +} + +#[cfg(all(feature = "serde", feature = "std"))] +pub fn to_writer( + value: &S, + writer: W, +) -> std::io::Result { + ser::Config::default().serialize_writer(value, writer) } #[cfg(feature = "serde")] diff --git a/src/ser.rs b/src/ser.rs index f014b96..906c374 100644 --- a/src/ser.rs +++ b/src/ser.rs @@ -469,6 +469,56 @@ impl Config { value.serialize(&mut serializer).expect("core::fmt::Error"); serializer.finish() } + + pub fn serialize_to_vec(&self, value: &S) -> alloc::vec::Vec { + self.serialize(value).into_bytes() + } +} + +#[cfg(feature = "std")] +mod serialize_writer { + use super::*; + struct Writer { + writer: T, + written: usize, + error: Option, + } + impl Write for Writer { + 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_writer( + &self, + value: &S, + writer: W, + ) -> std::io::Result { + 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]