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