1use std::convert::From;
4use std::fs;
5use std::path::Path;
6use std::fmt;
7use std::str::from_utf8_unchecked;
8
9#[path = "util.rs"]
10mod util;
11use util::xtob;
12
13#[path = "macros.rs"]
14#[macro_use]
15mod macros;
16
17#[derive(Debug, Clone, Copy)]
19pub struct Node([u8; 6]);
20
21impl From<[u8; 6]> for Node {
22 fn from(xs: [u8; 6]) -> Self {
23 Node(xs)
24 }
25}
26
27impl Node {
28 #[cfg(target_os = "linux")]
30 pub fn new(interface: &str) -> Self {
31 let dir = "/sys/class/net";
32 let mut node: [u8; 6] = Default::default();
33
34 let content = fs::read_to_string(Path::new(dir).join(interface).join("address"))
36 .unwrap_or("00:00:00:00:00:00".to_owned());
37
38 let bs = content.as_bytes();
39 for (idx, &x) in [0, 3, 6, 9, 12, 15].iter().enumerate() {
40 node[idx] = xtob(bs[x], bs[x + 1]).unwrap_or_default();
41 }
42
43 Node(node)
44 }
45
46 pub fn id(self) -> [u8; 6] {
47 self.0
48 }
49}
50
51impl fmt::Display for Node {
52 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
53 let xs = self.0;
54
55 let mut bs: [u8; 17] = [b':'; 17];
56 bytes_format!(bs, xs, 0, 0, 1,
57 3, 4,
58 6, 7,
59 9, 10,
60 12, 13,
61 15, 16);
62
63 unsafe {
64 f.write_str(from_utf8_unchecked(&bs))
65 }
66 }
67}
68
69#[cfg(test)]
70mod tests {
71 use super::*;
72
73 #[test]
74 #[cfg(target_os = "linux")]
75 fn test_lo_nodeid() {
76 assert_eq!(Node::new("lo").id(), [0; 6]);
77 }
78
79 #[test]
80 #[cfg(target_os = "linux")]
81 fn test_to_string() {
82 let node = Node::new("lo");
83
84 assert_eq!(node.to_string(), "00:00:00:00:00:00");
85 }
86}