minint 0.1.0

A simple FRC NetworkTables v4 client library for Rust
Documentation
use rmp::{decode::RmpRead, encode::RmpWrite};

pub enum Data {
    Bool(bool),
    F64(f64),
    I32(i32),
    F32(f32),
    String(String),
    BoolArray(Vec<bool>),
    F64Array(Vec<f64>),
    I32Array(Vec<i32>),
    F32Array(Vec<f32>),
    StringArray(Vec<String>),
}
impl Data {
    pub fn from<R: RmpRead>(rd: &mut R, data_type: u8) -> Result<Self, ()> {
        Ok(match data_type {
            <bool as DataWrap>::MSGPCK => Self::Bool(<bool as DataWrap>::decode(rd)?),
            <f64 as DataWrap>::MSGPCK => Self::F64(<f64 as DataWrap>::decode(rd)?),
            <i32 as DataWrap>::MSGPCK => Self::I32(<i32 as DataWrap>::decode(rd)?),
            <f32 as DataWrap>::MSGPCK => Self::F32(<f32 as DataWrap>::decode(rd)?),
            <String as DataWrap>::MSGPCK => Self::String(<String as DataWrap>::decode(rd)?),
            <Vec<bool> as DataWrap>::MSGPCK => {
                Self::BoolArray(<Vec<bool> as DataWrap>::decode(rd)?)
            }
            <Vec<f64> as DataWrap>::MSGPCK => Self::F64Array(<Vec<f64> as DataWrap>::decode(rd)?),
            <Vec<i32> as DataWrap>::MSGPCK => Self::I32Array(<Vec<i32> as DataWrap>::decode(rd)?),
            <Vec<f32> as DataWrap>::MSGPCK => Self::F32Array(<Vec<f32> as DataWrap>::decode(rd)?),
            <Vec<String> as DataWrap>::MSGPCK => {
                Self::StringArray(<Vec<String> as DataWrap>::decode(rd)?)
            }
            _ => return Err(()),
        })
    }
}

pub trait DataWrap: Sized {
    const MSGPCK: u8;
    const STRING: &'static str;

    fn decode<R: RmpRead>(rd: &mut R) -> Result<Self, ()>;
    fn encode<W: RmpWrite>(wr: &mut W, val: Self) -> Result<(), ()>;
}
impl<T: DataType> DataWrap for T {
    const MSGPCK: u8 = Self::DATATYPE_MSGPCK;
    const STRING: &'static str = Self::DATATYPE_STRING;

    fn decode<R: RmpRead>(rd: &mut R) -> Result<Self, ()> {
        Self::decode(rd)
    }
    fn encode<W: RmpWrite>(wr: &mut W, val: Self) -> Result<(), ()> {
        Self::encode(wr, val)
    }
}
impl<T: DataType> DataWrap for Vec<T> {
    const MSGPCK: u8 = T::ARRAYDATATYPE_MSGPCK;
    const STRING: &'static str = T::ARRAYDATATYPE_STRING;

    fn decode<R: RmpRead>(rd: &mut R) -> Result<Self, ()> {
        T::decode_array(rd)
    }
    fn encode<W: RmpWrite>(wr: &mut W, val: Self) -> Result<(), ()> {
        T::encode_array(wr, val)
    }
}

pub trait DataType: Sized {
    const DATATYPE_MSGPCK: u8;
    const ARRAYDATATYPE_MSGPCK: u8;
    const DATATYPE_STRING: &'static str;
    const ARRAYDATATYPE_STRING: &'static str;

    fn decode<R: RmpRead>(rd: &mut R) -> Result<Self, ()>;
    fn encode<W: RmpWrite>(wr: &mut W, val: Self) -> Result<(), ()>;

    fn decode_array<R: RmpRead>(rd: &mut R) -> Result<Vec<Self>, ()> {
        let mut buf = Vec::new();

        let len = rmp::decode::read_array_len(rd).map_err(|_| ())?;

        for _ in 0..len {
            buf.push(Self::decode(rd)?);
        }

        Ok(buf)
    }

    fn encode_array<W: RmpWrite>(wr: &mut W, vals: Vec<Self>) -> Result<(), ()> {
        rmp::encode::write_array_len(wr, vals.len() as u32).map_err(|_| ())?;

        for val in vals {
            Self::encode(wr, val)?;
        }

        Ok(())
    }
}

impl DataType for bool {
    const DATATYPE_MSGPCK: u8 = 0;
    const ARRAYDATATYPE_MSGPCK: u8 = 16;
    const DATATYPE_STRING: &'static str = "boolean";
    const ARRAYDATATYPE_STRING: &'static str = "boolean[]";

    fn decode<R: RmpRead>(rd: &mut R) -> Result<Self, ()> {
        let ret = rmp::decode::read_bool(rd).map_err(|_| ())?;

        Ok(ret)
    }

    fn encode<W: RmpWrite>(wr: &mut W, val: Self) -> Result<(), ()> {
        rmp::encode::write_bool(wr, val).map_err(|_| ())?;

        Ok(())
    }
}
impl DataType for f64 {
    const DATATYPE_MSGPCK: u8 = 1;
    const ARRAYDATATYPE_MSGPCK: u8 = 17;
    const DATATYPE_STRING: &'static str = "double";
    const ARRAYDATATYPE_STRING: &'static str = "double[]";

    fn decode<R: RmpRead>(rd: &mut R) -> Result<Self, ()> {
        let ret = rmp::decode::read_f64(rd).map_err(|_| ())?;

        Ok(ret)
    }

    fn encode<W: RmpWrite>(wr: &mut W, val: Self) -> Result<(), ()> {
        rmp::encode::write_f64(wr, val).map_err(|_| ())?;

        Ok(())
    }
}
impl DataType for i32 {
    const DATATYPE_MSGPCK: u8 = 2;
    const ARRAYDATATYPE_MSGPCK: u8 = 18;
    const DATATYPE_STRING: &'static str = "int";
    const ARRAYDATATYPE_STRING: &'static str = "int[]";

    fn decode<R: RmpRead>(rd: &mut R) -> Result<Self, ()> {
        let ret = rmp::decode::read_i32(rd).map_err(|_| ())?;

        Ok(ret)
    }

    fn encode<W: RmpWrite>(wr: &mut W, val: Self) -> Result<(), ()> {
        rmp::encode::write_i32(wr, val).map_err(|_| ())?;

        Ok(())
    }
}

impl DataType for f32 {
    const DATATYPE_MSGPCK: u8 = 3;
    const ARRAYDATATYPE_MSGPCK: u8 = 19;
    const DATATYPE_STRING: &'static str = "float";
    const ARRAYDATATYPE_STRING: &'static str = "float[]";

    fn decode<R: RmpRead>(rd: &mut R) -> Result<Self, ()> {
        let ret = rmp::decode::read_f32(rd).map_err(|_| ())?;

        Ok(ret)
    }

    fn encode<W: RmpWrite>(wr: &mut W, val: Self) -> Result<(), ()> {
        rmp::encode::write_f32(wr, val).map_err(|_| ())?;

        Ok::<(), _>(())
    }
}

impl DataType for String {
    const DATATYPE_MSGPCK: u8 = 4;
    const ARRAYDATATYPE_MSGPCK: u8 = 20;
    const DATATYPE_STRING: &'static str = "string";
    const ARRAYDATATYPE_STRING: &'static str = "string[]";

    fn decode<R: RmpRead>(rd: &mut R) -> Result<Self, ()> {
        let mut buf = Vec::new();

        let ret = rmp::decode::read_str(rd, &mut buf).map_err(|_| ())?;

        Ok(ret.to_string())
    }

    fn encode<W: RmpWrite>(wr: &mut W, val: Self) -> Result<(), ()> {
        rmp::encode::write_str(wr, &val).map_err(|_| ())?;

        Ok(())
    }
}