use std::io; use crate::identifier::Identifier; use crate::packet::raw_packet::RawPacket; use crate::packet::{Packet, ToPacket}; use crate::packet::packet_data::PacketData; pub mod vec; pub mod errors; #[derive(Debug, Clone, PartialEq, Eq)] pub enum NodeManagementCommand { Ping, RegisterNode { device_id: Identifier }, RemoveNode, AcknowledgePackets { packet_ids: Vec }, Error { error_code: u8, metadata: Vec, }, } impl NodeManagementCommand { pub fn command(&self) -> u8 { match self { NodeManagementCommand::Ping => 0x00, NodeManagementCommand::RegisterNode { .. } => 0x01, NodeManagementCommand::RemoveNode => 0x02, NodeManagementCommand::AcknowledgePackets { .. } => 0x0A, NodeManagementCommand::Error { .. } => 0x0E, } } } impl ToPacket for NodeManagementCommand { 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::NodeManagement(self.clone()) } } } impl TryFrom for NodeManagementCommand { 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 { // ping 0x00 => Ok(NodeManagementCommand::Ping), // register node 0x01 => if raw_packet.data_length == 4 { Ok(NodeManagementCommand::RegisterNode { device_id: Identifier::from(raw_packet.data) }) } else { build_invalid_input_err("expected 4 bytes") }, // remove node 0x02 => Ok(NodeManagementCommand::RemoveNode), 0x0A => if raw_packet.data_length >= 4 && (raw_packet.data_length % 4 == 0) { Ok(NodeManagementCommand::AcknowledgePackets { packet_ids: raw_packet.data.chunks(4) .map(|c| Identifier::from(c)) .collect() }) } else { build_invalid_input_err("expected at least 4 bytes and data_length%4=0") } // error 0x0E => if raw_packet.data_length >= 1 { Ok(NodeManagementCommand::Error { error_code: raw_packet.data[0], metadata: raw_packet.data[1..].to_vec(), }) } else { build_invalid_input_err("expected at least 3 bytes") }, _ => Err(io::Error::new(io::ErrorKind::InvalidInput, "command group is unsupported")) } } }