1use Error;
2
3#[derive(Debug, Clone)]
4pub struct Record<'a> {
5 bytes: &'a [u8],
6}
7
8#[derive(Debug)]
9pub struct RecordIter<'a> {
10 bytes: &'a [u8],
11}
12
13impl<'a> Iterator for RecordIter<'a> {
14 type Item = &'a [u8];
15 fn next(&mut self) -> Option<&'a [u8]> {
16 if self.bytes.len() >= 1 {
17 let len = self.bytes[0] as usize;
18 debug_assert!(self.bytes.len() >= len+1);
19 let (head, tail) = self.bytes[1..].split_at(len);
20 self.bytes = tail;
21 return Some(head);
22 }
23 return None;
24 }
25}
26
27impl<'a> Record<'a> {
28
29 pub fn iter(&self) -> RecordIter<'a> {
31 RecordIter {
32 bytes: self.bytes,
33 }
34 }
35}
36
37impl<'a> super::Record<'a> for Record<'a> {
38
39 const TYPE: isize = 16;
40
41 fn parse(rdata: &'a [u8], _original: &'a [u8]) -> super::RDataResult<'a> {
42 let len = rdata.len();
44 if len < 1 {
45 return Err(Error::WrongRdataLength);
46 }
47 let mut pos = 0;
48 while pos < len {
49 let rdlen = rdata[pos] as usize;
50 pos += 1;
51 if len < rdlen + pos {
52 return Err(Error::WrongRdataLength);
53 }
54 pos += rdlen;
55 }
56 Ok(super::RData::TXT(Record {
57 bytes: rdata,
58 }))
59 }
60}
61
62#[cfg(test)]
63mod test {
64
65 use std::str::from_utf8;
66
67 use {Packet, Header};
68 use Opcode::*;
69 use ResponseCode::NoError;
70 use QueryType as QT;
71 use QueryClass as QC;
72 use Class as C;
73 use RData;
74
75 #[test]
76 fn parse_response_multiple_strings() {
77 let response = b"\x06%\x81\x80\x00\x01\x00\x01\x00\x00\x00\x00\
78 \x08facebook\x03com\x00\x00\x10\x00\x01\
79 \xc0\x0c\x00\x10\x00\x01\x00\x01\x51\x3d\x00\x23\
80 \x15\x76\x3d\x73\x70\x66\x31\x20\x72\x65\x64\x69\
81 \x72\x65\x63\x74\x3d\x5f\x73\x70\x66\x2e\
82 \x0c\x66\x61\x63\x65\x62\x6f\x6f\x6b\x2e\x63\x6f\x6d";
83
84 let packet = Packet::parse(response).unwrap();
85 assert_eq!(packet.header, Header {
86 id: 1573,
87 query: false,
88 opcode: StandardQuery,
89 authoritative: false,
90 truncated: false,
91 recursion_desired: true,
92 recursion_available: true,
93 authenticated_data: false,
94 checking_disabled: false,
95 response_code: NoError,
96 questions: 1,
97 answers: 1,
98 nameservers: 0,
99 additional: 0,
100 });
101 assert_eq!(packet.questions.len(), 1);
102 assert_eq!(packet.questions[0].qtype, QT::TXT);
103 assert_eq!(packet.questions[0].qclass, QC::IN);
104 assert_eq!(&packet.questions[0].qname.to_string()[..], "facebook.com");
105 assert_eq!(packet.answers.len(), 1);
106 assert_eq!(&packet.answers[0].name.to_string()[..], "facebook.com");
107 assert_eq!(packet.answers[0].multicast_unique, false);
108 assert_eq!(packet.answers[0].cls, C::IN);
109 assert_eq!(packet.answers[0].ttl, 86333);
110 match packet.answers[0].data {
111 RData::TXT(ref text) => {
112 assert_eq!(text.iter()
113 .map(|x| from_utf8(x).unwrap())
114 .collect::<Vec<_>>()
115 .concat(), "v=spf1 redirect=_spf.facebook.com");
116
117 assert_eq!(text.iter().collect::<Vec<_>>(),
119 ["v=spf1 redirect=_spf.".as_bytes(),
120 "facebook.com".as_bytes()]);
121 }
122 ref x => panic!("Wrong rdata {:?}", x),
123 }
124 }
125}