1use alloc::string::ToString;
35pub use core::net::Ipv4Addr;
36use core::{
37 fmt,
38 net::AddrParseError,
39 ops::Deref,
40 str::{self, FromStr},
41};
42
43#[cfg(feature = "serde")]
44use serde::{Deserialize, Serialize};
45
46use crate::{
47 error::*,
48 rr::{RData, RecordData, RecordType},
49 serialize::{binary::*, txt::ParseError},
50};
51
52#[cfg_attr(feature = "serde", derive(Deserialize, Serialize))]
54#[derive(Debug, PartialEq, Eq, Hash, Clone, Copy)]
55pub struct A(pub Ipv4Addr);
56
57impl A {
58 pub const fn new(a: u8, b: u8, c: u8, d: u8) -> Self {
60 Self(Ipv4Addr::new(a, b, c, d))
61 }
62
63 pub(crate) fn from_tokens<'i, I: Iterator<Item = &'i str>>(
65 mut tokens: I,
66 ) -> Result<Self, ParseError> {
67 let address: Ipv4Addr = tokens
68 .next()
69 .ok_or_else(|| ParseError::MissingToken("ipv4 address".to_string()))
70 .and_then(|s| Ipv4Addr::from_str(s).map_err(Into::into))?;
71 Ok(address.into())
72 }
73}
74
75impl RecordData for A {
76 fn try_borrow(data: &RData) -> Option<&Self> {
77 match data {
78 RData::A(ipv4) => Some(ipv4),
79 _ => None,
80 }
81 }
82
83 fn record_type(&self) -> RecordType {
84 RecordType::A
85 }
86
87 fn into_rdata(self) -> RData {
88 RData::A(self)
89 }
90}
91
92impl BinEncodable for A {
93 fn emit(&self, encoder: &mut BinEncoder<'_>) -> ProtoResult<()> {
94 let segments = self.octets();
95
96 encoder.emit(segments[0])?;
97 encoder.emit(segments[1])?;
98 encoder.emit(segments[2])?;
99 encoder.emit(segments[3])?;
100 Ok(())
101 }
102}
103
104impl<'r> BinDecodable<'r> for A {
105 fn read(decoder: &mut BinDecoder<'r>) -> Result<Self, DecodeError> {
106 Ok(Ipv4Addr::new(
108 decoder.pop()?.unverified(),
109 decoder.pop()?.unverified(),
110 decoder.pop()?.unverified(),
111 decoder.pop()?.unverified(),
112 )
113 .into())
114 }
115}
116
117impl From<Ipv4Addr> for A {
118 fn from(a: Ipv4Addr) -> Self {
119 Self(a)
120 }
121}
122
123impl From<A> for Ipv4Addr {
124 fn from(a: A) -> Self {
125 a.0
126 }
127}
128
129impl Deref for A {
130 type Target = Ipv4Addr;
131
132 fn deref(&self) -> &Self::Target {
133 &self.0
134 }
135}
136
137impl fmt::Display for A {
138 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> Result<(), fmt::Error> {
139 write!(f, "{}", self.0)
140 }
141}
142
143impl FromStr for A {
144 type Err = AddrParseError;
145 fn from_str(s: &str) -> Result<Self, AddrParseError> {
146 Ipv4Addr::from_str(s).map(From::from)
147 }
148}
149
150#[cfg(test)]
151mod mytests {
152 use alloc::vec::Vec;
153
154 use super::*;
155 use crate::serialize::binary::bin_tests::{test_emit_data_set, test_read_data_set};
156
157 fn get_data() -> Vec<(A, Vec<u8>)> {
158 vec![
159 (A::from(Ipv4Addr::UNSPECIFIED), vec![0, 0, 0, 0]), (A::from(Ipv4Addr::new(1, 0, 0, 0)), vec![1, 0, 0, 0]),
161 (A::from(Ipv4Addr::new(0, 1, 0, 0)), vec![0, 1, 0, 0]),
162 (A::from(Ipv4Addr::new(0, 0, 1, 0)), vec![0, 0, 1, 0]),
163 (A::from(Ipv4Addr::new(0, 0, 0, 1)), vec![0, 0, 0, 1]),
164 (A::from(Ipv4Addr::LOCALHOST), vec![127, 0, 0, 1]),
165 (
166 A::from(Ipv4Addr::new(192, 168, 64, 32)),
167 vec![192, 168, 64, 32],
168 ),
169 ]
170 }
171
172 #[test]
173 fn test_parse() {
174 test_read_data_set(get_data(), |mut d| A::read(&mut d));
175 }
176
177 #[test]
178 fn test_write_to() {
179 test_emit_data_set(get_data(), |e, d| d.emit(e));
180 }
181}