turn_types/attribute/
channel.rs1use byteorder::{BigEndian, ByteOrder};
12
13use stun_types::{attribute::*, message::StunParseError};
14
15#[derive(Debug, Clone)]
22pub struct ChannelNumber {
23 channel: u16,
24}
25
26impl AttributeStaticType for ChannelNumber {
27 const TYPE: AttributeType = AttributeType::new(0x000C);
28}
29
30impl Attribute for ChannelNumber {
31 fn get_type(&self) -> AttributeType {
32 Self::TYPE
33 }
34
35 fn length(&self) -> u16 {
36 4
37 }
38}
39
40impl AttributeWrite for ChannelNumber {
41 fn to_raw(&self) -> RawAttribute<'_> {
42 let mut buf = [0; 4];
43 BigEndian::write_u16(&mut buf[..2], self.channel);
44 RawAttribute::new(self.get_type(), &buf).into_owned()
45 }
46 fn write_into_unchecked(&self, dest: &mut [u8]) {
47 self.write_header_unchecked(dest);
48 BigEndian::write_u16(&mut dest[4..6], self.channel);
49 dest[7..self.padded_len()].fill(0);
50 }
51}
52
53impl AttributeFromRaw<'_> for ChannelNumber {
54 fn from_raw_ref(raw: &RawAttribute) -> Result<Self, StunParseError>
55 where
56 Self: Sized,
57 {
58 Self::try_from(raw)
59 }
60}
61
62impl TryFrom<&RawAttribute<'_>> for ChannelNumber {
63 type Error = StunParseError;
64 fn try_from(raw: &RawAttribute) -> Result<Self, Self::Error> {
65 raw.check_type_and_len(Self::TYPE, 4..=4)?;
66 Ok(Self {
67 channel: BigEndian::read_u16(&raw.value),
68 })
69 }
70}
71
72impl ChannelNumber {
73 pub fn new(channel: u16) -> Self {
83 Self { channel }
84 }
85
86 pub fn channel(&self) -> u16 {
96 self.channel
97 }
98}
99
100impl core::fmt::Display for ChannelNumber {
101 fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
102 write!(f, "{}: '{}'", self.get_type(), self.channel)
103 }
104}
105
106#[cfg(test)]
107mod tests {
108 use super::*;
109 use alloc::{vec, vec::Vec};
110 use byteorder::{BigEndian, ByteOrder};
111 use tracing::trace;
112
113 #[test]
114 fn channel_number() {
115 let _log = crate::tests::test_init_log();
116 let c = ChannelNumber::new(6);
117 assert_eq!(c.get_type(), ChannelNumber::TYPE);
118 assert_eq!(c.channel(), 6);
119 }
120
121 #[test]
122 fn channel_number_raw() {
123 let _log = crate::tests::test_init_log();
124 let c = ChannelNumber::new(6);
125 assert_eq!(c.get_type(), ChannelNumber::TYPE);
126 assert_eq!(c.channel(), 6);
127 let raw: RawAttribute = c.to_raw();
128 trace!("{}", raw);
129 assert_eq!(raw.get_type(), ChannelNumber::TYPE);
130 let c2 = ChannelNumber::try_from(&raw).unwrap();
131 assert_eq!(c2.get_type(), ChannelNumber::TYPE);
132 assert_eq!(c2.channel(), 6);
133 }
134
135 #[test]
136 fn channel_number_raw_wrong_type() {
137 let _log = crate::tests::test_init_log();
138 let c = ChannelNumber::new(6);
139 assert_eq!(c.get_type(), ChannelNumber::TYPE);
140 assert_eq!(c.channel(), 6);
141 let raw: RawAttribute = c.to_raw();
142 let mut data: Vec<_> = raw.into();
144 BigEndian::write_u16(&mut data[0..2], 0);
145 assert!(matches!(
146 ChannelNumber::try_from(&RawAttribute::from_bytes(data.as_ref()).unwrap()),
147 Err(StunParseError::WrongAttributeImplementation)
148 ));
149 }
150
151 #[test]
152 fn channel_number_write_into() {
153 let _log = crate::tests::test_init_log();
154 let c = ChannelNumber::new(6);
155 assert_eq!(c.channel(), 6);
156 let raw: RawAttribute = c.to_raw();
157
158 let mut dest = vec![0; raw.padded_len()];
159 c.write_into(&mut dest).unwrap();
160 let raw = RawAttribute::from_bytes(&dest).unwrap();
161 let c2 = ChannelNumber::try_from(&raw).unwrap();
162 assert_eq!(c2.get_type(), ChannelNumber::TYPE);
163 assert_eq!(c2.channel(), c.channel());
164 }
165
166 #[test]
167 #[should_panic = "out of range"]
168 fn channel_number_write_into_unchecked() {
169 let _log = crate::tests::test_init_log();
170 let c = ChannelNumber::new(6);
171 assert_eq!(c.channel(), 6);
172 let raw: RawAttribute = c.to_raw();
173
174 let mut dest = vec![0; raw.padded_len() - 1];
175 c.write_into_unchecked(&mut dest);
176 }
177}