use core::fmt;
use core::str::FromStr;
#[cfg(any(test, feature = "arbitrary"))]
use proptest::{
arbitrary::{any, Arbitrary},
prop_oneof,
strategy::{BoxedStrategy, Strategy},
};
use super::{delegate, Address, Prefix, PrefixLength};
use crate::{
concrete::{self, Ipv4, Ipv6},
error::Error,
traits,
};
#[allow(variant_size_differences)]
#[derive(Clone, Copy, Debug, Hash, PartialEq, Eq)]
pub enum Interface {
Ipv4(concrete::Interface<Ipv4>),
Ipv6(concrete::Interface<Ipv6>),
}
impl traits::Interface for Interface {
type Address = Address;
type Prefix = Prefix;
type PrefixLength = PrefixLength;
delegate! {
fn network(&self) -> Self::Address;
fn addr(&self) -> Self::Address;
fn trunc(&self) -> Self::Prefix;
fn prefix_len(&self) -> Self::PrefixLength;
fn broadcast(&self) -> Self::Address;
}
}
impl From<concrete::Interface<Ipv4>> for Interface {
fn from(interface: concrete::Interface<Ipv4>) -> Self {
Self::Ipv4(interface)
}
}
impl From<concrete::Interface<Ipv6>> for Interface {
fn from(interface: concrete::Interface<Ipv6>) -> Self {
Self::Ipv6(interface)
}
}
impl FromStr for Interface {
type Err = Error;
fn from_str(s: &str) -> Result<Self, Self::Err> {
concrete::Interface::<Ipv4>::from_str(s)
.map(Self::from)
.or_else(|_| concrete::Interface::<Ipv6>::from_str(s).map(Self::from))
}
}
impl fmt::Display for Interface {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
match self {
Self::Ipv4(interface) => interface.fmt(f),
Self::Ipv6(interface) => interface.fmt(f),
}
}
}
#[cfg(any(test, feature = "arbitrary"))]
impl Arbitrary for Interface {
type Parameters = ();
type Strategy = BoxedStrategy<Self>;
fn arbitrary_with(_: Self::Parameters) -> Self::Strategy {
prop_oneof![
any::<concrete::Interface<Ipv4>>().prop_map(Self::Ipv4),
any::<concrete::Interface<Ipv6>>().prop_map(Self::Ipv6),
]
.boxed()
}
}