use std::io::{Read, Write};
use serde::{de::DeserializeOwned, Deserialize, Serialize};
use crate::{decoder, error::Result, ser};
#[derive(Clone, Copy, Debug, Default, Eq, PartialEq)]
pub enum Endian {
#[default]
Little,
Big,
Native,
}
impl Endian {
pub(crate) const fn little(self) -> bool {
match self {
Self::Little => true,
Self::Big => false,
Self::Native => cfg!(target_endian = "little"),
}
}
}
#[derive(Clone, Copy, Debug, Default, Eq, PartialEq)]
pub enum IntEncoding {
Fixed,
#[default]
Variable,
}
#[derive(Clone, Copy, Debug, Default, Eq, PartialEq)]
pub enum TrailingBytes {
Allow,
#[default]
Reject,
}
#[derive(Clone, Copy, Debug, Eq, PartialEq)]
pub struct Config {
pub(crate) endian: Endian,
pub(crate) integers: IntEncoding,
pub(crate) trailing: TrailingBytes,
pub(crate) limit: Option<u64>,
pub(crate) collection_limit: Option<u64>,
}
impl Default for Config {
fn default() -> Self {
Self::standard()
}
}
impl Config {
pub const fn standard() -> Self {
Self {
endian: Endian::Little,
integers: IntEncoding::Variable,
trailing: TrailingBytes::Reject,
limit: None,
collection_limit: Some(1_000_000),
}
}
pub const fn legacy() -> Self {
Self {
endian: Endian::Little,
integers: IntEncoding::Fixed,
trailing: TrailingBytes::Allow,
limit: None,
collection_limit: None,
}
}
pub const fn with_little_endian(mut self) -> Self {
self.endian = Endian::Little;
self
}
pub const fn with_big_endian(mut self) -> Self {
self.endian = Endian::Big;
self
}
pub const fn with_native_endian(mut self) -> Self {
self.endian = Endian::Native;
self
}
pub const fn with_fixint_encoding(mut self) -> Self {
self.integers = IntEncoding::Fixed;
self
}
pub const fn with_varint_encoding(mut self) -> Self {
self.integers = IntEncoding::Variable;
self
}
pub const fn with_limit(mut self, limit: u64) -> Self {
self.limit = Some(limit);
self.collection_limit = Some(match self.collection_limit {
Some(current) if current < limit => current,
_ => limit,
});
self
}
pub const fn with_no_limit(mut self) -> Self {
self.limit = None;
self
}
pub const fn with_collection_limit(mut self, limit: u64) -> Self {
self.collection_limit = Some(limit);
self
}
pub const fn with_no_collection_limit(mut self) -> Self {
self.collection_limit = None;
self
}
#[cfg(feature = "fingerprint")]
pub const fn with_fingerprint(self) -> crate::FingerprintedConfig {
crate::FingerprintedConfig::new(self)
}
#[cfg(feature = "cbor")]
pub const fn with_cbor_format(self) -> crate::CborConfig {
crate::CborConfig::new(self)
}
#[cfg(feature = "compression")]
pub const fn with_zstd_compression(self, level: i32) -> crate::CompressedConfig {
crate::CompressedConfig::binary(self, level)
}
#[cfg(feature = "encryption")]
pub fn with_encryption(self, key: crate::EncryptionKey) -> crate::EncryptedConfig {
crate::EncryptedConfig::binary(self, key)
}
#[cfg(feature = "bit-packing")]
pub const fn with_bit_packing(self) -> crate::BitPackedConfig {
crate::BitPackedConfig::new(self)
}
#[cfg(feature = "adaptive")]
pub const fn with_adaptive_encoding(self) -> crate::AdaptiveConfig {
crate::AdaptiveConfig::new(self.with_varint_encoding().with_little_endian())
}
#[cfg(feature = "parallel")]
pub fn with_parallel_serialization(self) -> crate::ParallelConfig {
crate::ParallelConfig::new(self)
}
#[cfg(feature = "schema-evolution")]
pub const fn with_schema_evolution(self) -> crate::EvolutionConfig {
crate::EvolutionConfig::new(self)
}
pub const fn reject_trailing_bytes(mut self) -> Self {
self.trailing = TrailingBytes::Reject;
self
}
pub const fn allow_trailing_bytes(mut self) -> Self {
self.trailing = TrailingBytes::Allow;
self
}
pub fn serialize<T: Serialize + ?Sized>(self, value: &T) -> Result<Vec<u8>> {
ser::to_vec(value, self)
}
pub fn serialize_into<W: Write, T: Serialize + ?Sized>(
self,
writer: W,
value: &T,
) -> Result<()> {
ser::to_writer(writer, value, self).map(|_| ())
}
pub fn serialize_into_slice<T: Serialize + ?Sized>(
self,
output: &mut [u8],
value: &T,
) -> Result<usize> {
ser::to_slice(output, value, self)
}
pub fn serialized_size<T: Serialize + ?Sized>(self, value: &T) -> Result<u64> {
ser::size(value, self)
}
pub fn deserialize<'de, T: Deserialize<'de>>(self, input: &'de [u8]) -> Result<T> {
decoder::from_slice(input, self)
}
pub fn deserialize_from<R: Read, T: DeserializeOwned>(self, reader: R) -> Result<T> {
decoder::from_reader(reader, self)
}
}
#[allow(missing_docs)]
pub trait Options: Sized {
fn config(self) -> Config;
fn with_little_endian(self) -> Config {
self.config().with_little_endian()
}
fn with_big_endian(self) -> Config {
self.config().with_big_endian()
}
fn with_native_endian(self) -> Config {
self.config().with_native_endian()
}
fn with_fixint_encoding(self) -> Config {
self.config().with_fixint_encoding()
}
fn with_varint_encoding(self) -> Config {
self.config().with_varint_encoding()
}
fn with_limit(self, limit: u64) -> Config {
self.config().with_limit(limit)
}
fn with_no_limit(self) -> Config {
self.config().with_no_limit()
}
fn with_collection_limit(self, limit: u64) -> Config {
self.config().with_collection_limit(limit)
}
fn with_no_collection_limit(self) -> Config {
self.config().with_no_collection_limit()
}
fn reject_trailing_bytes(self) -> Config {
self.config().reject_trailing_bytes()
}
fn allow_trailing_bytes(self) -> Config {
self.config().allow_trailing_bytes()
}
fn serialize<T: Serialize + ?Sized>(self, value: &T) -> Result<Vec<u8>> {
self.config().serialize(value)
}
fn serialize_into<W: Write, T: Serialize + ?Sized>(self, writer: W, value: &T) -> Result<()> {
self.config().serialize_into(writer, value)
}
fn serialize_into_slice<T: Serialize + ?Sized>(
self,
output: &mut [u8],
value: &T,
) -> Result<usize> {
self.config().serialize_into_slice(output, value)
}
fn serialized_size<T: Serialize + ?Sized>(self, value: &T) -> Result<u64> {
self.config().serialized_size(value)
}
fn deserialize<'de, T: Deserialize<'de>>(self, input: &'de [u8]) -> Result<T> {
self.config().deserialize(input)
}
fn deserialize_from<R: Read, T: DeserializeOwned>(self, reader: R) -> Result<T> {
self.config().deserialize_from(reader)
}
}
impl Options for Config {
fn config(self) -> Config {
self
}
}