macro_rules! family_address_attribute {
(
$(#[$meta:meta])*
$class_name:ident,
$attr_type:ident,
) => (
const FAMILY_ADDRESS_ATTRIBUTE_SIZE: usize = 4;
$(#[$meta])*
#[derive(Debug, Clone, PartialEq, Eq)]
pub struct $class_name(crate::AddressFamily);
impl $class_name {
pub fn new(family: crate::AddressFamily) -> Self {
Self(family)
}
pub fn family(&self) -> crate::AddressFamily {
self.0
}
}
impl<T> From<T> for $class_name
where
T: AsRef<std::net::IpAddr>,
{
fn from(addr: T) -> Self {
match addr.as_ref() {
std::net::IpAddr::V4(_) => Self(crate::AddressFamily::IPv4),
std::net::IpAddr::V6(_) => Self(crate::AddressFamily::IPv6),
}
}
}
impl From<crate::AddressFamily> for $class_name {
fn from(family: crate::AddressFamily) -> Self {
$class_name::new(family)
}
}
impl crate::attributes::DecodeAttributeValue for $class_name {
fn decode(ctx: crate::context::AttributeDecoderContext) -> Result<(Self, usize), crate::StunError> {
use crate::Decode;
crate::common::check_buffer_boundaries(ctx.raw_value(), FAMILY_ADDRESS_ATTRIBUTE_SIZE)?;
let (family, _) = crate::AddressFamily::decode(ctx.raw_value())?;
Ok((
$class_name::new(family),
FAMILY_ADDRESS_ATTRIBUTE_SIZE,
))
}
}
impl crate::attributes::EncodeAttributeValue for $class_name {
fn encode(&self, mut ctx: crate::context::AttributeEncoderContext) -> Result<usize, crate::StunError> {
use crate::Encode;
let raw_value = ctx.raw_value_mut();
crate::common::check_buffer_boundaries(raw_value, FAMILY_ADDRESS_ATTRIBUTE_SIZE)?;
let size = self.0.encode(raw_value)?;
raw_value[size..FAMILY_ADDRESS_ATTRIBUTE_SIZE].fill(0x0);
Ok(FAMILY_ADDRESS_ATTRIBUTE_SIZE)
}
}
impl crate::attributes::AsVerifiable for $class_name {}
crate::attributes::stunt_attribute!($class_name, $attr_type);
)
}
pub(crate) use family_address_attribute;