lbs 0.4.3

Lazy Binary Serialization
Documentation
use crate::error::LBSError;
use std::borrow::Cow;
use std::collections::BTreeMap;
use std::collections::BTreeSet;
use std::collections::HashMap;
use std::collections::HashSet;
use std::hash::BuildHasher;
use std::hash::Hash;
use std::io::Read;
use std::mem::size_of;
use std::net::IpAddr;
use std::net::Ipv4Addr;
use std::net::Ipv6Addr;
use std::ops::Range;
use std::rc::Rc;
use std::sync::Arc;
use std::time::Duration;
use std::time::SystemTime;

pub trait LBSRead: Sized {
    fn lbs_read<R: std::io::Read>(r: &mut R) -> Result<Self, LBSError>;
}

macro_rules! impl_read_primitive {
    ($t:ty, $l:expr) => {
        impl LBSRead for $t {
            #[inline]
            fn lbs_read<R: Read>(r: &mut R) -> Result<Self, LBSError> {
                let mut buf = [0; $l];
                r.read_exact(&mut buf)?;
                Ok(Self::from_le_bytes(buf))
            }
        }
    };
}

impl_read_primitive!(u8, 1);
impl_read_primitive!(u16, 2);
impl_read_primitive!(u32, 4);
impl_read_primitive!(u64, 8);
impl_read_primitive!(usize, 8);
impl_read_primitive!(u128, 16);

impl_read_primitive!(i8, 1);
impl_read_primitive!(i16, 2);
impl_read_primitive!(i32, 4);
impl_read_primitive!(i64, 8);
impl_read_primitive!(isize, 8);
impl_read_primitive!(i128, 16);

impl_read_primitive!(f32, 4);
impl_read_primitive!(f64, 8);

impl LBSRead for () {
    #[inline]
    fn lbs_read<R: Read>(_: &mut R) -> Result<Self, LBSError> {
        Ok(())
    }
}

impl<T1: LBSRead, T2: LBSRead> LBSRead for (T1, T2) {
    #[inline]
    fn lbs_read<R: Read>(r: &mut R) -> Result<Self, LBSError> {
        Ok((T1::lbs_read(r)?, T2::lbs_read(r)?))
    }
}

impl<T1: LBSRead, T2: LBSRead, T3: LBSRead> LBSRead for (T1, T2, T3) {
    #[inline]
    fn lbs_read<R: Read>(r: &mut R) -> Result<Self, LBSError> {
        Ok((T1::lbs_read(r)?, T2::lbs_read(r)?, T3::lbs_read(r)?))
    }
}

impl LBSRead for bool {
    #[inline]
    fn lbs_read<R: Read>(r: &mut R) -> Result<Self, LBSError> {
        let mut buf = [0; 1];
        r.read_exact(&mut buf)?;
        Ok(u8::from_le_bytes(buf) == 1)
    }
}

impl LBSRead for char {
    #[inline]
    fn lbs_read<R: Read>(r: &mut R) -> Result<Self, LBSError> {
        let mut buf = [0; 4];
        r.read_exact(&mut buf)?;
        Self::from_u32(u32::from_le_bytes(buf)).ok_or_else(|| LBSError::InvalidChar)
    }
}

impl LBSRead for String {
    #[inline]
    fn lbs_read<R: Read>(r: &mut R) -> Result<Self, LBSError> {
        let l = read_len(r)?;

        if l == 0 {
            return Ok(Self::new());
        }

        let mut buf = vec![0; l];
        r.read_exact(&mut buf)?;
        Self::from_utf8(buf).map_err(|e| LBSError::Parsing(e.to_string()))
    }
}

impl LBSRead for Duration {
    #[inline]
    fn lbs_read<R: Read>(r: &mut R) -> Result<Self, LBSError> {
        let secs = u64::lbs_read(r)?;
        let nanos = u32::lbs_read(r)?;
        Ok(Self::new(secs, nanos))
    }
}

impl LBSRead for SystemTime {
    #[inline]
    fn lbs_read<R: Read>(r: &mut R) -> Result<Self, LBSError> {
        Self::UNIX_EPOCH
            .checked_add(Duration::lbs_read(r)?)
            .ok_or_else(|| LBSError::InvalidTimestamp)
    }
}

impl LBSRead for Ipv4Addr {
    #[inline]
    fn lbs_read<R: Read>(r: &mut R) -> Result<Self, LBSError> {
        Ok(Self::from(u32::lbs_read(r)?))
    }
}

impl LBSRead for Ipv6Addr {
    #[inline]
    fn lbs_read<R: Read>(r: &mut R) -> Result<Self, LBSError> {
        Ok(Self::from(u128::lbs_read(r)?))
    }
}

impl LBSRead for IpAddr {
    #[inline]
    fn lbs_read<R: Read>(r: &mut R) -> Result<Self, LBSError> {
        Ok(match bool::lbs_read(r)? {
            true => IpAddr::V4(Ipv4Addr::lbs_read(r)?),
            false => IpAddr::V6(Ipv6Addr::lbs_read(r)?),
        })
    }
}

impl<T: LBSRead + PartialOrd> LBSRead for Range<T> {
    #[inline]
    fn lbs_read<R: Read>(r: &mut R) -> Result<Self, LBSError> {
        let start = T::lbs_read(r)?;
        let end = T::lbs_read(r)?;
        Ok(Range { start, end })
    }
}

impl<T: LBSRead> LBSRead for Box<T> {
    #[inline]
    fn lbs_read<R: Read>(r: &mut R) -> Result<Self, LBSError> {
        Ok(Self::new(T::lbs_read(r)?))
    }
}

impl<T: LBSRead> LBSRead for Rc<T> {
    #[inline]
    fn lbs_read<R: Read>(r: &mut R) -> Result<Self, LBSError> {
        Ok(Self::new(T::lbs_read(r)?))
    }
}

impl<T: LBSRead> LBSRead for Arc<T> {
    #[inline]
    fn lbs_read<R: Read>(r: &mut R) -> Result<Self, LBSError> {
        Ok(Self::new(T::lbs_read(r)?))
    }
}

impl LBSRead for Arc<str> {
    #[inline]
    fn lbs_read<R: Read>(r: &mut R) -> Result<Self, LBSError> {
        Ok(Self::from(String::lbs_read(r)?))
    }
}

impl<'a, T: LBSRead + ToOwned> LBSRead for Cow<'a, T> {
    #[inline]
    fn lbs_read<R: Read>(r: &mut R) -> Result<Self, LBSError> {
        Ok(Self::Owned(T::lbs_read(r)?.to_owned()))
    }
}

impl<'a, T> LBSRead for Cow<'a, [T]>
where
    T: LBSRead,
    [T]: ToOwned<Owned = Vec<T>>,
{
    #[inline]
    fn lbs_read<R: Read>(r: &mut R) -> Result<Self, LBSError> {
        Ok(Self::Owned(<Vec<T> as LBSRead>::lbs_read(r)?))
    }
}

impl<'a> LBSRead for Cow<'a, str> {
    #[inline]
    fn lbs_read<R: Read>(r: &mut R) -> Result<Self, LBSError> {
        Ok(Self::Owned(String::lbs_read(r)?))
    }
}

impl<T: LBSRead> LBSRead for Option<T> {
    #[inline]
    fn lbs_read<R: Read>(r: &mut R) -> Result<Self, LBSError> {
        let mut buf = [0; 1];
        r.read_exact(&mut buf)?;
        if u8::from_le_bytes(buf) == 1 {
            Ok(Some(T::lbs_read(r)?))
        } else {
            Ok(None)
        }
    }
}

impl<T: LBSRead> LBSRead for Vec<T> {
    #[inline]
    fn lbs_read<R: Read>(r: &mut R) -> Result<Self, LBSError> {
        let l = read_len(r)?;

        if l == 0 {
            return Ok(Self::new());
        }

        let mut v = Self::with_capacity(l);

        for _ in 0..l {
            v.push(T::lbs_read(r)?);
        }

        Ok(v)
    }
}

impl<K, V, S> LBSRead for HashMap<K, V, S>
where
    K: LBSRead + Eq + Hash,
    V: LBSRead,
    S: BuildHasher + Default,
{
    #[inline]
    fn lbs_read<R: Read>(r: &mut R) -> Result<Self, LBSError> {
        let l = read_len(r)?;

        if l == 0 {
            return Ok(Self::default());
        }

        let mut hm = Self::with_capacity_and_hasher(l, S::default());

        for _ in 0..l {
            let k = K::lbs_read(r)?;
            let v = V::lbs_read(r)?;
            hm.insert(k, v);
        }

        Ok(hm)
    }
}

impl<K, S> LBSRead for HashSet<K, S>
where
    K: LBSRead + Eq + Hash,
    S: BuildHasher + Default,
{
    #[inline]
    fn lbs_read<R: Read>(r: &mut R) -> Result<Self, LBSError> {
        let l = read_len(r)?;

        if l == 0 {
            return Ok(Self::default());
        }

        let mut hs = Self::with_capacity_and_hasher(l, S::default());

        for _ in 0..l {
            hs.insert(K::lbs_read(r)?);
        }

        Ok(hs)
    }
}

impl<K: LBSRead + Ord, V: LBSRead> LBSRead for BTreeMap<K, V> {
    #[inline]
    fn lbs_read<R: Read>(r: &mut R) -> Result<Self, LBSError> {
        let l = read_len(r)?;
        let mut bm = Self::new();

        if l == 0 {
            return Ok(bm);
        }

        for _ in 0..l {
            let k = K::lbs_read(r)?;
            let v = V::lbs_read(r)?;
            bm.insert(k, v);
        }

        Ok(bm)
    }
}

impl<K: LBSRead + Ord> LBSRead for BTreeSet<K> {
    #[inline]
    fn lbs_read<R: Read>(r: &mut R) -> Result<Self, LBSError> {
        let l = read_len(r)?;
        let mut bm = Self::new();

        if l == 0 {
            return Ok(bm);
        }

        for _ in 0..l {
            bm.insert(K::lbs_read(r)?);
        }

        Ok(bm)
    }
}

#[inline]
pub fn read_field_count<R: Read>(r: &mut R) -> Result<u16, LBSError> {
    u16::lbs_read(r)
}

#[inline]
pub fn read_field_id<R: Read>(r: &mut R) -> Result<u16, LBSError> {
    u16::lbs_read(r)
}

#[inline]
pub fn read<T: LBSRead, R: Read>(r: &mut R) -> Result<T, LBSError> {
    T::lbs_read(r)
}

#[inline]
pub fn read_len<R: Read>(r: &mut R) -> Result<usize, LBSError> {
    let mut buf = [0; size_of::<u32>()];
    r.read_exact(&mut buf)?;
    Ok(u32::from_le_bytes(buf) as usize)
}