- Introduce `bootstrap_load_balancer` module for handling initial load balancing configuration. - Add `bootstrap_dhcp` module for bootstrapping DHCP settings. - Create `harmony_types` crate to house shared types, including `MacAddress`. - Update `harmony_macros` to use `harmony_types` instead of directly referencing `harmony`.
79 lines
2.2 KiB
Rust
79 lines
2.2 KiB
Rust
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::<std::net::Ipv4Addr>() {
|
|
let expanded =
|
|
quote! { std::net::IpAddr::V4(#ip_str.parse::<std::net::Ipv4Addr>().unwrap()) };
|
|
return TokenStream::from(expanded);
|
|
}
|
|
|
|
if let Ok(_) = ip_str.parse::<std::net::Ipv6Addr>() {
|
|
let expanded =
|
|
quote! { std::net::IpAddr::V6(#ip_str.parse::<std::net::Ipv6Addr>().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::<std::net::Ipv4Addr>() {
|
|
let expanded = quote! { #ip_str.parse::<std::net::Ipv4Addr>().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)
|
|
}
|