turn_types/attribute/
channel.rs1use byteorder::{BigEndian, ByteOrder};
10
11use stun_types::{attribute::*, message::StunParseError};
12
13#[derive(Debug, Clone)]
20pub struct ChannelNumber {
21 channel: u16,
22}
23
24impl AttributeStaticType for ChannelNumber {
25 const TYPE: AttributeType = AttributeType::new(0x000C);
26}
27
28impl Attribute for ChannelNumber {
29 fn get_type(&self) -> AttributeType {
30 Self::TYPE
31 }
32
33 fn length(&self) -> u16 {
34 4
35 }
36}
37
38impl AttributeWrite for ChannelNumber {
39 fn to_raw(&self) -> RawAttribute<'_> {
40 let mut buf = [0; 4];
41 BigEndian::write_u16(&mut buf[..2], self.channel);
42 RawAttribute::new(self.get_type(), &buf).into_owned()
43 }
44 fn write_into_unchecked(&self, dest: &mut [u8]) {
45 self.write_header_unchecked(dest);
46 BigEndian::write_u16(&mut dest[4..6], self.channel);
47 }
48}
49
50impl AttributeFromRaw<'_> for ChannelNumber {
51 fn from_raw_ref(raw: &RawAttribute) -> Result<Self, StunParseError>
52 where
53 Self: Sized,
54 {
55 Self::try_from(raw)
56 }
57}
58
59impl TryFrom<&RawAttribute<'_>> for ChannelNumber {
60 type Error = StunParseError;
61 fn try_from(raw: &RawAttribute) -> Result<Self, Self::Error> {
62 raw.check_type_and_len(Self::TYPE, 4..=4)?;
63 Ok(Self {
64 channel: BigEndian::read_u16(&raw.value),
65 })
66 }
67}
68
69impl ChannelNumber {
70 pub fn new(channel: u16) -> Self {
80 Self { channel }
81 }
82
83 pub fn channel(&self) -> u16 {
93 self.channel
94 }
95}
96
97impl core::fmt::Display for ChannelNumber {
98 fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
99 write!(f, "{}: '{}'", self.get_type(), self.channel)
100 }
101}
102
103#[cfg(test)]
104mod tests {
105 use super::*;
106 use alloc::vec::Vec;
107 use byteorder::{BigEndian, ByteOrder};
108 use std::println;
109
110 #[test]
111 fn channel_number() {
112 let _log = crate::tests::test_init_log();
113 let c = ChannelNumber::new(6);
114 assert_eq!(c.get_type(), ChannelNumber::TYPE);
115 assert_eq!(c.channel(), 6);
116 let raw: RawAttribute = c.to_raw();
117 println!("{}", raw);
118 assert_eq!(raw.get_type(), ChannelNumber::TYPE);
119 let c2 = ChannelNumber::try_from(&raw).unwrap();
120 assert_eq!(c2.get_type(), ChannelNumber::TYPE);
121 assert_eq!(c2.channel(), 6);
122 let mut data: Vec<_> = raw.into();
124 BigEndian::write_u16(&mut data[0..2], 0);
125 assert!(matches!(
126 ChannelNumber::try_from(&RawAttribute::from_bytes(data.as_ref()).unwrap()),
127 Err(StunParseError::WrongAttributeImplementation)
128 ));
129 }
130}