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 = [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 core::fmt::Display for ReservationToken {
99 fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::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 alloc::vec::Vec;
108 use byteorder::{BigEndian, ByteOrder};
109 use std::println;
110
111 #[test]
112 fn reservation_token() {
113 let _log = crate::tests::test_init_log();
114 let token = ReservationToken::new(200);
115 assert_eq!(token.get_type(), ReservationToken::TYPE);
116 assert_eq!(token.token(), 200);
117 let raw: RawAttribute = token.to_raw();
118 println!("{}", raw);
119 assert_eq!(raw.get_type(), ReservationToken::TYPE);
120 let token2 = ReservationToken::try_from(&raw).unwrap();
121 assert_eq!(token2.get_type(), ReservationToken::TYPE);
122 assert_eq!(token2.token(), 200);
123 let mut data: Vec<_> = raw.into();
125 BigEndian::write_u16(&mut data[0..2], 0);
126 assert!(matches!(
127 ReservationToken::try_from(&RawAttribute::from_bytes(data.as_ref()).unwrap()),
128 Err(StunParseError::WrongAttributeImplementation)
129 ));
130 }
131}