1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
use core::fmt::{Debug, Display};
use core::hash::Hash;
use core::str::FromStr;

use super::{Address, Prefix, PrefixLength};
use crate::error::Error;

/// Address-family independent interface for IP interfaces.
///
/// Methods on `Interface` types that are well defined for all address-families
/// are implemented via this trait.
///
/// In general, methods on this trait have signatures and semantics compatible
/// with methods of the same names on the [`ipnet`] network types. Where
/// there is deviation, this is noted in the method documentation.
///
/// See also [`concrete::Interface<A>`][crate::concrete::Interface] and
/// [`any::Interface`][crate::any::Interface] for address-family specific items.
pub trait Interface:
    Copy + Clone + Debug + Display + FromStr<Err = Error> + Sized + Hash + PartialEq + Eq
{
    /// The type of IP address represented by this interface type.
    type Address: Address;

    /// The type used to represented IP prefixes for this IP interface type.
    type PrefixLength: PrefixLength;

    /// The type used to represented IP prefix lengths for this IP interface
    /// type.
    type Prefix: Prefix;

    /// Returns the network address of the IP subnet containing this interface.
    ///
    /// # Examples
    ///
    /// ``` rust
    /// use ip::{traits::Interface as _, Address, Any, Interface, Ipv4, Ipv6};
    ///
    /// assert_eq!(
    ///     "172.16.123.123/16".parse::<Interface<Ipv4>>()?.network(),
    ///     "172.16.0.0".parse::<Address<Ipv4>>()?,
    /// );
    ///
    /// assert_eq!(
    ///     "2001:db8:f00::baa/48".parse::<Interface<Ipv6>>()?.network(),
    ///     "2001:db8:f00::".parse::<Address<Ipv6>>()?,
    /// );
    ///
    /// assert_eq!(
    ///     "10.255.0.10/16".parse::<Interface<Any>>()?.network(),
    ///     Address::<Any>::Ipv4("10.255.0.0".parse()?),
    /// );
    /// # Ok::<(), ip::Error>(())
    /// ```
    fn network(&self) -> Self::Address;

    /// Returns the IP address of this interface.
    ///
    /// # Examples
    ///
    /// ``` rust
    /// use ip::{traits::Interface as _, Address, Any, Interface, Ipv4, Ipv6};
    ///
    /// assert_eq!(
    ///     "172.16.123.123/16".parse::<Interface<Ipv4>>()?.addr(),
    ///     "172.16.123.123".parse::<Address<Ipv4>>()?,
    /// );
    ///
    /// assert_eq!(
    ///     "2001:db8:f00::baa/48".parse::<Interface<Ipv6>>()?.addr(),
    ///     "2001:db8:f00::baa".parse::<Address<Ipv6>>()?,
    /// );
    ///
    /// assert_eq!(
    ///     "10.255.0.10/16".parse::<Interface<Any>>()?.addr(),
    ///     Address::<Any>::Ipv4("10.255.0.10".parse()?),
    /// );
    /// # Ok::<(), ip::Error>(())
    /// ```
    fn addr(&self) -> Self::Address;

    /// Returns the IP prefix containing this interface.
    ///
    /// # Examples
    ///
    /// ``` rust
    /// use ip::{traits::Interface as _, Any, Interface, Ipv4, Ipv6, Prefix};
    ///
    /// assert_eq!(
    ///     "172.16.123.123/16".parse::<Interface<Ipv4>>()?.trunc(),
    ///     "172.16.0.0/16".parse::<Prefix<Ipv4>>()?,
    /// );
    ///
    /// assert_eq!(
    ///     "2001:db8:f00::baa/48".parse::<Interface<Ipv6>>()?.trunc(),
    ///     "2001:db8:f00::/48".parse::<Prefix<Ipv6>>()?,
    /// );
    ///
    /// assert_eq!(
    ///     "10.255.0.10/16".parse::<Interface<Any>>()?.trunc(),
    ///     Prefix::<Any>::Ipv4("10.255.0.0/16".parse()?),
    /// );
    /// # Ok::<(), ip::Error>(())
    /// ```
    fn trunc(&self) -> Self::Prefix;

    /// Returns the prefix length of this interface.
    ///
    /// # Examples
    ///
    /// ``` rust
    /// use ip::{traits::Interface as _, Any, Interface, Ipv4, Ipv6, PrefixLength};
    ///
    /// assert_eq!(
    ///     "172.16.123.123/16".parse::<Interface<Ipv4>>()?.prefix_len(),
    ///     PrefixLength::<Ipv4>::from_primitive(16)?,
    /// );
    ///
    /// assert_eq!(
    ///     "2001:db8:f00::baa/48"
    ///         .parse::<Interface<Ipv6>>()?
    ///         .prefix_len(),
    ///     PrefixLength::<Ipv6>::from_primitive(48)?,
    /// );
    ///
    /// assert_eq!(
    ///     "10.255.0.10/16".parse::<Interface<Any>>()?.prefix_len(),
    ///     PrefixLength::<Ipv4>::from_primitive(16)?.into(),
    /// );
    /// # Ok::<(), ip::Error>(())
    /// ```
    fn prefix_len(&self) -> Self::PrefixLength;

    /// Returns the broadcast address of the IP subnet containing this
    /// interface.
    ///
    /// # [`ipnet`] Compatibility
    ///
    /// The term "broadcast address" has no meaning when applied to IPv6
    /// subnets. However, for compatibility with [`ipnet::Ipv6Net`], this
    /// method will return the last address covered by the prefix in all
    /// cases.
    ///
    /// # Examples
    ///
    /// ``` rust
    /// use ip::{traits::Interface as _, Address, Any, Interface, Ipv4, Ipv6};
    ///
    /// assert_eq!(
    ///     "172.16.123.123/16".parse::<Interface<Ipv4>>()?.broadcast(),
    ///     "172.16.255.255".parse::<Address<Ipv4>>()?,
    /// );
    ///
    /// assert_eq!(
    ///     "2001:db8:f00::baa/48"
    ///         .parse::<Interface<Ipv6>>()?
    ///         .broadcast(),
    ///     "2001:db8:f00:ffff:ffff:ffff:ffff:ffff".parse::<Address<Ipv6>>()?,
    /// );
    ///
    /// assert_eq!(
    ///     "2001:db8:dead:beef::/64"
    ///         .parse::<Interface<Any>>()?
    ///         .broadcast(),
    ///     Address::<Any>::Ipv6("2001:db8:dead:beef:ffff:ffff:ffff:ffff".parse()?),
    /// );
    /// # Ok::<(), ip::Error>(())
    /// ```
    fn broadcast(&self) -> Self::Address;
}