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 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110
use base::{DataType, DataValue, DataValueRaw, HasDataType}; use byteorder::{ReadBytesExt, WriteBytesExt}; use std::io; use std::io::{Read, Write}; use {DataTypeReaderExt, DataTypeWriterExt, Endian, PreliminaryTryFrom, PreliminaryTryInto, WithFixedPayloadLength}; impl WithFixedPayloadLength for DataValueRaw { const FIXED_PAYLOAD_LENGTH: u16 = DataType::FIXED_PAYLOAD_LENGTH + u64::FIXED_PAYLOAD_LENGTH; } impl PreliminaryTryFrom<(DataType, u64)> for DataValueRaw { type Error = io::Error; fn try_from(value: (DataType, u64)) -> io::Result<Self> { let (tag, data) = value; match tag { DataType::Boolean => Ok(DataValue::Boolean(data > 0u64)), DataType::Int8 => Ok(DataValue::Int8(data as i8)), DataType::Int16 => Ok(DataValue::Int16(data as i16)), DataType::Int32 => Ok(DataValue::Int32(data as i32)), DataType::Int64 => Ok(DataValue::Int64(data as i64)), DataType::UInt8 => Ok(DataValue::UInt8(data as u8)), DataType::UInt16 => Ok(DataValue::UInt16(data as u16)), DataType::UInt32 => Ok(DataValue::UInt32(data as u32)), DataType::UInt64 => Ok(DataValue::UInt64(data as u64)), DataType::ParameterMask => { Ok(DataValue::ParameterMask(data as u64)) } DataType::Invalid => 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<()> { let v = vec![r.clone()]; self.write_data_values(&v) } fn write_data_values( &mut self, values: &[DataValueRaw], ) -> io::Result<()> { for ref value in values { self.write_data_type(value.data_type())?; } for ref value in values { match **value { DataValue::Boolean(ref v) => { self.write_u64::<Endian>(*v as u64) } DataValue::Int8(ref v) => { self.write_u64::<Endian>(*v as u64) } DataValue::Int16(ref v) => { self.write_u64::<Endian>(*v as u64) } DataValue::Int32(ref v) => { self.write_u64::<Endian>(*v as u64) } DataValue::Int64(ref v) => self.write_i64::<Endian>(*v), DataValue::UInt8(ref v) => { self.write_u64::<Endian>(*v as u64) } DataValue::UInt16(ref v) => { self.write_u64::<Endian>(*v as u64) } DataValue::UInt32(ref v) => { self.write_u64::<Endian>(*v as u64) } DataValue::UInt64(ref v) => self.write_u64::<Endian>(*v), DataValue::ParameterMask(ref v) => { 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> { Ok(self.read_data_values(1usize)? .into_iter() .next() .unwrap()) } fn read_data_values( &mut self, count: usize, ) -> io::Result<Vec<DataValueRaw>> { let tags = self.read_data_types(count)?; tags.into_iter() .map(|tag| { let value = self.read_u64::<Endian>()?; Ok((tag, value).try_into()?) }) .collect::<io::Result<Vec<DataValueRaw>>>() } } impl<B: Read + ?Sized> DataValueReaderExt for B {}