mdns_proto/wire/
reader.rs1use super::{HEADER_SIZE, Header, QuestionRef, Ref};
4use crate::error::ParseError;
5
6#[derive(Debug, Copy, Clone)]
9pub struct MessageReader<'a> {
10 message: &'a [u8],
11 header: Header,
12}
13
14impl<'a> MessageReader<'a> {
15 pub fn try_parse(message: &'a [u8]) -> Result<Self, ParseError> {
18 let (header, _rest) = Header::try_parse(message)?;
19 Ok(Self { message, header })
20 }
21
22 #[inline(always)]
24 pub const fn header(&self) -> &Header {
25 &self.header
26 }
27
28 pub fn questions(&self) -> Questions<'a> {
30 Questions {
31 message: self.message,
32 cursor: HEADER_SIZE,
33 remaining: self.header.question_count(),
34 }
35 }
36
37 pub fn answers(&self) -> Records<'a> {
39 Records::new_after_questions(self.message, &self.header, self.header.answer_count())
40 }
41
42 pub fn authority(&self) -> Records<'a> {
45 Records::new_after_answers(self.message, &self.header, self.header.authority_count())
46 }
47
48 pub fn additional(&self) -> Records<'a> {
53 Records::new_after_authority(self.message, &self.header, self.header.additional_count())
54 }
55}
56
57pub struct Questions<'a> {
59 message: &'a [u8],
60 cursor: usize,
61 remaining: u16,
62}
63
64impl<'a> Iterator for Questions<'a> {
65 type Item = Result<QuestionRef<'a>, ParseError>;
66
67 fn next(&mut self) -> Option<Self::Item> {
68 if self.remaining == 0 {
69 return None;
70 }
71 match QuestionRef::try_parse(self.message, self.cursor) {
72 Ok((q, next)) => {
73 self.cursor = next;
74 self.remaining = self.remaining.saturating_sub(1);
75 Some(Ok(q))
76 }
77 Err(e) => {
78 self.remaining = 0;
79 Some(Err(e))
80 }
81 }
82 }
83}
84
85pub struct Records<'a> {
87 message: &'a [u8],
88 cursor: usize,
89 remaining: u16,
90}
91
92fn skip_questions(message: &[u8], header: &Header) -> Option<usize> {
96 let mut cursor = HEADER_SIZE;
97 let mut remaining = header.question_count();
98 while remaining > 0 {
99 let (_, next) = QuestionRef::try_parse(message, cursor).ok()?;
100 cursor = next;
101 remaining = remaining.saturating_sub(1);
102 }
103 Some(cursor)
104}
105
106fn skip_records(message: &[u8], mut cursor: usize, mut count: u16) -> Option<usize> {
109 while count > 0 {
110 let (_, next) = Ref::try_parse(message, cursor).ok()?;
111 cursor = next;
112 count = count.saturating_sub(1);
113 }
114 Some(cursor)
115}
116
117impl<'a> Records<'a> {
118 fn new_after_questions(message: &'a [u8], header: &Header, count: u16) -> Self {
121 Self::at_or_empty(message, count, skip_questions(message, header))
122 }
123
124 fn new_after_answers(message: &'a [u8], header: &Header, count: u16) -> Self {
127 let cursor =
128 skip_questions(message, header).and_then(|c| skip_records(message, c, header.answer_count()));
129 Self::at_or_empty(message, count, cursor)
130 }
131
132 fn new_after_authority(message: &'a [u8], header: &Header, count: u16) -> Self {
135 let cursor = skip_questions(message, header)
136 .and_then(|c| skip_records(message, c, header.answer_count()))
137 .and_then(|c| skip_records(message, c, header.authority_count()));
138 Self::at_or_empty(message, count, cursor)
139 }
140
141 fn at_or_empty(message: &'a [u8], count: u16, cursor: Option<usize>) -> Self {
146 match cursor {
147 Some(cursor) => Self {
148 message,
149 cursor,
150 remaining: count,
151 },
152 None => Self {
153 message,
154 cursor: HEADER_SIZE,
155 remaining: 0,
156 },
157 }
158 }
159}
160
161impl<'a> Iterator for Records<'a> {
162 type Item = Result<Ref<'a>, ParseError>;
163
164 fn next(&mut self) -> Option<Self::Item> {
165 if self.remaining == 0 {
166 return None;
167 }
168 match Ref::try_parse(self.message, self.cursor) {
169 Ok((r, next)) => {
170 self.cursor = next;
171 self.remaining = self.remaining.saturating_sub(1);
172 Some(Ok(r))
173 }
174 Err(e) => {
175 self.remaining = 0;
176 Some(Err(e))
177 }
178 }
179 }
180}
181
182#[cfg(all(test, any(feature = "alloc", feature = "std")))]
183#[allow(warnings)]
184mod tests;