use arrayvec for packets (#4)

This commit is contained in:
Hubert 2022-06-24 13:13:18 +02:00 committed by GitHub
parent 0fc9f33117
commit f3dc6b118d
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
2 changed files with 63 additions and 14 deletions

View File

@ -1,6 +1,6 @@
[package] [package]
name = "wakey" name = "wakey"
version = "0.2.0" version = "0.2.1"
authors = ["Hubert Bugaj<lesny.rumcajs@gmail.com>"] authors = ["Hubert Bugaj<lesny.rumcajs@gmail.com>"]
edition = "2021" edition = "2021"
@ -14,4 +14,5 @@ categories = ["network-programming"]
[dependencies] [dependencies]
hex = "~0.3" hex = "~0.3"
arrayvec = "0.7.2"
clap = { version = "3.1.18", features = ["derive"] } clap = { version = "3.1.18", features = ["derive"] }

View File

@ -12,14 +12,20 @@
use std::iter; use std::iter;
use std::net::{SocketAddr, ToSocketAddrs, UdpSocket}; use std::net::{SocketAddr, ToSocketAddrs, UdpSocket};
use arrayvec::ArrayVec;
const MAC_SIZE: usize = 6; const MAC_SIZE: usize = 6;
const MAC_PER_MAGIC: usize = 16; const MAC_PER_MAGIC: usize = 16;
static HEADER: [u8; 6] = [0xFF; 6]; const HEADER: [u8; 6] = [0xFF; 6];
const PACKET_LEN: usize = HEADER.len() + MAC_SIZE * MAC_PER_MAGIC;
type Packet = ArrayVec<u8, PACKET_LEN>;
/// Wake-on-LAN packet /// Wake-on-LAN packet
#[derive(Debug, Clone, PartialEq, Eq)]
pub struct WolPacket { pub struct WolPacket {
/// WOL packet bytes /// WOL packet bytes
packet: Vec<u8>, packet: Packet,
} }
impl WolPacket { impl WolPacket {
@ -80,28 +86,39 @@ impl WolPacket {
/// Converts string representation of MAC address (e.x. 00:01:02:03:04:05) to raw bytes. /// Converts string representation of MAC address (e.x. 00:01:02:03:04:05) to raw bytes.
/// # Panic /// # Panic
/// Panics when input MAC is invalid (i.e. contains non-byte characters) /// Panics when input MAC is invalid (i.e. contains non-byte characters)
fn mac_to_byte(data: &str, sep: char) -> Vec<u8> { fn mac_to_byte(data: &str, sep: char) -> ArrayVec<u8, MAC_SIZE> {
data.split(sep) let bytes = data
.split(sep)
.flat_map(|x| hex::decode(x).expect("Invalid mac!")) .flat_map(|x| hex::decode(x).expect("Invalid mac!"))
.collect() .collect::<ArrayVec<u8, MAC_SIZE>>();
debug_assert_eq!(MAC_SIZE, bytes.len());
bytes
} }
/// Extends the MAC address to fill the magic packet /// Extends the MAC address to fill the magic packet
fn extend_mac(mac: &[u8]) -> Vec<u8> { fn extend_mac(mac: &[u8]) -> ArrayVec<u8, { MAC_SIZE * MAC_PER_MAGIC }> {
iter::repeat(mac) let magic = iter::repeat(mac)
.take(MAC_PER_MAGIC) .take(MAC_PER_MAGIC)
.flatten() .flatten()
.cloned() .copied()
.collect() .collect::<ArrayVec<u8, { MAC_SIZE * MAC_PER_MAGIC }>>();
debug_assert_eq!(MAC_SIZE * MAC_PER_MAGIC, magic.len());
magic
} }
/// Creates bytes of the magic packet from MAC address /// Creates bytes of the magic packet from MAC address
fn create_packet_bytes(mac: &[u8]) -> Vec<u8> { fn create_packet_bytes(mac: &[u8]) -> Packet {
let mut packet = Vec::with_capacity(HEADER.len() + MAC_SIZE * MAC_PER_MAGIC); let mut packet = Packet::new();
packet.extend(HEADER.iter()); packet.extend(HEADER);
packet.extend(WolPacket::extend_mac(mac)); packet.extend(WolPacket::extend_mac(mac));
debug_assert_eq!(PACKET_LEN, packet.len());
packet packet
} }
} }
@ -121,12 +138,29 @@ mod tests {
); );
} }
#[test]
#[should_panic]
fn extend_mac_mac_too_long_test() {
let mac = vec![0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07];
super::WolPacket::extend_mac(&mac);
}
#[test]
#[should_panic]
fn extend_mac_mac_too_short_test() {
let mac = vec![0x01, 0x02, 0x03, 0x04, 0x05];
super::WolPacket::extend_mac(&mac);
}
#[test] #[test]
fn mac_to_byte_test() { fn mac_to_byte_test() {
let mac = "01:02:03:04:05:06"; let mac = "01:02:03:04:05:06";
let result = super::WolPacket::mac_to_byte(mac, ':'); let result = super::WolPacket::mac_to_byte(mac, ':');
assert_eq!(result, vec![0x01, 0x02, 0x03, 0x04, 0x05, 0x06]); assert_eq!(
result.into_inner().unwrap(),
[0x01, 0x02, 0x03, 0x04, 0x05, 0x06]
);
} }
#[test] #[test]
@ -143,6 +177,20 @@ mod tests {
super::WolPacket::mac_to_byte(mac, ':'); super::WolPacket::mac_to_byte(mac, ':');
} }
#[test]
#[should_panic]
fn mac_to_byte_mac_too_long_test() {
let mac = "01:02:03:04:05:06:07";
super::WolPacket::mac_to_byte(mac, ':');
}
#[test]
#[should_panic]
fn mac_to_byte_mac_too_short_test() {
let mac = "01:02:03:04:05";
super::WolPacket::mac_to_byte(mac, ':');
}
#[test] #[test]
fn create_packet_bytes_test() { fn create_packet_bytes_test() {
let bytes = super::WolPacket::create_packet_bytes(&[0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF]); let bytes = super::WolPacket::create_packet_bytes(&[0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF]);