xio_common 0.12.0

XIO commonly used functionality
Documentation
use crate::base::{ParameterValue, ParameterValueRaw};
use snafu::ResultExt;
use std::io::{Read, Write};
use crate::{
    error, Endian, ReadExt, Result, TryInto, WithFixedPayloadLength,
    WriteExt,
};

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

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

pub(crate) trait ParameterValueWriterExt: Write {
    fn write_type(
        &mut self,
        type_id: u8,
        mode: &ParameterValueWriteMode,
    ) -> 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,
    ) -> 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,
    ) -> 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,
    ) -> 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) -> Result<u8> {
        self.read_u8()
    }

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

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

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