bacnet_encoding/constructed/
property_access_result.rs1use bacnet_types::constructed::{AccessResult, BACnetPropertyAccessResult};
13use bacnet_types::enums::{ErrorClass, ErrorCode};
14use bacnet_types::error::Error;
15use bytes::BytesMut;
16
17use super::tagged::{decode_app_enumerated, decode_framed_value, expect_closing};
18use super::{decode_dopr_body, encode_dopr_body};
19use crate::{primitives, tags};
20
21const WHAT: &str = "BACnetPropertyAccessResult";
22
23pub fn encode_property_access_result(
29 buf: &mut BytesMut,
30 result: &BACnetPropertyAccessResult,
31) -> Result<(), Error> {
32 let start = buf.len();
33 encode_dopr_body(buf, &result.reference);
34 match &result.access_result {
35 AccessResult::Value(value) => {
36 tags::encode_opening_tag(buf, 4);
37 if let Err(error) = primitives::encode_property_value(buf, value) {
38 buf.truncate(start);
39 return Err(error);
40 }
41 tags::encode_closing_tag(buf, 4);
42 }
43 AccessResult::Error { class, code } => {
44 tags::encode_opening_tag(buf, 5);
45 primitives::encode_app_enumerated(buf, u32::from(class.to_raw()));
46 primitives::encode_app_enumerated(buf, u32::from(code.to_raw()));
47 tags::encode_closing_tag(buf, 5);
48 }
49 }
50 Ok(())
51}
52
53pub fn decode_property_access_result(
66 data: &[u8],
67 offset: usize,
68) -> Result<(BACnetPropertyAccessResult, usize), Error> {
69 let (reference, offset) = decode_dopr_body(data, offset, WHAT)?;
70 let (tag, content) = tags::decode_tag(data, offset)?;
71 let (access_result, end) = if tag.is_opening_tag(4) {
72 let (value, end) = decode_framed_value(data, content, 4, WHAT)?;
73 (AccessResult::Value(value), end)
74 } else if tag.is_opening_tag(5) {
75 let (class, next) = decode_app_enumerated::<u32>(data, content, WHAT)?;
76 let (code, next) = decode_app_enumerated::<u32>(data, next, WHAT)?;
77 let class = u16::try_from(class).map_err(|_| {
78 Error::out_of_range(content, format!("{WHAT}: error class exceeds u16"))
79 })?;
80 let code = u16::try_from(code)
81 .map_err(|_| Error::out_of_range(content, format!("{WHAT}: error code exceeds u16")))?;
82 let end = expect_closing(data, next, 5, WHAT)?;
83 let error = AccessResult::Error {
84 class: ErrorClass::from_raw(class),
85 code: ErrorCode::from_raw(code),
86 };
87 (error, end)
88 } else {
89 return Err(Error::decoding(
90 offset,
91 format!("{WHAT}: expected property-value [4] or property-access-error [5]"),
92 ));
93 };
94 Ok((
95 BACnetPropertyAccessResult {
96 reference,
97 access_result,
98 },
99 end,
100 ))
101}