turn_types/attribute/
data.rs1use stun_types::{attribute::*, message::StunParseError};
12
13#[derive(Debug, Clone)]
19pub struct Data<'a> {
20 data: stun_types::data::Data<'a>,
21}
22
23impl AttributeStaticType for Data<'_> {
24 const TYPE: AttributeType = AttributeType::new(0x0013);
25}
26
27impl Attribute for Data<'_> {
28 fn get_type(&self) -> AttributeType {
29 Self::TYPE
30 }
31
32 fn length(&self) -> u16 {
33 self.data.len() as u16
34 }
35}
36
37impl AttributeWrite for Data<'_> {
38 fn to_raw(&self) -> RawAttribute<'_> {
39 RawAttribute::new(self.get_type(), &self.data)
40 }
41
42 fn write_into_unchecked(&self, dest: &mut [u8]) {
43 self.write_header_unchecked(dest);
44 dest[4..4 + self.data.len()].copy_from_slice(&self.data);
45 dest[4 + self.data.len()..self.padded_len()].fill(0);
46 }
47}
48
49impl<'a> AttributeFromRaw<'a> for Data<'a> {
50 fn from_raw_ref(raw: &RawAttribute) -> Result<Self, StunParseError>
51 where
52 Self: Sized,
53 {
54 raw.check_type_and_len(Self::TYPE, ..)?;
55 Ok(Self {
56 data: raw.value.clone().into_owned(),
57 })
58 }
59
60 fn from_raw(raw: RawAttribute<'a>) -> Result<Self, StunParseError>
61 where
62 Self: Sized,
63 {
64 Self::try_from(raw)
65 }
66}
67
68impl<'a> TryFrom<RawAttribute<'a>> for Data<'a> {
69 type Error = StunParseError;
70
71 fn try_from(raw: RawAttribute<'a>) -> Result<Self, Self::Error> {
72 raw.check_type_and_len(Self::TYPE, ..)?;
73 Ok(Self { data: raw.value })
74 }
75}
76
77impl<'a> Data<'a> {
78 pub fn new(data: &'a [u8]) -> Self {
89 if data.len() > u16::MAX as usize {
90 panic!(
91 "Attempt made to create a Data attribute larger than {}",
92 u16::MAX
93 );
94 }
95 Self {
96 data: stun_types::data::Data::from(data),
97 }
98 }
99
100 pub fn data(&self) -> &[u8] {
111 &self.data
112 }
113}
114
115impl core::fmt::Display for Data<'_> {
116 fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
117 write!(f, "{}: len:{}", self.get_type(), self.data.len())
118 }
119}
120
121#[cfg(test)]
122mod tests {
123 use super::*;
124 use alloc::vec;
125 use alloc::vec::Vec;
126 use byteorder::{BigEndian, ByteOrder};
127 use tracing::trace;
128
129 #[test]
130 fn data() {
131 let _log = crate::tests::test_init_log();
132 let bytes = vec![0, 1, 2, 3, 4, 5];
133 let data = Data::new(&bytes);
134 assert_eq!(data.get_type(), Data::TYPE);
135 assert_eq!(data.data(), &bytes);
136 }
137
138 #[test]
139 fn data_raw() {
140 let _log = crate::tests::test_init_log();
141 let bytes = vec![0, 1, 2, 3, 4, 5];
142 let data = Data::new(&bytes);
143 let raw: RawAttribute = data.to_raw();
144 trace!("{}", raw);
145 assert_eq!(raw.get_type(), Data::TYPE);
146 let data2 = Data::try_from(raw.clone()).unwrap();
147 assert_eq!(data2.get_type(), Data::TYPE);
148 assert_eq!(data2.data(), &bytes);
149 }
150
151 #[test]
152 fn data_raw_wrong_type() {
153 let _log = crate::tests::test_init_log();
154 let bytes = vec![0, 1, 2, 3, 4, 5];
155 let data = Data::new(&bytes);
156 let raw: RawAttribute = data.to_raw();
157 let mut data: Vec<_> = raw.into();
159 BigEndian::write_u16(&mut data[0..2], 0);
160 assert!(matches!(
161 Data::try_from(RawAttribute::from_bytes(data.as_ref()).unwrap()),
162 Err(StunParseError::WrongAttributeImplementation)
163 ));
164 }
165
166 #[test]
167 fn data_write_into() {
168 let _log = crate::tests::test_init_log();
169 let bytes = vec![0, 1, 2, 3];
170 let data = Data::new(&bytes);
171 let raw: RawAttribute = data.to_raw();
172 let mut dest = vec![0; raw.padded_len()];
173 data.write_into(&mut dest).unwrap();
174 let raw = RawAttribute::from_bytes(&dest).unwrap();
175 let data2 = Data::try_from(raw.clone()).unwrap();
176 assert_eq!(data2.get_type(), Data::TYPE);
177 assert_eq!(data2.data(), &bytes);
178 }
179
180 #[test]
181 #[should_panic = "out of range"]
182 fn data_write_into_unchecked() {
183 let _log = crate::tests::test_init_log();
184 let bytes = vec![0, 1, 2, 3, 4, 5];
185 let data = Data::new(&bytes);
186 let raw: RawAttribute = data.to_raw();
187 let mut dest = vec![0; raw.padded_len() - 1];
188 data.write_into_unchecked(&mut dest);
189 }
190}