diff options
| author | Will Dillon <william@housedillon.com> | 2025-12-04 17:07:12 +0000 |
|---|---|---|
| committer | Will Dillon <william@housedillon.com> | 2025-12-04 17:07:12 +0000 |
| commit | bf21ebaaae44b267cfefc87eee9608c09aab96b7 (patch) | |
| tree | 67234092d3c85a9c58d1fa9ca51337ac480ebfb7 /src/packet.rs | |
| parent | Better than 90% everywhere. (diff) | |
| download | meshcore-rs-bf21ebaaae44b267cfefc87eee9608c09aab96b7.tar.gz meshcore-rs-bf21ebaaae44b267cfefc87eee9608c09aab96b7.zip | |
Getting closer to no-std being done
Diffstat (limited to 'src/packet.rs')
| -rw-r--r-- | src/packet.rs | 166 |
1 files changed, 90 insertions, 76 deletions
diff --git a/src/packet.rs b/src/packet.rs index 3fa26cb..50374a7 100644 --- a/src/packet.rs +++ b/src/packet.rs @@ -1,27 +1,29 @@ -use std::{fmt::{Debug, Display}, str::FromStr}; +#[cfg(feature = "std")] +use crate::std_identity::Keystore; + +#[cfg(not(feature = "std"))] +use crate::no_std_identity::Keystore; -use hex::decode; use bytes::{Buf, Bytes}; -use structdiff::{Difference, StructDiff}; -use crate::{anon_req::ClearAnonRequest, identity::Keystore, packet_content::PacketContent, request::ClearRequest, response::ClearResponse, text::ClearText}; +use tinyvec::ArrayVec; +use crate::{anon_req::ClearAnonRequest, packet_content::PacketContent, request::ClearRequest, response::ClearResponse, text::ClearText}; -#[derive(PartialEq, Debug, Clone, Difference)] -#[difference(expose)] +#[derive(PartialEq, Clone, core::fmt::Debug)] pub struct Packet { pub route_type: RouteType, pub version: PayloadVersion, - pub path: Vec<u16>, + pub path: ArrayVec<[u16; 64]>, pub transport: [u16; 2], pub raw_content: Bytes, pub content: PacketContent, pub incomplete: bool } -impl FromStr for Packet { +impl core::str::FromStr for Packet { type Err = hex::FromHexError; fn from_str(hex_str: &str) -> Result<Self, Self::Err> { - let hex = decode(hex_str)?; + let hex = hex::decode(hex_str)?; Ok(Packet::from(Bytes::copy_from_slice(&hex))) } } @@ -67,22 +69,24 @@ impl From<Bytes> for Packet { // The packet isn't long enough for the indicated route if bytes.len() < path_length { return packet; } - let route: Vec<u16> = bytes - .split_to(path_length) - .into_iter() - .map(|x| x as u16) - .collect(); + let mut route = ArrayVec::new(); + for _ in 0..path_length { + let path_element = bytes.get_u8() as u16; + route.push(path_element); + } + route }, + PayloadVersion::VersionTwo => { // The packet isn't long enough for the indicated route if bytes.len() < path_length * 2 { return packet; } - let route: Vec<u16> = bytes - .split_to(path_length * 2) - .chunks(2) - .map(|c| Bytes::copy_from_slice(c).get_u16_le()) - .collect(); + let mut route = ArrayVec::new(); + for i in 0..path_length { + let path_element = bytes.get_u16(); + route[i] = path_element; + } route }, @@ -101,12 +105,18 @@ impl From<Bytes> for Packet { if let PacketContent::Trace(trace) = packet.content { let mut trace = trace; let path_snr = packet.path; - packet.path = trace.temp_path.iter().map(|i| *i as u16).collect(); - trace.path_snr = path_snr.iter().map( |u| { + + for (index, element) in trace.temp_path.iter().enumerate() { + packet.path[index] = *element as u16; + } + + for u in path_snr.iter() { let i = *u as i8; let f = i as f32; - f / 4.0 - }).collect(); + + trace.path_snr.push(f / 4.0); + } + // DON'T delete the temp path, so Trace has access to the path // when it prints the SNR results in its Display function. packet.content = PacketContent::Trace(trace); @@ -124,7 +134,7 @@ impl Default for Packet { Packet { route_type: RouteType::Invalid, version: PayloadVersion::Invalid, - path: vec![], + path: ArrayVec::new(), transport: [0, 0], raw_content: Bytes::new(), content: PacketContent::Invalid, @@ -133,11 +143,11 @@ impl Default for Packet { } } -impl Display for Packet { - fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { - std::fmt::Display::fmt(&self.route_type, f)?; +impl core::fmt::Display for Packet { + fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result { + core::fmt::Display::fmt(&self.route_type, f)?; f.write_str(" | ")?; - std::fmt::Display::fmt(&self.version, f)?; + core::fmt::Display::fmt(&self.version, f)?; if self.route_type == RouteType::TransportDirect || self.route_type == RouteType::TransportFlood { f.write_fmt(format_args!(" | {:4x?}, {:4x?} | ", self.transport[0], self.transport[1]))? @@ -160,11 +170,12 @@ impl Display for Packet { f.write_str(" | ") }?; - std::fmt::Display::fmt(&self.content, f) + core::fmt::Display::fmt(&self.content, f) } } impl Packet { + #[cfg(feature = "std")] pub fn try_decrypt(&mut self, keystore: &Keystore) -> bool { match self.content { // Encrypted packet types @@ -240,8 +251,8 @@ pub enum RouteType { Invalid, } -impl Display for RouteType { - fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { +impl core::fmt::Display for RouteType { + fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result { match self { RouteType::TransportFlood => f.write_str("T-Flood "), RouteType::Flood => f.write_str(" Flood "), @@ -288,8 +299,8 @@ impl From<u8> for PayloadVersion { } } -impl Display for PayloadVersion { - fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { +impl core::fmt::Display for PayloadVersion { + fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result { match self { PayloadVersion::VersionOne => f.write_str("v1"), PayloadVersion::VersionTwo => f.write_str("v2"), @@ -302,54 +313,57 @@ impl Display for PayloadVersion { #[cfg(test)] mod tests { + use core::str::FromStr; + use tinyvec::array_vec; + use crate::packet_content::{PacketContent, Raw}; use super::*; #[test] fn header_route_type() { // The route type is the lowest-order two bits - assert!(RouteType::TransportFlood == RouteType::from(0x00)); - assert!(RouteType::TransportFlood == RouteType::from(0xFC)); - assert!(RouteType::Flood == RouteType::from(0x01)); - assert!(RouteType::Flood == RouteType::from(0xFD)); - assert!(RouteType::Direct == RouteType::from(0x02)); - assert!(RouteType::Direct == RouteType::from(0xFE)); - assert!(RouteType::TransportDirect == RouteType::from(0x03)); - assert!(RouteType::TransportDirect == RouteType::from(0xFF)); - - assert!(format!("{}", RouteType::TransportFlood) == "T-Flood "); - assert!(format!("{}", RouteType::Flood) == " Flood "); - assert!(format!("{}", RouteType::Direct) == " Direct"); - assert!(format!("{}", RouteType::TransportDirect) == "T-Direct"); - assert!(format!("{}", RouteType::Invalid) == "INVALID "); + assert_eq!(RouteType::TransportFlood, RouteType::from(0x00)); + assert_eq!(RouteType::TransportFlood, RouteType::from(0xFC)); + assert_eq!(RouteType::Flood, RouteType::from(0x01)); + assert_eq!(RouteType::Flood, RouteType::from(0xFD)); + assert_eq!(RouteType::Direct, RouteType::from(0x02)); + assert_eq!(RouteType::Direct, RouteType::from(0xFE)); + assert_eq!(RouteType::TransportDirect, RouteType::from(0x03)); + assert_eq!(RouteType::TransportDirect, RouteType::from(0xFF)); + + assert_eq!(format!("{}", RouteType::TransportFlood), "T-Flood "); + assert_eq!(format!("{}", RouteType::Flood), " Flood "); + assert_eq!(format!("{}", RouteType::Direct), " Direct"); + assert_eq!(format!("{}", RouteType::TransportDirect), "T-Direct"); + assert_eq!(format!("{}", RouteType::Invalid), "INVALID "); } #[test] fn header_version() { - assert!(PayloadVersion::VersionOne == PayloadVersion::from(0x00)); - assert!(PayloadVersion::VersionOne == PayloadVersion::from(0x3F)); - assert!(PayloadVersion::VersionTwo == PayloadVersion::from(0x40)); - assert!(PayloadVersion::VersionTwo == PayloadVersion::from(0x7F)); - assert!(PayloadVersion::VersionThree == PayloadVersion::from(0x80)); - assert!(PayloadVersion::VersionThree == PayloadVersion::from(0xBF)); - assert!(PayloadVersion::VersionFour == PayloadVersion::from(0xC0)); - assert!(PayloadVersion::VersionFour == PayloadVersion::from(0xFF)); - - assert!(format!("{}", PayloadVersion::VersionOne) == "v1"); - assert!(format!("{}", PayloadVersion::VersionTwo) == "v2"); - assert!(format!("{}", PayloadVersion::VersionThree) == "v3"); - assert!(format!("{}", PayloadVersion::VersionFour) == "v4"); - assert!(format!("{}", PayloadVersion::Invalid) == "xx"); + assert_eq!(PayloadVersion::VersionOne, PayloadVersion::from(0x00)); + assert_eq!(PayloadVersion::VersionOne, PayloadVersion::from(0x3F)); + assert_eq!(PayloadVersion::VersionTwo, PayloadVersion::from(0x40)); + assert_eq!(PayloadVersion::VersionTwo, PayloadVersion::from(0x7F)); + assert_eq!(PayloadVersion::VersionThree, PayloadVersion::from(0x80)); + assert_eq!(PayloadVersion::VersionThree, PayloadVersion::from(0xBF)); + assert_eq!(PayloadVersion::VersionFour, PayloadVersion::from(0xC0)); + assert_eq!(PayloadVersion::VersionFour, PayloadVersion::from(0xFF)); + + assert_eq!(format!("{}", PayloadVersion::VersionOne), "v1"); + assert_eq!(format!("{}", PayloadVersion::VersionTwo), "v2"); + assert_eq!(format!("{}", PayloadVersion::VersionThree), "v3"); + assert_eq!(format!("{}", PayloadVersion::VersionFour), "v4"); + assert_eq!(format!("{}", PayloadVersion::Invalid), "xx"); } #[test] fn packet() { // Check the hex decode errors - assert!(Err(hex::FromHexError::InvalidHexCharacter { c: 's', index: 0 }) == Packet::from_str("s0")); - assert!(Err(hex::FromHexError::OddLength) == Packet::from_str("0")); + assert_eq!(Err(hex::FromHexError::InvalidHexCharacter { c: 's', index: 0 }), Packet::from_str("s0")); + assert_eq!(Err(hex::FromHexError::OddLength), Packet::from_str("0")); // Check errors related to packet length issues - assert!(Packet::default() == Packet::from_str("").unwrap()); + assert_eq!(Packet::default(), Packet::from_str("").unwrap()); let rhs_packet = Packet::from_str("01").unwrap(); assert_eq!(Packet::default(), rhs_packet); @@ -379,17 +393,17 @@ mod tests { let lhs_packet = Packet { route_type: RouteType::TransportDirect, version: PayloadVersion::VersionOne, - path: [0x06, 0x07, 0x08, 0x09, 0x0A].to_vec(), + path: array_vec!([u16; 64] => 0x06, 0x07, 0x08, 0x09, 0x0A), transport: [0x0102, 0x0304], raw_content: Bytes::copy_from_slice(&[0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, 0x18, 0x19]), content: PacketContent::Raw(Raw { bytes: Bytes::copy_from_slice(&[0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, 0x18, 0x19])}), incomplete: false, }; - let rhs_packet = Packet::from_str("3F0201040305060708090A10111213141516171819").unwrap(); + let rhs_packet: Packet = Packet::from_str("3F0201040305060708090A10111213141516171819").unwrap(); let compare_string = "T-Direct | v1 | 102, 304 | [06, 07, ... 09, 0a] | | RAW | Raw { bytes: b\"\\x10\\x11\\x12\\x13\\x14\\x15\\x16\\x17\\x18\\x19\" }"; - assert!(format!("{}", rhs_packet) == compare_string); + assert_eq!(format!("{}", rhs_packet), compare_string); assert_eq!(lhs_packet, rhs_packet); } @@ -399,25 +413,25 @@ mod tests { let mut packet = Packet { route_type: RouteType::Direct, version: PayloadVersion::VersionOne, - path: vec![], + path: ArrayVec::new(), transport: [0, 1], raw_content: Bytes::new(), content: PacketContent::Invalid, incomplete: false }; - assert!(format!("{}", packet) == " Direct | v1 | | [] | | INVALID | INVALID"); + assert_eq!(format!("{}", packet), " Direct | v1 | | [] | | INVALID | INVALID"); - packet.path = vec![0x01]; - assert!(format!("{}", packet) == " Direct | v1 | | [01] | | INVALID | INVALID"); + packet.path.push(0x01); + assert_eq!(format!("{}", packet), " Direct | v1 | | [01] | | INVALID | INVALID"); - packet.path = vec![0x01, 0x02]; - assert!(format!("{}", packet) == " Direct | v1 | | [01, 02] | | INVALID | INVALID"); + packet.path.push(0x02); + assert_eq!(format!("{}", packet), " Direct | v1 | | [01, 02] | | INVALID | INVALID"); - packet.path = vec![0x01, 0x02, 0xff]; - assert!(format!("{}", packet) == " Direct | v1 | | [01, 02, ff] | | INVALID | INVALID"); + packet.path.push(0xff); + assert_eq!(format!("{}", packet), " Direct | v1 | | [01, 02, ff] | | INVALID | INVALID"); packet.incomplete = true; - assert!(format!("{}", packet) == " Direct | v1 | | [01, 02, ff] | x | INVALID | INVALID"); + assert_eq!(format!("{}", packet), " Direct | v1 | | [01, 02, ff] | x | INVALID | INVALID"); } }
\ No newline at end of file |
