codee 0.2.0

Easy and flexible way of encoding and decoding data into either strings or bytes
Documentation
use crate::{Decoder, Encoder};
use thiserror::Error;

#[derive(Debug, Error)]
pub enum HybridCoderError<E> {
    #[error("Not implemented: {0}")]
    NotImplemented(&'static str),
    #[error("Decoding error")]
    Coder(#[from] E),
}

pub trait HybridDecoder<T, E: ?Sized> {
    type Error;

    fn is_binary_decoder() -> bool;

    fn decode_str(_val: &str) -> Result<T, HybridCoderError<Self::Error>> {
        Err(HybridCoderError::NotImplemented(
            "You're trying to decode from a string. This codec is binary.",
        ))
    }

    fn decode_bin(_val: &[u8]) -> Result<T, HybridCoderError<Self::Error>> {
        Err(HybridCoderError::NotImplemented(
            "You're trying to decode from a byte slice. This codec is a string codec.",
        ))
    }
}

impl<T, D> HybridDecoder<T, [u8]> for D
where
    D: Decoder<T, Encoded = [u8]>,
{
    type Error = D::Error;

    #[inline(always)]
    fn is_binary_decoder() -> bool {
        true
    }

    fn decode_bin(val: &[u8]) -> Result<T, HybridCoderError<Self::Error>> {
        Ok(D::decode(val)?)
    }
}

impl<T, D> HybridDecoder<T, str> for D
where
    D: Decoder<T, Encoded = str>,
{
    type Error = D::Error;

    #[inline(always)]
    fn is_binary_decoder() -> bool {
        false
    }

    fn decode_str(val: &str) -> Result<T, HybridCoderError<Self::Error>> {
        Ok(D::decode(val)?)
    }
}

pub trait HybridEncoder<T, E> {
    type Error;

    fn is_binary_encoder() -> bool;

    fn encode_str(_val: &T) -> Result<String, HybridCoderError<Self::Error>> {
        Err(HybridCoderError::NotImplemented(
            "You're trying to encode into a string. This codec is binary.",
        ))
    }

    fn encode_bin(_val: &T) -> Result<Vec<u8>, HybridCoderError<Self::Error>> {
        Err(HybridCoderError::NotImplemented(
            "You're trying to encode into a byte vec. This codec is a string codec.",
        ))
    }
}

impl<T, E> HybridEncoder<T, Vec<u8>> for E
where
    E: Encoder<T, Encoded = Vec<u8>>,
{
    type Error = E::Error;

    #[inline(always)]
    fn is_binary_encoder() -> bool {
        true
    }

    fn encode_bin(val: &T) -> Result<Vec<u8>, HybridCoderError<Self::Error>> {
        Ok(E::encode(val)?)
    }
}

impl<T, E> HybridEncoder<T, String> for E
where
    E: Encoder<T, Encoded = String>,
{
    type Error = E::Error;

    #[inline(always)]
    fn is_binary_encoder() -> bool {
        false
    }

    fn encode_str(val: &T) -> Result<String, HybridCoderError<Self::Error>> {
        Ok(E::encode(val)?)
    }
}