use core::marker::PhantomData;
use crate::error::Error;
use crate::im::encoding::{ClusterId, CmdId, EndptId};
use crate::im::{CmdDataTag, CmdPathTag, InvReqTag, IM_REVISION};
use crate::tlv::{TLVBuilder, TLVBuilderParent, TLVTag, TLVWrite, ToTLV};
pub struct InvReqBuilder<P, const F: usize = 0> {
p: P,
}
impl<P> InvReqBuilder<P, 0>
where
P: TLVBuilderParent,
{
pub fn new(mut p: P, tag: &TLVTag) -> Result<Self, Error> {
p.writer().start_struct(tag)?;
Ok(Self { p })
}
}
impl<P> TLVBuilder<P> for InvReqBuilder<P, 0>
where
P: TLVBuilderParent,
{
fn new(parent: P, tag: &TLVTag) -> Result<Self, Error> {
Self::new(parent, tag)
}
fn unchecked_into_parent(self) -> P {
self.p
}
}
impl<P> InvReqBuilder<P, 0>
where
P: TLVBuilderParent,
{
pub fn suppress_response(mut self, value: bool) -> Result<InvReqBuilder<P, 1>, Error> {
self.p
.writer()
.bool(&TLVTag::Context(InvReqTag::SupressResponse as u8), value)?;
Ok(InvReqBuilder { p: self.p })
}
}
impl<P> InvReqBuilder<P, 0>
where
P: TLVBuilderParent,
{
pub fn timed_request(self, value: bool) -> Result<InvReqBuilder<P, 2>, Error> {
self.suppress_response(false)?.timed_request(value)
}
}
impl<P> InvReqBuilder<P, 1>
where
P: TLVBuilderParent,
{
pub fn timed_request(mut self, value: bool) -> Result<InvReqBuilder<P, 2>, Error> {
self.p
.writer()
.bool(&TLVTag::Context(InvReqTag::TimedReq as u8), value)?;
Ok(InvReqBuilder { p: self.p })
}
}
impl<P> InvReqBuilder<P, 0>
where
P: TLVBuilderParent,
{
pub fn invoke_requests(self) -> Result<CmdDataArrayBuilder<InvReqBuilder<P, 3>>, Error> {
self.suppress_response(false)?.invoke_requests()
}
}
impl<P> InvReqBuilder<P, 1>
where
P: TLVBuilderParent,
{
pub fn invoke_requests(self) -> Result<CmdDataArrayBuilder<InvReqBuilder<P, 3>>, Error> {
self.timed_request(false)?.invoke_requests()
}
}
impl<P> InvReqBuilder<P, 2>
where
P: TLVBuilderParent,
{
pub fn invoke_requests(self) -> Result<CmdDataArrayBuilder<InvReqBuilder<P, 3>>, Error> {
CmdDataArrayBuilder::new(
InvReqBuilder { p: self.p },
&TLVTag::Context(InvReqTag::InvokeRequests as u8),
)
}
}
impl<P> InvReqBuilder<P, 3>
where
P: TLVBuilderParent,
{
pub fn interaction_model_revision(mut self, value: u8) -> Result<InvReqBuilder<P, 4>, Error> {
self.p.writer().u8(
&TLVTag::Context(crate::im::encoding::IM_REVISION_TAG),
value,
)?;
Ok(InvReqBuilder { p: self.p })
}
pub fn end(self) -> Result<P, Error> {
self.interaction_model_revision(IM_REVISION)?.end()
}
}
impl<P> InvReqBuilder<P, 4>
where
P: TLVBuilderParent,
{
pub fn end(mut self) -> Result<P, Error> {
self.p.writer().end_container()?;
Ok(self.p)
}
}
impl<P, const F: usize> TLVBuilderParent for InvReqBuilder<P, F>
where
P: TLVBuilderParent,
{
type Write = P::Write;
fn writer(&mut self) -> &mut Self::Write {
self.p.writer()
}
}
impl<P, const F: usize> core::fmt::Debug for InvReqBuilder<P, F>
where
P: core::fmt::Debug,
{
fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
write!(f, "{:?}::InvokeRequestMessage<{}>", self.p, F)
}
}
#[cfg(feature = "defmt")]
impl<P, const F: usize> defmt::Format for InvReqBuilder<P, F>
where
P: defmt::Format,
{
fn format(&self, fmt: defmt::Formatter<'_>) {
defmt::write!(fmt, "{:?}::InvokeRequestMessage<{}>", self.p, F);
}
}
pub struct CmdDataArrayBuilder<P> {
p: P,
}
impl<P> CmdDataArrayBuilder<P>
where
P: TLVBuilderParent,
{
pub fn new(mut p: P, tag: &TLVTag) -> Result<Self, Error> {
p.writer().start_array(tag)?;
Ok(Self { p })
}
pub fn push(self) -> Result<CmdDataBuilder<Self, 0>, Error> {
CmdDataBuilder::new(self, &TLVTag::Anonymous)
}
pub fn end(mut self) -> Result<P, Error> {
self.p.writer().end_container()?;
Ok(self.p)
}
}
impl<P> TLVBuilder<P> for CmdDataArrayBuilder<P>
where
P: TLVBuilderParent,
{
fn new(parent: P, tag: &TLVTag) -> Result<Self, Error> {
Self::new(parent, tag)
}
fn unchecked_into_parent(self) -> P {
self.p
}
}
impl<P> TLVBuilderParent for CmdDataArrayBuilder<P>
where
P: TLVBuilderParent,
{
type Write = P::Write;
fn writer(&mut self) -> &mut Self::Write {
self.p.writer()
}
}
impl<P> core::fmt::Debug for CmdDataArrayBuilder<P>
where
P: core::fmt::Debug,
{
fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
write!(f, "{:?}[]", self.p)
}
}
#[cfg(feature = "defmt")]
impl<P> defmt::Format for CmdDataArrayBuilder<P>
where
P: defmt::Format,
{
fn format(&self, fmt: defmt::Formatter<'_>) {
defmt::write!(fmt, "{:?}[]", self.p);
}
}
pub struct CmdDataBuilder<P, const F: usize = 0> {
p: P,
_f: PhantomData<[(); F]>,
}
impl<P> CmdDataBuilder<P, 0>
where
P: TLVBuilderParent,
{
pub fn new(mut p: P, tag: &TLVTag) -> Result<Self, Error> {
p.writer().start_struct(tag)?;
Ok(Self { p, _f: PhantomData })
}
}
impl<P> TLVBuilder<P> for CmdDataBuilder<P, 0>
where
P: TLVBuilderParent,
{
fn new(parent: P, tag: &TLVTag) -> Result<Self, Error> {
Self::new(parent, tag)
}
fn unchecked_into_parent(self) -> P {
self.p
}
}
impl<P> CmdDataBuilder<P, 0>
where
P: TLVBuilderParent,
{
pub fn path(
mut self,
endpoint: EndptId,
cluster: ClusterId,
cmd: CmdId,
) -> Result<CmdDataBuilder<P, 1>, Error> {
let w = self.p.writer();
w.start_list(&TLVTag::Context(CmdDataTag::Path as u8))?;
w.u16(&TLVTag::Context(CmdPathTag::Endpoint as u8), endpoint)?;
w.u32(&TLVTag::Context(CmdPathTag::Cluster as u8), cluster)?;
w.u32(&TLVTag::Context(CmdPathTag::Command as u8), cmd)?;
w.end_container()?;
Ok(CmdDataBuilder {
p: self.p,
_f: PhantomData,
})
}
pub fn path_from(mut self, path: &crate::im::CmdPath) -> Result<CmdDataBuilder<P, 1>, Error> {
path.to_tlv(&TLVTag::Context(CmdDataTag::Path as u8), self.p.writer())?;
Ok(CmdDataBuilder {
p: self.p,
_f: PhantomData,
})
}
}
impl<P> CmdDataBuilder<P, 1>
where
P: TLVBuilderParent,
{
pub fn data<F>(mut self, f: F) -> Result<CmdDataBuilder<P, 2>, Error>
where
F: FnOnce(&mut P::Write) -> Result<(), Error>,
{
f(self.p.writer())?;
Ok(CmdDataBuilder {
p: self.p,
_f: PhantomData,
})
}
pub fn data_builder<B>(self) -> Result<B, Error>
where
B: TLVBuilder<CmdDataBuilder<P, 2>>,
{
let advanced = CmdDataBuilder {
p: self.p,
_f: PhantomData,
};
B::new(advanced, &TLVTag::Context(CmdDataTag::Data as u8))
}
}
impl<P> CmdDataBuilder<P, 2>
where
P: TLVBuilderParent,
{
pub fn command_ref(mut self, value: u16) -> Result<CmdDataBuilder<P, 3>, Error> {
self.p
.writer()
.u16(&TLVTag::Context(CmdDataTag::CommandRef as u8), value)?;
Ok(CmdDataBuilder {
p: self.p,
_f: PhantomData,
})
}
}
impl<P> CmdDataBuilder<P, 2>
where
P: TLVBuilderParent,
{
pub fn end(self) -> Result<P, Error> {
CmdDataBuilder::<P, 3> {
p: self.p,
_f: PhantomData,
}
.end()
}
}
impl<P> CmdDataBuilder<P, 3>
where
P: TLVBuilderParent,
{
pub fn end(mut self) -> Result<P, Error> {
self.p.writer().end_container()?;
Ok(self.p)
}
}
impl<P, const F: usize> TLVBuilderParent for CmdDataBuilder<P, F>
where
P: TLVBuilderParent,
{
type Write = P::Write;
fn writer(&mut self) -> &mut Self::Write {
self.p.writer()
}
}
impl<P, const F: usize> core::fmt::Debug for CmdDataBuilder<P, F>
where
P: core::fmt::Debug,
{
fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
write!(f, "{:?}::CmdData<{}>", self.p, F)
}
}
#[cfg(feature = "defmt")]
impl<P, const F: usize> defmt::Format for CmdDataBuilder<P, F>
where
P: defmt::Format,
{
fn format(&self, fmt: defmt::Formatter<'_>) {
defmt::write!(fmt, "{:?}::CmdData<{}>", self.p, F);
}
}