use crate::Endian;
use crate::{Error, Result};
#[derive(Copy, Clone, Debug, PartialEq)]
pub struct Codec {
endian: Endian,
limit: Limit,
}
impl Codec {
#[doc(alias = "new")]
#[inline]
pub const fn builder() -> CodecBuilder {
CodecBuilder { endian: None, limit: None }
}
#[inline]
pub const fn endian(&self) -> Endian {
self.endian
}
#[inline]
pub const fn limit(&self) -> Limit {
self.limit
}
#[inline]
pub const fn is_big_endian(&self) -> bool {
self.endian.is_big_endian()
}
#[inline]
pub const fn is_little_endian(&self) -> bool {
self.endian.is_little_endian()
}
}
impl Default for Codec {
#[inline]
fn default() -> Self {
Codec::builder()
.with_little_endian()
.with_limit(Limit::new(0x1000))
.try_build()
.expect("CodecBuilder failed to produce properly initialized Codec instance.")
}
}
#[derive(Clone, Copy, Debug, PartialEq)]
#[repr(transparent)]
pub struct Limit(u32);
impl Limit {
const DEFAULT_MAX_LIMIT: u32 = 0x1000;
#[inline]
pub const fn new(value: u32) -> Limit {
Limit(value)
}
#[inline]
pub const fn get(self) -> u32 {
self.0
}
}
impl core::ops::Deref for Limit {
type Target = u32;
#[inline]
fn deref(&self) -> &Self::Target {
&self.0
}
}
impl Default for Limit {
#[inline(always)]
fn default() -> Limit {
Limit(Self::DEFAULT_MAX_LIMIT)
}
}
pub struct CodecBuilder {
endian: Option<Endian>,
limit: Option<Limit>,
}
impl CodecBuilder {
#[inline]
pub const fn new() -> CodecBuilder {
CodecBuilder { endian: None, limit: None }
}
#[inline]
pub const fn with_big_endian(self) -> CodecBuilder {
CodecBuilder { endian: Some(Endian::Little), ..self }
}
#[inline]
pub const fn with_little_endian(self) -> CodecBuilder {
CodecBuilder { endian: Some(Endian::Little), ..self }
}
#[inline]
pub const fn with_const_limit<const LIMIT: u32>(self) -> CodecBuilder {
CodecBuilder { limit: Some(Limit::new(LIMIT)), ..self }
}
#[inline]
pub const fn with_endian(mut self, endian: Endian) -> CodecBuilder {
self.endian = Some(endian);
self
}
#[inline]
pub const fn with_limit(mut self, limit: Limit) -> CodecBuilder {
self.limit = Some(limit);
self
}
#[inline]
pub const fn try_build(self) -> Result<Codec> {
let Some(endian) = self.endian else {
return Err(Error::invalid_codec("endianness must be set"));
};
let Some(limit) = self.limit else {
return Err(Error::invalid_codec("byte limit must be set"));
};
Ok(Codec { endian, limit })
}
#[inline]
pub const fn build(self, fallback: Codec) -> Codec {
let endian = match self.endian {
Some(endian) => endian,
None => fallback.endian(),
};
let limit = match self.limit {
Some(limit) => limit,
None => fallback.limit(),
};
Codec { endian, limit }
}
}