use core::cmp::Ordering;
use core::fmt;
use core::net::Ipv4Addr;
use core::str::FromStr;
use crate::new::base::build::{BuildInMessage, NameCompressor};
use crate::new::base::parse::ParseMessageBytes;
use crate::new::base::wire::*;
use crate::new::base::{
CanonicalRecordData, ParseRecordData, ParseRecordDataBytes, RType,
};
use crate::utils::dst::UnsizedCopy;
#[derive(
Copy,
Clone,
PartialEq,
Eq,
PartialOrd,
Ord,
Hash,
AsBytes,
BuildBytes,
ParseBytes,
ParseBytesZC,
SplitBytes,
SplitBytesZC,
UnsizedCopy,
)]
#[repr(transparent)]
pub struct A {
pub octets: [u8; 4],
}
impl From<Ipv4Addr> for A {
fn from(value: Ipv4Addr) -> Self {
Self {
octets: value.octets(),
}
}
}
impl From<A> for Ipv4Addr {
fn from(value: A) -> Self {
Self::from(value.octets)
}
}
impl CanonicalRecordData for A {
fn cmp_canonical(&self, other: &Self) -> Ordering {
self.octets.cmp(&other.octets)
}
}
impl FromStr for A {
type Err = <Ipv4Addr as FromStr>::Err;
fn from_str(s: &str) -> Result<Self, Self::Err> {
Ipv4Addr::from_str(s).map(A::from)
}
}
impl fmt::Debug for A {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
write!(f, "A({self})")
}
}
impl fmt::Display for A {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
Ipv4Addr::from(*self).fmt(f)
}
}
impl ParseMessageBytes<'_> for A {
fn parse_message_bytes(
contents: &'_ [u8],
start: usize,
) -> Result<Self, ParseError> {
contents
.get(start..)
.ok_or(ParseError)
.and_then(Self::parse_bytes)
}
}
impl BuildInMessage for A {
fn build_in_message(
&self,
contents: &mut [u8],
start: usize,
_compressor: &mut NameCompressor,
) -> Result<usize, TruncationError> {
let end = start + core::mem::size_of::<Self>();
contents
.get_mut(start..end)
.ok_or(TruncationError)?
.copy_from_slice(&self.octets);
Ok(end)
}
}
impl ParseRecordData<'_> for A {}
impl ParseRecordDataBytes<'_> for A {
fn parse_record_data_bytes(
bytes: &'_ [u8],
rtype: RType,
) -> Result<Self, ParseError> {
match rtype {
RType::A => Self::parse_bytes(bytes),
_ => Err(ParseError),
}
}
}
impl<'a> ParseRecordData<'a> for &'a A {}
impl<'a> ParseRecordDataBytes<'a> for &'a A {
fn parse_record_data_bytes(
bytes: &'a [u8],
rtype: RType,
) -> Result<Self, ParseError> {
match rtype {
RType::A => Self::parse_bytes(bytes),
_ => Err(ParseError),
}
}
}