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