internet 0.1.0

Network library for rust
Documentation
//! Codec for structures.

use crate::Cursor;
use crate::{Buf, BufMut, BufResult};

/// A `Codec` trait provides encoding and decoding.
pub trait Codec<C = ()>: Sized {
    /// Encodes `self` using `writer` and returns `()` or [`BufError`] if error.
    ///
    /// [`BufError`]: crate::BufError
    fn encode<W: BufMut>(&self, writer: &mut Cursor<W>, context: C) -> BufResult<()>;

    /// Decodes bytes from `reader` and returns `Self` or [`BufError`] if error.
    ///
    /// [`BufError`]: crate::BufError
    fn decode<R: Buf>(reader: &mut Cursor<R>, context: C) -> BufResult<Self>;
}

impl Codec for u8 {
    #[inline]
    fn encode<W: BufMut>(&self, writer: &mut Cursor<W>, _: ()) -> BufResult<()> {
        writer.write_u8(*self)
    }

    #[inline]
    fn decode<R: Buf>(reader: &mut Cursor<R>, _: ()) -> BufResult<Self> {
        reader.read_u8()
    }
}

impl Codec for u16 {
    #[inline]
    fn encode<W: BufMut>(&self, writer: &mut Cursor<W>, _: ()) -> BufResult<()> {
        writer.write_u16_be(*self)
    }

    #[inline]
    fn decode<R: Buf>(reader: &mut Cursor<R>, _: ()) -> BufResult<Self> {
        reader.read_u16_be()
    }
}

impl Codec for u32 {
    #[inline]
    fn encode<W: BufMut>(&self, writer: &mut Cursor<W>, _: ()) -> BufResult<()> {
        writer.write_u32_be(*self)
    }

    #[inline]
    fn decode<R: Buf>(reader: &mut Cursor<R>, _: ()) -> BufResult<Self> {
        reader.read_u32_be()
    }
}

impl Codec for u64 {
    #[inline]
    fn encode<W: BufMut>(&self, writer: &mut Cursor<W>, _: ()) -> BufResult<()> {
        writer.write_array(&self.to_be_bytes())
    }

    #[inline]
    fn decode<R: Buf>(reader: &mut Cursor<R>, _: ()) -> BufResult<Self> {
        let bytes = reader.read_array::<8>()?;
        Ok(u64::from_be_bytes(bytes))
    }
}

impl<const N: usize> Codec for [u8; N] {
    #[inline]
    fn encode<W: BufMut>(&self, writer: &mut Cursor<W>, _: ()) -> BufResult<()> {
        writer.write_array(self)
    }

    #[inline]
    fn decode<R: Buf>(reader: &mut Cursor<R>, _: ()) -> BufResult<Self> {
        reader.read_array::<N>()
    }
}

#[cfg(feature = "alloc")]
impl<T: Codec> Codec for Vec<T> {
    fn encode<W: BufMut>(&self, writer: &mut Cursor<W>, _: ()) -> BufResult<()> {
        for item in self.iter() {
            item.encode(writer, ())?;
        }
        Ok(())
    }

    fn decode<R: Buf>(reader: &mut Cursor<R>, _: ()) -> BufResult<Self> {
        let mut vec = Vec::new();

        while !reader.is_eof() {
            vec.push(T::decode(reader, ())?);
        }

        Ok(vec)
    }
}

#[cfg(feature = "alloc")]
impl<T: Codec> Codec<usize> for Vec<T> {
    fn encode<W: BufMut>(&self, writer: &mut Cursor<W>, _: usize) -> BufResult<()> {
        for item in self.iter() {
            item.encode(writer, ())?;
        }
        Ok(())
    }

    fn decode<R: Buf>(reader: &mut Cursor<R>, to_decode: usize) -> BufResult<Self> {
        let mut vec = Vec::new();

        for _ in 0..to_decode {
            if reader.is_eof() {
                use crate::BufError;

                return Err(BufError::OutOfBounds);
            }
            vec.push(T::decode(reader, ())?);
        }

        Ok(vec)
    }
}