bacnet_encoding/constructed/
property_access_result.rs1use bacnet_types::constructed::{AccessResult, BACnetPropertyAccessResult};
13use bacnet_types::enums::{ErrorClass, ErrorCode};
14use bacnet_types::error::{DecodeError, DecodingKind, 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 DecodeError::new(DecodingKind::OutOfRange, content, "error class exceeds u16")
79 .within(WHAT)
80 })?;
81 let code = u16::try_from(code).map_err(|_| {
82 DecodeError::new(DecodingKind::OutOfRange, content, "error code exceeds u16")
83 .within(WHAT)
84 })?;
85 let end = expect_closing(data, next, 5, WHAT)?;
86 let error = AccessResult::Error {
87 class: ErrorClass::from_raw(class),
88 code: ErrorCode::from_raw(code),
89 };
90 (error, end)
91 } else {
92 return Err(DecodeError::new(
93 DecodingKind::InvalidEncoding,
94 offset,
95 "expected property-value [4] or property-access-error [5]",
96 )
97 .within(WHAT)
98 .into());
99 };
100 Ok((
101 BACnetPropertyAccessResult {
102 reference,
103 access_result,
104 },
105 end,
106 ))
107}