pub use std::net::Ipv4Addr;
use std::{fmt, net::AddrParseError, ops::Deref, str};
#[cfg(feature = "serde-config")]
use serde::{Deserialize, Serialize};
use crate::{
error::*,
rr::{RData, RecordData, RecordType},
serialize::binary::*,
};
#[cfg_attr(feature = "serde-config", derive(Deserialize, Serialize))]
#[derive(Debug, PartialEq, Eq, Hash, Clone, Copy)]
pub struct A(pub Ipv4Addr);
impl A {
pub const fn new(a: u8, b: u8, c: u8, d: u8) -> Self {
Self(Ipv4Addr::new(a, b, c, d))
}
}
impl RecordData for A {
fn try_from_rdata(data: RData) -> Result<Self, crate::rr::RData> {
match data {
RData::A(ipv4) => Ok(ipv4),
_ => Err(data),
}
}
fn try_borrow(data: &RData) -> Option<&Self> {
match data {
RData::A(ipv4) => Some(ipv4),
_ => None,
}
}
fn record_type(&self) -> RecordType {
RecordType::A
}
fn into_rdata(self) -> RData {
RData::A(self)
}
}
impl BinEncodable for A {
fn emit(&self, encoder: &mut BinEncoder<'_>) -> ProtoResult<()> {
let segments = self.octets();
encoder.emit(segments[0])?;
encoder.emit(segments[1])?;
encoder.emit(segments[2])?;
encoder.emit(segments[3])?;
Ok(())
}
}
impl<'r> BinDecodable<'r> for A {
fn read(decoder: &mut BinDecoder<'r>) -> ProtoResult<Self> {
Ok(Ipv4Addr::new(
decoder.pop()?.unverified(),
decoder.pop()?.unverified(),
decoder.pop()?.unverified(),
decoder.pop()?.unverified(),
)
.into())
}
}
#[deprecated(note = "use the BinDecodable::read method instead")]
pub fn read(decoder: &mut BinDecoder<'_>) -> ProtoResult<A> {
<A as BinDecodable>::read(decoder)
}
#[deprecated(note = "use the BinEncodable::emit method instead")]
pub fn emit(encoder: &mut BinEncoder<'_>, address: Ipv4Addr) -> ProtoResult<()> {
BinEncodable::emit(&A::from(address), encoder)
}
impl From<Ipv4Addr> for A {
fn from(a: Ipv4Addr) -> Self {
Self(a)
}
}
impl From<A> for Ipv4Addr {
fn from(a: A) -> Self {
a.0
}
}
impl Deref for A {
type Target = Ipv4Addr;
fn deref(&self) -> &Self::Target {
&self.0
}
}
impl fmt::Display for A {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> Result<(), fmt::Error> {
write!(f, "{}", self.0)
}
}
impl str::FromStr for A {
type Err = AddrParseError;
fn from_str(s: &str) -> Result<Self, AddrParseError> {
Ipv4Addr::from_str(s).map(From::from)
}
}
#[cfg(test)]
mod mytests {
use std::str::FromStr;
use super::*;
use crate::serialize::binary::bin_tests::{test_emit_data_set, test_read_data_set};
fn get_data() -> Vec<(A, Vec<u8>)> {
vec![
(A::from_str("0.0.0.0").unwrap(), vec![0, 0, 0, 0]), (A::from_str("1.0.0.0").unwrap(), vec![1, 0, 0, 0]),
(A::from_str("0.1.0.0").unwrap(), vec![0, 1, 0, 0]),
(A::from_str("0.0.1.0").unwrap(), vec![0, 0, 1, 0]),
(A::from_str("0.0.0.1").unwrap(), vec![0, 0, 0, 1]),
(A::from_str("127.0.0.1").unwrap(), vec![127, 0, 0, 1]),
(
A::from_str("192.168.64.32").unwrap(),
vec![192, 168, 64, 32],
),
]
}
#[test]
fn test_parse() {
test_read_data_set(get_data(), |ref mut d| A::read(d));
}
#[test]
fn test_write_to() {
test_emit_data_set(get_data(), |ref mut e, d| d.emit(e));
}
}