use crate::{
alphabet::{Alphabet, DecodingTable},
padding::{Padding, Unpadded}
};
#[derive(Clone, Copy, Debug, Default, Eq, Hash, PartialEq)]
pub struct GenericEncoder<A, D, P, const LEN: usize> {
alphabet: A,
decoding_table: D,
padding: P
}
impl<A, D, P, const LEN: usize> GenericEncoder<A, D, P, LEN>
where
A: AsRef<Alphabet<LEN>> + Copy,
D: AsRef<DecodingTable<LEN>> + Copy,
P: Padding
{
pub fn new(alphabet: A, decoding_table: D, padding: P) -> Option<Self> {
if decoding_table.as_ref().check(alphabet.as_ref())
&& padding.padding().is_none_or(|b| !alphabet.as_ref().contains(&b))
{
Some(Self { alphabet, decoding_table, padding })
} else {
None
}
}
#[allow(clippy::missing_safety_doc)]
pub const unsafe fn new_unchecked(alphabet: A, decoding_table: D, padding: P) -> Self {
Self { alphabet, decoding_table, padding }
}
pub const fn alphabet(&self) -> &A {
&self.alphabet
}
pub const fn decoding_table(&self) -> &D {
&self.decoding_table
}
pub const fn padding(self) -> P {
self.padding
}
pub const fn into_unpadded(self) -> GenericEncoder<A, D, Unpadded, LEN> {
GenericEncoder {
alphabet: self.alphabet,
decoding_table: self.decoding_table,
padding: Unpadded
}
}
}
impl<A, D, const LEN: usize> GenericEncoder<A, D, Unpadded, LEN>
where
A: AsRef<Alphabet<LEN>> + Copy,
D: AsRef<DecodingTable<LEN>> + Copy
{
pub fn new_unpadded(alphabet: A, decoding_table: D) -> Option<Self> {
GenericEncoder::new(alphabet, decoding_table, Unpadded)
}
#[allow(clippy::missing_safety_doc)]
pub const unsafe fn new_unpadded_unchecked(alphabet: A, decoding_table: D) -> Self {
unsafe { GenericEncoder::new_unchecked(alphabet, decoding_table, Unpadded) }
}
}
impl<A, D, P, const LEN: usize> AsRef<Alphabet<LEN>> for GenericEncoder<A, D, P, LEN>
where
A: AsRef<Alphabet<LEN>>
{
fn as_ref(&self) -> &Alphabet<LEN> {
self.alphabet.as_ref()
}
}
impl<A, D, P, const LEN: usize> AsRef<DecodingTable<LEN>> for GenericEncoder<A, D, P, LEN>
where
D: AsRef<DecodingTable<LEN>>
{
fn as_ref(&self) -> &DecodingTable<LEN> {
self.decoding_table.as_ref()
}
}
#[derive(Clone, Copy, Debug, Default, Eq, Hash, PartialEq)]
pub struct GenericDecoder<D, P, const LEN: usize> {
decoding_table: D,
padding: P
}
impl<D, P, const LEN: usize> GenericDecoder<D, P, LEN>
where
D: AsRef<DecodingTable<LEN>> + Copy,
P: Padding
{
pub const fn new(decoding_table: D, padding: P) -> Option<Self> {
Some(Self { decoding_table, padding })
}
#[allow(clippy::missing_safety_doc)]
pub const unsafe fn new_unchecked(decoding_table: D, padding: P) -> Self {
Self { decoding_table, padding }
}
pub const fn decoding_table(&self) -> &D {
&self.decoding_table
}
pub const fn padding(self) -> P {
self.padding
}
}
impl<D, const LEN: usize> GenericDecoder<D, Unpadded, LEN>
where
D: AsRef<DecodingTable<LEN>>
{
pub const fn new_unpadded(decoding_table: D) -> Self {
Self { decoding_table, padding: Unpadded }
}
}
impl<D, P, const LEN: usize> AsRef<DecodingTable<LEN>> for GenericDecoder<D, P, LEN>
where
D: AsRef<DecodingTable<LEN>>
{
fn as_ref(&self) -> &DecodingTable<LEN> {
self.decoding_table.as_ref()
}
}
impl<A, D, P, const LEN: usize> From<GenericEncoder<A, D, P, LEN>> for GenericDecoder<D, P, LEN> {
fn from(encoder: GenericEncoder<A, D, P, LEN>) -> Self {
Self { decoding_table: encoder.decoding_table, padding: encoder.padding }
}
}