bacnet_encoding/primitives/
timestamp.rs1use bacnet_types::primitives::BACnetTimeStamp;
4
5use crate::sink::{EncodeSink, SinkFull};
6use crate::tags::{self, TagClass};
7
8use super::{encode_app_date_to_sink, encode_app_time_to_sink, encode_ctx_unsigned_to_sink};
9
10pub fn encode_timestamp_choice_to_sink<S: EncodeSink + ?Sized>(
23 sink: &mut S,
24 timestamp: &BACnetTimeStamp,
25) -> Result<usize, SinkFull> {
26 let mut encoded = [0; 12];
27 let used = stage_choice(&mut &mut encoded[..], timestamp)
28 .expect("each timestamp choice fits twelve bytes");
29 write_timestamp(sink, &encoded[..used])
30}
31
32pub fn encode_timestamp_to_sink<S: EncodeSink + ?Sized>(
53 sink: &mut S,
54 tag_number: u8,
55 timestamp: &BACnetTimeStamp,
56) -> Result<usize, SinkFull> {
57 let mut encoded = [0; 16];
58 let mut tail = &mut encoded[..];
59 let opening = tags::encode_opening_tag_to_sink(&mut tail, tag_number)
60 .expect("an opening marker fits the timestamp staging buffer");
61 let inner = stage_choice(&mut tail, timestamp)
62 .expect("the timestamp choice fits after its opening marker");
63 let closing = tags::encode_closing_tag_to_sink(&mut tail, tag_number)
64 .expect("the closing marker fits after the timestamp choice");
65 let used = opening + inner + closing;
66 write_timestamp(sink, &encoded[..used])
67}
68
69fn stage_choice(tail: &mut &mut [u8], timestamp: &BACnetTimeStamp) -> Result<usize, SinkFull> {
71 let before = tail.len();
72 match timestamp {
73 BACnetTimeStamp::Time(time) => {
74 tags::encode_tag_to_sink(tail, 0, TagClass::Context, 4)?;
75 tail.write(&time.encode())?;
76 }
77 BACnetTimeStamp::SequenceNumber(number) => {
78 encode_ctx_unsigned_to_sink(tail, 1, u64::from(*number))?;
79 }
80 BACnetTimeStamp::DateTime { date, time } => {
81 tags::encode_opening_tag_to_sink(tail, 2)?;
82 encode_app_date_to_sink(tail, date)?;
83 encode_app_time_to_sink(tail, time)?;
84 tags::encode_closing_tag_to_sink(tail, 2)?;
85 }
86 }
87 Ok(before - tail.len())
88}
89
90fn write_timestamp<S: EncodeSink + ?Sized>(
91 sink: &mut S,
92 encoded: &[u8],
93) -> Result<usize, SinkFull> {
94 if let Some(available) = sink.remaining_capacity()
95 && available < encoded.len()
96 {
97 return Err(SinkFull {
98 needed: encoded.len(),
99 available,
100 });
101 }
102 sink.write(encoded)?;
103 Ok(encoded.len())
104}