#![doc = include_str!("../crate-docs.md")]
#![forbid(unsafe_code)]
#![warn(
clippy::cargo,
missing_docs,
// clippy::missing_docs_in_private_items,
clippy::pedantic,
future_incompatible,
rust_2018_idioms,
)]
#![allow(
clippy::missing_errors_doc, // TODO clippy::missing_errors_doc
clippy::option_if_let_else,
clippy::used_underscore_binding, // false positive with tracing
clippy::module_name_repetitions,
)]
pub mod de;
mod error;
pub mod format;
pub mod reader;
pub mod ser;
mod value;
use std::io::Read;
use byteorder::WriteBytesExt;
pub use self::error::Error;
pub use self::value::{OwnedValue, Value, ValueError, ValueIter};
pub type Result<T, E = Error> = std::result::Result<T, E>;
use serde::de::DeserializeOwned;
use serde::{Deserialize, Serialize};
use crate::de::SymbolMapRef;
use crate::reader::IoReader;
#[inline]
pub fn to_vec<T>(value: &T) -> Result<Vec<u8>>
where
T: Serialize,
{
Config::default().serialize(value)
}
#[inline]
pub fn to_writer<T, W>(value: &T, writer: W) -> Result<()>
where
T: Serialize,
W: WriteBytesExt,
{
Config::default().serialize_into(value, writer)
}
#[inline]
pub fn from_slice<'a, T>(serialized: &'a [u8]) -> Result<T>
where
T: Deserialize<'a>,
{
Config::default().deserialize(serialized)
}
#[inline]
pub fn from_reader<T, R>(reader: R) -> Result<T>
where
T: DeserializeOwned,
R: Read,
{
Config::default().deserialize_from(reader)
}
#[must_use]
#[derive(Clone, Debug)]
pub struct Config {
allocation_budget: usize,
compatibility: Compatibility,
}
impl Default for Config {
#[inline]
fn default() -> Self {
Self::new()
}
}
impl Config {
pub const fn new() -> Self {
Self {
allocation_budget: usize::MAX,
compatibility: Compatibility::const_default(),
}
}
#[inline]
pub const fn allocation_budget(mut self, budget: usize) -> Self {
self.allocation_budget = budget;
self
}
pub const fn compatibility(mut self, compatibilty: Compatibility) -> Self {
self.compatibility = compatibilty;
self
}
#[inline]
pub fn deserialize<'de, T>(&self, serialized: &'de [u8]) -> Result<T>
where
T: Deserialize<'de>,
{
let mut deserializer = de::Deserializer::from_slice(serialized, self.allocation_budget)?;
let t = T::deserialize(&mut deserializer)?;
if deserializer.end_of_input() {
Ok(t)
} else {
Err(Error::TrailingBytes)
}
}
#[inline]
pub fn deserialize_from<T, R: Read>(&self, reader: R) -> Result<T>
where
T: DeserializeOwned,
{
let mut deserializer = de::Deserializer::from_read(
IoReader::new(reader),
SymbolMapRef::temporary(),
self.allocation_budget,
)?;
T::deserialize(&mut deserializer)
}
#[inline]
pub fn serialize<T: Serialize>(&self, value: &T) -> Result<Vec<u8>> {
let mut output = Vec::new();
self.serialize_into(value, &mut output)?;
Ok(output)
}
#[allow(clippy::unused_self)]
#[inline]
pub fn serialize_into<T, W>(&self, value: &T, writer: W) -> Result<()>
where
T: Serialize,
W: WriteBytesExt,
{
let mut serializer = ser::Serializer::new_with_compatibility(writer, self.compatibility)?;
value.serialize(&mut serializer)
}
}
#[derive(Debug, Eq, PartialEq, Clone, Copy)]
#[non_exhaustive]
pub enum Compatibility {
Full,
V4,
}
impl Compatibility {
const fn const_default() -> Self {
Self::Full
}
}
impl Default for Compatibility {
fn default() -> Self {
Self::const_default()
}
}
#[cfg(test)]
mod tests;