domain_core/bits/header.rs
1//! The header of a DNS message.
2//!
3//! Each DNS message starts with a twelve octet long header section
4//! containing some general information related to the message as well as
5//! the number of records in each of the four sections that follow the header.
6//! Its content and format are defined in section 4.1.1 of [RFC 1035].
7//!
8//! In order to reflect the fact that changing the section counts may
9//! invalidate the rest of the message whereas the other elements of the
10//! header section can safely be modified, the whole header has been split
11//! into two separate types: [`Header`] contains the safely modifyable part
12//! at the beginning and [`HeaderCounts`] contains the section counts. In
13//! addition, the [`HeaderSection`] type wraps both of them into a single
14//! type.
15//!
16//! [`Header`]: struct.Header.html
17//! [`HeaderCounts`]: struct.HeaderCounts.html
18//! [`HeaderSection`]: struct.HeaderSection.html
19//! [RFC 1035]: https://tools.ietf.org/html/rfc1035
20
21use std::mem;
22use bytes::{BigEndian, BufMut, ByteOrder};
23use ::iana::{Opcode, Rcode};
24use super::compose::Compose;
25use super::parse::{Parse, Parser, ShortBuf};
26
27
28//------------ Header --------------------------------------------------
29
30/// The first part of the header of a DNS message.
31///
32/// This type represents the information contained in the first four bytes of
33/// the header: the message ID, opcode, rcode, and the various flags.
34///
35/// The type’s data contains such a header in its wire format which is layed
36/// out like this:
37///
38/// ```text
39/// 1 1 1 1 1 1
40/// 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5
41/// +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
42/// | ID |
43/// +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
44/// |QR| Opcode |AA|TC|RD|RA|Z |AD|CD| RCODE |
45/// +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
46/// ```
47///
48/// Methods are available for accessing each of these fields.
49/// See [Field Access] below.
50///
51/// The basic structure and most of the fields re defined in [RFC 1035],
52/// except for the AD and CD flags, which are defined in [RFC 4035].
53///
54/// [Field Access]: #field-access
55/// [RFC 1035]: https://tools.ietf.org/html/rfc1035
56/// [RFC 4035]: https://tools.ietf.org/html/rfc4035
57#[derive(Clone, Copy, Debug, Default, Eq, PartialEq)]
58pub struct Header {
59 /// The actual header in its wire format representation.
60 ///
61 /// This means that the ID field is in big endian.
62 inner: [u8; 4]
63}
64
65/// # Creation and Conversion
66///
67impl Header {
68 /// Creates a new header.
69 ///
70 /// The new header has all fields as either zero or false. Thus, the
71 /// opcode will be `Opcode::Query` and the response code will be
72 /// `Rcode::NoError`.
73 pub fn new() -> Self {
74 Self::default()
75 }
76
77 /// Creates a header reference from a byte slice of a message.
78 ///
79 /// # Panics
80 ///
81 /// This function panics if the byte slice is too short.
82 pub fn for_message_slice(s: &[u8]) -> &Header {
83 assert!(s.len() >= mem::size_of::<Header>());
84 unsafe { &*(s.as_ptr() as *const Header) }
85 }
86
87 /// Creates a mutable header reference from a byte slice of a message.
88 ///
89 /// # Panics
90 ///
91 /// This function panics if the byte slice is too short.
92 pub fn for_message_slice_mut(s: &mut [u8]) -> &mut Header {
93 assert!(s.len() >= mem::size_of::<Header>());
94 unsafe { &mut *(s.as_ptr() as *mut Header) }
95 }
96
97 /// Returns a reference to the underlying bytes slice.
98 pub fn as_slice(&self) -> &[u8] {
99 &self.inner
100 }
101}
102
103
104/// # Field Access
105///
106impl Header {
107 /// Returns the value of the ID field.
108 ///
109 /// The ID field is an identifier chosen by whoever created a query
110 /// and is copied into a response by a server. It allows matching
111 /// incoming responses to their queries.
112 pub fn id(self) -> u16 {
113 BigEndian::read_u16(&self.inner)
114 }
115
116 /// Sets the value of the ID field.
117 pub fn set_id(&mut self, value: u16) {
118 BigEndian::write_u16(&mut self.inner, value)
119 }
120
121 /// Sets the value of the ID field to a randomly chosen number.
122 ///
123 /// This uses [`rand::random`] which may not be good enough.
124 pub fn set_random_id(&mut self) { self.set_id(::rand::random()) }
125
126 /// Returns whether the QR bit is set.
127 ///
128 /// The QR bit specifies whether this message is a query (`false`) or
129 /// a response (`true`). In other words, this bit is actually stating
130 /// whether the message is *not* a query. So, perhaps it might be good
131 /// to read ‘QR’ as ‘query response.’
132 pub fn qr(self) -> bool { self.get_bit(2, 7) }
133
134 /// Sets the value of the QR bit.
135 ///
136 pub fn set_qr(&mut self, set: bool) { self.set_bit(2, 7, set) }
137
138 /// Returns the value of the Opcode field.
139 ///
140 /// This field specifies the kind of query this message contains. See
141 /// the [`Opcode`] type for more information on the possible values and
142 /// their meaning. Normal queries have the variant [`Opcode::Query`]
143 /// which is also the value set when creating a new header.
144 ///
145 /// [`Opcode`]: ../../iana/opcode/enum.Opcode.html
146 /// [`Opcode::Query`]: ../../iana/opcode/enum.Opcode.html#variant.Query
147 pub fn opcode(self) -> Opcode {
148 Opcode::from_int((self.inner[2] >> 3) & 0x0F)
149 }
150
151 /// Sets the value of the opcode field.
152 pub fn set_opcode(&mut self, opcode: Opcode) {
153 self.inner[2] = self.inner[2] & 0x87 | (opcode.to_int() << 3);
154 }
155
156 /// Returns whether the AA bit is set.
157 ///
158 /// Using this bit, a name server generating a response states whether
159 /// it is authoritative for the requested domain name, ie., whether this
160 /// response is an *authoritative answer.* The field has no meaning in
161 /// a query.
162 pub fn aa(self) -> bool { self.get_bit(2, 2) }
163
164 /// Sets the value of the AA bit.
165 pub fn set_aa(&mut self, set: bool) { self.set_bit(2, 2, set) }
166
167 /// Returns whether the TC bit is set.
168 ///
169 /// The *truncation* bit is set if there was more data available then
170 /// fit into the message. This is typically used when employing
171 /// datagram transports such as UDP to signal to try again using a
172 /// stream transport such as TCP.
173 pub fn tc(self) -> bool { self.get_bit(2, 1) }
174
175 /// Sets the value of the TC bit.
176 pub fn set_tc(&mut self, set: bool) { self.set_bit(2, 1, set) }
177
178 /// Returns whether the RD bit is set.
179 ///
180 /// The *recursion desired* bit may be set in a query to ask the name
181 /// server to try and recursively gather a response if it doesn’t have
182 /// the data available locally. The bit’s value is copied into the
183 /// response.
184 pub fn rd(self) -> bool { self.get_bit(2, 0) }
185
186 /// Sets the value of the RD bit.
187 pub fn set_rd(&mut self, set: bool) { self.set_bit(2, 0, set) }
188
189 /// Returns whether the RA bit is set.
190 ///
191 /// In a response, the *recursion available* bit denotes whether the
192 /// responding name server supports recursion. It has no meaning in
193 /// a query.
194 pub fn ra(self) -> bool { self.get_bit(3, 7) }
195
196 /// Sets the value of the RA bit.
197 pub fn set_ra(&mut self, set: bool) { self.set_bit(3, 7, set) }
198
199 /// Returns whether the reserved bit is set.
200 ///
201 /// This bit must be `false` in all queries and responses.
202 pub fn z(self) -> bool { self.get_bit(3, 6) }
203
204 /// Sets the value of the reserved bit.
205 pub fn set_z(&mut self, set: bool) { self.set_bit(3, 6, set) }
206
207 /// Returns whether the AD bit is set.
208 ///
209 /// The *authentic data* bit is used by security-aware recursive name
210 /// servers to indicate that it considers all RRsets in its response to
211 /// be authentic.
212 pub fn ad(self) -> bool { self.get_bit(3, 5) }
213
214 /// Sets the value of the AD bit.
215 pub fn set_ad(&mut self, set: bool) { self.set_bit(3, 5, set) }
216
217 /// Returns whether the CD bit is set.
218 ///
219 /// The *checking disabled* bit is used by a security-aware resolver
220 /// to indicate that it does not want upstream name servers to perform
221 /// verification but rather would like to verify everything itself.
222 pub fn cd(self) -> bool { self.get_bit(3, 4) }
223
224 /// Sets the value of the CD bit.
225 pub fn set_cd(&mut self, set: bool) { self.set_bit(3, 4, set) }
226
227 /// Returns the value of the RCODE field.
228 ///
229 /// The *response code* is used in a response to indicate what happened
230 /// when processing the query. See the [`Rcode`] type for information on
231 /// possible values and their meaning.
232 ///
233 /// [`Rcode`]: ../../iana/rcode/enum.Rcode.html
234 pub fn rcode(self) -> Rcode {
235 Rcode::from_int(self.inner[3] & 0x0F)
236 }
237
238 /// Sets the value of the RCODE field.
239 pub fn set_rcode(&mut self, rcode: Rcode) {
240 self.inner[3] = self.inner[3] & 0xF0 | (rcode.to_int() & 0x0F);
241 }
242
243
244 //--- Internal helpers
245
246 /// Returns the value of the bit at the given position.
247 ///
248 /// The argument `offset` gives the byte offset of the underlying bytes
249 /// slice and `bit` gives the number of the bit with the most significant
250 /// bit being 7.
251 fn get_bit(self, offset: usize, bit: usize) -> bool {
252 self.inner[offset] & (1 << bit) != 0
253 }
254
255 /// Sets or resets the given bit.
256 fn set_bit(&mut self, offset: usize, bit: usize, set: bool) {
257 if set { self.inner[offset] |= 1 << bit }
258 else { self.inner[offset] &= !(1 << bit) }
259 }
260}
261
262
263//------------ HeaderCounts -------------------------------------------------
264
265/// The section count part of the header section of a DNS message.
266///
267/// This part consists of four 16 bit counters for the number of entries in
268/// the four sections of a DNS message.
269///
270/// The counters are arranged in the same order as the sections themselves:
271/// QDCOUNT for the question section, ANCOUNT for the answer section,
272/// NSCOUNT for the authority section, and ARCOUNT for the additional section.
273/// These are defined in [RFC 1035].
274///
275/// [RFC 2136] defines the UPDATE method and reuses the four section for
276/// different purposes. Here the counters are ZOCOUNT for the zone section,
277/// PRCOUNT for the prerequisite section, UPCOUNT for the update section,
278/// and ADCOUNT for the additional section. The type has convenience methods
279/// for these fields as well so you don’t have to remember which is which.
280///
281/// For each field there are three methods for getting, setting, and
282/// incrementing.
283///
284/// [RFC 1035]: https://tools.ietf.org/html/rfc1035
285/// [RFC 2136]: https://tools.ietf.org/html/rfc2136
286#[derive(Clone, Copy, Debug, Default, Eq, PartialEq)]
287pub struct HeaderCounts {
288 /// The actual headers in their wire-format representation.
289 ///
290 /// Ie., all values are stored big endian.
291 inner: [u8; 8]
292}
293
294/// # Creation and Conversion
295///
296impl HeaderCounts {
297 /// Creates a new value with all counters set to zero.
298 pub fn new() -> Self {
299 Self::default()
300 }
301
302 /// Creates a header reference from a byte slice of a message.
303 ///
304 /// The slice `message` mut be the whole message, i.e., start with the
305 /// bytes of the [`Header`](struct.Header.html).
306 ///
307 /// # Panics
308 ///
309 /// This function panics if the bytes slice is too short.
310 pub fn for_message_slice(message: &[u8]) -> &Self {
311 assert!(message.len() >= mem::size_of::<HeaderSection>());
312 unsafe {
313 &*((message[mem::size_of::<Header>()..].as_ptr())
314 as *const HeaderCounts)
315 }
316 }
317
318 /// Creates a mutable header reference from a bytes slice of a message.
319 ///
320 /// The slice `message` mut be the whole message, i.e., start with the
321 /// bytes of the [`Header`](struct.Header.html).
322 ///
323 /// # Panics
324 ///
325 /// This function panics if the bytes slice is too short.
326 pub fn for_message_slice_mut(message: &mut [u8]) -> &mut Self {
327 assert!(message.len() >= mem::size_of::<HeaderSection>());
328 unsafe {
329 &mut *((message[mem::size_of::<Header>()..].as_ptr())
330 as *mut HeaderCounts)
331 }
332 }
333
334 /// Returns a reference to the raw byte slice of the header counts.
335 pub fn as_slice(&self) -> &[u8] {
336 &self.inner
337 }
338
339 /// Returns a mutable reference to the raw byte slice of the header counts.
340 pub fn as_slice_mut(&mut self) -> &mut [u8] {
341 &mut self.inner
342 }
343
344 /// Sets the counts to those from `counts`.
345 pub fn set(&mut self, counts: HeaderCounts) {
346 self.as_slice_mut().copy_from_slice(counts.as_slice())
347 }
348}
349
350
351/// # Field Access
352///
353impl HeaderCounts {
354 //--- Count fields in regular messages
355
356 /// Returns the value of the QDCOUNT field.
357 ///
358 /// This field contains the number of questions in the first
359 /// section of the message, normally the question section.
360 pub fn qdcount(self) -> u16 {
361 self.get_u16(0)
362 }
363
364 /// Sets the value of the QDCOUNT field.
365 pub fn set_qdcount(&mut self, value: u16) {
366 self.set_u16(0, value)
367 }
368
369 /// Increases the value of the QDCOUNT field by one.
370 ///
371 /// # Panics
372 ///
373 /// This method panics if the count is already at its maximum.
374 pub fn inc_qdcount(&mut self) {
375 let count = self.qdcount();
376 assert!(count < ::std::u16::MAX);
377 self.set_qdcount(count + 1);
378 }
379
380 /// Returns the value of the ANCOUNT field.
381 ///
382 /// This field contains the number of resource records in the second
383 /// section of the message, normally the answer section.
384 pub fn ancount(self) -> u16 {
385 self.get_u16(2)
386 }
387
388 /// Sets the value of the ANCOUNT field.
389 pub fn set_ancount(&mut self, value: u16) {
390 self.set_u16(2, value)
391 }
392
393 /// Increases the value of the ANCOUNT field by one.
394 ///
395 /// # Panics
396 ///
397 /// This method panics if the count is already at its maximum.
398 pub fn inc_ancount(&mut self) {
399 let count = self.ancount();
400 assert!(count < ::std::u16::MAX);
401 self.set_ancount(count + 1);
402 }
403
404 /// Returns the value of the NSCOUNT field.
405 ///
406 /// This field contains the number of resource records in the third
407 /// section of the message, normally the authority section.
408 pub fn nscount(self) -> u16 {
409 self.get_u16(4)
410 }
411
412 /// Sets the value of the NSCOUNT field.
413 pub fn set_nscount(&mut self, value: u16) {
414 self.set_u16(4, value)
415 }
416
417 /// Increases the value of the NSCOUNT field by one.
418 ///
419 /// # Panics
420 ///
421 /// This method panics if the count is already at its maximum.
422 pub fn inc_nscount(&mut self) {
423 let count = self.nscount();
424 assert!(count < ::std::u16::MAX);
425 self.set_nscount(count + 1);
426 }
427
428 /// Returns the value of the ARCOUNT field.
429 ///
430 /// This field contains the number of resource records in the fourth
431 /// section of the message, normally the additional section.
432 pub fn arcount(self) -> u16 {
433 self.get_u16(6)
434 }
435
436 /// Sets the value of the ARCOUNT field.
437 pub fn set_arcount(&mut self, value: u16) {
438 self.set_u16(6, value)
439 }
440
441 /// Increases the value of the ARCOUNT field by one.
442 ///
443 /// # Panics
444 ///
445 /// This method panics if the count is already at its maximum.
446 pub fn inc_arcount(&mut self) {
447 let count = self.arcount();
448 assert!(count < ::std::u16::MAX);
449 self.set_arcount(count + 1);
450 }
451
452
453 //--- Count fields in UPDATE messages
454
455 /// Returns the value of the ZOCOUNT field.
456 ///
457 /// This is the same as the `qdcount()`. It is used in UPDATE queries
458 /// where the first section is the zone section.
459 pub fn zocount(self) -> u16 {
460 self.qdcount()
461 }
462
463 /// Sets the value of the ZOCOUNT field.
464 pub fn set_zocount(&mut self, value: u16) {
465 self.set_qdcount(value)
466 }
467
468 /// Returns the value of the PRCOUNT field.
469 ///
470 /// This is the same as the `ancount()`. It is used in UPDATE queries
471 /// where the first section is the prerequisite section.
472 pub fn prcount(self) -> u16 {
473 self.ancount()
474 }
475
476 /// Sete the value of the PRCOUNT field.
477 pub fn set_prcount(&mut self, value: u16) {
478 self.set_ancount(value)
479 }
480
481 /// Returns the value of the UPCOUNT field.
482 ///
483 /// This is the same as the `nscount()`. It is used in UPDATE queries
484 /// where the first section is the update section.
485 pub fn upcount(self) -> u16 {
486 self.nscount()
487 }
488
489 /// Sets the value of the UPCOUNT field.
490 pub fn set_upcount(&mut self, value: u16) {
491 self.set_nscount(value)
492 }
493
494 /// Returns the value of the ADCOUNT field.
495 ///
496 /// This is the same as the `arcount()`. It is used in UPDATE queries
497 /// where the first section is the additional section.
498 pub fn adcount(self) -> u16 {
499 self.arcount()
500 }
501
502 /// Sets the value of the ADCOUNT field.
503 pub fn set_adcount(&mut self, value: u16) {
504 self.set_arcount(value)
505 }
506
507
508 //--- Internal helpers
509
510 /// Returns the value of the 16 bit integer starting at a given offset.
511 fn get_u16(self, offset: usize) -> u16 {
512 BigEndian::read_u16(&self.inner[offset..])
513 }
514
515 /// Sets the value of the 16 bit integer starting at a given offset.
516 fn set_u16(&mut self, offset: usize, value: u16) {
517 BigEndian::write_u16(&mut self.inner[offset..], value)
518 }
519}
520
521
522//------------ HeaderSection -------------------------------------------------
523
524/// The complete header section of a DNS message.
525///
526/// Consists of a `Header` and a `HeaderCounts`.
527#[derive(Clone, Copy, Debug, Default, Eq, PartialEq)]
528pub struct HeaderSection {
529 inner: [u8; 12]
530}
531
532/// # Creation and Conversion
533///
534impl HeaderSection {
535 /// Creates a new empty header section.
536 pub fn new() -> Self {
537 Self::default()
538 }
539
540 /// Creates a reference from the bytes slice of a message.
541 ///
542 /// # Panics
543 ///
544 /// This function panics if the size of the bytes slice is smaller than
545 /// the header section.
546 pub fn for_message_slice(s: &[u8]) -> &HeaderSection {
547 assert!(s.len() >= mem::size_of::<HeaderSection>());
548 unsafe { &*(s.as_ptr() as *const HeaderSection) }
549 }
550
551 /// Creates a mutable reference from the bytes slice of a message.
552 ///
553 /// # Panics
554 ///
555 /// This function panics if the size of the bytes slice is smaller than
556 /// the header section.
557 pub fn for_message_slice_mut(s: &mut [u8]) -> &mut HeaderSection {
558 assert!(s.len() >= mem::size_of::<HeaderSection>());
559 unsafe { &mut *(s.as_ptr() as *mut HeaderSection) }
560 }
561
562 /// Returns a reference to the underlying bytes slice.
563 pub fn as_slice(&self) -> &[u8] {
564 &self.inner
565 }
566}
567
568
569/// # Access to Header and Counts
570///
571impl HeaderSection {
572 /// Returns a reference to the header.
573 pub fn header(&self) -> &Header {
574 Header::for_message_slice(&self.inner)
575 }
576
577 /// Returns a mutable reference to the header.
578 pub fn header_mut(&mut self) -> &mut Header {
579 Header::for_message_slice_mut(&mut self. inner)
580 }
581
582 /// Returns a reference to the header counts.
583 pub fn counts(&self) -> &HeaderCounts {
584 HeaderCounts::for_message_slice(&self.inner)
585 }
586
587 /// Returns a mutable reference to the header counts.
588 pub fn counts_mut(&mut self) -> &mut HeaderCounts {
589 HeaderCounts::for_message_slice_mut(&mut self.inner)
590 }
591}
592
593
594//--- Parse and Compose
595
596impl Parse for HeaderSection {
597 type Err = ShortBuf;
598
599 fn parse(parser: &mut Parser) -> Result<Self, Self::Err> {
600 let mut res = Self::default();
601 parser.parse_buf(&mut res.inner)?;
602 Ok(res)
603 }
604
605 fn skip(parser: &mut Parser) -> Result<(), Self::Err> {
606 parser.advance(12)
607 }
608}
609
610impl Compose for HeaderSection {
611 fn compose_len(&self) -> usize {
612 12
613 }
614
615 fn compose<B: BufMut>(&self, buf: &mut B) {
616 buf.put_slice(&self.inner)
617 }
618}
619
620
621//============ Testing ======================================================
622
623#[cfg(test)]
624mod test {
625 use super::*;
626 use iana::{Opcode, Rcode};
627
628 #[test]
629 fn for_slice() {
630 let header = b"\x01\x02\x00\x00\x12\x34\x56\x78\x9a\xbc\xde\xf0";
631 let mut vec = Vec::from(&header[..]);
632 assert_eq!(Header::for_message_slice(header).as_slice(),
633 b"\x01\x02\x00\x00");
634 assert_eq!(Header::for_message_slice_mut(vec.as_mut()).as_slice(),
635 b"\x01\x02\x00\x00");
636 assert_eq!(HeaderCounts::for_message_slice(header).as_slice(),
637 b"\x12\x34\x56\x78\x9a\xbc\xde\xf0");
638 assert_eq!(HeaderCounts::for_message_slice_mut(vec.as_mut()).as_slice(),
639 b"\x12\x34\x56\x78\x9a\xbc\xde\xf0");
640 assert_eq!(HeaderSection::for_message_slice(header).as_slice(),
641 header);
642 assert_eq!(HeaderSection::for_message_slice_mut(vec.as_mut())
643 .as_slice(),
644 header);
645 }
646
647 #[test]
648 #[should_panic]
649 fn short_header() {
650 Header::for_message_slice(b"134");
651 }
652
653 #[test]
654 #[should_panic]
655 fn short_header_counts() {
656 HeaderCounts::for_message_slice(b"12345678");
657 }
658
659 #[test]
660 #[should_panic]
661 fn short_header_section() {
662 HeaderSection::for_message_slice(b"1234");
663 }
664
665 macro_rules! test_field {
666 ($get:ident, $set:ident, $default:expr, $($value:expr),*) => {
667 $({
668 let mut h = Header::new();
669 assert_eq!(h.$get(), $default);
670 h.$set($value);
671 assert_eq!(h.$get(), $value);
672 })*
673 }
674 }
675
676 #[test]
677 fn header() {
678 test_field!(id, set_id, 0, 0x1234);
679 test_field!(qr, set_qr, false, true, false);
680 test_field!(opcode, set_opcode, Opcode::Query, Opcode::Notify);
681 test_field!(aa, set_aa, false, true, false);
682 test_field!(tc, set_tc, false, true, false);
683 test_field!(rd, set_rd, false, true, false);
684 test_field!(ra, set_ra, false, true, false);
685 test_field!(z, set_z, false, true, false);
686 test_field!(ad, set_ad, false, true, false);
687 test_field!(cd, set_cd, false, true, false);
688 test_field!(rcode, set_rcode, Rcode::NoError, Rcode::Refused);
689 }
690
691 #[test]
692 fn counts() {
693 let mut c = HeaderCounts { inner: [ 1, 2, 3, 4, 5, 6, 7, 8 ] };
694 assert_eq!(c.qdcount(), 0x0102);
695 assert_eq!(c.ancount(), 0x0304);
696 assert_eq!(c.nscount(), 0x0506);
697 assert_eq!(c.arcount(), 0x0708);
698 c.inc_qdcount();
699 c.inc_ancount();
700 c.inc_nscount();
701 c.inc_arcount();
702 assert_eq!(c.inner, [ 1, 3, 3, 5, 5, 7, 7, 9 ]);
703 c.set_qdcount(0x0807);
704 c.set_ancount(0x0605);
705 c.set_nscount(0x0403);
706 c.set_arcount(0x0201);
707 assert_eq!(c.inner, [ 8, 7, 6, 5, 4, 3, 2, 1 ]);
708 }
709
710 #[test]
711 fn update_counts() {
712 let mut c = HeaderCounts { inner: [ 1, 2, 3, 4, 5, 6, 7, 8 ] };
713 assert_eq!(c.zocount(), 0x0102);
714 assert_eq!(c.prcount(), 0x0304);
715 assert_eq!(c.upcount(), 0x0506);
716 assert_eq!(c.adcount(), 0x0708);
717 c.set_zocount(0x0807);
718 c.set_prcount(0x0605);
719 c.set_upcount(0x0403);
720 c.set_adcount(0x0201);
721 assert_eq!(c.inner, [ 8, 7, 6, 5, 4, 3, 2, 1 ]);
722 }
723
724 #[test]
725 #[should_panic]
726 fn bad_inc_qdcount() {
727 let mut c = HeaderCounts {
728 inner: [ 0xff, 0xff,0xff,0xff,0xff,0xff,0xff,0xff ]
729 };
730 c.inc_qdcount()
731 }
732
733 #[test]
734 #[should_panic]
735 fn bad_inc_ancount() {
736 let mut c = HeaderCounts {
737 inner: [ 0xff, 0xff,0xff,0xff,0xff,0xff,0xff,0xff ]
738 };
739 c.inc_ancount()
740 }
741
742 #[test]
743 #[should_panic]
744 fn bad_inc_nscount() {
745 let mut c = HeaderCounts {
746 inner: [ 0xff, 0xff,0xff,0xff,0xff,0xff,0xff,0xff ]
747 };
748 c.inc_nscount()
749 }
750
751 #[test]
752 #[should_panic]
753 fn bad_inc_arcount() {
754 let mut c = HeaderCounts {
755 inner: [ 0xff, 0xff,0xff,0xff,0xff,0xff,0xff,0xff ]
756 };
757 c.inc_arcount()
758 }
759}