#![forbid(unsafe_code)]
mod accumulator;
pub mod error;
pub mod event;
pub mod invoke;
pub mod invoke_server;
pub mod path;
pub mod read;
pub mod status;
pub mod subscription;
pub mod timed;
pub mod write;
pub use accumulator::{ReportAccumulator, DEFAULT_MAX_BYTES, DEFAULT_MAX_ELEMENTS};
pub use error::ImError;
pub use event::{
EventFilter, EventPath, EventPriority, EventReport, EventReportItem, EventTimestamp,
};
pub use invoke::{
build_invoke_request, build_invoke_request_batch, build_invoke_request_group,
build_invoke_request_timed, parse_invoke_response, parse_invoke_response_batch, InvokeResponse,
InvokeResponseEntry,
};
pub use invoke_server::{
build_invoke_response_command, build_invoke_response_status, parse_invoke_request,
InvokedCommand, ParsedInvokeRequest,
};
pub use path::{AttributePath, CommandPath, ReadPath};
pub use read::{
build_read_request, build_read_request_full, build_read_request_paths, parse_report_data,
AttributeReportItem, ReportData, ReportOp,
};
pub use status::{parse_status_response, ImStatus};
pub use subscription::{
build_status_response, build_subscribe_request, parse_subscribe_response, SubscribeRequest,
SubscribeResponse,
};
pub use timed::build_timed_request;
pub use write::{
build_list_write_chunks, build_write_request, build_write_request_timed, parse_write_response,
AttributeWriteRequest,
};
pub const IM_REVISION: u8 = 11;
use matter_codec::{ContainerKind, Element, Tag, TlvReader, Value};
pub fn expect_message_struct(r: &mut TlvReader<'_>) -> Result<(), error::ImError> {
match r.next()? {
Some(Element::ContainerStart {
tag: Tag::Anonymous,
kind: ContainerKind::Structure,
}) => Ok(()),
Some(_) | None => Err(error::ImError::NotAStruct),
}
}
pub fn read_container_members(r: &mut TlvReader<'_>) -> Result<Vec<(Tag, Value)>, error::ImError> {
let mut out = Vec::new();
loop {
match r.next()? {
None => {
return Err(error::ImError::Codec(
matter_codec::Error::UnclosedContainer,
))
}
Some(Element::ContainerEnd) => return Ok(out),
Some(Element::Scalar { tag, value }) => out.push((tag, value)),
Some(Element::ContainerStart { tag, kind }) => {
let v = read_container_value(r, kind)?;
out.push((tag, v));
}
Some(_) => {}
}
}
}
pub fn read_container_value(
r: &mut TlvReader<'_>,
kind: ContainerKind,
) -> Result<Value, error::ImError> {
let members = read_container_members(r)?;
Ok(match kind {
ContainerKind::Structure => Value::Structure(members),
ContainerKind::Array => Value::Array(members.into_iter().map(|(_, v)| v).collect()),
_ => Value::List(members),
})
}
pub fn skip_container(r: &mut TlvReader<'_>) -> Result<(), error::ImError> {
let _ = read_container_members(r)?;
Ok(())
}