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