diameter_interface/modeling/avp/
time.rs1use crate::errors::Error::EncodeError;
6use crate::errors::{DiameterResult, Error};
7use crate::modeling::avp::avp::AvpValue;
8use crate::modeling::avp::AvpData;
9use chrono::{DateTime, TimeZone, Utc};
10use std::io::{Read, Write};
11
12pub type Time = AvpData<DateTime<Utc>>;
13
14const RFC868_OFFSET: u32 = 2208988800; impl Time {
17 pub(super) fn encode_to<W: Write>(&self, writer: &mut W) -> DiameterResult<()> {
18 let unix_timestamp = self.0.timestamp();
19 let diameter_timestamp = unix_timestamp + RFC868_OFFSET as i64;
20 if diameter_timestamp > u32::MAX as i64 {
21 Err(EncodeError(
22 "Time is too far in the future to fit into 32 bits",
23 ))?
24 }
25 let diameter_timestamp = diameter_timestamp as u32;
26 let encoded_data = Vec::from(diameter_timestamp.to_be_bytes());
27 writer.write(&encoded_data)?;
28 Ok(())
29 }
30
31 pub(super) fn decode_from<R: Read>(reader: &mut R) -> DiameterResult<AvpData<DateTime<Utc>>> {
32 let mut b = [0; 4];
33 reader.read_exact(&mut b)?;
34
35 let diameter_timestamp = u32::from_be_bytes(b); let unix_timestamp = diameter_timestamp as i64 - RFC868_OFFSET as i64;
37 let timestamp = Utc
38 .timestamp_opt(unix_timestamp, 0)
39 .single()
40 .ok_or_else(|| Error::DecodeError("Invalid time"))?;
41 Ok(Time::new(timestamp))
42 }
43
44 pub(super) fn len(&self) -> u32 {
45 4
46 }
47}
48
49impl Into<AvpValue> for Time {
50 fn into(self) -> AvpValue {
51 AvpValue::Time(self)
52 }
53}