internet/ietf/ipv4/encoding/
address.rs1use crate::{Buf, BufMut, BufResult, Codec, Cursor};
8use core::fmt;
9
10#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash)]
12#[repr(transparent)]
13pub struct Address(pub [u8; 4]);
14
15impl Address {
16 pub const UNSPECIFIED: Self = Self([0, 0, 0, 0]);
18
19 pub const BROADCAST: Self = Self([255, 255, 0, 0]);
21
22 pub const LOOPBACK: Self = Self([127, 0, 0, 1]);
24
25 pub const fn new(a: u8, b: u8, c: u8, d: u8) -> Self {
27 Self([a, b, c, d])
28 }
29
30 pub const fn from_octets(octets: [u8; 4]) -> Self {
32 Self(octets)
33 }
34
35 pub const fn octets(self) -> [u8; 4] {
37 self.0
38 }
39
40 pub const fn from_bits(bits: u32) -> Self {
42 Self(bits.to_be_bytes())
43 }
44
45 pub const fn to_bits(self) -> u32 {
47 u32::from_be_bytes(self.0)
48 }
49
50 pub const fn is_private(self) -> bool {
52 self.0[0] == 10
53 || (self.0[0] == 172 && (self.0[1] & 0xF0) == 16)
54 || (self.0[0] == 192 && self.0[1] == 168)
55 }
56
57 pub const fn is_link_local(self) -> bool {
59 self.0[0] == 169 && self.0[1] == 254
60 }
61
62 pub const fn is_multicast(self) -> bool {
64 (self.0[0] & 0xF0) == 224
65 }
66
67 pub const fn is_documentation(self) -> bool {
69 matches!(
70 (self.0[0], self.0[1], self.0[2]),
71 (192, 0, 2) | (198, 51, 100) | (203, 0, 113)
72 )
73 }
74}
75
76#[cfg(feature = "std")]
77impl From<std::net::Ipv4Addr> for Address {
78 fn from(addr: std::net::Ipv4Addr) -> Self {
79 Self(addr.octets())
80 }
81}
82
83#[cfg(feature = "std")]
84impl From<Address> for std::net::Ipv4Addr {
85 fn from(addr: Address) -> Self {
86 std::net::Ipv4Addr::from(addr.0)
87 }
88}
89
90impl From<[u8; 4]> for Address {
91 fn from(octets: [u8; 4]) -> Self {
92 Self(octets)
93 }
94}
95
96impl From<Address> for [u8; 4] {
97 fn from(addr: Address) -> Self {
98 addr.0
99 }
100}
101
102impl From<u32> for Address {
103 fn from(value: u32) -> Self {
104 Self(value.to_be_bytes())
105 }
106}
107
108impl From<Address> for u32 {
109 fn from(addr: Address) -> Self {
110 addr.to_bits()
111 }
112}
113
114impl Codec for Address {
115 fn encode<W: BufMut>(&self, writer: &mut Cursor<W>, _: ()) -> BufResult<()> {
116 self.0.encode(writer, ())
117 }
118
119 fn decode<R: Buf>(reader: &mut Cursor<R>, _: ()) -> BufResult<Self> {
120 Ok(Self(reader.read_array::<4>()?))
121 }
122}
123
124impl fmt::Display for Address {
125 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
126 write!(f, "{}.{}.{}.{}", self.0[0], self.0[1], self.0[2], self.0[3])
127 }
128}
129
130#[cfg(test)]
131mod tests {
132 use super::*;
133
134 #[test]
135 fn address_properties() {
136 assert!(Address::new(10, 0, 0, 1).is_private());
137 assert!(Address::new(192, 168, 1, 1).is_private());
138 assert!(Address::new(169, 254, 1, 1).is_link_local());
139 assert!(Address::new(224, 0, 0, 1).is_multicast());
140 assert!(Address::new(192, 0, 2, 1).is_documentation());
141 }
142}