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