use bacnet_types::constructed::BACnetShedLevel;
use bacnet_types::error::Error;
use bytes::BytesMut;
use super::tagged::contents;
use crate::{primitives, tags};
const WHAT: &str = "BACnetShedLevel";
pub fn encode_shed_level(buf: &mut BytesMut, value: &BACnetShedLevel) {
match *value {
BACnetShedLevel::Percent(percent) => primitives::encode_ctx_unsigned(buf, 0, percent),
BACnetShedLevel::Level(level) => primitives::encode_ctx_unsigned(buf, 1, level),
BACnetShedLevel::Amount(amount) => primitives::encode_ctx_real(buf, 2, amount),
}
}
pub fn decode_shed_level(data: &[u8], offset: usize) -> Result<(BACnetShedLevel, usize), Error> {
let (tag, pos) = tags::decode_tag(data, offset)?;
let alternative = (0..=2u8).find(|&number| tag.is_context(number));
let Some(alternative) = alternative else {
return Err(Error::decoding(
offset,
format!("{WHAT}: expected percent [0], level [1] or amount [2]"),
));
};
let (contents, end) = contents(data, pos, tag.length)?;
let unsigned = |name: &str| {
primitives::decode_unsigned(contents)
.map_err(|_| Error::decoding(pos, format!("{WHAT}: {name} needs 1 to 8 octets")))
};
let value = match alternative {
0 => BACnetShedLevel::Percent(unsigned("percent [0]")?),
1 => BACnetShedLevel::Level(unsigned("level [1]")?),
_ => BACnetShedLevel::Amount(
primitives::decode_real(contents)
.map_err(|_| Error::decoding(pos, format!("{WHAT}: amount [2] needs 4 octets")))?,
),
};
Ok((value, end))
}