1use core::fmt;
4
5use super::{ComposeRdata, ParseRdata, ParseRdataText};
6use crate::name::Name;
7use crate::wire::{Composer, NameEncoding, OutBuf, WireReader};
8use crate::zone::Scanner;
9use crate::{Result, Rtype};
10
11#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash)]
13pub struct Mx<'a> {
14 pub preference: u16,
16 pub exchange: Name<'a>,
18}
19
20impl<'a> ParseRdata<'a> for Mx<'a> {
21 const RTYPE: Rtype = Rtype::MX;
22
23 fn parse_rdata(rdata: &mut WireReader<'a>) -> Result<Self> {
24 Ok(Mx {
25 preference: rdata.read_u16()?,
26 exchange: rdata.read_name()?,
27 })
28 }
29}
30
31impl ComposeRdata for Mx<'_> {
32 fn rtype(&self) -> Rtype {
33 Rtype::MX
34 }
35
36 fn compose_rdata<C: Composer + ?Sized>(&self, c: &mut C) -> Result<()> {
37 c.put_u16(self.preference)?;
38 c.put_name(self.exchange, NameEncoding::Compressible)
39 }
40}
41
42impl fmt::Display for Mx<'_> {
43 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
44 write!(f, "{} {}", self.preference, self.exchange)
45 }
46}
47
48impl ParseRdataText for Mx<'_> {
49 fn parse_text<B: OutBuf + ?Sized>(s: &mut Scanner<'_>, out: &mut B) -> Result<()> {
51 out.put_u16(s.u16()?)?;
52 s.name_into(out, NameEncoding::Compressible)
53 }
54}
55
56#[cfg(test)]
57mod tests {
58 use crate::rdata::tests::{text_error, text_round_trip};
59 use crate::{Error, Rtype};
60
61 #[test]
62 fn text() {
63 text_round_trip(
65 Rtype::MX,
66 "10 VENERA",
67 b"\x00\x0a\x06VENERA\x07example\x00",
68 "10 VENERA.example.",
69 );
70 text_round_trip(Rtype::MX, "0 .", b"\x00\x00\x00", "0 .");
71 text_round_trip(
72 Rtype::MX,
73 "( 65535\n mx.example.net. ) ; comment",
74 b"\xff\xff\x02mx\x07example\x03net\x00",
75 "65535 mx.example.net.",
76 );
77 assert_eq!(text_error(Rtype::MX, "65536 a."), Error::InvalidText);
78 assert_eq!(text_error(Rtype::MX, "-1 a."), Error::InvalidText);
79 assert_eq!(text_error(Rtype::MX, "10"), Error::UnexpectedEof);
80 assert_eq!(text_error(Rtype::MX, "10 a. b."), Error::InvalidText);
81 assert_eq!(text_error(Rtype::MX, "10 a..b"), Error::EmptyLabel);
82 assert_eq!(text_error(Rtype::MX, "x a."), Error::InvalidText);
83 }
84}