use core::fmt;
use crate::error::{Error, ErrorCode};
use crate::im::encoding::{AttrId, ClusterId, EndptId};
use crate::im::{AttrData, AttrStatus};
use crate::tlv::{FromTLV, TLVArray, TLVElement, ToTLV};
#[derive(Clone, PartialEq, Eq, Hash, FromTLV, ToTLV)]
#[tlvargs(lifetime = "'a")]
pub struct WriteReq<'a>(TLVElement<'a>);
impl<'a> WriteReq<'a> {
pub const fn new(element: TLVElement<'a>) -> Self {
Self(element)
}
pub fn supress_response(&self) -> Result<bool, Error> {
self.0
.r#struct()?
.find_ctx(0)?
.non_empty()
.map(|t| t.bool())
.unwrap_or(Ok(false))
}
pub fn timed_request(&self) -> Result<bool, Error> {
self.0
.r#struct()?
.find_ctx(1)?
.non_empty()
.map(|t| t.bool())
.unwrap_or(Ok(false))
}
pub fn write_requests(&self) -> Result<TLVArray<'a, AttrData<'_>>, Error> {
TLVArray::new(self.0.r#struct()?.find_ctx(2)?)
}
pub fn more_chunks(&self) -> Result<bool, Error> {
self.0
.r#struct()?
.find_ctx(3)?
.non_empty()
.map(|t| t.bool())
.unwrap_or(Ok(false))
}
}
impl fmt::Debug for WriteReq<'_> {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
f.debug_struct("WriteReqRef")
.field("supress_response", &self.supress_response())
.field("timed_request", &self.timed_request())
.field("write_requests", &self.write_requests())
.field("more_chunks", &self.more_chunks())
.finish()
}
}
#[cfg(feature = "defmt")]
impl defmt::Format for WriteReq<'_> {
fn format(&self, f: defmt::Formatter<'_>) {
defmt::write!(f,
"WriteReqRef {{\n supress_response: {:?},\n timed_request: {:?},\n write_requests: {:?},\n more_chunks: {:?},\n}}",
self.supress_response(),
self.timed_request(),
self.write_requests(),
self.more_chunks(),
)
}
}
#[derive(Debug, Copy, Clone, Eq, PartialEq, Hash)]
#[cfg_attr(feature = "defmt", derive(defmt::Format))]
#[repr(u8)]
pub enum WriteReqTag {
SuppressResponse = 0,
TimedRequest = 1,
WriteRequests = 2,
MoreChunked = 3,
}
#[derive(ToTLV, FromTLV, Debug)]
#[cfg_attr(feature = "defmt", derive(defmt::Format))]
#[tlvargs(lifetime = "'a")]
pub struct WriteResp<'a> {
pub write_responses: TLVArray<'a, AttrStatus>,
#[tagval(crate::im::encoding::IM_REVISION_TAG)]
pub interaction_model_revision: Option<u8>,
}
impl<'a> WriteResp<'a> {
pub fn statuses(
&self,
cluster: ClusterId,
attr: AttrId,
) -> impl Iterator<Item = (EndptId, Result<(), Error>)> + '_ {
self.write_responses
.iter()
.filter_map(move |status| filter_attr_status(status.ok()?, cluster, attr))
}
}
fn filter_attr_status(
s: AttrStatus,
cluster: ClusterId,
attr: AttrId,
) -> Option<(EndptId, Result<(), Error>)> {
if s.path.cluster != Some(cluster) || s.path.attr != Some(attr) {
return None;
}
let endpoint = s.path.endpoint?;
let result = if s.status.status == crate::im::IMStatusCode::Success {
Ok(())
} else {
let err: Error = s
.status
.status
.to_error_code()
.unwrap_or(ErrorCode::Failure)
.into();
Err(err)
};
Some((endpoint, result))
}
#[derive(Debug, Copy, Clone, Eq, PartialEq, Hash)]
#[cfg_attr(feature = "defmt", derive(defmt::Format))]
#[repr(u8)]
pub enum WriteRespTag {
WriteResponses = 0,
}