bacnet_encoding/constructed/
read_access.rs1use bacnet_types::constructed::{PropertyReference, ReadAccessSpecification};
11use bacnet_types::enums::PropertyIdentifier;
12use bacnet_types::error::Error;
13use bytes::BytesMut;
14
15use super::tagged::{
16 decode_ctx_object_id, decode_ctx_unsigned, decode_optional_ctx, expect_opening,
17};
18use super::MAX_FRAMED_ITEMS;
19use crate::{primitives, tags};
20
21pub fn encode_property_reference(buf: &mut BytesMut, reference: &PropertyReference) {
23 primitives::encode_ctx_unsigned(buf, 0, u64::from(reference.property_identifier.to_raw()));
24 if let Some(index) = reference.property_array_index {
25 primitives::encode_ctx_unsigned(buf, 1, u64::from(index));
26 }
27}
28
29pub fn decode_property_reference(
38 data: &[u8],
39 offset: usize,
40) -> Result<(PropertyReference, usize), Error> {
41 const PROPERTY: &str = "PropertyReference property-id";
42 const INDEX: &str = "PropertyReference array-index";
43 let (property, next) = decode_ctx_unsigned::<u32>(data, offset, 0, PROPERTY)?;
44 let (property_array_index, offset) =
45 decode_optional_ctx(data, next, 1, INDEX, decode_ctx_unsigned::<u32>)?;
46 Ok((
47 PropertyReference {
48 property_identifier: PropertyIdentifier::from_raw(property),
49 property_array_index,
50 },
51 offset,
52 ))
53}
54
55pub fn encode_read_access_specification(buf: &mut BytesMut, spec: &ReadAccessSpecification) {
59 primitives::encode_ctx_object_id(buf, 0, &spec.object_identifier);
60 tags::encode_opening_tag(buf, 1);
61 for reference in &spec.list_of_property_references {
62 encode_property_reference(buf, reference);
63 }
64 tags::encode_closing_tag(buf, 1);
65}
66
67pub fn decode_read_access_specification(
72 data: &[u8],
73 offset: usize,
74) -> Result<(ReadAccessSpecification, usize), Error> {
75 const WHAT: &str = "ReadAccessSpecification";
76 let (object_identifier, end) = decode_ctx_object_id(data, offset, 0, WHAT)?;
77 let mut offset = expect_opening(data, end, 1, WHAT)?;
78 let mut list_of_property_references = Vec::new();
79 loop {
80 if offset >= data.len() {
81 return Err(Error::missing(
82 offset,
83 format!("{WHAT} missing closing tag 1"),
84 ));
85 }
86 if list_of_property_references.len() >= MAX_FRAMED_ITEMS {
87 return Err(Error::overflow(
88 offset,
89 format!("{WHAT} property references exceed the item limit"),
90 ));
91 }
92 let (tag, tag_end) = tags::decode_tag(data, offset)?;
93 if tag.is_closing_tag(1) {
94 offset = tag_end;
95 break;
96 }
97 let (reference, next) = decode_property_reference(data, offset)?;
98 list_of_property_references.push(reference);
99 offset = next;
100 }
101 Ok((
102 ReadAccessSpecification {
103 object_identifier,
104 list_of_property_references,
105 },
106 offset,
107 ))
108}