#![cfg_attr(not(feature = "std"), no_std)]
#[cfg(feature = "alloc")]
extern crate alloc;
mod buffer;
mod config;
pub mod de;
pub mod docs;
mod error;
mod format;
mod io;
pub mod ser;
#[cfg(feature = "alloc")]
pub mod value;
#[allow(unused_imports, reason = "Different feature sets")]
use ::serde::{de::DeserializeOwned, Deserialize, Serialize};
#[cfg(feature = "std")]
use ::std::io::{Read, Write};
#[cfg(feature = "alloc")]
pub use self::value::{from_value, from_value_with_config, to_value, to_value_with_config};
pub use self::{config::Config, de::Deserializer, error::Error, ser::Serializer};
pub type Result<T, E = Error> = ::core::result::Result<T, E>;
#[cfg_attr(feature = "tracing", ::tracing::instrument(skip_all, fields(config)))]
pub fn to_slice_with_config<'buf, T>(
value: &T,
buffer: &'buf mut [u8],
config: Config,
) -> Result<&'buf mut [u8]>
where
T: Serialize,
{
let remaining = if let Some(max) = config.max_size {
let mut ser = Serializer::new(io::SizeLimit::new(&mut *buffer, max.into()))
.use_indices(config.use_indices);
value.serialize(&mut ser)?;
ser.into_output().into_inner().len()
} else {
let mut ser = Serializer::new(&mut *buffer).use_indices(config.use_indices);
value.serialize(&mut ser)?;
ser.into_output().len()
};
let used = buffer.len() - remaining;
Ok(buffer.split_at_mut(used).0)
}
pub fn to_slice<'buf, T>(value: &T, buffer: &'buf mut [u8]) -> Result<&'buf mut [u8]>
where
T: Serialize,
{
to_slice_with_config(value, buffer, Config::default())
}
#[cfg(feature = "alloc")]
#[cfg_attr(feature = "tracing", ::tracing::instrument(skip_all, fields(config)))]
pub fn to_vec_with_config<T>(value: &T, config: Config) -> Result<::alloc::vec::Vec<u8>>
where
T: Serialize,
{
if let Some(max) = config.max_size {
let mut ser = Serializer::new(io::SizeLimit::new(::alloc::vec::Vec::new(), max.into()))
.use_indices(config.use_indices);
value.serialize(&mut ser)?;
Ok(ser.into_output().into_inner())
} else {
let mut ser = Serializer::new(::alloc::vec::Vec::new()).use_indices(config.use_indices);
value.serialize(&mut ser)?;
Ok(ser.into_output())
}
}
#[cfg(feature = "alloc")]
pub fn to_vec<T>(value: &T) -> Result<::alloc::vec::Vec<u8>>
where
T: Serialize,
{
to_vec_with_config(value, Config::default())
}
#[cfg(feature = "heapless")]
#[cfg_attr(feature = "tracing", ::tracing::instrument(skip_all, fields(config)))]
pub fn to_heapless_vec_with_config<const N: usize, T>(
value: &T,
config: Config,
) -> Result<::heapless::Vec<u8, N>>
where
T: Serialize,
{
if let Some(max) = config.max_size {
let mut ser = Serializer::new(io::SizeLimit::new(::heapless::Vec::new(), max.into()))
.use_indices(config.use_indices);
value.serialize(&mut ser)?;
Ok(ser.into_output().into_inner())
} else {
let mut ser = Serializer::new(::heapless::Vec::new()).use_indices(config.use_indices);
value.serialize(&mut ser)?;
Ok(ser.into_output())
}
}
#[cfg(feature = "heapless")]
pub fn to_heapless_vec<const N: usize, T>(value: &T) -> Result<::heapless::Vec<u8, N>>
where
T: Serialize,
{
to_heapless_vec_with_config(value, Config::default())
}
#[cfg(feature = "std")]
#[cfg_attr(feature = "tracing", ::tracing::instrument(skip_all, fields(config)))]
pub fn to_writer_with_config<T, W>(value: &T, writer: W, config: Config) -> Result<()>
where
T: Serialize,
W: Write,
{
if let Some(max) = config.max_size {
let mut ser = Serializer::new(io::SizeLimit::new(io::IoWriter::new(writer), max.into()))
.use_indices(config.use_indices);
value.serialize(&mut ser)?;
} else {
let mut ser = Serializer::new(io::IoWriter::new(writer)).use_indices(config.use_indices);
value.serialize(&mut ser)?;
}
Ok(())
}
#[cfg(feature = "std")]
pub fn to_writer<T, W>(value: &T, writer: W) -> Result<()>
where
T: Serialize,
W: Write,
{
to_writer_with_config(value, writer, Config::default())
}
#[cfg_attr(feature = "tracing", ::tracing::instrument(skip_all, fields(config)))]
pub fn from_slice_with_config<'de, T>(bytes: &'de [u8], config: Config) -> Result<T>
where
T: Deserialize<'de>,
{
let error_on_excess = config.error_on_excess_data;
let (value, peek) = if let Some(max) = config.max_size {
let mut de = Deserializer::new(io::SizeLimit::new(bytes, max.into()));
(T::deserialize(&mut de)?, io::Input::peek_byte(&mut de.into_input()))
} else {
let mut de = Deserializer::new(bytes);
(T::deserialize(&mut de)?, io::Input::peek_byte(&mut de.into_input()))
};
if error_on_excess && peek.is_ok() {
return Err(Error::ExcessData);
}
Ok(value)
}
pub fn from_slice<'de, T>(bytes: &'de [u8]) -> Result<T>
where
T: Deserialize<'de>,
{
from_slice_with_config(bytes, Config::default())
}
#[cfg(feature = "std")]
#[cfg_attr(feature = "tracing", ::tracing::instrument(skip_all, fields(config)))]
pub fn from_reader_with_config<R, T>(reader: R, config: Config) -> Result<T>
where
R: Read,
T: DeserializeOwned,
{
let error_on_excess = config.error_on_excess_data;
let (value, peek) = if let Some(max) = config.max_size {
let mut de = Deserializer::new(io::SizeLimit::new(io::IoReader::new(reader), max.into()))
.with_buffer(Vec::new());
(T::deserialize(&mut de)?, io::Input::peek_byte(&mut de.into_input()))
} else {
let mut de = Deserializer::new(io::IoReader::new(reader)).with_buffer(Vec::new());
(T::deserialize(&mut de)?, io::Input::peek_byte(&mut de.into_input()))
};
if error_on_excess && peek.is_ok() {
return Err(Error::ExcessData);
}
Ok(value)
}
#[cfg(feature = "std")]
pub fn from_reader<R, T>(reader: R) -> Result<T>
where
R: Read,
T: DeserializeOwned,
{
from_reader_with_config(reader, Config::default())
}
#[cfg(test)]
mod tests;