s2n_quic_core/inet/
udp.rs

1// Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.
2// SPDX-License-Identifier: Apache-2.0
3
4use core::fmt;
5use s2n_codec::zerocopy::U16;
6
7// NOTE: duvet doesn't know how to parse this RFC since it doesn't follow more modern formatting
8//# https://www.rfc-editor.org/rfc/rfc768#format
9//# Format
10//# ------
11//#                  0      7 8     15 16    23 24    31
12//#                 +--------+--------+--------+--------+
13//#                 |     Source      |   Destination   |
14//#                 |      Port       |      Port       |
15//#                 +--------+--------+--------+--------+
16//#                 |                 |                 |
17//#                 |     Length      |    Checksum     |
18//#                 +--------+--------+--------+--------+
19//#                 |
20//#                 |          data octets ...
21//#                 +---------------- ...
22
23define_inet_type!(
24    pub struct Header {
25        source: U16,
26        destination: U16,
27        len: U16,
28        checksum: U16,
29    }
30);
31
32impl Header {
33    /// Swaps the direction of the header
34    #[inline]
35    pub fn swap(&mut self) {
36        core::mem::swap(&mut self.source, &mut self.destination)
37    }
38
39    #[inline]
40    pub const fn source(&self) -> &U16 {
41        &self.source
42    }
43
44    #[inline]
45    pub fn source_mut(&mut self) -> &mut U16 {
46        &mut self.source
47    }
48
49    #[inline]
50    pub const fn destination(&self) -> &U16 {
51        &self.destination
52    }
53
54    #[inline]
55    pub fn destination_mut(&mut self) -> &mut U16 {
56        &mut self.destination
57    }
58
59    #[inline]
60    pub const fn len(&self) -> &U16 {
61        &self.len
62    }
63
64    #[inline]
65    pub fn len_mut(&mut self) -> &mut U16 {
66        &mut self.len
67    }
68
69    #[inline]
70    pub const fn checksum(&self) -> &U16 {
71        &self.checksum
72    }
73
74    #[inline]
75    pub fn checksum_mut(&mut self) -> &mut U16 {
76        &mut self.checksum
77    }
78}
79
80impl fmt::Debug for Header {
81    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
82        f.debug_struct("udp::Header")
83            .field("source", &self.source)
84            .field("destination", &self.destination)
85            .field("len", &self.len)
86            .field("checksum", &format_args!("0x{:04x}", &self.checksum.get()))
87            .finish()
88    }
89}
90
91#[cfg(test)]
92mod tests {
93    use super::*;
94    use bolero::check;
95    use s2n_codec::DecoderBuffer;
96
97    #[test]
98    #[cfg_attr(miri, ignore)]
99    fn snapshot_test() {
100        let mut buffer = vec![0u8; core::mem::size_of::<Header>()];
101        for (idx, byte) in buffer.iter_mut().enumerate() {
102            *byte = idx as u8;
103        }
104        let decoder = DecoderBuffer::new(&buffer);
105        let (header, _) = decoder.decode::<&Header>().unwrap();
106        insta::assert_debug_snapshot!("snapshot_test", header);
107
108        buffer.fill(255);
109        let decoder = DecoderBuffer::new(&buffer);
110        let (header, _) = decoder.decode::<&Header>().unwrap();
111        insta::assert_debug_snapshot!("snapshot_filled_test", header);
112    }
113
114    #[test]
115    fn header_round_trip_test() {
116        check!().for_each(|buffer| {
117            s2n_codec::assert_codec_round_trip_bytes!(Header, buffer);
118        });
119    }
120}