bacnet_encoding/constructed/
name_value.rs1use bacnet_types::constructed::BACnetNameValue;
9use bacnet_types::error::Error;
10use bytes::BytesMut;
11
12use super::tagged::decode_ctx_character_string;
13use crate::primitives;
14use crate::tags::{self, TagClass};
15
16const WHAT: &str = "BACnetNameValue";
17
18pub fn encode_name_value(buf: &mut BytesMut, value: &BACnetNameValue) -> Result<(), Error> {
23 if value
24 .value
25 .as_ref()
26 .is_some_and(|value| !value.is_primitive())
27 {
28 return Err(Error::Encoding(format!(
29 "{WHAT}: a value must be a primitive datatype"
30 )));
31 }
32 primitives::encode_ctx_character_string(buf, 0, &value.name)?;
33 if let Some(primitive) = &value.value {
34 primitives::encode_property_value(buf, primitive)?;
35 }
36 Ok(())
37}
38
39fn next_is_application(data: &[u8], offset: usize) -> Result<bool, Error> {
41 if offset >= data.len() {
42 return Ok(false);
43 }
44 let (tag, _) = tags::decode_tag(data, offset)?;
45 Ok(tag.class == TagClass::Application)
46}
47
48pub fn decode_name_value(data: &[u8], offset: usize) -> Result<(BACnetNameValue, usize), Error> {
56 let (name, offset) = decode_ctx_character_string(data, offset, 0, WHAT)?;
57 if !next_is_application(data, offset)? {
58 return Ok((BACnetNameValue { name, value: None }, offset));
59 }
60 let (value, offset) = primitives::decode_application_value(data, offset)?;
61 if next_is_application(data, offset)? {
62 return Err(Error::decoding(
63 offset,
64 format!("{WHAT}: a value must contain only one primitive"),
65 ));
66 }
67 Ok((
68 BACnetNameValue {
69 name,
70 value: Some(value),
71 },
72 offset,
73 ))
74}