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::*;
use crate::new::base::{
CanonicalRecordData, ParseRecordData, ParseRecordDataBytes, RType,
};
#[derive(
Copy,
Clone,
Debug,
PartialEq,
Eq,
PartialOrd,
Ord,
Hash,
AsBytes,
BuildBytes,
ParseBytes,
SplitBytes,
)]
#[repr(C)]
pub struct Mx<N> {
pub preference: U16,
pub exchange: N,
}
impl<N> Mx<N> {
pub fn map_name<R, F: FnOnce(N) -> R>(self, f: F) -> Mx<R> {
Mx {
preference: self.preference,
exchange: (f)(self.exchange),
}
}
pub fn map_name_by_ref<'r, R, F: FnOnce(&'r N) -> R>(
&'r self,
f: F,
) -> Mx<R> {
Mx {
preference: self.preference,
exchange: (f)(&self.exchange),
}
}
}
impl<N: CanonicalName> CanonicalRecordData for Mx<N> {
fn build_canonical_bytes<'b>(
&self,
bytes: &'b mut [u8],
) -> Result<&'b mut [u8], TruncationError> {
let bytes = self.preference.build_bytes(bytes)?;
let bytes = self.exchange.build_lowercased_bytes(bytes)?;
Ok(bytes)
}
fn cmp_canonical(&self, other: &Self) -> Ordering {
self.preference.cmp(&other.preference).then_with(|| {
self.exchange.cmp_lowercase_composed(&other.exchange)
})
}
}
impl<'a, N: ParseMessageBytes<'a>> ParseMessageBytes<'a> for Mx<N> {
fn parse_message_bytes(
contents: &'a [u8],
start: usize,
) -> Result<Self, ParseError> {
let (&preference, rest) =
<&U16>::split_message_bytes(contents, start)?;
let exchange = N::parse_message_bytes(contents, rest)?;
Ok(Self {
preference,
exchange,
})
}
}
impl<N: BuildInMessage> BuildInMessage for Mx<N> {
fn build_in_message(
&self,
contents: &mut [u8],
mut start: usize,
compressor: &mut NameCompressor,
) -> Result<usize, TruncationError> {
start = self
.preference
.as_bytes()
.build_in_message(contents, start, compressor)?;
start = self
.exchange
.build_in_message(contents, start, compressor)?;
Ok(start)
}
}
impl<'a, N: ParseMessageBytes<'a>> ParseRecordData<'a> for Mx<N> {
fn parse_record_data(
contents: &'a [u8],
start: usize,
rtype: RType,
) -> Result<Self, ParseError> {
match rtype {
RType::MX => Self::parse_message_bytes(contents, start),
_ => Err(ParseError),
}
}
}
impl<'a, N: ParseBytes<'a>> ParseRecordDataBytes<'a> for Mx<N> {
fn parse_record_data_bytes(
bytes: &'a [u8],
rtype: RType,
) -> Result<Self, ParseError> {
match rtype {
RType::MX => Self::parse_bytes(bytes),
_ => Err(ParseError),
}
}
}