1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
use byteorder::{ReadBytesExt, WriteBytesExt};
use std::io;
use std::io::{Read, Write};
use {DataValue, DataValueRaw, Endian, PreliminaryTryFrom,
     PreliminaryTryInto, WithFixedPayloadLength};

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

impl PreliminaryTryFrom<(u8, u64)> for DataValueRaw {
    type Error = io::Error;
    fn try_from(value: (u8, u64)) -> io::Result<Self> {
        let (tag, data) = value;
        match tag {
            0 => Ok(DataValue::Boolean(data > 0u64)),
            1 => Ok(DataValue::Int8(data as i8)),
            2 => Ok(DataValue::Int16(data as i16)),
            3 => Ok(DataValue::Int32(data as i32)),
            4 => Ok(DataValue::Int64(data as i64)),
            5 => Ok(DataValue::UInt8(data as u8)),
            6 => Ok(DataValue::UInt16(data as u16)),
            7 => Ok(DataValue::UInt32(data as u32)),
            8 => Ok(DataValue::UInt64(data as u64)),
            9 => Ok(DataValue::ParameterMask(data as u64)),
            _ => Err(io::Error::new(
                io::ErrorKind::InvalidData,
                format!("Invalid DataValue enum tag {}", tag),
            )),
        }
    }
}

pub(crate) trait DataValueWriterExt: Write {
    fn write_data_value(&mut self, r: &DataValueRaw) -> io::Result<()> {
        match *r {
            DataValue::Boolean(v) => {
                self.write_u8(0u8)?;
                self.write_u64::<Endian>(v as u64)?;
            }
            DataValue::Int8(v) => {
                self.write_u8(1u8)?;
                self.write_u64::<Endian>(v as u64)?;
            }
            DataValue::Int16(v) => {
                self.write_u8(2u8)?;
                self.write_u64::<Endian>(v as u64)?;
            }
            DataValue::Int32(v) => {
                self.write_u8(3u8)?;
                self.write_u64::<Endian>(v as u64)?;
            }
            DataValue::Int64(v) => {
                self.write_u8(4u8)?;
                self.write_i64::<Endian>(v)?;
            }
            DataValue::UInt8(v) => {
                self.write_u8(5u8)?;
                self.write_u64::<Endian>(u64::from(v))?;
            }
            DataValue::UInt16(v) => {
                self.write_u8(6u8)?;
                self.write_u64::<Endian>(u64::from(v))?;
            }
            DataValue::UInt32(v) => {
                self.write_u8(7u8)?;
                self.write_u64::<Endian>(u64::from(v))?;
            }
            DataValue::UInt64(v) => {
                self.write_u8(8u8)?;
                self.write_u64::<Endian>(v)?;
            }
            DataValue::ParameterMask(v) => {
                self.write_u8(9u8)?;
                self.write_u64::<Endian>(v)?;
            }
        }
        Ok(())
    }
}

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

pub(crate) trait DataValueReaderExt: Read {
    fn read_data_value(&mut self) -> io::Result<DataValueRaw> {
        let tag = self.read_u8()?;
        let value = self.read_u64::<Endian>()?;
        Ok((tag, value).try_into()?)
    }
}

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