use bacnet_encoding::constructed::decode_name_value;
use bacnet_encoding::primitives::decode_application_value;
use bacnet_types::constructed::BACnetNameValue;
use bacnet_types::error::Error;
use bacnet_types::primitives::PropertyValue;
#[derive(Debug, Clone, PartialEq)]
pub enum TagsRead {
Whole(Vec<BACnetNameValue>),
Element(BACnetNameValue),
Size(u32),
}
pub fn decode_tags_read(array_index: Option<u32>, octets: &[u8]) -> Result<TagsRead, Error> {
if array_index == Some(0) {
let (value, end) = decode_application_value(octets, 0)?;
if let PropertyValue::Unsigned(size) = value
&& end == octets.len()
{
return u32::try_from(size)
.map(TagsRead::Size)
.map_err(|_| Error::decoding(0, "Tags array size exceeds u32"));
}
return Err(Error::decoding(0, "Tags array size must be one Unsigned"));
}
if array_index.is_some() {
let (tag, end) = decode_name_value(octets, 0)?;
if end != octets.len() {
return Err(Error::decoding(end, "trailing bytes after Tags element"));
}
return Ok(TagsRead::Element(tag));
}
let mut tags = Vec::new();
let mut offset = 0;
while offset < octets.len() {
let (tag, end) = decode_name_value(octets, offset)?;
if end <= offset || end > octets.len() {
return Err(Error::decoding(offset, "invalid Tags element boundary"));
}
tags.push(tag);
offset = end;
}
Ok(TagsRead::Whole(tags))
}
#[cfg(test)]
mod tests;