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