pub(crate) use self::internal::*;
use core::marker::PhantomData;
#[derive(Copy, Clone, Debug)]
pub struct Configuration<E = LittleEndian, I = Varint, L = NoLimit> {
_e: PhantomData<E>,
_i: PhantomData<I>,
_l: PhantomData<L>,
}
pub const fn standard() -> Configuration {
generate()
}
pub const fn legacy() -> Configuration<LittleEndian, Fixint, NoLimit> {
generate()
}
impl<E, I, L> Default for Configuration<E, I, L> {
fn default() -> Self {
generate()
}
}
const fn generate<E, I, L>() -> Configuration<E, I, L> {
Configuration {
_e: PhantomData,
_i: PhantomData,
_l: PhantomData,
}
}
impl<E, I, L> Configuration<E, I, L> {
pub const fn with_big_endian(self) -> Configuration<BigEndian, I, L> {
generate()
}
pub const fn with_little_endian(self) -> Configuration<LittleEndian, I, L> {
generate()
}
pub const fn with_variable_int_encoding(self) -> Configuration<E, Varint, L> {
generate()
}
pub const fn with_fixed_int_encoding(self) -> Configuration<E, Fixint, L> {
generate()
}
pub const fn with_limit<const N: usize>(self) -> Configuration<E, I, Limit<N>> {
generate()
}
pub const fn with_no_limit(self) -> Configuration<E, I, NoLimit> {
generate()
}
}
pub trait Config:
InternalEndianConfig + InternalIntEncodingConfig + InternalLimitConfig + Copy + Clone
{
fn endianness(&self) -> Endianness;
fn int_encoding(&self) -> IntEncoding;
fn limit(&self) -> Option<usize>;
}
impl<T> Config for T
where
T: InternalEndianConfig + InternalIntEncodingConfig + InternalLimitConfig + Copy + Clone,
{
fn endianness(&self) -> Endianness {
<T as InternalEndianConfig>::ENDIAN
}
fn int_encoding(&self) -> IntEncoding {
<T as InternalIntEncodingConfig>::INT_ENCODING
}
fn limit(&self) -> Option<usize> {
<T as InternalLimitConfig>::LIMIT
}
}
#[derive(Copy, Clone)]
pub struct BigEndian {}
impl InternalEndianConfig for BigEndian {
const ENDIAN: Endianness = Endianness::Big;
}
#[derive(Copy, Clone)]
pub struct LittleEndian {}
impl InternalEndianConfig for LittleEndian {
const ENDIAN: Endianness = Endianness::Little;
}
#[derive(Copy, Clone)]
pub struct Fixint {}
impl InternalIntEncodingConfig for Fixint {
const INT_ENCODING: IntEncoding = IntEncoding::Fixed;
}
#[derive(Copy, Clone)]
pub struct Varint {}
impl InternalIntEncodingConfig for Varint {
const INT_ENCODING: IntEncoding = IntEncoding::Variable;
}
#[derive(Copy, Clone)]
pub struct NoLimit {}
impl InternalLimitConfig for NoLimit {
const LIMIT: Option<usize> = None;
}
#[derive(Copy, Clone)]
pub struct Limit<const N: usize> {}
impl<const N: usize> InternalLimitConfig for Limit<N> {
const LIMIT: Option<usize> = Some(N);
}
#[derive(PartialEq, Eq)]
#[non_exhaustive]
pub enum Endianness {
Little,
Big,
}
#[derive(PartialEq, Eq)]
#[non_exhaustive]
pub enum IntEncoding {
Fixed,
Variable,
}
mod internal {
use super::{Configuration, Endianness, IntEncoding};
pub trait InternalEndianConfig {
const ENDIAN: Endianness;
}
impl<E: InternalEndianConfig, I, L> InternalEndianConfig for Configuration<E, I, L> {
const ENDIAN: Endianness = E::ENDIAN;
}
pub trait InternalIntEncodingConfig {
const INT_ENCODING: IntEncoding;
}
impl<E, I: InternalIntEncodingConfig, L> InternalIntEncodingConfig for Configuration<E, I, L> {
const INT_ENCODING: IntEncoding = I::INT_ENCODING;
}
pub trait InternalLimitConfig {
const LIMIT: Option<usize>;
}
impl<E, I, L: InternalLimitConfig> InternalLimitConfig for Configuration<E, I, L> {
const LIMIT: Option<usize> = L::LIMIT;
}
}