#[cfg(not(feature = "std"))]
use alloc::vec::Vec;
use bacnet_types::error::Error;
use bytes::BytesMut;
use super::members::{narrow, unsigned_member};
use super::tagged::{decode_ctx_primitive, expect_closing, expect_opening, next_is_closing};
use super::MAX_FRAMED_ITEMS;
use crate::primitives;
use crate::tags;
pub(super) struct PairNames {
pub(super) value: &'static str,
pub(super) frame: &'static str,
pub(super) floor: &'static str,
pub(super) second: &'static str,
pub(super) second_oversized: &'static str,
}
pub(super) fn encode_floor_pairs(buf: &mut BytesMut, pairs: impl IntoIterator<Item = (u8, u32)>) {
tags::encode_opening_tag(buf, 0);
for (floor, value) in pairs {
primitives::encode_ctx_unsigned(buf, 0, floor.into());
primitives::encode_ctx_enumerated(buf, 1, value);
}
tags::encode_closing_tag(buf, 0);
}
pub(super) fn decode_floor_pairs(
data: &[u8],
offset: usize,
names: &PairNames,
) -> Result<(Vec<(u8, u32)>, usize), Error> {
let mut oversized = None;
let mut offset = expect_opening(data, offset, 0, names.frame)?;
let mut pairs = Vec::new();
loop {
if next_is_closing(data, offset, 0)? {
if let Some(member) = oversized {
return Err(Error::OutOfRange(format!("{} {member}", names.value)));
}
return Ok((pairs, expect_closing(data, offset, 0, names.frame)?));
}
if pairs.len() >= MAX_FRAMED_ITEMS {
return Err(Error::overflow(
offset,
format!("{} exceeds the decoded item limit", names.value),
));
}
let (floor, next) = decode_ctx_primitive(data, offset, 0, names.floor)?;
let floor_number = narrow(
unsigned_member(floor, next - floor.len())?,
"floor-number [0] exceeds an Unsigned8",
&mut oversized,
);
let (raw, next) = decode_ctx_primitive(data, next, 1, names.second)?;
let value: u32 = narrow(
unsigned_member(raw, next - raw.len())?,
names.second_oversized,
&mut oversized,
);
pairs.push((floor_number, value));
offset = next;
}
}