bacnet_types/constructed/read_access.rs
1//! `BACnetPropertyReference` and `ReadAccessSpecification` (Clause 21): the
2//! object and properties a ReadPropertyMultiple request names, and the
3//! element of a Group object's List_Of_Group_Members (Clause 12.14.5).
4
5#[cfg(not(feature = "std"))]
6use alloc::vec::Vec;
7
8use super::AuditPropertyReference;
9use crate::enums::PropertyIdentifier;
10use crate::error::Error;
11use crate::primitives::ObjectIdentifier;
12
13/// One property of an object, whole or one array element
14/// (`BACnetPropertyReference`, Clause 21).
15///
16/// On the wire the property identifier is context tag `[0]` and the optional
17/// Unsigned array index `[1]`. The codec is
18/// `bacnet_encoding::constructed::{encode_property_reference,
19/// decode_property_reference}`.
20#[derive(Debug, Clone, PartialEq, Eq)]
21pub struct PropertyReference {
22 /// Property being referred to.
23 pub property_identifier: PropertyIdentifier,
24 /// Array element index; `None` refers to the whole property.
25 pub property_array_index: Option<u32>,
26}
27
28/// An object and the properties of it to read (`ReadAccessSpecification`,
29/// Clause 21).
30///
31/// On the wire the object identifier is context tag `[0]`, followed by the
32/// property references back to back inside an opening/closing tag pair
33/// `[1]`. The codec is
34/// `bacnet_encoding::constructed::{encode_read_access_specification,
35/// decode_read_access_specification}`.
36#[derive(Debug, Clone, PartialEq, Eq)]
37pub struct ReadAccessSpecification {
38 /// Object to read from.
39 pub object_identifier: ObjectIdentifier,
40 /// Properties to read from that object; may name the special ALL, REQUIRED or OPTIONAL
41 /// selectors.
42 pub list_of_property_references: Vec<PropertyReference>,
43}
44
45/// [`PropertyReference`] narrows the optional array index to `u32`, while
46/// Clause 21 leaves it an unconstrained Unsigned, so the Audit form keeps
47/// every value the primitive layer supports and converting back can fail.
48impl From<PropertyReference> for AuditPropertyReference {
49 fn from(value: PropertyReference) -> Self {
50 Self {
51 property_identifier: value.property_identifier,
52 property_array_index: value.property_array_index.map(u64::from),
53 }
54 }
55}
56
57impl TryFrom<AuditPropertyReference> for PropertyReference {
58 type Error = Error;
59
60 fn try_from(value: AuditPropertyReference) -> Result<Self, Self::Error> {
61 Ok(Self {
62 property_identifier: value.property_identifier,
63 property_array_index: value
64 .property_array_index
65 .map(u32::try_from)
66 .transpose()
67 .map_err(|_| {
68 Error::OutOfRange(
69 "Audit property-array-index exceeds shared PropertyReference u32 limit"
70 .into(),
71 )
72 })?,
73 })
74 }
75}