Skip to main content

bacnet_encoding/constructed/
event_notification_subscription.rs

1//! Encode and decode a Notification Forwarder's Subscribed_Recipients
2//! elements (Clause 12.51.9, Clause 21 BACnetEventNotificationSubscription).
3//!
4//! Each element is a bare sequence of four context-tagged members, all
5//! required: `[0]` wraps the recipient CHOICE, `[1]` is the process identifier
6//! (Unsigned32), `[2]` the confirmation flag and `[3]` the minutes remaining.
7//! The BACnetLIST concatenates elements with no wrapper, so the decoder reads
8//! one element at `offset` and returns the offset just past it.
9//!
10//! A subscription's recipient decodes through [`decode_recipient`] and
11//! encodes through the same bound: an address MAC is at most
12//! `BACnetAddress::MAX_MAC_LEN` octets (#1124, #1156).
13
14use bacnet_types::constructed::BACnetEventNotificationSubscription;
15use bacnet_types::error::Error;
16use bytes::BytesMut;
17
18use crate::{primitives, tags};
19
20use super::decode_recipient;
21use super::recipient::{check_encoded_recipient, write_recipient};
22use super::tagged::{decode_ctx_boolean, decode_ctx_unsigned, expect_closing, expect_opening};
23
24/// Encode one bare `BACnetEventNotificationSubscription` sequence. A
25/// recipient MAC past `BACnetAddress::MAX_MAC_LEN` octets is an error,
26/// returned before `buf` changes.
27pub fn encode_event_notification_subscription(
28    buf: &mut BytesMut,
29    subscription: &BACnetEventNotificationSubscription,
30) -> Result<(), Error> {
31    check_encoded_recipient(&subscription.recipient)?;
32    write_subscription(buf, subscription);
33    Ok(())
34}
35
36/// Encode a `BACnetLIST of BACnetEventNotificationSubscription` in slice
37/// order. Every recipient is checked before `buf` changes, so a refused list
38/// writes nothing.
39pub fn encode_event_notification_subscription_list(
40    buf: &mut BytesMut,
41    subscriptions: &[BACnetEventNotificationSubscription],
42) -> Result<(), Error> {
43    for subscription in subscriptions {
44        check_encoded_recipient(&subscription.recipient)?;
45    }
46    for subscription in subscriptions {
47        write_subscription(buf, subscription);
48    }
49    Ok(())
50}
51
52/// Write a subscription whose recipient has passed [`check_encoded_recipient`].
53fn write_subscription(buf: &mut BytesMut, subscription: &BACnetEventNotificationSubscription) {
54    tags::encode_opening_tag(buf, 0);
55    write_recipient(buf, &subscription.recipient);
56    tags::encode_closing_tag(buf, 0);
57    primitives::encode_ctx_unsigned(buf, 1, u64::from(subscription.process_identifier));
58    primitives::encode_ctx_boolean(buf, 2, subscription.issue_confirmed_notifications);
59    primitives::encode_ctx_unsigned(buf, 3, u64::from(subscription.time_remaining));
60}
61
62/// Decode one bare `BACnetEventNotificationSubscription` at `offset`; returns
63/// it and the offset past its `[3]` member. A member that is missing, out of
64/// order, or past its range (a process identifier or time remaining beyond
65/// Unsigned32) is a decode error.
66pub fn decode_event_notification_subscription(
67    data: &[u8],
68    offset: usize,
69) -> Result<(BACnetEventNotificationSubscription, usize), Error> {
70    let what = "BACnetEventNotificationSubscription";
71    let pos = expect_opening(data, offset, 0, what)?;
72    let (recipient, pos) = decode_recipient(data, pos)?;
73    let pos = expect_closing(data, pos, 0, what)?;
74    let (process_identifier, pos) = decode_ctx_unsigned::<u32>(data, pos, 1, what)?;
75    let (issue_confirmed_notifications, pos) = decode_ctx_boolean(data, pos, 2, what)?;
76    let (time_remaining, pos) = decode_ctx_unsigned::<u32>(data, pos, 3, what)?;
77    Ok((
78        BACnetEventNotificationSubscription {
79            recipient,
80            process_identifier,
81            issue_confirmed_notifications,
82            time_remaining,
83        },
84        pos,
85    ))
86}