diff --git a/CHANGELOG.md b/CHANGELOG.md index 916fe56..2c45432 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,5 +1,9 @@ # CHANGELOG +## v1.1.0 + +1. Allow flexible mac addr strings + ## v1.0.1 From @konanzheng diff --git a/Cargo.toml b/Cargo.toml index 313a9b4..bdf93ff 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "wol-rs" -version = "1.0.1" +version = "1.1.0" edition = "2021" authors = ["fengyingcai "] description = "Wake-on-LAN utility" @@ -29,6 +29,10 @@ bin = ["dep:clap"] [dependencies] clap = { version = "4.5.20", features = ["derive"], optional = true } +eui48 = { version = "1.1.0", features = ["disp_hexstring"] } [profile.release] -strip = true \ No newline at end of file +strip = true + +[dev-dependencies] +rstest = "0.23.0" diff --git a/src/lib.rs b/src/lib.rs index 99de0ab..13d7e1f 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -3,6 +3,8 @@ use std::io; use std::net::{IpAddr, UdpSocket}; use std::str::FromStr; +use eui48::MacAddress; + /// Mac address size of bytes const MAC_ADDR_SIZE: usize = 6; @@ -14,7 +16,7 @@ const WOL_PORT: u16 = 9; /// Mac address. /// -/// A 6 bytes mac address, e.g. "00:0a:0b:0c:0d:0e". +/// A 6 bytes mac address, e.g. "00:0a:0b:0c:0d:0e" or "0:a:b:c:d:e". #[derive(Debug, Default, Eq, PartialEq, Copy, Clone)] pub struct MacAddr(pub [u8; MAC_ADDR_SIZE]); @@ -40,26 +42,18 @@ impl Debug for MacAddrError { } } +impl From for MacAddr { + fn from(value: MacAddress) -> Self { + Self(value.to_array()) + } +} + impl FromStr for MacAddr { type Err = MacAddrError; fn from_str(s: &str) -> Result { - if s.len() != 17 { - return Err(MacAddrError {}); - } - let separator = s.chars().nth(2).unwrap(); - let v: Vec<&str> = s.split(separator).collect(); - if v.len() != MAC_ADDR_SIZE { - return Err(MacAddrError {}); - } - let mut mac_addr = MacAddr([0; MAC_ADDR_SIZE]); - for i in 0..MAC_ADDR_SIZE { - match u8::from_str_radix(v[i], 16) { - Ok(n) => mac_addr.0[i] = n, - Err(_) => return Err(MacAddrError {}), - } - } - Ok(mac_addr) + let m = MacAddress::from_str(s).map_err(|_| MacAddrError {})?; + Ok(m.into()) } } @@ -102,3 +96,25 @@ pub fn send_wol( Ok(()) } + +#[cfg(test)] +mod tests { + use std::str::FromStr; + + use rstest::rstest; + + use crate::MacAddr; + + #[rstest] + #[case("00:01:11:34:88:99", true)] + #[case("G0:01:11:34:88:99", true)] + #[case("00-01:11:34:88:99", true)] + #[case("00:1:11:34:88:99", true)] + #[case("00-01-11-34-88-99", true)] + #[case("00-1-11-34-88-99", true)] + #[case("0102.030A.0b0f", true)] // This case is from eui48 + #[case("0x1234567890ab", true)] // This case if from eui48 + fn test_mac_addr(#[case] s: &str, #[case] ok: bool) { + assert!(MacAddr::from_str(s).is_ok() == ok) + } +} diff --git a/src/main.rs b/src/main.rs index 4cd93cd..bc03386 100644 --- a/src/main.rs +++ b/src/main.rs @@ -23,7 +23,9 @@ fn main() { let mac_addr: MacAddr = args.mac_addr.parse().unwrap(); let bcast_addr: IpAddr = args.bcast_addr.parse().unwrap(); let bind_addr: IpAddr = args.bind_addr.parse().unwrap(); - if (bind_addr.is_ipv4() && bcast_addr.is_ipv6()) || (bind_addr.is_ipv6() && bcast_addr.is_ipv4()) { + if (bind_addr.is_ipv4() && bcast_addr.is_ipv6()) + || (bind_addr.is_ipv6() && bcast_addr.is_ipv4()) + { panic!("The IP versions of bind_addr and bcast_addr do not match"); } send_wol(mac_addr, Some(bcast_addr), Some(bind_addr)).unwrap();