use core::marker::PhantomData;
use crate::error::Error;
use crate::im::encoding::{AttrId, ClusterId, EndptId};
use crate::im::{AttrDataTag, AttrPathTag, WriteReqTag, IM_REVISION};
use crate::tlv::{TLVBuilder, TLVBuilderParent, TLVTag, TLVWrite};
pub struct WriteReqBuilder<P, const F: usize = 0> {
p: P,
}
impl<P> WriteReqBuilder<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 WriteReqBuilder<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> WriteReqBuilder<P, 0>
where
P: TLVBuilderParent,
{
pub fn suppress_response(mut self, value: bool) -> Result<WriteReqBuilder<P, 1>, Error> {
self.p
.writer()
.bool(&TLVTag::Context(WriteReqTag::SuppressResponse as u8), value)?;
Ok(WriteReqBuilder { p: self.p })
}
}
impl<P> WriteReqBuilder<P, 0>
where
P: TLVBuilderParent,
{
pub fn timed_request(self, value: bool) -> Result<WriteReqBuilder<P, 2>, Error> {
WriteReqBuilder::<P, 1> { p: self.p }.timed_request(value)
}
}
impl<P> WriteReqBuilder<P, 1>
where
P: TLVBuilderParent,
{
pub fn timed_request(mut self, value: bool) -> Result<WriteReqBuilder<P, 2>, Error> {
self.p
.writer()
.bool(&TLVTag::Context(WriteReqTag::TimedRequest as u8), value)?;
Ok(WriteReqBuilder { p: self.p })
}
}
impl<P> WriteReqBuilder<P, 0>
where
P: TLVBuilderParent,
{
pub fn write_requests(self) -> Result<AttrDataArrayBuilder<WriteReqBuilder<P, 3>>, Error> {
WriteReqBuilder::<P, 2> { p: self.p }.write_requests()
}
}
impl<P> WriteReqBuilder<P, 1>
where
P: TLVBuilderParent,
{
pub fn write_requests(self) -> Result<AttrDataArrayBuilder<WriteReqBuilder<P, 3>>, Error> {
WriteReqBuilder::<P, 2> { p: self.p }.write_requests()
}
}
impl<P> WriteReqBuilder<P, 2>
where
P: TLVBuilderParent,
{
pub fn write_requests(self) -> Result<AttrDataArrayBuilder<WriteReqBuilder<P, 3>>, Error> {
AttrDataArrayBuilder::new(
WriteReqBuilder { p: self.p },
&TLVTag::Context(WriteReqTag::WriteRequests as u8),
)
}
}
impl<P> WriteReqBuilder<P, 3>
where
P: TLVBuilderParent,
{
pub fn more_chunks(mut self, value: bool) -> Result<WriteReqBuilder<P, 4>, Error> {
self.p
.writer()
.bool(&TLVTag::Context(WriteReqTag::MoreChunked as u8), value)?;
Ok(WriteReqBuilder { p: self.p })
}
}
impl<P> WriteReqBuilder<P, 3>
where
P: TLVBuilderParent,
{
pub fn end(self) -> Result<P, Error> {
WriteReqBuilder::<P, 4> { p: self.p }.end()
}
}
impl<P> WriteReqBuilder<P, 3>
where
P: TLVBuilderParent,
{
pub fn interaction_model_revision(self, value: u8) -> Result<WriteReqBuilder<P, 5>, Error> {
WriteReqBuilder::<P, 4> { p: self.p }.interaction_model_revision(value)
}
}
impl<P> WriteReqBuilder<P, 4>
where
P: TLVBuilderParent,
{
pub fn interaction_model_revision(mut self, value: u8) -> Result<WriteReqBuilder<P, 5>, Error> {
self.p.writer().u8(
&TLVTag::Context(crate::im::encoding::IM_REVISION_TAG),
value,
)?;
Ok(WriteReqBuilder { p: self.p })
}
pub fn end(self) -> Result<P, Error> {
self.interaction_model_revision(IM_REVISION)?.end()
}
}
impl<P> WriteReqBuilder<P, 5>
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 WriteReqBuilder<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 WriteReqBuilder<P, F>
where
P: core::fmt::Debug,
{
fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
write!(f, "{:?}::WriteRequestMessage<{}>", self.p, F)
}
}
#[cfg(feature = "defmt")]
impl<P, const F: usize> defmt::Format for WriteReqBuilder<P, F>
where
P: defmt::Format,
{
fn format(&self, fmt: defmt::Formatter<'_>) {
defmt::write!(fmt, "{:?}::WriteRequestMessage<{}>", self.p, F);
}
}
pub struct AttrDataArrayBuilder<P> {
p: P,
}
impl<P> AttrDataArrayBuilder<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<AttrDataBuilder<Self, 0>, Error> {
AttrDataBuilder::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 AttrDataArrayBuilder<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 AttrDataArrayBuilder<P>
where
P: TLVBuilderParent,
{
type Write = P::Write;
fn writer(&mut self) -> &mut Self::Write {
self.p.writer()
}
}
impl<P> core::fmt::Debug for AttrDataArrayBuilder<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 AttrDataArrayBuilder<P>
where
P: defmt::Format,
{
fn format(&self, fmt: defmt::Formatter<'_>) {
defmt::write!(fmt, "{:?}[]", self.p);
}
}
pub struct AttrDataBuilder<P, const F: usize = 0> {
p: P,
_f: PhantomData<[(); F]>,
}
impl<P> AttrDataBuilder<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 AttrDataBuilder<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> AttrDataBuilder<P, 0>
where
P: TLVBuilderParent,
{
pub fn data_version(mut self, value: u32) -> Result<AttrDataBuilder<P, 1>, Error> {
self.p
.writer()
.u32(&TLVTag::Context(AttrDataTag::DataVer as u8), value)?;
Ok(AttrDataBuilder {
p: self.p,
_f: PhantomData,
})
}
}
impl<P> AttrDataBuilder<P, 0>
where
P: TLVBuilderParent,
{
pub fn path(
self,
endpoint: EndptId,
cluster: ClusterId,
attr: AttrId,
) -> Result<AttrDataBuilder<P, 2>, Error> {
AttrDataBuilder::<P, 1> {
p: self.p,
_f: PhantomData,
}
.path(endpoint, cluster, attr)
}
pub fn path_from(self, path: &crate::im::AttrPath) -> Result<AttrDataBuilder<P, 2>, Error> {
AttrDataBuilder::<P, 1> {
p: self.p,
_f: PhantomData,
}
.path_from(path)
}
}
impl<P> AttrDataBuilder<P, 1>
where
P: TLVBuilderParent,
{
pub fn path(
mut self,
endpoint: EndptId,
cluster: ClusterId,
attr: AttrId,
) -> Result<AttrDataBuilder<P, 2>, Error> {
let w = self.p.writer();
w.start_list(&TLVTag::Context(AttrDataTag::Path as u8))?;
w.u16(&TLVTag::Context(AttrPathTag::Endpoint as u8), endpoint)?;
w.u32(&TLVTag::Context(AttrPathTag::Cluster as u8), cluster)?;
w.u32(&TLVTag::Context(AttrPathTag::Attribute as u8), attr)?;
w.end_container()?;
Ok(AttrDataBuilder {
p: self.p,
_f: PhantomData,
})
}
pub fn path_from(mut self, path: &crate::im::AttrPath) -> Result<AttrDataBuilder<P, 2>, Error> {
use crate::tlv::ToTLV;
path.to_tlv(&TLVTag::Context(AttrDataTag::Path as u8), self.p.writer())?;
Ok(AttrDataBuilder {
p: self.p,
_f: PhantomData,
})
}
}
impl<P> AttrDataBuilder<P, 2>
where
P: TLVBuilderParent,
{
pub fn data<F>(mut self, f: F) -> Result<AttrDataBuilder<P, 3>, Error>
where
F: FnOnce(&mut P::Write) -> Result<(), Error>,
{
f(self.p.writer())?;
Ok(AttrDataBuilder {
p: self.p,
_f: PhantomData,
})
}
pub fn data_builder<B>(self) -> Result<B, Error>
where
B: TLVBuilder<AttrDataBuilder<P, 3>>,
{
let advanced = AttrDataBuilder {
p: self.p,
_f: PhantomData,
};
B::new(advanced, &TLVTag::Context(AttrDataTag::Data as u8))
}
}
impl<P> AttrDataBuilder<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 AttrDataBuilder<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 AttrDataBuilder<P, F>
where
P: core::fmt::Debug,
{
fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
write!(f, "{:?}::AttrData<{}>", self.p, F)
}
}
#[cfg(feature = "defmt")]
impl<P, const F: usize> defmt::Format for AttrDataBuilder<P, F>
where
P: defmt::Format,
{
fn format(&self, fmt: defmt::Formatter<'_>) {
defmt::write!(fmt, "{:?}::AttrData<{}>", self.p, F);
}
}