bacnet_encoding/constructed/
shed_level.rs1use bacnet_types::constructed::BACnetShedLevel;
10use bacnet_types::error::{DecodeError, DecodingKind, Error};
11use bytes::BytesMut;
12
13use super::tagged::contents;
14use crate::{primitives, tags};
15
16const WHAT: &str = "BACnetShedLevel";
17
18pub fn encode_shed_level(buf: &mut BytesMut, value: &BACnetShedLevel) {
20 match *value {
21 BACnetShedLevel::Percent(percent) => primitives::encode_ctx_unsigned(buf, 0, percent),
22 BACnetShedLevel::Level(level) => primitives::encode_ctx_unsigned(buf, 1, level),
23 BACnetShedLevel::Amount(amount) => primitives::encode_ctx_real(buf, 2, amount),
24 }
25}
26
27pub fn decode_shed_level(data: &[u8], offset: usize) -> Result<(BACnetShedLevel, usize), Error> {
36 let (tag, pos) = tags::decode_tag(data, offset)?;
37 let alternative = (0..=2u8).find(|&number| tag.is_context(number));
38 let Some(alternative) = alternative else {
39 return Err(DecodeError::new(
40 DecodingKind::InvalidEncoding,
41 offset,
42 "expected percent [0], level [1] or amount [2]",
43 )
44 .within(WHAT)
45 .into());
46 };
47 let (contents, end) = contents(data, pos, tag.length)?;
48 let refused = |label: &'static str| {
49 DecodeError::new(DecodingKind::InvalidEncoding, pos, label).within(WHAT)
50 };
51 let unsigned =
52 |label: &'static str| primitives::decode_unsigned(contents).map_err(|_| refused(label));
53 let value = match alternative {
54 0 => BACnetShedLevel::Percent(unsigned("percent [0] needs 1 to 8 octets")?),
55 1 => BACnetShedLevel::Level(unsigned("level [1] needs 1 to 8 octets")?),
56 _ => BACnetShedLevel::Amount(
57 primitives::decode_real(contents).map_err(|_| refused("amount [2] needs 4 octets"))?,
58 ),
59 };
60 Ok((value, end))
61}