use core::cmp::Ordering;
use crate::new::base::build::{BuildInMessage, NameCompressor};
use crate::new::base::name::CanonicalName;
use crate::new::base::parse::{ParseMessageBytes, SplitMessageBytes};
use crate::new::base::{
wire::*, CanonicalRecordData, ParseRecordData, ParseRecordDataBytes,
RType, Serial,
};
#[derive(
Copy,
Clone,
Debug,
PartialEq,
Eq,
Hash,
BuildBytes,
ParseBytes,
SplitBytes,
)]
pub struct Soa<N> {
pub mname: N,
pub rname: N,
pub serial: Serial,
pub refresh: U32,
pub retry: U32,
pub expire: U32,
pub minimum: U32,
}
impl<N> Soa<N> {
pub fn map_names<R, F: FnMut(N) -> R>(self, mut f: F) -> Soa<R> {
Soa {
mname: (f)(self.mname),
rname: (f)(self.rname),
serial: self.serial,
refresh: self.refresh,
retry: self.retry,
expire: self.expire,
minimum: self.minimum,
}
}
pub fn map_names_by_ref<'r, R, F: FnMut(&'r N) -> R>(
&'r self,
mut f: F,
) -> Soa<R> {
Soa {
mname: (f)(&self.mname),
rname: (f)(&self.rname),
serial: self.serial,
refresh: self.refresh,
retry: self.retry,
expire: self.expire,
minimum: self.minimum,
}
}
}
impl<N: CanonicalName> CanonicalRecordData for Soa<N> {
fn build_canonical_bytes<'b>(
&self,
bytes: &'b mut [u8],
) -> Result<&'b mut [u8], TruncationError> {
let bytes = self.mname.build_lowercased_bytes(bytes)?;
let bytes = self.rname.build_lowercased_bytes(bytes)?;
let bytes = self.serial.build_bytes(bytes)?;
let bytes = self.refresh.build_bytes(bytes)?;
let bytes = self.retry.build_bytes(bytes)?;
let bytes = self.expire.build_bytes(bytes)?;
let bytes = self.minimum.build_bytes(bytes)?;
Ok(bytes)
}
fn cmp_canonical(&self, other: &Self) -> Ordering {
self.mname
.cmp_lowercase_composed(&other.mname)
.then_with(|| self.rname.cmp_lowercase_composed(&other.rname))
.then_with(|| self.serial.as_bytes().cmp(other.serial.as_bytes()))
.then_with(|| self.refresh.cmp(&other.refresh))
.then_with(|| self.retry.cmp(&other.retry))
.then_with(|| self.expire.cmp(&other.expire))
.then_with(|| self.minimum.cmp(&other.minimum))
}
}
impl<'a, N: SplitMessageBytes<'a>> ParseMessageBytes<'a> for Soa<N> {
fn parse_message_bytes(
contents: &'a [u8],
start: usize,
) -> Result<Self, ParseError> {
let (mname, rest) = N::split_message_bytes(contents, start)?;
let (rname, rest) = N::split_message_bytes(contents, rest)?;
let (&serial, rest) = <&Serial>::split_message_bytes(contents, rest)?;
let (&refresh, rest) = <&U32>::split_message_bytes(contents, rest)?;
let (&retry, rest) = <&U32>::split_message_bytes(contents, rest)?;
let (&expire, rest) = <&U32>::split_message_bytes(contents, rest)?;
let &minimum = <&U32>::parse_message_bytes(contents, rest)?;
Ok(Self {
mname,
rname,
serial,
refresh,
retry,
expire,
minimum,
})
}
}
impl<N: BuildInMessage> BuildInMessage for Soa<N> {
fn build_in_message(
&self,
contents: &mut [u8],
mut start: usize,
compressor: &mut NameCompressor,
) -> Result<usize, TruncationError> {
start = self.mname.build_in_message(contents, start, compressor)?;
start = self.rname.build_in_message(contents, start, compressor)?;
let end = start + 20;
let bytes = contents.get_mut(start..end).ok_or(TruncationError)?;
bytes[0..4].copy_from_slice(self.serial.as_bytes());
bytes[4..8].copy_from_slice(self.refresh.as_bytes());
bytes[8..12].copy_from_slice(self.retry.as_bytes());
bytes[12..16].copy_from_slice(self.expire.as_bytes());
bytes[16..20].copy_from_slice(self.minimum.as_bytes());
Ok(end)
}
}
impl<'a, N: SplitMessageBytes<'a>> ParseRecordData<'a> for Soa<N> {
fn parse_record_data(
contents: &'a [u8],
start: usize,
rtype: RType,
) -> Result<Self, ParseError> {
match rtype {
RType::SOA => Self::parse_message_bytes(contents, start),
_ => Err(ParseError),
}
}
}
impl<'a, N: SplitBytes<'a>> ParseRecordDataBytes<'a> for Soa<N> {
fn parse_record_data_bytes(
bytes: &'a [u8],
rtype: RType,
) -> Result<Self, ParseError> {
match rtype {
RType::SOA => Self::parse_bytes(bytes),
_ => Err(ParseError),
}
}
}