feat: rust proto implementation

This commit is contained in:
Strix 2023-10-15 18:06:20 +02:00
parent 1e68840042
commit e4b508ae86
No known key found for this signature in database
GPG key ID: 49B2E37B8915B774
12 changed files with 381 additions and 0 deletions

View file

@ -0,0 +1,94 @@
pub mod data_types;
pub mod identifier;
pub mod packet_data;
use crate::prelude;
use identifier::Identifier;
use packet_data::PacketData;
use std::convert::TryFrom;
use std::fmt::Debug;
#[derive(Debug)]
pub enum Packet {
V1 {
src: Identifier,
dest: Identifier,
packet_id: Identifier,
reply_to: Identifier,
command: u8,
data: PacketData,
},
}
impl Packet {
/// Build packet **without** CRC32
pub fn build_base_packet(&self) -> Vec<u8> {
match self {
Packet::V1 {
src,
dest,
packet_id,
reply_to,
command,
data,
} => {
let mut buf = Vec::new();
let data_length = data.len();
buf.push(0x01);
buf.extend_from_slice(&src.bytes);
buf.extend_from_slice(&dest.bytes);
buf.extend_from_slice(&packet_id.bytes);
buf.extend_from_slice(&reply_to.bytes);
buf.push(command.clone());
buf.push((data_length >> 8) as u8);
buf.push((data_length & 0xFF) as u8);
buf.extend(data.get_data());
buf
}
}
}
pub fn build_full_packet(&self) -> Vec<u8> {
match self {
Packet::V1 { .. } => {
let mut buf = self.build_base_packet();
buf.extend_from_slice(crc32fast::hash(&buf.as_slice()).to_be_bytes().as_ref());
buf
}
}
}
}
impl TryFrom<Vec<u8>> for Packet {
type Error = ();
fn try_from(value: Vec<u8>) -> Result<Self, Self::Error> {
match value[0] {
0x01 => {
let header: Vec<u16> = value[..0x15].iter().map(|v| u16::from(*v)).collect();
let data_length = (header[0x12] << 8) | header[0x13];
let crc32 = prelude::as_u32_be(&value[(0x14 + data_length as usize)..]);
let packet = Packet::V1 {
src: Identifier::from(&value[0x01..0x05]),
dest: Identifier::from(&value[0x05..0x09]),
packet_id: Identifier::from(&value[0x09..0x0D]),
reply_to: Identifier::from(&value[0x0D..0x11]),
command: value[0x11],
data: PacketData::new(value[0x14..(data_length as usize + 0x14)].to_owned()),
};
if crc32fast::hash(packet.build_base_packet().as_slice()) != crc32 {
Err(())
} else {
Ok(packet)
}
}
_ => Err(()),
}
}
}
impl Into<Vec<u8>> for Packet {
fn into(self) -> Vec<u8> {
self.build_full_packet()
}
}