use byteorder::{ReadBytesExt, WriteBytesExt};
use std::io;
use std::io::{Read, Write};
use base::{DataValue,DataValueRaw};
use {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 {}