macro_rules! impl_encoding {
($encoder:ident, $decoder:ident, $len:literal, $encoder_impl:ident, $decoder_impl:ident) => {
use crate::{
DecodeIntoExactError, Decoder, DynDecoder, DynEncoder, EncodeIntoExactError, Encoder,
alphabet::{Alphabet, DecodingTable, DynAlphabet, DynDecodingTable},
generic::{GenericDecoder, GenericEncoder},
padding::Padding
};
pub type $encoder<A, D, P> = GenericEncoder<A, D, P, $len>;
pub type $decoder<D, P> = GenericDecoder<D, P, $len>;
impl<A, D, P> Encoder<$len> for $encoder<A, D, P>
where
A: AsRef<Alphabet<$len>> + Copy,
D: AsRef<DecodingTable<$len>> + Copy,
P: Padding
{
fn alphabet(&self) -> &Alphabet<$len> {
self.as_ref()
}
}
impl<A, D, P> DynEncoder for $encoder<A, D, P>
where
A: AsRef<Alphabet<$len>> + Copy,
D: AsRef<DecodingTable<$len>> + Copy,
P: Padding
{
fn dyn_alphabet(&self) -> &DynAlphabet {
self.alphabet().as_ref().as_dyn_alphabet()
}
fn encoded_len(&self, len: usize) -> Option<usize> {
$encoder_impl::from(*self).encoded_len(len)
}
fn encode_into_exact<'a>(
&self,
src: &[u8],
dst: &'a mut [u8]
) -> Result<&'a str, EncodeIntoExactError> {
$encoder_impl::from(*self).encode_into_exact(src, dst)
}
}
impl<A, D, P> Decoder<$len> for $encoder<A, D, P>
where
A: AsRef<Alphabet<$len>> + Copy,
D: AsRef<DecodingTable<$len>> + Copy,
P: Padding
{
fn decoding_table(&self) -> &DecodingTable<$len> {
self.as_ref()
}
}
impl<A, D, P> DynDecoder for $encoder<A, D, P>
where
A: AsRef<Alphabet<$len>> + Copy,
D: AsRef<DecodingTable<$len>> + Copy,
P: Padding
{
fn dyn_decoding_table(&self) -> &DynDecodingTable {
self.decoding_table().as_ref().as_dyn_decoding_table()
}
fn decoded_len(&self, src: &[u8]) -> Option<usize> {
$decoder::from(*self).decoded_len(src)
}
fn decode_into_exact<'a>(
&self,
src: &[u8],
dst: &'a mut [u8]
) -> Result<&'a [u8], DecodeIntoExactError> {
$decoder::from(*self).decode_into_exact(src, dst)
}
}
impl<D, P> Decoder<$len> for $decoder<D, P>
where
D: AsRef<DecodingTable<$len>> + Copy,
P: Padding
{
fn decoding_table(&self) -> &DecodingTable<$len> {
self.as_ref()
}
}
impl<D, P> DynDecoder for $decoder<D, P>
where
D: AsRef<DecodingTable<$len>> + Copy,
P: Padding
{
fn dyn_decoding_table(&self) -> &DynDecodingTable {
self.decoding_table().as_ref().as_dyn_decoding_table()
}
fn decoded_len(&self, src: &[u8]) -> Option<usize> {
$decoder_impl::from(*self).decoded_len(src)
}
fn decode_into_exact<'a>(
&self,
src: &[u8],
dst: &'a mut [u8]
) -> Result<&'a [u8], DecodeIntoExactError> {
$decoder_impl::from(*self).decode_into_exact(src, dst)
}
}
};
}
macro_rules! impl_encoder {
($name:ident, $len:literal, $alphabet:literal, $decoding_table:expr, $padding:ident) => {
#[derive(Clone, Copy, Debug, Default, Eq, Hash, Ord, PartialEq, PartialOrd)]
pub struct $name;
impl $name {
pub const ALPHABET: &Alphabet<$len> = unsafe { Alphabet::new_unchecked($alphabet) };
pub const DECODING_TABLE: &DecodingTable<$len> = &$decoding_table;
}
impl AsRef<Alphabet<$len>> for $name {
#[inline]
fn as_ref(&self) -> &Alphabet<$len> {
Self::ALPHABET
}
}
impl AsRef<DecodingTable<$len>> for $name {
#[inline]
fn as_ref(&self) -> &DecodingTable<$len> {
Self::DECODING_TABLE
}
}
impl From<$name> for GenericEncoder<$name, $name, $padding, $len> {
#[inline]
fn from(_: $name) -> Self {
unsafe { Self::new_unchecked($name, $name, $padding) }
}
}
impl From<$name> for GenericDecoder<$name, $padding, $len> {
#[inline]
fn from(_: $name) -> Self {
unsafe { Self::new_unchecked($name, $padding) }
}
}
impl Encoder<$len> for $name {
fn alphabet(&self) -> &Alphabet<$len> {
self.as_ref()
}
}
impl DynEncoder for $name {
#[inline]
fn dyn_alphabet(&self) -> &DynAlphabet {
Self::ALPHABET.as_dyn_alphabet()
}
#[inline]
fn encoded_len(&self, len: usize) -> Option<usize> {
GenericEncoder::from($name).encoded_len(len)
}
#[inline]
fn encode_into_exact<'a>(
&self,
src: &[u8],
dst: &'a mut [u8]
) -> Result<&'a str, EncodeIntoExactError> {
GenericEncoder::from($name).encode_into_exact(src, dst)
}
}
impl Decoder<$len> for $name {
fn decoding_table(&self) -> &DecodingTable<$len> {
self.as_ref()
}
}
impl DynDecoder for $name {
#[inline]
fn dyn_decoding_table(&self) -> &DynDecodingTable {
Self::DECODING_TABLE.as_dyn_decoding_table()
}
#[inline]
fn decoded_len(&self, src: &[u8]) -> Option<usize> {
GenericDecoder::from($name).decoded_len(src)
}
#[inline]
fn decode_into_exact<'a>(
&self,
src: &[u8],
dst: &'a mut [u8]
) -> Result<&'a [u8], DecodeIntoExactError> {
GenericDecoder::from($name).decode_into_exact(src, dst)
}
}
};
($name:ident, $len:literal, $alphabet:literal, $padding:ident) => {
impl_encoder!($name, $len, $alphabet, Self::ALPHABET.decoding_table(), $padding);
};
}