Rust EUI-48和EUI-64地址处理库eui48的使用,支持MAC地址的解析、格式化和操作

Rust EUI-48和EUI-64地址处理库eui48的使用,支持MAC地址的解析、格式化和操作

eui48是一个Rust库,用于表示和解析IEEE EUI-48(也称为MAC-48)媒体访问控制地址。IEEE对名称EUI-48和EUI-64拥有商标权,其中EUI是Extended Unique Identifier(扩展唯一标识符)的缩写。

使用

在您的Cargo.toml中添加:

[dependencies]
eui48 = "1.1.0"

并在您的crate root中添加:

extern crate eui48;

示例

创建一个新的MAC地址并以规范形式打印出来:

extern crate eui48;
use eui48::{MacAddress, Eui48};

fn main() {
    let eui: Eui48 = [ 0x12, 0x34, 0x56, 0xAB, 0xCD, 0xEF ];
    let mac = MacAddress::new( eui );

    println!("{}", mac.to_canonical());
    println!("{}", mac.to_hex_string());
    println!("{}", mac.to_dot_string());
    println!("{}", mac.to_hexadecimal());
    println!("{}", mac.to_interfaceid());
    println!("{}", mac.to_link_local());

    let mac = MacAddress::parse_str( "01-02-03-0A-0b-0f" ).expect("Parse error {}");
    let mac = MacAddress::parse_str( "01:02:03:0A-0b-0f" ).expect("Parse error {}");
    let mac = MacAddress::parse_str( "0102.030A.0b0f" ).expect("Parse error {}");
    let mac = MacAddress::parse_str( "0x1234567890ab" ).expect("Parse error {}");
}

完整示例代码

extern crate eui48;
use eui48::{MacAddress, Eui48};

fn main() {
    // 通过数组创建MAC地址
    let eui: Eui48 = [0x12, 0x34, 0x56, 0xAB, 0xCD, 0xEF];
    let mac = MacAddress::new(eui);
    
    // 输出不同格式的MAC地址
    println!("规范格式: {}", mac.to_canonical());     // 12-34-56-ab-cd-ef
    println!("十六进制字符串: {}", mac.to_hex_string());        // 12:34:56:ab:cd:ef
    println!("点分格式: {}", mac.to_dot_string());      // 1234.56ab.cdef
    println!("十六进制: {}", mac.to_hexadecimal());      // 0x123456abcdef
    println!("接口ID: {}", mac.to_interfaceid());     // 1234:56ff:feab:cdef
    println!("本地链路地址: {}", mac.to_link_local());        // fe80::1234:56ff:feab:cdef
    
    // 从字符串解析MAC地址
    let mac1 = MacAddress::parse_str("01-02-03-0A-0b-0f").unwrap();
    println!("解析的MAC: {}", mac1.to_canonical());
    
    let mac2 = MacAddress::parse_str("01:02:03:0A:0b:0f").unwrap();
    println!("解析的MAC: {}", mac2.to_canonical());
    
    let mac3 = MacAddress::parse_str("0102.030A.0b0f").unwrap();
    println!("解析的MAC: {}", mac3.to_canonical());
    
    let mac4 = MacAddress::parse_str("0x1234567890ab").unwrap();
    println!("解析的MAC: {}", mac4.to_canonical());
}

注意事项

  • 默认显示格式是规范形式01-02-03-04-05-06,除非启用编译时功能disp_hexstring,则默认格式为01:02:03:04:05:06

1.0.0及以上版本允许更灵活地解析MAC地址字符串:

  • 允许库的调用者解析不符合固定长度MAC地址约定的MAC
  • 解析函数现在更努力地解释给定的字符串
  • 将parse_str重写为使用正则表达式并更宽松(现在它允许一次性字符串截断错误和接受混合分隔符,只要我们能读取6个字节)

序列化

当使用serde序列化MAC地址时,地址存储为格式化字符串。这非常适合基于文本的协议如JSON,但会为二进制序列化创建开销。要减少这种开销,在序列化和反序列化MAC地址到二进制协议时使用serde_bytes功能。

注意:serde_bytesserde_json是互斥的!


1 回复

Rust EUI-48和EUI-64地址处理库eui48使用指南

eui48是一个用于处理EUI-48和EUI-64地址(即MAC地址)的Rust库,提供了MAC地址的解析、格式化和各种操作功能。

安装

在Cargo.toml中添加依赖:

[dependencies]
eui48 = "1.0.0"

基本用法

创建MAC地址

use eui48::{MacAddress, Eui48};

// 从字节数组创建
let mac = MacAddress::new([0x00, 0x1A, 0x2B, 0x3C, 0x4D, 0x5E]);

// 从字符串解析
let mac: MacAddress = "00-1A-2B-3C-4D-5E".parse().unwrap();
let mac = MacAddress::parse_str("00:1A:2B:3C:4D:5E").unwrap();

格式化输出

let mac = MacAddress::new([0x00, 0x1A, 0x2B, 0x3C, 0x4D, 0x5E]);

// 默认格式(带冒号)
println!("{}", mac); // 00:1A:2B:3C:4D:5E

// 指定格式
println!("{}", mac.to_canonical()); // 00-1A-2B-3C-4D-5E
println!("{}", mac.to_hex_string()); // 001A2B3C4D5E
println!("{}", mac.to_dot_string()); // 001A.2B3C.4D5E

操作MAC地址

let mut mac = MacAddress::new([0x00, 0x1A, 0x2B, 0x3C, 0x4D, 0x5E]);

// 获取单个字节
let first_byte = mac.as_bytes()[0]; // 0x00

// 修改MAC地址
mac as_mut_bytes()[5] = 0xFF; // 最后一个字节改为0xFF

// 检查是否为组播地址
if mac.is_multicast() {
    println!("这是一个组播地址");
}

// 检查是否为本地管理地址
if mac.is_local() {
    println!("这是一个本地管理地址");
}

// 转换为EUI-64
let eui64 = mac.to_eui64();
println!("EUI-64: {}", eui64); // 02:1A:2B:FF:FE:3C:4D:5E

高级功能

生成随机MAC地址

use eui48::MacAddress;
use rand::Rng;

let mut rng = rand::thread_rng();
let random_mac = MacAddress::random(&mut rng);
println!("随机MAC地址: {}", random_mac);

比较和排序

let mac1 = MacAddress::parse_str("00:1A:2B:3C:4D:5E").unwrap();
let mac2 = MacAddress::parse_str("00:1A:2B:3C:4D:5F").unwrap();

if mac1 < mac2 {
    println!("{} 小于 {}", mac1, mac2);
}

// 也可以直接比较字节数组
assert!(mac1.as_bytes() < mac2.as_bytes());

序列化和反序列化

use serde::{Serialize, Deserialize};

#[derive(Serialize, Deserialize)]
struct NetworkDevice {
    name: String,
    mac: MacAddress,
}

let device = NetworkDevice {
    name: "Router".to_string(),
    mac: MacAddress::parse_str("00:1A:2B:3C:4D:5E").unwrap(),
};

// 序列化为JSON
let json = serde_json::to_string(&device).unwrap();
println!("{}", json); // {"name":"Router","mac":"00:1A:2B:3C:4D:5E"}

// 从JSON反序列化
let device: NetworkDevice = serde_json::from_str(&json).unwrap();

处理EUI-64地址

use eui48::Eui64;

// 创建EUI-64地址
let eui64 = Eui64::new([0x00, 0x1A, 0x2B, 0xFF, 0xFE, 0x3C, 0x4D, 0x5E]);

// 从EUI-48转换
let mac = MacAddress::new([0x00, 0x1A, 0x2B, 0x3C, 0x4D, 0x5E]);
let eui64 = mac.to_eui64();

// 格式化输出
println!("{}", eui64); // 00:1A:2B:FF:FE:3C:4D:5E
println!("{}", eui64.to_hex_string()); // 001A2BFFFE3C4D5E

完整示例代码

下面是一个综合使用eui48库的完整示例:

use eui48::{MacAddress, Eui64};
use rand::Rng;
use serde::{Serialize, Deserialize};

#[derive(Serialize, Deserialize, Debug)]
struct NetworkInterface {
    name: String,
    mac: MacAddress,
    eui64: Option<Eui64>,
}

fn main() {
    // 1. 创建MAC地址
    let mac1 = MacAddress::new([0x00, 0x1A, 0x2B, 0x3C, 0x4D, 0x5E]);
    let mac2: MacAddress = "00-1A-2B-3C-4D-5F".parse().unwrap();
    
    // 2. 格式化输出
    println!("MAC地址1: {}", mac1);
    println!("规范格式: {}", mac1.to_canonical());
    println!("点分格式: {}", mac1.to_dot_string());
    
    // 3. 修改MAC地址
    let mut mac = mac1;
    mac.as_mut_bytes()[5] = 0xFF;
    println!("修改后的MAC: {}", mac);
    
    // 4. 检查地址属性
    println!("是组播地址吗? {}", mac.is_multicast());
    println!("是本地管理地址吗? {}", mac.is_local());
    
    // 5. 生成随机MAC地址
    let mut rng = rand::thread_rng();
    let random_mac = MacAddress::random(&mut rng);
    println!("随机MAC地址: {}", random_mac);
    
    // 6. 比较MAC地址
    if mac1 < mac2 {
        println!("{} 小于 {}", mac1, mac2);
    }
    
    // 7. 转换为EUI-64
    let eui64 = mac1.to_eui64();
    println!("EUI-64地址: {}", eui64);
    
    // 8. 序列化和反序列化
    let interface = NetworkInterface {
        name: "eth0".to_string(),
        mac: mac1,
        eui64: Some(eui64),
    };
    
    let json = serde_json::to_string(&interface).unwrap();
    println!("序列化结果: {}", json);
    
    let decoded: NetworkInterface = serde_json::from_str(&json).unwrap();
    println!("反序列化结果: {:?}", decoded);
}

这个完整示例演示了:

  1. 创建MAC地址的多种方式
  2. 不同的格式化输出方法
  3. 修改MAC地址字节
  4. 检查地址属性
  5. 生成随机MAC地址
  6. 比较MAC地址
  7. 转换为EUI-64地址
  8. 结构体的序列化和反序列化

eui48库提供了简单直观的API来处理MAC地址和EUI-64标识符,非常适合网络编程和设备管理相关的应用。

回到顶部