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::{DecodeError, DecodingKind, Error};
16use bytes::BytesMut;
17
18pub use super::reference_sinks::encode_property_reference_to_sink;
19use super::tagged::{
20 decode_ctx_object_id, decode_ctx_unsigned, decode_optional_ctx, expect_opening,
21};
22use super::MAX_FRAMED_ITEMS;
23use crate::{primitives, tags};
24
25pub fn encode_property_reference(buf: &mut BytesMut, reference: &PropertyReference) {
27 encode_property_reference_to_sink(buf, reference).expect("BytesMut accepts each reference");
28}
29
30pub fn decode_property_reference(
39 data: &[u8],
40 offset: usize,
41) -> Result<(PropertyReference, usize), Error> {
42 const PROPERTY: &str = "PropertyReference property-id";
43 const INDEX: &str = "PropertyReference array-index";
44 let (property, next) = decode_ctx_unsigned::<u32>(data, offset, 0, PROPERTY)?;
45 let (property_array_index, offset) =
46 decode_optional_ctx(data, next, 1, INDEX, decode_ctx_unsigned::<u32>)?;
47 Ok((
48 PropertyReference {
49 property_identifier: PropertyIdentifier::from_raw(property),
50 property_array_index,
51 },
52 offset,
53 ))
54}
55
56pub fn encode_read_access_specification(buf: &mut BytesMut, spec: &ReadAccessSpecification) {
60 primitives::encode_ctx_object_id(buf, 0, &spec.object_identifier);
61 tags::encode_opening_tag(buf, 1);
62 for reference in &spec.list_of_property_references {
63 encode_property_reference(buf, reference);
64 }
65 tags::encode_closing_tag(buf, 1);
66}
67
68pub fn decode_read_access_specification(
73 data: &[u8],
74 offset: usize,
75) -> Result<(ReadAccessSpecification, usize), Error> {
76 const WHAT: &str = "ReadAccessSpecification";
77 let (object_identifier, end) = decode_ctx_object_id(data, offset, 0, WHAT)?;
78 let mut offset = expect_opening(data, end, 1, WHAT)?;
79 let mut list_of_property_references = Vec::new();
80 loop {
81 if offset >= data.len() {
82 return Err(DecodeError::new(
83 DecodingKind::Missing,
84 offset,
85 "missing closing tag 1",
86 )
87 .within(WHAT)
88 .into());
89 }
90 if list_of_property_references.len() >= MAX_FRAMED_ITEMS {
91 return Err(DecodeError::new(
92 DecodingKind::Overflow,
93 offset,
94 "property references exceed the item limit",
95 )
96 .within(WHAT)
97 .into());
98 }
99 let (tag, tag_end) = tags::decode_tag(data, offset)?;
100 if tag.is_closing_tag(1) {
101 offset = tag_end;
102 break;
103 }
104 let (reference, next) = decode_property_reference(data, offset)?;
105 list_of_property_references.push(reference);
106 offset = next;
107 }
108 Ok((
109 ReadAccessSpecification {
110 object_identifier,
111 list_of_property_references,
112 },
113 offset,
114 ))
115}