1use core::fmt;
2use core::str::FromStr;
3
4#[cfg(any(test, feature = "arbitrary"))]
5use proptest::{
6 arbitrary::{any, Arbitrary},
7 prop_oneof,
8 strategy::{BoxedStrategy, Strategy},
9};
10
11use super::{delegate, Address, Prefix, PrefixLength};
12use crate::{
13 concrete::{self, Ipv4, Ipv6},
14 error::Error,
15 traits,
16};
17
18#[allow(variant_size_differences)]
42#[derive(Clone, Copy, Debug, Hash, PartialEq, Eq)]
43pub enum Interface {
44 Ipv4(concrete::Interface<Ipv4>),
46 Ipv6(concrete::Interface<Ipv6>),
48}
49
50impl traits::Interface for Interface {
51 type Address = Address;
52 type Prefix = Prefix;
53 type PrefixLength = PrefixLength;
54
55 delegate! {
56 fn network(&self) -> Self::Address;
57 fn addr(&self) -> Self::Address;
58 fn trunc(&self) -> Self::Prefix;
59 fn prefix_len(&self) -> Self::PrefixLength;
60 fn broadcast(&self) -> Self::Address;
61 }
62}
63
64impl From<concrete::Interface<Ipv4>> for Interface {
65 fn from(interface: concrete::Interface<Ipv4>) -> Self {
66 Self::Ipv4(interface)
67 }
68}
69
70impl From<concrete::Interface<Ipv6>> for Interface {
71 fn from(interface: concrete::Interface<Ipv6>) -> Self {
72 Self::Ipv6(interface)
73 }
74}
75
76impl FromStr for Interface {
77 type Err = Error;
78
79 fn from_str(s: &str) -> Result<Self, Self::Err> {
80 concrete::Interface::<Ipv4>::from_str(s)
81 .map(Self::from)
82 .or_else(|_| concrete::Interface::<Ipv6>::from_str(s).map(Self::from))
83 }
84}
85
86impl fmt::Display for Interface {
87 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
88 match self {
89 Self::Ipv4(interface) => interface.fmt(f),
90 Self::Ipv6(interface) => interface.fmt(f),
91 }
92 }
93}
94
95#[cfg(any(test, feature = "arbitrary"))]
96impl Arbitrary for Interface {
97 type Parameters = ();
98 type Strategy = BoxedStrategy<Self>;
99
100 fn arbitrary_with((): Self::Parameters) -> Self::Strategy {
101 prop_oneof![
102 any::<concrete::Interface<Ipv4>>().prop_map(Self::Ipv4),
103 any::<concrete::Interface<Ipv6>>().prop_map(Self::Ipv6),
104 ]
105 .boxed()
106 }
107}