data-stream 0.3.1

A simple serialization library based on streams
Documentation
use crate::{FromStream, ToStream, from_stream, numbers::EndianSettings, to_stream};

use std::{
    collections::{BTreeMap, BTreeSet, BinaryHeap, HashMap, HashSet, LinkedList, VecDeque},
    hash::Hash,
    io::{Read, Result, Write},
};

/// The encoding for sizes for collections.
pub enum Size {
    /// Encodes sizes as `usize`.
    Usize,
    /// Encodes sizes as `u8`.
    U8,
    /// Encodes sizes as `u16`.
    U16,
    /// Encodes sizes as `u32`.
    U32,
    /// Encodes sizes as `u64`.
    U64,
    /// Encodes sizes as `u128`.
    U128,
}

/// The size settings required for reading and writing collections.
pub trait SizeSettings: EndianSettings {
    /// The size used by these size settings.
    const SIZE: Size;

    /// Writes some size using specific settings.
    fn size_to_stream<W: Write>(size: usize, stream: &mut W) -> Result<()> {
        use Size::*;
        match Self::SIZE {
            U8 => to_stream::<Self, _, _>(&(size as u8), stream),
            U16 => to_stream::<Self, _, _>(&(size as u16), stream),
            U32 => to_stream::<Self, _, _>(&(size as u32), stream),
            U64 => to_stream::<Self, _, _>(&(size as u64), stream),
            U128 => to_stream::<Self, _, _>(&(size as u128), stream),
            Usize => to_stream::<Self, _, _>(&size, stream),
        }
    }

    /// Reads some size using specific settings.
    fn size_from_stream<R: Read>(stream: &mut R) -> Result<usize> {
        use Size::*;
        Ok(match Self::SIZE {
            U8 => from_stream::<Self, u8, _>(stream)? as usize,
            U16 => from_stream::<Self, u16, _>(stream)? as usize,
            U32 => from_stream::<Self, u32, _>(stream)? as usize,
            U64 => from_stream::<Self, u64, _>(stream)? as usize,
            U128 => from_stream::<Self, u128, _>(stream)? as usize,
            Usize => from_stream::<Self, usize, _>(stream)?,
        })
    }
}

macro_rules! impl_list_collection {
    ($t: ident) => {
        impl<T: ToStream<S>, S: SizeSettings> ToStream<S> for $t<T> {
            fn to_stream<W: Write>(&self, stream: &mut W) -> Result<()> {
                S::size_to_stream(self.len(), stream)?;

                for element in self {
                    element.to_stream(stream)?
                }

                Ok(())
            }
        }

        impl<T: FromStream<S>, S: SizeSettings> FromStream<S> for $t<T> {
            fn from_stream<R: Read>(stream: &mut R) -> Result<Self> {
                let size = S::size_from_stream(stream)?;

                (0..size)
                    .map(|_| from_stream(stream))
                    .collect::<Result<_>>()
            }
        }
    };
    ($t: ident, $($rest: ident),+) => {
        impl_list_collection!($t);
        impl_list_collection!($($rest),+);
    };
}

impl_list_collection!(Vec, VecDeque, LinkedList);

macro_rules! impl_set_collection {
    ($t: ident, $bound: tt $(+ $others: tt )*) => {
        impl<T: ToStream<S> + $bound $(+ $others)*, S: SizeSettings> ToStream<S> for $t<T> {
            fn to_stream<W: Write>(&self, stream: &mut W) -> Result<()> {
                S::size_to_stream(self.len(), stream)?;

                for element in self {
                    element.to_stream(stream)?
                }

                Ok(())
            }
        }

        impl<T: FromStream<S> + $bound $(+ $others)*, S: SizeSettings> FromStream<S> for $t<T> {
            fn from_stream<R: Read>(stream: &mut R) -> Result<Self> {
                let size = S::size_from_stream(stream)?;

                (0..size)
                    .map(|_| from_stream(stream))
                    .collect::<Result<_>>()
            }
        }
    };
}

impl_set_collection!(HashSet, Eq + Hash);
impl_set_collection!(BTreeSet, Ord);
impl_set_collection!(BinaryHeap, Ord);

macro_rules! impl_map_collection {
    ($t: ident, $bound: tt $(+ $others: tt )*) => {
        impl<K: ToStream<S> + $bound $(+ $others)*, V: ToStream<S>, S: SizeSettings> ToStream<S> for $t<K, V> {
            fn to_stream<W: Write>(&self, stream: &mut W) -> Result<()> {
                S::size_to_stream(self.len(), stream)?;

                for (key, value) in self {
                    key.to_stream(stream)?;
                    value.to_stream(stream)?;
                }

                Ok(())
            }
        }

        impl<K: FromStream<S> + $bound $(+ $others)*, V: FromStream<S>, S: SizeSettings> FromStream<S> for $t<K, V> {
            fn from_stream<R: Read>(stream: &mut R) -> Result<Self> {
                let size = S::size_from_stream(stream)?;

                (0..size)
                    .map(|_| Ok((from_stream(stream)?, from_stream(stream)?)))
                    .collect::<Result<_>>()
            }
        }
    };
}

impl_map_collection!(HashMap, Eq + Hash);
impl_map_collection!(BTreeMap, Ord);