mdns_proto/wire/
question.rs1use super::{NameRef, ResourceClass, ResourceType, resource_class::UNICAST_RESPONSE_BIT};
4use crate::error::{BufferTooShortDetail, ParseError};
5
6#[derive(Debug, Copy, Clone, Eq, PartialEq, Hash)]
8pub struct QuestionRef<'a> {
9 qname: NameRef<'a>,
10 qtype: ResourceType,
11 qclass: ResourceClass,
12 unicast_response: bool,
13}
14
15impl<'a> QuestionRef<'a> {
16 pub fn try_parse(message: &'a [u8], offset: usize) -> Result<(Self, usize), ParseError> {
19 let (qname, name_bytes) = NameRef::try_parse(message, offset)?;
20 let after_name = offset.saturating_add(name_bytes);
21
22 let qtype_slot = message
23 .get(after_name..after_name.saturating_add(2))
24 .and_then(|s| s.first_chunk::<2>())
25 .ok_or_else(|| {
26 ParseError::BufferTooShort(BufferTooShortDetail::new(
27 2,
28 after_name,
29 message.len().saturating_sub(after_name),
30 ))
31 })?;
32 let qtype = ResourceType::from_u16(u16::from_be_bytes(*qtype_slot));
33
34 let after_type = after_name.saturating_add(2);
35 let qclass_slot = message
36 .get(after_type..after_type.saturating_add(2))
37 .and_then(|s| s.first_chunk::<2>())
38 .ok_or_else(|| {
39 ParseError::BufferTooShort(BufferTooShortDetail::new(
40 2,
41 after_type,
42 message.len().saturating_sub(after_type),
43 ))
44 })?;
45 let raw = u16::from_be_bytes(*qclass_slot);
46 let unicast_response = (raw & UNICAST_RESPONSE_BIT) != 0;
47 let qclass = ResourceClass::from_u16(raw);
48
49 let after_class = after_type.saturating_add(2);
50 Ok((
51 Self {
52 qname,
53 qtype,
54 qclass,
55 unicast_response,
56 },
57 after_class,
58 ))
59 }
60
61 #[inline(always)]
63 pub const fn qname(&self) -> &NameRef<'a> {
64 &self.qname
65 }
66
67 #[inline(always)]
69 pub const fn qtype(&self) -> ResourceType {
70 self.qtype
71 }
72
73 #[inline(always)]
75 pub const fn qclass(&self) -> ResourceClass {
76 self.qclass
77 }
78
79 #[inline(always)]
82 pub const fn unicast_response_requested(&self) -> bool {
83 self.unicast_response
84 }
85}
86
87#[cfg(test)]
88#[cfg(any(feature = "alloc", feature = "std"))]
89#[allow(clippy::unwrap_used)]
90mod tests;