ufotofu 0.12.5

Abstractions for lazily consuming and producing sequences
Documentation
//! Wrappers around fixed-width integer types for big-endian and little-endian encoding and decoding.
//!
//! See also the corresponding methods on [`BulkConsumerExt`] ([`encode_u16_be`](BulkConsumerExt::encode_u16_be), [`encode_i16_be`](BulkConsumerExt::encode_i16_be), [`encode_u16_le`](BulkConsumerExt::encode_u16_le), [`encode_i16_le`](BulkConsumerExt::encode_i16_le), etc.) and on [`BulkProducerExt`] ([`decode_u16_be`](BulkProducerExt::decode_u16_be), [`decode_i16_be`](BulkProducerExt::decode_i16_be), [`decode_u16_le`](BulkProducerExt::decode_u16_le), [`decode_i16_le`](BulkProducerExt::decode_i16_le), etc.); these can be more convenient than using explicit wrapper types.

use crate::codec_prelude::*;

#[cfg(feature = "dev")]
use arbitrary::Arbitrary;

macro_rules! endian_wrapper {
    (name $wrapper_name:ident; integer $int:ident; doc_array $arr:expr; from_bytes $from_bytes:ident; to_bytes $to_bytes:ident; word $word:ident) => {
        #[doc = concat!("A thin wrapper around [`", stringify!($int), "`] for ", stringify!($word), "-endian encoding.
```
use ufotofu::codec_prelude::*;
use ufotofu::codec::endian::*;

# #[cfg(feature = \"alloc\")] {
# pollster::block_on(async{
assert_eq!(
    &", stringify!($arr), "[..],
    &", stringify!($wrapper_name), "(0x12cd).new_boxed_slice_storing_encoding().await[..],
);
assert_eq!(
    0x12cd,
    ", stringify!($wrapper_name), "::decode(&mut ", stringify!($arr), ".into_producer()).await?.0,
);
# Result::<(), DecodeError::<(), Infallible, Infallible>>::Ok(())
# });
# }
```")]
        #[derive(Debug, PartialEq, Eq, PartialOrd, Ord, Clone, Copy, Hash)]
        #[cfg_attr(feature = "dev", derive(Arbitrary))]
        pub struct $wrapper_name(pub $int);

        impl From<$int> for $wrapper_name {
            fn from(value: $int) -> Self {
                $wrapper_name(value)
            }
        }

        impl From<$wrapper_name> for $int {
            fn from(value: $wrapper_name) -> Self {
                value.0
            }
        }

        impl Encodable for $wrapper_name {
            async fn encode<C>(
                &self,
                consumer: &mut C,
            ) -> Result<(), C::Error>
            where
                C: BulkConsumer<Item = u8> + ?Sized,
            {
                let bytes = self.0.$to_bytes();
                consumer
                    .bulk_consume_full_slice(&bytes[..])
                    .await.map_err(|err| err.into_reason())?;
                Ok(())
            }
        }

        impl EncodableKnownLength for $wrapper_name {
            fn len_of_encoding(&self) -> usize {
                ($int::BITS / 8) as usize
            }
        }

        impl Decodable for $wrapper_name {
            type ErrorReason = Infallible;

            async fn decode<P>(
                producer: &mut P,
            ) -> Result<Self, DecodeError<P::Final, P::Error, Self::ErrorReason>>
            where
                P: BulkProducer<Item = u8> + ?Sized,
            {
                let mut bytes = [0u8; ($int::BITS / 8) as usize];
                producer.bulk_overwrite_full_slice(&mut bytes[..]).await?;
                Ok($wrapper_name($int::$from_bytes(bytes)))
            }
        }

        impl DecodableCanonic for $wrapper_name {
            type ErrorCanonic = Self::ErrorReason;

            async fn decode_canonic<P>(
                producer: &mut P,
            ) -> Result<Self, DecodeError<P::Final, P::Error, Self::ErrorCanonic>>
            where
                P: BulkProducer<Item = u8> + ?Sized,
            {
                Self::decode(producer).await
            }
        }
    }
}

macro_rules! endian_wrapper_single_byte {
    (name $wrapper_name:ident; integer $int:ident; word $word:ident) => {
        #[doc = concat!("A thin wrapper around [`", stringify!($int), "`] for ", stringify!($word), "-endian encoding.
```
use ufotofu::codec_prelude::*;
use ufotofu::codec::endian::*;

# #[cfg(feature = \"alloc\")] {
# pollster::block_on(async{
assert_eq!(
    &[0x12][..],
    &", stringify!($wrapper_name), "(0x12).new_boxed_slice_storing_encoding().await[..],
);
assert_eq!(
    0x12,
    ", stringify!($wrapper_name), "::decode(&mut [0x12].into_producer()).await?.0,
);
# Result::<(), DecodeError::<(), Infallible, Infallible>>::Ok(())
# });
# }
```")]
        #[derive(Debug, PartialEq, Eq, PartialOrd, Ord, Clone, Copy, Hash)]
        #[cfg_attr(feature = "dev", derive(Arbitrary))]
        pub struct $wrapper_name(pub $int);

        impl From<$int> for $wrapper_name {
            fn from(value: $int) -> Self {
                $wrapper_name(value)
            }
        }

        impl From<$wrapper_name> for $int {
            fn from(value: $wrapper_name) -> Self {
                value.0
            }
        }

        impl Encodable for $wrapper_name {
            async fn encode<C>(
                &self,
                consumer: &mut C,
            ) -> Result<(), C::Error>
            where
                C: BulkConsumer<Item = u8> + ?Sized,
            {
                let bytes = self.0.to_be_bytes();
                consumer
                    .bulk_consume_full_slice(&bytes[..])
                    .await
                    .map_err(|err| err.into_reason())
            }
        }

        impl EncodableKnownLength for $wrapper_name {
            fn len_of_encoding(&self) -> usize {
                ($int::BITS / 8) as usize
            }
        }

        impl Decodable for $wrapper_name {
            type ErrorReason = Infallible;

            async fn decode<P>(
                producer: &mut P,
            ) -> Result<Self, DecodeError<P::Final, P::Error, Self::ErrorReason>>
            where
                P: BulkProducer<Item = u8> + ?Sized,
            {
                let mut bytes = [0u8; ($int::BITS / 8) as usize];
                producer
                    .bulk_overwrite_full_slice(&mut bytes[..])
                    .await?;
                Ok($wrapper_name($int::from_be_bytes(bytes)))
            }
        }

        impl DecodableCanonic for $wrapper_name {
            type ErrorCanonic = Self::ErrorReason;

            async fn decode_canonic<P>(
                producer: &mut P,
            ) -> Result<Self, DecodeError<P::Final, P::Error, Self::ErrorCanonic>>
            where
                P: BulkProducer<Item = u8> + ?Sized,
            {
                Self::decode(producer).await
            }
        }
    }
}

macro_rules! wrapper_be {
    (name $wrapper_name:ident; integer $int:ident; doc_array $arr:expr) => {
        endian_wrapper!(name $wrapper_name; integer $int; doc_array $arr; from_bytes from_be_bytes; to_bytes to_be_bytes; word big);
    }
}

macro_rules! wrapper_le {
    (name $wrapper_name:ident; integer $int:ident; doc_array $arr:expr) => {
        endian_wrapper!(name $wrapper_name; integer $int; doc_array $arr; from_bytes from_le_bytes; to_bytes to_le_bytes; word little);
    }
}

endian_wrapper_single_byte!(name U8BE; integer u8; word big);
wrapper_be!(name U16BE; integer u16; doc_array [0x12, 0xcd]);
wrapper_be!(name U32BE; integer u32; doc_array [0, 0, 0x12, 0xcd]);
wrapper_be!(name U64BE; integer u64; doc_array [0, 0, 0, 0, 0, 0, 0x12, 0xcd]);
wrapper_be!(name U128BE; integer u128; doc_array [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0x12, 0xcd]);

endian_wrapper_single_byte!(name I8BE; integer i8; word big);
wrapper_be!(name I16BE; integer i16; doc_array [0x12, 0xcd]);
wrapper_be!(name I32BE; integer i32; doc_array [0, 0, 0x12, 0xcd]);
wrapper_be!(name I64BE; integer i64; doc_array [0, 0, 0, 0, 0, 0, 0x12, 0xcd]);
wrapper_be!(name I128BE; integer i128; doc_array [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0x12, 0xcd]);

endian_wrapper_single_byte!(name U8LE; integer u8; word little);
wrapper_le!(name U16LE; integer u16; doc_array [0xcd, 0x12]);
wrapper_le!(name U32LE; integer u32; doc_array [0xcd, 0x12, 0, 0]);
wrapper_le!(name U64LE; integer u64; doc_array [0xcd, 0x12, 0, 0, 0, 0, 0, 0]);
wrapper_le!(name U128LE; integer u128; doc_array [0xcd, 0x12, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]);

endian_wrapper_single_byte!(name I8LE; integer i8; word little);
wrapper_le!(name I16LE; integer i16; doc_array [0xcd, 0x12]);
wrapper_le!(name I32LE; integer i32; doc_array [0xcd, 0x12, 0, 0]);
wrapper_le!(name I64LE; integer i64; doc_array [0xcd, 0x12, 0, 0, 0, 0, 0, 0]);
wrapper_le!(name I128LE; integer i128; doc_array [0xcd, 0x12, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]);