use bacnet_types::error::Error;
use super::lighting_command::decode_fields;
use super::tagged::expect_closing;
use crate::primitives;
use crate::tags::{self, TagClass};
pub fn channel_value_end(data: &[u8], offset: usize) -> Result<usize, Error> {
if offset >= data.len() {
return Err(Error::decoding(offset, "missing channel value"));
}
let (tag, pos) = tags::decode_tag(data, offset)?;
if tag.class == TagClass::Application {
return primitives::validate_application_value(data, offset);
}
if !tag.is_opening_tag(0) {
return Err(Error::decoding(
offset,
"a channel value is an application-tagged primitive or a context 0 lighting command",
));
}
let (command, end, oversized) = decode_fields(data, pos)?;
let after = expect_closing(data, end, 0, "lighting command")?;
if let Some(field) = oversized {
return Err(Error::decoding(offset, format!("lighting command {field}")));
}
if let Some(priority) = command.priority.filter(|p| !(1..=16).contains(p)) {
return Err(Error::out_of_range(
offset,
format!("lighting command priority {priority} out of range 1-16"),
));
}
Ok(after)
}
pub fn is_lighting_command_channel_value(data: &[u8]) -> bool {
data.first() == Some(&0x0E) && channel_value_end(data, 0).is_ok_and(|end| end == data.len())
}