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