extern crate proc_macro; use proc_macro::TokenStream; use quote::quote; use syn::{LitStr, parse_macro_input}; #[proc_macro] pub fn ip(input: TokenStream) -> TokenStream { let input = parse_macro_input!(input as LitStr); let ip_str = input.value(); if let Ok(_) = ip_str.parse::() { let expanded = quote! { std::net::IpAddr::V4(#ip_str.parse::().unwrap()) }; return TokenStream::from(expanded); } if let Ok(_) = ip_str.parse::() { let expanded = quote! { std::net::IpAddr::V6(#ip_str.parse::().unwrap()) }; return TokenStream::from(expanded); } panic!("Invalid IP address: {}", ip_str); } #[proc_macro] pub fn ipv4(input: TokenStream) -> TokenStream { let input = parse_macro_input!(input as LitStr); let ip_str = input.value(); if let Ok(_) = ip_str.parse::() { let expanded = quote! { #ip_str.parse::().unwrap() }; return TokenStream::from(expanded); } panic!("Invalid IPv4 address: {}", ip_str); } #[proc_macro] pub fn mac_address(input: TokenStream) -> TokenStream { let input = parse_macro_input!(input as LitStr); let mac_str = input.value(); match parse_mac_address(&mac_str) { Ok(bytes) => { let b0 = bytes[0]; let b1 = bytes[1]; let b2 = bytes[2]; let b3 = bytes[3]; let b4 = bytes[4]; let b5 = bytes[5]; quote! { MacAddress( [#b0, #b1, #b2, #b3, #b4, #b5] ) } .into() } Err(err) => syn::Error::new(input.span(), err).to_compile_error().into(), } } fn parse_mac_address(mac: &str) -> Result<[u8; 6], String> { let parts: Vec<&str> = mac.split(':').collect(); if parts.len() != 6 { return Err("MAC address must contain exactly six octets separated by colons".to_string()); } let mut bytes = [0u8; 6]; for (i, part) in parts.iter().enumerate() { match u8::from_str_radix(part, 16) { Ok(byte) => bytes[i] = byte, Err(_) => return Err(format!("Invalid MAC address octet: {}", part)), } } Ok(bytes) }