aboutsummaryrefslogtreecommitdiffstats
path: root/src/packet.rs
diff options
context:
space:
mode:
authorWill Dillon <william@housedillon.com>2025-12-04 17:07:12 +0000
committerWill Dillon <william@housedillon.com>2025-12-04 17:07:12 +0000
commitbf21ebaaae44b267cfefc87eee9608c09aab96b7 (patch)
tree67234092d3c85a9c58d1fa9ca51337ac480ebfb7 /src/packet.rs
parentBetter than 90% everywhere. (diff)
downloadmeshcore-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.rs166
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