light_tool/
mac.rs

1use std::process::Command;
2
3/// Returns one MAC address of the current machine
4///
5/// # Example
6///
7/// ```no_run
8/// use light_tool::mac;
9/// println!("mac address: {}", mac::address().unwrap())
10/// ```
11pub fn address() -> Option<String> {
12    let output = match std::env::consts::OS {
13        "linux" => Command::new("ifconfig").output(),
14        "macos" => Command::new("ifconfig").output(),
15        "windows" => Command::new("getmac").output(),
16        _ => return None,
17    };
18
19    if let Ok(output) = output {
20        if output.status.success() {
21            let output_str = String::from_utf8_lossy(&output.stdout);
22
23            for line in output_str.lines() {
24                for mac_candidate in line.split_whitespace() {
25                    if is_valid_address(mac_candidate) {
26                        return Some(mac_candidate.to_string());
27                    }
28                }
29            }
30        }
31    }
32    None
33}
34
35fn is_valid_address(mac: &str) -> bool {
36    // windows mac address -> C4-75-AB-75-9C-25
37    // linux mac address -> 5A:9A:C3:47:2D:33
38    let parts: Vec<&str> = mac.split(|c| c == ':' || c == '-').collect();
39    parts.len() == 6 && parts.iter().all(|p| p.len() == 2 && p.chars().all(|c| c.is_ascii_hexdigit()))
40}
41
42#[cfg(test)]
43mod tests {
44    use super::*;
45
46    #[test]
47    fn test_get_mac_address() {
48        println!("mac address: {:?}", address());
49    }
50}