use crate::data_types::DataType; use crate::identifier::Identifier; use crate::packet::packet_data::PacketData; use crate::packet::raw_packet::RawPacket; use crate::packet::{Packet, ToPacket}; use crate::prelude::as_u32_be; use std::io; pub mod vec; #[derive(Debug, Clone, PartialEq, Eq)] pub enum PropertyControlCommand { Register { property_name: String, data_type: u8, read_only: bool, // TODO: descriptive }, Remove { property_name: String, }, Get { property_name: String, data: DataType, }, Set { property_name: String, data: DataType, }, Reset { property_name: String, }, Subscribe { device_id: Identifier, property_name: String, }, Unsubscribe { device_id: Identifier, property_name: String, }, } impl PropertyControlCommand { pub fn command(&self) -> u8 { match self { PropertyControlCommand::Register { .. } => 0x10, PropertyControlCommand::Remove { .. } => 0x11, PropertyControlCommand::Get { .. } => 0x12, PropertyControlCommand::Set { .. } => 0x13, PropertyControlCommand::Reset { .. } => 0x14, PropertyControlCommand::Subscribe { .. } => 0x1A, PropertyControlCommand::Unsubscribe { .. } => 0x1B, } } } impl ToPacket for PropertyControlCommand { fn to_packet( self, src: Identifier, dest: Identifier, packet_id: Identifier, reply_to: Identifier, ) -> Packet { Packet { src, dest, packet_id, reply_to, command: self.command(), data: PacketData::PropertyControl(self.clone()), } } } impl TryFrom for PropertyControlCommand { type Error = io::Error; fn try_from(raw_packet: RawPacket) -> io::Result { let build_invalid_input_err = |r: &str| Err(io::Error::new(io::ErrorKind::InvalidInput, r)); match raw_packet.command { // remove node 0x10 => { if raw_packet.data_length == 34 { Ok(PropertyControlCommand::Register { property_name: String::from_utf8(raw_packet.data[..32].to_vec()).map_err( |_| io::Error::new(io::ErrorKind::InvalidInput, "String is not UTF-8"), )?, data_type: raw_packet.data[33], read_only: raw_packet.data[34] != 0, }) } else { build_invalid_input_err("expected 34 bytes") } } // remove property 0x11 => { if raw_packet.data_length == 32 { Ok(PropertyControlCommand::Remove { property_name: String::from_utf8(raw_packet.data.to_vec()).map_err( |_| io::Error::new(io::ErrorKind::InvalidInput, "String is not UTF-8"), )?, }) } else { build_invalid_input_err("expected 32 bytes") } } // get property 0x12 => { if raw_packet.data_length == 33 { Ok(PropertyControlCommand::Get { property_name: String::from_utf8(raw_packet.data[..0x34].to_vec()) .map_err(|_| { io::Error::new(io::ErrorKind::InvalidInput, "String is not UTF-8") })?, data: DataType::try_from(raw_packet.data[0x34..].to_vec())?, }) } else { build_invalid_input_err("expected 33 bytes") } } // set property 0x13 => { if raw_packet.data_length == 33 { Ok(PropertyControlCommand::Set { property_name: String::from_utf8(raw_packet.data[..0x34].to_vec()) .map_err(|_| { io::Error::new(io::ErrorKind::InvalidInput, "String is not UTF-8") })?, data: DataType::try_from(raw_packet.data[0x34..].to_vec())?, }) } else { build_invalid_input_err("expected 33 bytes") } } // reset property 0x14 => { if raw_packet.data_length == 33 { Ok(PropertyControlCommand::Reset { property_name: String::from_utf8(raw_packet.data[..0x34].to_vec()) .map_err(|_| { io::Error::new(io::ErrorKind::InvalidInput, "String is not UTF-8") })?, }) } else { build_invalid_input_err("expected 33 bytes") } } // subscribe to property 0x1A => { if raw_packet.data_length == 36 { Ok(PropertyControlCommand::Subscribe { device_id: Identifier::from(as_u32_be( raw_packet.data[0x14..0x18].as_ref(), )), property_name: String::from_utf8(raw_packet.data[0x18..0x4C].to_vec()) .map_err(|_| { io::Error::new(io::ErrorKind::InvalidInput, "String is not UTF-8") })?, }) } else { build_invalid_input_err("expected 36 bytes") } } // unsubscribe from property 0x1B => { if raw_packet.data_length == 36 { Ok(PropertyControlCommand::Unsubscribe { device_id: Identifier::from(as_u32_be( raw_packet.data[0x14..0x18].as_ref(), )), property_name: String::from_utf8(raw_packet.data[0x18..0x4C].to_vec()) .map_err(|_| { io::Error::new(io::ErrorKind::InvalidInput, "String is not UTF-8") })?, }) } else { build_invalid_input_err("expected 36 bytes") } } _ => Err(io::Error::new( io::ErrorKind::InvalidInput, "command group is unsupported", )), } } }