bacnet_encoding/constructed/
name_value.rs1use bacnet_types::constructed::BACnetNameValue;
9use bacnet_types::error::{DecodeError, DecodingKind, EncodeError, 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(EncodeError::new("a value must be a primitive datatype")
29 .within(WHAT)
30 .into());
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(DecodeError::new(
63 DecodingKind::InvalidEncoding,
64 offset,
65 "a value must contain only one primitive",
66 )
67 .within(WHAT)
68 .into());
69 }
70 Ok((
71 BACnetNameValue {
72 name,
73 value: Some(value),
74 },
75 offset,
76 ))
77}