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