xio_common 0.5.0

XIO commonly used functionality
Documentation
use byteorder::{ReadBytesExt, WriteBytesExt};
use std::io;
use std::io::{Read, Write};
use base::{ParameterValue,ParameterValueRaw};
use {Endian, PreliminaryTryFrom,
     PreliminaryTryInto, WithFixedPayloadLength};

impl WithFixedPayloadLength for ParameterValueRaw {
    const FIXED_PAYLOAD_LENGTH: u16 =
        u8::FIXED_PAYLOAD_LENGTH + u64::FIXED_PAYLOAD_LENGTH;
}

impl PreliminaryTryFrom<(u8, u64)> for ParameterValueRaw {
    type Error = io::Error;
    fn try_from(value: (u8, u64)) -> io::Result<Self> {
        let (tag, data) = value;
        match tag {
            0x00 => Ok(ParameterValue::Boolean(data > 0u64)),
            0x01 => Ok(ParameterValue::Int8(data as i8)),
            0x02 => Ok(ParameterValue::Int16(data as i16)),
            0x03 => Ok(ParameterValue::Int32(data as i32)),
            0x04 => Ok(ParameterValue::Int64(data as i64)),
            0x05 => Ok(ParameterValue::UInt8(data as u8)),
            0x06 => Ok(ParameterValue::UInt16(data as u16)),
            0x07 => Ok(ParameterValue::UInt32(data as u32)),
            0x08 => Ok(ParameterValue::UInt64(data as u64)),
            0x09 => Ok(ParameterValue::ParameterMask(data as u64)),
            0x10 => Ok(ParameterValue::BooleanChannel(data.into())),
            0x11 => Ok(ParameterValue::Int8Channel(data.into())),
            0x12 => Ok(ParameterValue::Int16Channel(data.into())),
            0x13 => Ok(ParameterValue::Int32Channel(data.into())),
            0x14 => Ok(ParameterValue::Int64Channel(data.into())),
            0x15 => Ok(ParameterValue::UInt8Channel(data.into())),
            0x16 => Ok(ParameterValue::UInt16Channel(data.into())),
            0x17 => Ok(ParameterValue::UInt32Channel(data.into())),
            0x18 => Ok(ParameterValue::UInt64Channel(data.into())),
            0x19 => Ok(ParameterValue::ParameterMaskChannel(data.into())),
            _ => Err(io::Error::new(
                io::ErrorKind::InvalidData,
                format!("Invalid ParameterValue enum tag {}", tag),
            )),
        }
    }
}

pub(crate) enum ParameterValueWriteMode {
    Type,
    Value,
    TypeAndValue,
}

pub(crate) trait ParameterValueWriterExt: Write {
    fn write_type(
        &mut self,
        type_id: u8,
        mode: &ParameterValueWriteMode,
    ) -> io::Result<()> {
        use self::ParameterValueWriteMode::*;
        match *mode {
            Type | TypeAndValue => self.write_u8(type_id),
            Value => Ok(()),
        }
    }

    fn write_value_u64(
        &mut self,
        value: u64,
        mode: &ParameterValueWriteMode,
    ) -> io::Result<()> {
        use self::ParameterValueWriteMode::*;
        match *mode {
            Value | TypeAndValue => self.write_u64::<Endian>(value),
            Type => Ok(()),
        }
    }

    fn write_value_i64(
        &mut self,
        value: i64,
        mode: &ParameterValueWriteMode,
    ) -> io::Result<()> {
        use self::ParameterValueWriteMode::*;
        match *mode {
            Value | TypeAndValue => self.write_i64::<Endian>(value),
            Type => Ok(()),
        }
    }

    fn write_parameter_value(
        &mut self,
        r: &ParameterValueRaw,
        mode: &ParameterValueWriteMode,
    ) -> io::Result<()> {
        match *r {
            ParameterValue::Boolean(ref v) => {
                self.write_type(0x00u8, mode)?;
                self.write_value_u64(*v as u64, mode)?;
            }
            ParameterValue::Int8(ref v) => {
                self.write_type(0x01u8, mode)?;
                self.write_value_u64(*v as u64, mode)?;
            }
            ParameterValue::Int16(ref v) => {
                self.write_type(0x02u8, mode)?;
                self.write_value_u64(*v as u64, mode)?;
            }
            ParameterValue::Int32(ref v) => {
                self.write_type(0x03u8, mode)?;
                self.write_value_u64(*v as u64, mode)?;
            }
            ParameterValue::Int64(ref v) => {
                self.write_type(0x04u8, mode)?;
                self.write_value_i64(*v, mode)?;
            }
            ParameterValue::UInt8(ref v) => {
                self.write_type(0x05u8, mode)?;
                self.write_value_u64(u64::from(*v), mode)?;
            }
            ParameterValue::UInt16(ref v) => {
                self.write_type(0x06u8, mode)?;
                self.write_value_u64(u64::from(*v), mode)?;
            }
            ParameterValue::UInt32(ref v) => {
                self.write_type(0x07u8, mode)?;
                self.write_value_u64(u64::from(*v), mode)?;
            }
            ParameterValue::UInt64(ref v) => {
                self.write_type(0x08u8, mode)?;
                self.write_value_u64(*v, mode)?;
            }
            ParameterValue::ParameterMask(ref v) => {
                self.write_type(0x09u8, mode)?;
                self.write_value_u64(*v, mode)?;
            }
            ParameterValue::BooleanChannel(ref v) => {
                self.write_type(0x10u8, mode)?;
                self.write_value_u64(v.into(), mode)?;
            }
            ParameterValue::Int8Channel(ref v) => {
                self.write_type(0x11u8, mode)?;
                self.write_value_u64(v.into(), mode)?;
            }
            ParameterValue::Int16Channel(ref v) => {
                self.write_type(0x12u8, mode)?;
                self.write_value_u64(v.into(), mode)?;
            }
            ParameterValue::Int32Channel(ref v) => {
                self.write_type(0x13u8, mode)?;
                self.write_value_u64(v.into(), mode)?;
            }
            ParameterValue::Int64Channel(ref v) => {
                self.write_type(0x14u8, mode)?;
                self.write_value_u64(v.into(), mode)?;
            }
            ParameterValue::UInt8Channel(ref v) => {
                self.write_type(0x15u8, mode)?;
                self.write_value_u64(v.into(), mode)?;
            }
            ParameterValue::UInt16Channel(ref v) => {
                self.write_type(0x16u8, mode)?;
                self.write_value_u64(v.into(), mode)?;
            }
            ParameterValue::UInt32Channel(ref v) => {
                self.write_type(0x17u8, mode)?;
                self.write_value_u64(v.into(), mode)?;
            }
            ParameterValue::UInt64Channel(ref v) => {
                self.write_type(0x18u8, mode)?;
                self.write_value_u64(v.into(), mode)?;
            }
            ParameterValue::ParameterMaskChannel(ref v) => {
                self.write_type(0x19u8, mode)?;
                self.write_value_u64(v.into(), mode)?;
            }
        }
        Ok(())
    }
}

impl<B: Write + ?Sized> ParameterValueWriterExt for B {}

pub(crate) trait ParameterValueReaderExt: Read {
    fn read_type(&mut self) -> io::Result<u8> {
        self.read_u8()
    }

    fn read_value(&mut self) -> io::Result<u64> {
        self.read_u64::<Endian>()
    }

    fn read_parameter_value(&mut self) -> io::Result<ParameterValueRaw> {
        Ok((self.read_type()?, self.read_value()?).try_into()?)
    }
}

impl<B: Read + ?Sized> ParameterValueReaderExt for B {}