btt 0.5.0

Binary to text encodings
Documentation
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> {
		// TODO: check
		Some(Self { decoding_table, padding })
	}

	#[allow(clippy::missing_safety_doc)]
	pub const unsafe fn new_unchecked(decoding_table: D, padding: P) -> Self {
		// TODO: check
		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 }
	}
}