oxidef_compact1 0.1.0-alpha.1

Oxidef is an experimental interface definition language and serialisation scheme for efficient and strongly-typed payloads.
Documentation
use core::convert::Infallible;

use bytes::BufMut;

use crate::{
    codec::{Compact1Codec, Compact1CodecOpinion},
    decoder::{DecError, Decoder, MeasureBuf},
    encoder::{EncError, Encoder, ImprovidentBufMut},
};

impl Compact1Codec for bool {
    fn encode<B: ImprovidentBufMut>(&self, encoder: &mut Encoder<B>) -> Result<(), EncError>
    where
        Self: Sized,
    {
        encoder.write_stash_bit(*self);
        Ok(())
    }

    fn decode<B: MeasureBuf>(decoder: &mut Decoder<B>) -> Result<Self, DecError>
    where
        Self: Sized,
    {
        decoder.read_stash_bit()
    }
}

impl<T: Compact1Codec> Compact1Codec for Option<T> {
    fn encode<B: ImprovidentBufMut>(&self, encoder: &mut Encoder<B>) -> Result<(), EncError>
    where
        Self: Sized,
    {
        encoder.write_stash_bit(self.is_some());
        if let Some(inner) = self {
            inner.encode(encoder)?;
        }
        Ok(())
    }

    fn decode<B: MeasureBuf>(decoder: &mut Decoder<B>) -> Result<Self, DecError>
    where
        Self: Sized,
    {
        if decoder.read_stash_bit()? {
            T::decode(decoder).map(Some)
        } else {
            Ok(None)
        }
    }
}

impl Compact1Codec for u8 {
    fn encode<B: ImprovidentBufMut>(&self, encoder: &mut Encoder<B>) -> Result<(), EncError>
    where
        Self: Sized,
    {
        encoder.buf.put_u8(*self);
        Ok(())
    }

    fn decode<B: MeasureBuf>(decoder: &mut Decoder<B>) -> Result<Self, DecError>
    where
        Self: Sized,
    {
        decoder.buf.try_get_u8().map_err(Into::into)
    }
}

impl Compact1Codec for i8 {
    fn encode<B: ImprovidentBufMut>(&self, encoder: &mut Encoder<B>) -> Result<(), EncError>
    where
        Self: Sized,
    {
        encoder.buf.put_i8(*self);
        Ok(())
    }

    fn decode<B: MeasureBuf>(decoder: &mut Decoder<B>) -> Result<Self, DecError>
    where
        Self: Sized,
    {
        decoder.buf.try_get_i8().map_err(Into::into)
    }
}

impl Compact1Codec for u16 {
    fn encode<B: ImprovidentBufMut>(&self, encoder: &mut Encoder<B>) -> Result<(), EncError>
    where
        Self: Sized,
    {
        encoder.buf.put_u16_le(*self);
        Ok(())
    }

    fn decode<B: MeasureBuf>(decoder: &mut Decoder<B>) -> Result<Self, DecError>
    where
        Self: Sized,
    {
        decoder.buf.try_get_u16_le().map_err(Into::into)
    }
}

impl Compact1Codec for i16 {
    fn encode<B: ImprovidentBufMut>(&self, encoder: &mut Encoder<B>) -> Result<(), EncError>
    where
        Self: Sized,
    {
        encoder.buf.put_i16_le(*self);
        Ok(())
    }

    fn decode<B: MeasureBuf>(decoder: &mut Decoder<B>) -> Result<Self, DecError>
    where
        Self: Sized,
    {
        decoder.buf.try_get_i16_le().map_err(Into::into)
    }
}

impl Compact1Codec for u32 {
    fn encode<B: ImprovidentBufMut>(&self, encoder: &mut Encoder<B>) -> Result<(), EncError>
    where
        Self: Sized,
    {
        encoder.buf.put_u32_le(*self);
        Ok(())
    }

    fn decode<B: MeasureBuf>(decoder: &mut Decoder<B>) -> Result<Self, DecError>
    where
        Self: Sized,
    {
        decoder.buf.try_get_u32_le().map_err(Into::into)
    }
}

impl Compact1Codec for i32 {
    fn encode<B: ImprovidentBufMut>(&self, encoder: &mut Encoder<B>) -> Result<(), EncError>
    where
        Self: Sized,
    {
        encoder.buf.put_i32_le(*self);
        Ok(())
    }

    fn decode<B: MeasureBuf>(decoder: &mut Decoder<B>) -> Result<Self, DecError>
    where
        Self: Sized,
    {
        decoder.buf.try_get_i32_le().map_err(Into::into)
    }
}

impl Compact1Codec for u64 {
    fn encode<B: ImprovidentBufMut>(&self, encoder: &mut Encoder<B>) -> Result<(), EncError>
    where
        Self: Sized,
    {
        encoder.buf.put_u64_le(*self);
        Ok(())
    }

    fn decode<B: MeasureBuf>(decoder: &mut Decoder<B>) -> Result<Self, DecError>
    where
        Self: Sized,
    {
        decoder.buf.try_get_u64_le().map_err(Into::into)
    }
}

impl Compact1Codec for i64 {
    fn encode<B: ImprovidentBufMut>(&self, encoder: &mut Encoder<B>) -> Result<(), EncError>
    where
        Self: Sized,
    {
        encoder.buf.put_i64_le(*self);
        Ok(())
    }

    fn decode<B: MeasureBuf>(decoder: &mut Decoder<B>) -> Result<Self, DecError>
    where
        Self: Sized,
    {
        decoder.buf.try_get_i64_le().map_err(Into::into)
    }
}

impl Compact1Codec for u128 {
    fn encode<B: ImprovidentBufMut>(&self, encoder: &mut Encoder<B>) -> Result<(), EncError>
    where
        Self: Sized,
    {
        encoder.buf.put_u128_le(*self);
        Ok(())
    }

    fn decode<B: MeasureBuf>(decoder: &mut Decoder<B>) -> Result<Self, DecError>
    where
        Self: Sized,
    {
        decoder.buf.try_get_u128_le().map_err(Into::into)
    }
}

impl Compact1Codec for i128 {
    fn encode<B: ImprovidentBufMut>(&self, encoder: &mut Encoder<B>) -> Result<(), EncError>
    where
        Self: Sized,
    {
        encoder.buf.put_i128_le(*self);
        Ok(())
    }

    fn decode<B: MeasureBuf>(decoder: &mut Decoder<B>) -> Result<Self, DecError>
    where
        Self: Sized,
    {
        decoder.buf.try_get_i128_le().map_err(Into::into)
    }
}

impl Compact1Codec for f32 {
    fn encode<B: ImprovidentBufMut>(&self, encoder: &mut Encoder<B>) -> Result<(), EncError>
    where
        Self: Sized,
    {
        if !self.is_finite() {
            return Err(EncError::FloatNotFinite);
        }

        encoder.buf.put_f32_le(*self);
        Ok(())
    }

    fn decode<B: MeasureBuf>(decoder: &mut Decoder<B>) -> Result<Self, DecError>
    where
        Self: Sized,
    {
        let val = decoder.buf.try_get_f32_le()?;

        if !val.is_finite() {
            return Err(DecError::FloatNotFinite);
        }

        Ok(val)
    }
}

impl Compact1Codec for f64 {
    fn encode<B: ImprovidentBufMut>(&self, encoder: &mut Encoder<B>) -> Result<(), EncError>
    where
        Self: Sized,
    {
        if !self.is_finite() {
            return Err(EncError::FloatNotFinite);
        }

        encoder.buf.put_f64_le(*self);
        Ok(())
    }

    fn decode<B: MeasureBuf>(decoder: &mut Decoder<B>) -> Result<Self, DecError>
    where
        Self: Sized,
    {
        let val = decoder.buf.try_get_f64_le()?;

        if !val.is_finite() {
            return Err(DecError::FloatNotFinite);
        }

        Ok(val)
    }
}

#[derive(Default)]
pub struct RawFloatOpinion;

impl Compact1CodecOpinion<f32> for RawFloatOpinion {
    fn encode<B: ImprovidentBufMut>(
        &self,
        encoder: &mut Encoder<B>,
        what: &f32,
    ) -> Result<(), EncError>
    where
        Self: Sized,
    {
        encoder.buf.put_f32_le(*what);
        Ok(())
    }

    fn decode<B: MeasureBuf>(&self, decoder: &mut Decoder<B>) -> Result<f32, DecError>
    where
        f32: Sized,
    {
        decoder.buf.try_get_f32_le().map_err(Into::into)
    }
}

impl Compact1CodecOpinion<f64> for RawFloatOpinion {
    fn encode<B: ImprovidentBufMut>(
        &self,
        encoder: &mut Encoder<B>,
        what: &f64,
    ) -> Result<(), EncError>
    where
        Self: Sized,
    {
        encoder.buf.put_f64_le(*what);
        Ok(())
    }

    fn decode<B: MeasureBuf>(&self, decoder: &mut Decoder<B>) -> Result<f64, DecError>
    where
        f64: Sized,
    {
        decoder.buf.try_get_f64_le().map_err(Into::into)
    }
}

impl Compact1Codec for Infallible {
    fn encode<B: ImprovidentBufMut>(&self, _encoder: &mut Encoder<B>) -> Result<(), EncError>
    where
        Self: Sized,
    {
        unreachable!("infallible unreachable")
    }

    fn decode<B: MeasureBuf>(_decoder: &mut Decoder<B>) -> Result<Self, DecError>
    where
        Self: Sized,
    {
        Err(DecError::Never)
    }
}

/// Opinion on how to represent an `Option`
pub struct OptionOpinion<TO> {
    /// Opinion for representing items
    inner: TO,
}

impl<TO> OptionOpinion<TO> {
    pub fn new(inner: TO) -> Self {
        Self { inner }
    }
}

impl<T, TO: Compact1CodecOpinion<T>> Compact1CodecOpinion<Option<T>> for OptionOpinion<TO> {
    fn encode<B: ImprovidentBufMut>(
        &self,
        encoder: &mut Encoder<B>,
        what: &Option<T>,
    ) -> Result<(), EncError>
    where
        Self: Sized,
    {
        match what {
            Some(inner) => {
                encoder.write_stash_bit(true);
                self.inner.encode(encoder, inner)?;
            }
            None => {
                encoder.write_stash_bit(false);
            }
        }

        Ok(())
    }

    fn decode<B: MeasureBuf>(&self, decoder: &mut Decoder<B>) -> Result<Option<T>, DecError> {
        Ok(if decoder.read_stash_bit()? {
            Some(self.inner.decode(decoder)?)
        } else {
            None
        })
    }
}