turn_types/attribute/
fragment.rs

1// Copyright (C) 2025 Matthew Waters <matthew@centricular.com>
2//
3// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
4// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
5// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
6// option. This file may not be copied, modified, or distributed
7// except according to those terms.
8
9use stun_types::{attribute::*, message::StunParseError};
10
11/// The DontFragment [`Attribute`]
12#[derive(Default, Debug, Clone)]
13pub struct DontFragment {}
14impl AttributeStaticType for DontFragment {
15    const TYPE: AttributeType = AttributeType::new(0x001A);
16}
17
18impl Attribute for DontFragment {
19    fn get_type(&self) -> AttributeType {
20        Self::TYPE
21    }
22
23    fn length(&self) -> u16 {
24        0
25    }
26}
27
28impl AttributeWrite for DontFragment {
29    fn to_raw(&self) -> RawAttribute {
30        RawAttribute::new(self.get_type(), &[])
31    }
32    fn write_into_unchecked(&self, dest: &mut [u8]) {
33        self.write_header_unchecked(dest);
34    }
35}
36
37impl AttributeFromRaw<'_> for DontFragment {
38    fn from_raw_ref(raw: &RawAttribute) -> Result<Self, StunParseError>
39    where
40        Self: Sized,
41    {
42        Self::try_from(raw)
43    }
44}
45
46impl TryFrom<&RawAttribute<'_>> for DontFragment {
47    type Error = StunParseError;
48    fn try_from(raw: &RawAttribute) -> Result<Self, Self::Error> {
49        raw.check_type_and_len(Self::TYPE, 0..=0)?;
50        Ok(Self {})
51    }
52}
53
54impl DontFragment {
55    /// Create a new DontFragment [`Attribute`]
56    ///
57    /// # Examples
58    ///
59    /// ```
60    /// # use turn_types::attribute::*;
61    /// let dont_fragment = DontFragment::new();
62    /// ```
63    pub fn new() -> Self {
64        Self {}
65    }
66}
67
68impl std::fmt::Display for DontFragment {
69    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
70        write!(f, "{}", self.get_type())
71    }
72}
73
74#[cfg(test)]
75mod tests {
76    use super::*;
77    use byteorder::{BigEndian, ByteOrder};
78
79    #[test]
80    fn dont_fragment() {
81        let _log = crate::tests::test_init_log();
82        let frag = DontFragment::new();
83        assert_eq!(frag.get_type(), DontFragment::TYPE);
84        let raw: RawAttribute = frag.to_raw();
85        println!("{}", raw);
86        assert_eq!(raw.get_type(), DontFragment::TYPE);
87        let frag2 = DontFragment::try_from(&raw).unwrap();
88        assert_eq!(frag2.get_type(), DontFragment::TYPE);
89        // provide incorrectly typed data
90        let mut data: Vec<_> = raw.into();
91        BigEndian::write_u16(&mut data[0..2], 0);
92        assert!(matches!(
93            DontFragment::try_from(&RawAttribute::from_bytes(data.as_ref()).unwrap()),
94            Err(StunParseError::WrongAttributeImplementation)
95        ));
96    }
97}