/*
*
* Copyright (c) 2025-2026 Project CHIP Authors
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
//! This module contains the implementation of the Unit Testing cluster and its handler.
use core::num::NonZeroU8;
use crate::dm::{
ArrayAttributeRead, ArrayAttributeWrite, Cluster, Dataver, InvokeContext, ReadContext,
WriteContext,
};
use crate::error::{Error, ErrorCode};
use crate::tlv::{
Nullable, NullableBuilder, OctetStr, Octets, OctetsArrayBuilder, OctetsBuilder, TLVArray,
TLVBuilder, TLVBuilderParent, TLVTag, TLVWrite, ToTLVArrayBuilder, ToTLVBuilder, Utf8Str,
Utf8StrBuilder,
};
use crate::utils::cell::RefCell;
use crate::utils::init::{init, Init, IntoFallibleInit};
use crate::utils::storage::Vec;
pub use crate::dm::clusters::decl::globals::*;
pub use crate::dm::clusters::decl::unit_testing::*;
use crate::{except, with};
#[derive(Debug)]
#[cfg_attr(feature = "defmt", derive(defmt::Format))]
struct TestListStructOctetOwned {
member_1: u64,
member_2: Vec<u8, 32>,
}
#[derive(Debug)]
#[cfg_attr(feature = "defmt", derive(defmt::Format))]
struct SimpleStructOwned {
a: u8,
b: bool,
c: SimpleEnum,
d: Vec<u8, 10>,
e: heapless::String<10>,
f: SimpleBitmap,
g: f32,
h: f64,
i: Option<TestGlobalEnum>,
}
impl SimpleStructOwned {
pub fn init() -> impl Init<Self> {
init!(Self {
a: 0,
b: false,
c: SimpleEnum::ValueA,
d <- Vec::init(),
e: heapless::String::new(),
f: SimpleBitmap::empty(),
g: 0.0,
h: 0.0,
i: Some(TestGlobalEnum::SomeValue),
})
}
}
#[derive(Debug)]
#[cfg_attr(feature = "defmt", derive(defmt::Format))]
struct TestGlobalStructOwned {
name: heapless::String<10>,
my_bitmap: Nullable<TestGlobalBitmap>,
my_enum: Option<Nullable<TestGlobalEnum>>,
}
impl TestGlobalStructOwned {
pub fn init() -> impl Init<Self> {
init!(Self {
name: heapless::String::new(),
my_bitmap <- Nullable::init_none(),
my_enum: None,
})
}
}
#[derive(Debug)]
#[cfg_attr(feature = "defmt", derive(defmt::Format))]
struct NullablesAndOptionalsStructOwned {
nullable_int: Nullable<u16>,
optional_int: Option<u16>,
nullable_optional_int: Option<Nullable<u16>>,
nullable_string: Nullable<heapless::String<10>>,
optional_string: Option<heapless::String<10>>,
nullable_optional_string: Option<Nullable<heapless::String<10>>>,
nullable_struct: Nullable<SimpleStructOwned>,
optional_struct: Option<SimpleStructOwned>,
nullable_optional_struct: Option<Nullable<SimpleStructOwned>>,
nullable_list: Nullable<Vec<SimpleEnum, 16>>,
optional_list: Option<Vec<SimpleEnum, 16>>,
nullable_optional_list: Option<Nullable<Vec<SimpleEnum, 16>>>,
}
impl NullablesAndOptionalsStructOwned {
pub fn init() -> impl Init<Self> {
init!(Self {
nullable_int <- Nullable::init_none(),
optional_int: None,
nullable_optional_int: None,
nullable_string <- Nullable::init_none(),
optional_string: None,
nullable_optional_string: None,
nullable_struct <- Nullable::init_none(),
optional_struct: None,
nullable_optional_struct: None,
nullable_list <- Nullable::init_none(),
optional_list: None,
nullable_optional_list: None,
})
}
pub fn update(&mut self, s: &NullablesAndOptionalsStruct) -> Result<(), Error> {
self.nullable_int = s.nullable_int()?.clone();
self.optional_int = s.optional_int()?;
self.nullable_optional_int = s.nullable_optional_int()?.clone();
self.nullable_string = Nullable::new(
s.nullable_string()?
.into_option()
.map(|s| s.try_into().map_err(|_| ErrorCode::InvalidAction))
.transpose()?,
);
self.optional_string = s
.optional_string()?
.map(|s| s.try_into().map_err(|_| ErrorCode::InvalidAction))
.transpose()?;
self.nullable_optional_string = if let Some(ss) = s.nullable_optional_string()? {
Some(Nullable::new(
ss.into_option()
.map(|s| s.try_into().map_err(|_| ErrorCode::InvalidAction))
.transpose()?,
))
} else {
None
};
self.nullable_struct = if let Some(s) = s.nullable_struct()?.as_opt_ref() {
Nullable::some(SimpleStructOwned {
a: s.a()?,
b: s.b()?,
c: s.c()?,
d: s.d()?
.0
.try_into()
.map_err(|_| ErrorCode::ConstraintError)?,
e: s.e()?.try_into().map_err(|_| ErrorCode::ConstraintError)?,
f: s.f()?,
g: s.g()?,
h: s.h()?,
i: s.i()?,
})
} else {
Nullable::none()
};
self.optional_struct = if let Some(s) = s.optional_struct()?.as_ref() {
Some(SimpleStructOwned {
a: s.a()?,
b: s.b()?,
c: s.c()?,
d: s.d()?
.0
.try_into()
.map_err(|_| ErrorCode::ConstraintError)?,
e: s.e()?.try_into().map_err(|_| ErrorCode::ConstraintError)?,
f: s.f()?,
g: s.g()?,
h: s.h()?,
i: s.i()?,
})
} else {
None
};
self.nullable_optional_struct = if let Some(s) = s.nullable_optional_struct()?.as_ref() {
Some(if let Some(s) = s.as_opt_ref() {
Nullable::some(SimpleStructOwned {
a: s.a()?,
b: s.b()?,
c: s.c()?,
d: s.d()?
.0
.try_into()
.map_err(|_| ErrorCode::ConstraintError)?,
e: s.e()?.try_into().map_err(|_| ErrorCode::ConstraintError)?,
f: s.f()?,
g: s.g()?,
h: s.h()?,
i: s.i()?,
})
} else {
Nullable::none()
})
} else {
None
};
self.optional_list = if let Some(l) = s.optional_list()?.as_ref() {
Some(l.iter().collect::<Result<Vec<_, 16>, _>>()?)
} else {
None
};
self.nullable_list = if let Some(l) = s.nullable_list()?.as_opt_ref() {
Nullable::some(l.iter().collect::<Result<Vec<_, 16>, _>>()?)
} else {
Nullable::none()
};
self.nullable_optional_list = if let Some(l) = s.nullable_optional_list()?.as_ref() {
Some(if let Some(l) = l.as_opt_ref() {
Nullable::some(l.iter().collect::<Result<Vec<_, 16>, _>>()?)
} else {
Nullable::none()
})
} else {
None
};
Ok(())
}
}
#[derive(Debug)]
#[cfg_attr(feature = "defmt", derive(defmt::Format))]
struct TestFabricScopedOwned {
fabric_sensitive_int8u: u8,
optional_fabric_sensitive_int8u: Option<u8>,
nullable_fabric_sensitive_int8u: Nullable<u8>,
optional_nullable_fabric_sensitive_int8u: Option<Nullable<u8>>,
fabric_sensitive_char_string: heapless::String<32>,
fabric_sensitive_struct: SimpleStructOwned,
fabric_sensitive_int8u_list: heapless::Vec<u8, 32>,
}
impl TestFabricScopedOwned {
pub fn init() -> impl Init<Self> {
init!(Self {
fabric_sensitive_int8u: 0,
optional_fabric_sensitive_int8u: None,
nullable_fabric_sensitive_int8u <- Nullable::init_none(),
optional_nullable_fabric_sensitive_int8u: None,
fabric_sensitive_char_string: heapless::String::new(),
fabric_sensitive_struct <- SimpleStructOwned::init(),
fabric_sensitive_int8u_list: heapless::Vec::new(),
})
}
pub fn update(&mut self, s: &TestFabricScoped) -> Result<(), crate::error::Error> {
self.fabric_sensitive_int8u = s
.fabric_sensitive_int_8_u()?
.ok_or(ErrorCode::ConstraintError)?;
self.optional_fabric_sensitive_int8u = s.optional_fabric_sensitive_int_8_u()?;
self.nullable_fabric_sensitive_int8u = s
.nullable_fabric_sensitive_int_8_u()?
.ok_or(ErrorCode::ConstraintError)?
.clone();
self.optional_nullable_fabric_sensitive_int8u =
s.nullable_optional_fabric_sensitive_int_8_u()?.clone();
self.fabric_sensitive_char_string = s
.fabric_sensitive_char_string()?
.ok_or(ErrorCode::ConstraintError)?
.try_into()
.map_err(|_| ErrorCode::ConstraintError)?;
let ss = s
.fabric_sensitive_struct()?
.ok_or(ErrorCode::ConstraintError)?;
self.fabric_sensitive_struct.a = ss.a()?;
self.fabric_sensitive_struct.b = ss.b()?;
self.fabric_sensitive_struct.c = ss.c()?;
self.fabric_sensitive_struct.d = ss
.d()?
.0
.try_into()
.map_err(|_| ErrorCode::ConstraintError)?;
self.fabric_sensitive_struct.e =
ss.e()?.try_into().map_err(|_| ErrorCode::ConstraintError)?;
self.fabric_sensitive_struct.f = ss.f()?;
self.fabric_sensitive_struct.g = ss.g()?;
self.fabric_sensitive_struct.h = ss.h()?;
self.fabric_sensitive_int8u_list.clear();
for i in s
.fabric_sensitive_int_8_u_list()?
.ok_or(ErrorCode::ConstraintError)?
.iter()
{
self.fabric_sensitive_int8u_list
.push(i?)
.map_err(|_| ErrorCode::ConstraintError)?;
}
Ok(())
}
}
#[derive(Debug)]
#[cfg_attr(feature = "defmt", derive(defmt::Format))]
pub struct UnitTestingHandlerData {
boolean: bool,
bitmap_8: Bitmap8MaskMap,
bitmap_16: Bitmap16MaskMap,
bitmap_32: Bitmap32MaskMap,
bitmap_64: Bitmap64MaskMap,
int_8_u: u8,
int_16_u: u16,
int_24_u: u32,
int_32_u: u32,
int_40_u: u64,
int_48_u: u64,
int_56_u: u64,
int_64_u: u64,
int_8_s: i8,
int_16_s: i16,
int_24_s: i32,
int_32_s: i32,
int_40_s: i64,
int_48_s: i64,
int_56_s: i64,
int_64_s: i64,
enum_8: u8,
enum_16: u16,
float_single: f32,
float_double: f64,
octet_string: Vec<u8, 10>,
list_int_8_u: Vec<u8, 16>,
list_octet_string: Vec<Vec<u8, 10>, 16>,
list_struct_octet_string: Vec<TestListStructOctetOwned, 16>,
long_octet_string: Vec<u8, 1000>,
char_string: heapless::String<10>,
long_char_string: heapless::String<1000>,
epoch_us: u64,
epoch_s: u32,
vendor_id: u16,
list_nullables_and_optionals_struct: Vec<NullablesAndOptionalsStructOwned, 16>,
enum_attr: SimpleEnum,
struct_attr: SimpleStructOwned,
range_restricted_int_8_u: u8,
range_restricted_int_8_s: i8,
range_restricted_int_16_u: u16,
range_restricted_int_16_s: i16,
list_long_octet_string: Vec<Vec<u8, 1000>, 16>,
list_fabric_scoped: Vec<(NonZeroU8, Vec<TestFabricScopedOwned, 16>), 16>,
timed_write_boolean: bool,
nullable_boolean: Nullable<bool>,
nullable_bitmap_8: Nullable<Bitmap8MaskMap>,
nullable_bitmap_16: Nullable<Bitmap16MaskMap>,
nullable_bitmap_32: Nullable<Bitmap32MaskMap>,
nullable_bitmap_64: Nullable<Bitmap64MaskMap>,
nullable_int_8_u: Nullable<u8>,
nullable_int_16_u: Nullable<u16>,
nullable_int_24_u: Nullable<u32>,
nullable_int_32_u: Nullable<u32>,
nullable_int_40_u: Nullable<u64>,
nullable_int_48_u: Nullable<u64>,
nullable_int_56_u: Nullable<u64>,
nullable_int_64_u: Nullable<u64>,
nullable_int_8_s: Nullable<i8>,
nullable_int_16_s: Nullable<i16>,
nullable_int_24_s: Nullable<i32>,
nullable_int_32_s: Nullable<i32>,
nullable_int_40_s: Nullable<i64>,
nullable_int_48_s: Nullable<i64>,
nullable_int_56_s: Nullable<i64>,
nullable_int_64_s: Nullable<i64>,
nullable_enum_8: Nullable<u8>,
nullable_enum_16: Nullable<u16>,
nullable_float_single: Nullable<f32>,
nullable_float_double: Nullable<f64>,
nullable_octet_string: Nullable<Vec<u8, 10>>,
nullable_char_string: Nullable<heapless::String<10>>,
nullable_enum_attr: Nullable<SimpleEnum>,
nullable_struct: Nullable<SimpleStructOwned>,
nullable_range_restricted_int_8_u: Nullable<u8>,
nullable_range_restricted_int_8_s: Nullable<i8>,
nullable_range_restricted_int_16_u: Nullable<u16>,
nullable_range_restricted_int_16_s: Nullable<i16>,
mei_int_8_u: u8,
global_enum: TestGlobalEnum,
global_struct: TestGlobalStructOwned,
nullable_global_enum: Nullable<TestGlobalEnum>,
nullable_global_struct: Nullable<TestGlobalStructOwned>,
}
impl UnitTestingHandlerData {
pub fn init() -> impl Init<Self> {
init!(Self {
boolean: false,
bitmap_8: Bitmap8MaskMap::empty(),
bitmap_16: Bitmap16MaskMap::empty(),
bitmap_32: Bitmap32MaskMap::empty(),
bitmap_64: Bitmap64MaskMap::empty(),
int_8_u: 0,
int_16_u: 0,
int_24_u: 0,
int_32_u: 0,
int_40_u: 0,
int_48_u: 0,
int_56_u: 0,
int_64_u: 0,
int_8_s: 0,
int_16_s: 0,
int_24_s: 0,
int_32_s: 0,
int_40_s: 0,
int_48_s: 0,
int_56_s: 0,
int_64_s: 0,
enum_8: 0,
enum_16: 0,
float_single: 0.0,
float_double: 0.0,
octet_string <- Vec::init(),
list_int_8_u <- Vec::init(),
list_octet_string <- Vec::init(),
list_struct_octet_string <- Vec::init(),
long_octet_string <- Vec::init(),
char_string: heapless::String::new(),
long_char_string: heapless::String::new(),
epoch_us: 0,
epoch_s: 0,
vendor_id: 0,
list_nullables_and_optionals_struct <- Vec::init().chain(|vec| {
unwrap!(vec.push_init_unchecked(NullablesAndOptionalsStructOwned::init()));
Ok(())
}),
enum_attr: SimpleEnum::ValueA,
struct_attr <- SimpleStructOwned::init(),
range_restricted_int_8_u: 70,
range_restricted_int_8_s: -20,
range_restricted_int_16_u: 200,
range_restricted_int_16_s: -100,
list_long_octet_string <- Vec::init().chain(|vec| {
for _ in 0..4 {
let item = Vec::init()
.chain(|item| {
unwrap!(item.extend_from_slice(b"0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef"));
Ok(())
});
unwrap!(vec.push_init_unchecked(item));
}
Ok(())
}),
list_fabric_scoped <- Vec::init(),
timed_write_boolean: false,
nullable_boolean <- Nullable::init_none(),
nullable_bitmap_8 <- Nullable::init_none(),
nullable_bitmap_16 <- Nullable::init_none(),
nullable_bitmap_32 <- Nullable::init_none(),
nullable_bitmap_64 <- Nullable::init_none(),
nullable_int_8_u : Nullable::some(0),
nullable_int_16_u : Nullable::some(0),
nullable_int_24_u : Nullable::some(0),
nullable_int_32_u : Nullable::some(0),
nullable_int_40_u : Nullable::some(0),
nullable_int_48_u : Nullable::some(0),
nullable_int_56_u : Nullable::some(0),
nullable_int_64_u : Nullable::some(0),
nullable_int_8_s : Nullable::some(0),
nullable_int_16_s : Nullable::some(0),
nullable_int_24_s : Nullable::some(0),
nullable_int_32_s : Nullable::some(0),
nullable_int_40_s : Nullable::some(0),
nullable_int_48_s : Nullable::some(0),
nullable_int_56_s : Nullable::some(0),
nullable_int_64_s : Nullable::some(0),
nullable_enum_8 <- Nullable::init_none(),
nullable_enum_16 <- Nullable::init_none(),
nullable_float_single <- Nullable::init_none(),
nullable_float_double <- Nullable::init_none(),
nullable_octet_string <- Nullable::init_some(Vec::init()),
nullable_char_string: Nullable::some(heapless::String::new()),
nullable_enum_attr <- Nullable::init_none(),
nullable_struct <- Nullable::init_none(),
nullable_range_restricted_int_8_u: Nullable::some(70),
nullable_range_restricted_int_8_s: Nullable::some(-20),
nullable_range_restricted_int_16_u: Nullable::some(200),
nullable_range_restricted_int_16_s: Nullable::some(-100),
mei_int_8_u: 0,
global_enum: TestGlobalEnum::SomeValue,
global_struct <- TestGlobalStructOwned::init(),
nullable_global_enum <- Nullable::init_none(),
nullable_global_struct <- Nullable::init_none(),
})
}
}
pub struct UnitTestingHandler<'a> {
dataver: Dataver,
data: &'a RefCell<UnitTestingHandlerData>,
}
impl<'a> UnitTestingHandler<'a> {
pub const fn new(dataver: Dataver, data: &'a RefCell<UnitTestingHandlerData>) -> Self {
Self { dataver, data }
}
pub const fn adapt(self) -> HandlerAdaptor<Self> {
HandlerAdaptor(self)
}
}
impl ClusterHandler for UnitTestingHandler<'_> {
const CLUSTER: Cluster<'static> = FULL_CLUSTER.with_attrs(with!(required)).with_cmds(except!(
CommandId::TestUnknownCommand
| CommandId::TestSimpleArgumentRequest
| CommandId::TestStructArrayArgumentRequest
| CommandId::TestComplexNullableOptionalRequest
));
fn dataver(&self) -> u32 {
self.dataver.get()
}
fn dataver_changed(&self) {
self.dataver.changed();
}
fn boolean(&self, _ctx: impl ReadContext) -> Result<bool, Error> {
Ok(self.data.borrow().boolean)
}
fn bitmap_8(&self, _ctx: impl ReadContext) -> Result<Bitmap8MaskMap, Error> {
Ok(self.data.borrow().bitmap_8)
}
fn bitmap_16(&self, _ctx: impl ReadContext) -> Result<Bitmap16MaskMap, Error> {
Ok(self.data.borrow().bitmap_16)
}
fn bitmap_32(&self, _ctx: impl ReadContext) -> Result<Bitmap32MaskMap, Error> {
Ok(self.data.borrow().bitmap_32)
}
fn bitmap_64(&self, _ctx: impl ReadContext) -> Result<Bitmap64MaskMap, Error> {
Ok(self.data.borrow().bitmap_64)
}
fn int_8_u(&self, _ctx: impl ReadContext) -> Result<u8, Error> {
Ok(self.data.borrow().int_8_u)
}
fn int_16_u(&self, _ctx: impl ReadContext) -> Result<u16, Error> {
Ok(self.data.borrow().int_16_u)
}
fn int_24_u(&self, _ctx: impl ReadContext) -> Result<u32, Error> {
Ok(self.data.borrow().int_24_u)
}
fn int_32_u(&self, _ctx: impl ReadContext) -> Result<u32, Error> {
Ok(self.data.borrow().int_32_u)
}
fn int_40_u(&self, _ctx: impl ReadContext) -> Result<u64, Error> {
Ok(self.data.borrow().int_40_u)
}
fn int_48_u(&self, _ctx: impl ReadContext) -> Result<u64, Error> {
Ok(self.data.borrow().int_48_u)
}
fn int_56_u(&self, _ctx: impl ReadContext) -> Result<u64, Error> {
Ok(self.data.borrow().int_56_u)
}
fn int_64_u(&self, _ctx: impl ReadContext) -> Result<u64, Error> {
Ok(self.data.borrow().int_64_u)
}
fn int_8_s(&self, _ctx: impl ReadContext) -> Result<i8, Error> {
Ok(self.data.borrow().int_8_s)
}
fn int_16_s(&self, _ctx: impl ReadContext) -> Result<i16, Error> {
Ok(self.data.borrow().int_16_s)
}
fn int_24_s(&self, _ctx: impl ReadContext) -> Result<i32, Error> {
Ok(self.data.borrow().int_24_s)
}
fn int_32_s(&self, _ctx: impl ReadContext) -> Result<i32, Error> {
Ok(self.data.borrow().int_32_s)
}
fn int_40_s(&self, _ctx: impl ReadContext) -> Result<i64, Error> {
Ok(self.data.borrow().int_40_s)
}
fn int_48_s(&self, _ctx: impl ReadContext) -> Result<i64, Error> {
Ok(self.data.borrow().int_48_s)
}
fn int_56_s(&self, _ctx: impl ReadContext) -> Result<i64, Error> {
Ok(self.data.borrow().int_56_s)
}
fn int_64_s(&self, _ctx: impl ReadContext) -> Result<i64, Error> {
Ok(self.data.borrow().int_64_s)
}
fn enum_8(&self, _ctx: impl ReadContext) -> Result<u8, Error> {
Ok(self.data.borrow().enum_8)
}
fn enum_16(&self, _ctx: impl ReadContext) -> Result<u16, Error> {
Ok(self.data.borrow().enum_16)
}
fn float_single(&self, _ctx: impl ReadContext) -> Result<f32, Error> {
Ok(self.data.borrow().float_single)
}
fn float_double(&self, _ctx: impl ReadContext) -> Result<f64, Error> {
Ok(self.data.borrow().float_double)
}
fn octet_string<P: TLVBuilderParent>(
&self,
_ctx: impl ReadContext,
builder: OctetsBuilder<P>,
) -> Result<P, Error> {
builder.set(Octets(self.data.borrow().octet_string.as_slice()))
}
fn list_int_8_u<P: TLVBuilderParent>(
&self,
_ctx: impl ReadContext,
builder: ArrayAttributeRead<ToTLVArrayBuilder<P, u8>, ToTLVBuilder<P, u8>>,
) -> Result<P, Error> {
match builder {
ArrayAttributeRead::ReadOne(index, builder) => {
let data = self.data.borrow();
if index < data.list_int_8_u.len() as u16 {
builder.set(&data.list_int_8_u[index as usize])
} else {
Err(ErrorCode::ConstraintError.into())
}
}
ArrayAttributeRead::ReadAll(mut builder) => {
let data = self.data.borrow();
for i in &data.list_int_8_u {
builder = builder.push(i)?;
}
builder.end()
}
ArrayAttributeRead::ReadNone(builder) => builder.end(),
}
}
fn list_octet_string<P: TLVBuilderParent>(
&self,
_ctx: impl ReadContext,
builder: ArrayAttributeRead<OctetsArrayBuilder<P>, OctetsBuilder<P>>,
) -> Result<P, Error> {
match builder {
ArrayAttributeRead::ReadOne(index, builder) => {
let data = self.data.borrow();
if index < data.list_octet_string.len() as u16 {
builder.set(Octets(data.list_octet_string[index as usize].as_slice()))
} else {
Err(ErrorCode::ConstraintError.into())
}
}
ArrayAttributeRead::ReadAll(mut builder) => {
let data = self.data.borrow();
for i in &data.list_octet_string {
builder = builder.push(Octets(i.as_slice()))?;
}
builder.end()
}
ArrayAttributeRead::ReadNone(builder) => builder.end(),
}
}
fn list_struct_octet_string<P: TLVBuilderParent>(
&self,
_ctx: impl ReadContext,
builder: ArrayAttributeRead<
TestListStructOctetArrayBuilder<P>,
TestListStructOctetBuilder<P>,
>,
) -> Result<P, Error> {
match builder {
ArrayAttributeRead::ReadOne(index, builder) => {
let data = self.data.borrow();
if index < data.list_struct_octet_string.len() as u16 {
let s = &data.list_struct_octet_string[index as usize];
builder
.member_1(s.member_1)?
.member_2(Octets(&s.member_2))?
.end()
} else {
Err(ErrorCode::ConstraintError.into())
}
}
ArrayAttributeRead::ReadAll(mut builder) => {
let data = self.data.borrow();
for s in &data.list_struct_octet_string {
builder = builder
.push()?
.member_1(s.member_1)?
.member_2(Octets(&s.member_2))?
.end()?;
}
builder.end()
}
ArrayAttributeRead::ReadNone(builder) => builder.end(),
}
}
fn long_octet_string<P: TLVBuilderParent>(
&self,
_ctx: impl ReadContext,
builder: OctetsBuilder<P>,
) -> Result<P, Error> {
builder.set(Octets(self.data.borrow().long_octet_string.as_slice()))
}
fn char_string<P: TLVBuilderParent>(
&self,
_ctx: impl ReadContext,
builder: Utf8StrBuilder<P>,
) -> Result<P, Error> {
builder.set(self.data.borrow().char_string.as_str())
}
fn long_char_string<P: TLVBuilderParent>(
&self,
_ctx: impl ReadContext,
builder: Utf8StrBuilder<P>,
) -> Result<P, Error> {
builder.set(self.data.borrow().long_char_string.as_str())
}
fn epoch_us(&self, _ctx: impl ReadContext) -> Result<u64, Error> {
Ok(self.data.borrow().epoch_us)
}
fn epoch_s(&self, _ctx: impl ReadContext) -> Result<u32, Error> {
Ok(self.data.borrow().epoch_s)
}
fn vendor_id(&self, _ctx: impl ReadContext) -> Result<u16, Error> {
Ok(self.data.borrow().vendor_id)
}
fn list_nullables_and_optionals_struct<P: TLVBuilderParent>(
&self,
_ctx: impl ReadContext,
builder: ArrayAttributeRead<
NullablesAndOptionalsStructArrayBuilder<P>,
NullablesAndOptionalsStructBuilder<P>,
>,
) -> Result<P, Error> {
fn read_one<PP: TLVBuilderParent>(
builder: NullablesAndOptionalsStructBuilder<PP>,
s: &NullablesAndOptionalsStructOwned,
) -> Result<PP, Error> {
builder
.nullable_int(s.nullable_int.clone())?
.optional_int(s.optional_int)?
.nullable_optional_int(s.nullable_optional_int.clone())?
.nullable_string(s.nullable_string.as_deref())?
.optional_string(s.optional_string.as_deref())?
.nullable_optional_string(
s.nullable_optional_string.as_ref().map(|s| s.as_deref()),
)?
.nullable_struct()?
.with_non_null(s.nullable_struct.as_ref(), |ss, builder| {
builder
.a(ss.a)?
.b(ss.b)?
.c(ss.c)?
.d(Octets(&ss.d))?
.e(ss.e.as_str())?
.f(ss.f)?
.g(ss.g)?
.h(ss.h)?
.i(ss.i)?
.end()
})?
.optional_struct()?
.with_some(s.optional_struct.as_ref(), |ss, builder| {
builder
.a(ss.a)?
.b(ss.b)?
.c(ss.c)?
.d(Octets(&ss.d))?
.e(ss.e.as_str())?
.f(ss.f)?
.g(ss.g)?
.h(ss.h)?
.i(ss.i)?
.end()
})?
.nullable_optional_struct()?
.with_some(s.nullable_optional_struct.as_ref(), |ss, builder| {
builder.with_non_null(ss.as_ref(), |ss, builder| {
builder
.a(ss.a)?
.b(ss.b)?
.c(ss.c)?
.d(Octets(&ss.d))?
.e(ss.e.as_str())?
.f(ss.f)?
.g(ss.g)?
.h(ss.h)?
.i(ss.i)?
.end()
})
})?
.nullable_list()?
.with_non_null(s.nullable_list.as_ref(), |l, mut builder| {
for s in *l {
builder = builder.push(s)?;
}
builder.end()
})?
.optional_list()?
.with_some(s.optional_list.as_ref(), |l, mut builder| {
for s in *l {
builder = builder.push(s)?;
}
builder.end()
})?
.nullable_optional_list()?
.with_some(s.nullable_optional_list.as_ref(), |l, builder| {
builder.with_non_null(l.as_ref(), |l, mut builder| {
for s in *l {
builder = builder.push(s)?;
}
builder.end()
})
})?
.end()
}
match builder {
ArrayAttributeRead::ReadOne(index, builder) => {
let data = self.data.borrow();
if index < data.list_nullables_and_optionals_struct.len() as u16 {
let s = &data.list_nullables_and_optionals_struct[index as usize];
read_one(builder, s)
} else {
Err(ErrorCode::ConstraintError.into())
}
}
ArrayAttributeRead::ReadAll(mut builder) => {
let data = self.data.borrow();
for s in &data.list_nullables_and_optionals_struct {
builder = read_one(builder.push()?, s)?;
}
builder.end()
}
ArrayAttributeRead::ReadNone(builder) => builder.end(),
}
}
fn enum_attr(&self, _ctx: impl ReadContext) -> Result<SimpleEnum, Error> {
Ok(self.data.borrow().enum_attr)
}
fn struct_attr<P: TLVBuilderParent>(
&self,
_ctx: impl ReadContext,
builder: SimpleStructBuilder<P>,
) -> Result<P, Error> {
let data = self.data.borrow();
let s = &data.struct_attr;
builder
.a(s.a)?
.b(s.b)?
.c(s.c)?
.d(Octets(&s.d))?
.e(s.e.as_str())?
.f(s.f)?
.g(s.g)?
.h(s.h)?
.i(s.i)?
.end()
}
fn range_restricted_int_8_u(&self, _ctx: impl ReadContext) -> Result<u8, Error> {
Ok(self.data.borrow().range_restricted_int_8_u)
}
fn range_restricted_int_8_s(&self, _ctx: impl ReadContext) -> Result<i8, Error> {
Ok(self.data.borrow().range_restricted_int_8_s)
}
fn range_restricted_int_16_u(&self, _ctx: impl ReadContext) -> Result<u16, Error> {
Ok(self.data.borrow().range_restricted_int_16_u)
}
fn range_restricted_int_16_s(&self, _ctx: impl ReadContext) -> Result<i16, Error> {
Ok(self.data.borrow().range_restricted_int_16_s)
}
fn list_long_octet_string<P: TLVBuilderParent>(
&self,
_ctx: impl ReadContext,
builder: ArrayAttributeRead<OctetsArrayBuilder<P>, OctetsBuilder<P>>,
) -> Result<P, Error> {
match builder {
ArrayAttributeRead::ReadOne(index, builder) => {
let data = self.data.borrow();
if index < data.list_long_octet_string.len() as u16 {
builder.set(Octets(
data.list_long_octet_string[index as usize].as_slice(),
))
} else {
Err(ErrorCode::ConstraintError.into())
}
}
ArrayAttributeRead::ReadAll(mut builder) => {
let data = self.data.borrow();
for i in &data.list_long_octet_string {
builder = builder.push(Octets(i.as_slice()))?;
}
builder.end()
}
ArrayAttributeRead::ReadNone(builder) => builder.end(),
}
}
fn list_fabric_scoped<P: TLVBuilderParent>(
&self,
ctx: impl ReadContext,
builder: ArrayAttributeRead<TestFabricScopedArrayBuilder<P>, TestFabricScopedBuilder<P>>,
) -> Result<P, Error> {
fn read_into<P: TLVBuilderParent>(
accessing_fab_idx: u8,
fabric_idx: NonZeroU8,
s: &TestFabricScopedOwned,
builder: TestFabricScopedBuilder<P>,
) -> Result<P, Error> {
let same_fab_idx = accessing_fab_idx == fabric_idx.get();
builder
.fabric_sensitive_int_8_u(same_fab_idx.then_some(s.fabric_sensitive_int8u))?
.optional_fabric_sensitive_int_8_u(
same_fab_idx
.then_some(s.optional_fabric_sensitive_int8u)
.flatten(),
)?
.nullable_fabric_sensitive_int_8_u(
same_fab_idx.then_some(s.nullable_fabric_sensitive_int8u.clone()),
)?
.nullable_optional_fabric_sensitive_int_8_u(
same_fab_idx
.then_some(s.optional_nullable_fabric_sensitive_int8u.clone())
.flatten(),
)?
.fabric_sensitive_char_string(
same_fab_idx.then_some(s.fabric_sensitive_char_string.as_str()),
)?
.fabric_sensitive_struct()?
.with_some_if(same_fab_idx, |builder| {
builder
.a(s.fabric_sensitive_struct.a)?
.b(s.fabric_sensitive_struct.b)?
.c(s.fabric_sensitive_struct.c)?
.d(Octets(&s.fabric_sensitive_struct.d))?
.e(s.fabric_sensitive_struct.e.as_str())?
.f(s.fabric_sensitive_struct.f)?
.g(s.fabric_sensitive_struct.g)?
.h(s.fabric_sensitive_struct.h)?
.i(s.fabric_sensitive_struct.i)?
.end()
})?
.fabric_sensitive_int_8_u_list()?
.with_some_if(same_fab_idx, |mut builder| {
for i in &s.fabric_sensitive_int8u_list {
builder = builder.push(i)?;
}
builder.end()
})?
.fabric_index(Some(fabric_idx.get()))?
.end()
}
let attr = ctx.attr();
let data = self.data.borrow();
let mut list = data
.list_fabric_scoped
.iter()
.flat_map(|(fab_idx, fab_items)| fab_items.iter().map(move |item| (fab_idx, item)))
.filter(|s| !attr.fab_filter || s.0.get() == attr.fab_idx);
match builder {
ArrayAttributeRead::ReadOne(index, builder) => {
let item = list.nth(index as _).ok_or(ErrorCode::ConstraintError)?;
read_into(attr.fab_idx, *item.0, item.1, builder)
}
ArrayAttributeRead::ReadAll(mut builder) => {
for s in list {
builder = read_into(attr.fab_idx, *s.0, s.1, builder.push()?)?;
}
builder.end()
}
ArrayAttributeRead::ReadNone(builder) => builder.end(),
}
}
fn timed_write_boolean(&self, _ctx: impl ReadContext) -> Result<bool, Error> {
Ok(self.data.borrow().timed_write_boolean)
}
fn general_error_boolean(&self, _ctx: impl ReadContext) -> Result<bool, Error> {
Err(ErrorCode::InvalidDataType.into())
}
fn cluster_error_boolean(&self, _ctx: impl ReadContext) -> Result<bool, Error> {
Err(ErrorCode::Invalid.into())
}
fn nullable_boolean(&self, _ctx: impl ReadContext) -> Result<Nullable<bool>, Error> {
Ok(self.data.borrow().nullable_boolean.clone())
}
fn nullable_bitmap_8(&self, _ctx: impl ReadContext) -> Result<Nullable<Bitmap8MaskMap>, Error> {
Ok(self.data.borrow().nullable_bitmap_8.clone())
}
fn nullable_bitmap_16(
&self,
_ctx: impl ReadContext,
) -> Result<Nullable<Bitmap16MaskMap>, Error> {
Ok(self.data.borrow().nullable_bitmap_16.clone())
}
fn nullable_bitmap_32(
&self,
_ctx: impl ReadContext,
) -> Result<Nullable<Bitmap32MaskMap>, Error> {
Ok(self.data.borrow().nullable_bitmap_32.clone())
}
fn nullable_bitmap_64(
&self,
_ctx: impl ReadContext,
) -> Result<Nullable<Bitmap64MaskMap>, Error> {
Ok(self.data.borrow().nullable_bitmap_64.clone())
}
fn nullable_int_8_u(&self, _ctx: impl ReadContext) -> Result<Nullable<u8>, Error> {
Ok(self.data.borrow().nullable_int_8_u.clone())
}
fn nullable_int_16_u(&self, _ctx: impl ReadContext) -> Result<Nullable<u16>, Error> {
Ok(self.data.borrow().nullable_int_16_u.clone())
}
fn nullable_int_24_u(&self, _ctx: impl ReadContext) -> Result<Nullable<u32>, Error> {
Ok(self.data.borrow().nullable_int_24_u.clone())
}
fn nullable_int_32_u(&self, _ctx: impl ReadContext) -> Result<Nullable<u32>, Error> {
Ok(self.data.borrow().nullable_int_32_u.clone())
}
fn nullable_int_40_u(&self, _ctx: impl ReadContext) -> Result<Nullable<u64>, Error> {
Ok(self.data.borrow().nullable_int_40_u.clone())
}
fn nullable_int_48_u(&self, _ctx: impl ReadContext) -> Result<Nullable<u64>, Error> {
Ok(self.data.borrow().nullable_int_48_u.clone())
}
fn nullable_int_56_u(&self, _ctx: impl ReadContext) -> Result<Nullable<u64>, Error> {
Ok(self.data.borrow().nullable_int_56_u.clone())
}
fn nullable_int_64_u(&self, _ctx: impl ReadContext) -> Result<Nullable<u64>, Error> {
Ok(self.data.borrow().nullable_int_64_u.clone())
}
fn nullable_int_8_s(&self, _ctx: impl ReadContext) -> Result<Nullable<i8>, Error> {
Ok(self.data.borrow().nullable_int_8_s.clone())
}
fn nullable_int_16_s(&self, _ctx: impl ReadContext) -> Result<Nullable<i16>, Error> {
Ok(self.data.borrow().nullable_int_16_s.clone())
}
fn nullable_int_24_s(&self, _ctx: impl ReadContext) -> Result<Nullable<i32>, Error> {
Ok(self.data.borrow().nullable_int_24_s.clone())
}
fn nullable_int_32_s(&self, _ctx: impl ReadContext) -> Result<Nullable<i32>, Error> {
Ok(self.data.borrow().nullable_int_32_s.clone())
}
fn nullable_int_40_s(&self, _ctx: impl ReadContext) -> Result<Nullable<i64>, Error> {
Ok(self.data.borrow().nullable_int_40_s.clone())
}
fn nullable_int_48_s(&self, _ctx: impl ReadContext) -> Result<Nullable<i64>, Error> {
Ok(self.data.borrow().nullable_int_48_s.clone())
}
fn nullable_int_56_s(&self, _ctx: impl ReadContext) -> Result<Nullable<i64>, Error> {
Ok(self.data.borrow().nullable_int_56_s.clone())
}
fn nullable_int_64_s(&self, _ctx: impl ReadContext) -> Result<Nullable<i64>, Error> {
Ok(self.data.borrow().nullable_int_64_s.clone())
}
fn nullable_enum_8(&self, _ctx: impl ReadContext) -> Result<Nullable<u8>, Error> {
Ok(self.data.borrow().nullable_enum_8.clone())
}
fn nullable_enum_16(&self, _ctx: impl ReadContext) -> Result<Nullable<u16>, Error> {
Ok(self.data.borrow().nullable_enum_16.clone())
}
fn nullable_float_single(&self, _ctx: impl ReadContext) -> Result<Nullable<f32>, Error> {
Ok(self.data.borrow().nullable_float_single.clone())
}
fn nullable_float_double(&self, _ctx: impl ReadContext) -> Result<Nullable<f64>, Error> {
Ok(self.data.borrow().nullable_float_double.clone())
}
fn nullable_octet_string<P: TLVBuilderParent>(
&self,
_ctx: impl ReadContext,
builder: NullableBuilder<P, OctetsBuilder<P>>,
) -> Result<P, Error> {
if let Some(o) = self.data.borrow().nullable_octet_string.as_opt_deref() {
builder.non_null()?.set(Octets(o))
} else {
builder.null()
}
}
fn nullable_char_string<P: TLVBuilderParent>(
&self,
_ctx: impl ReadContext,
builder: NullableBuilder<P, Utf8StrBuilder<P>>,
) -> Result<P, Error> {
if let Some(o) = self.data.borrow().nullable_char_string.as_opt_deref() {
builder.non_null()?.set(o)
} else {
builder.null()
}
}
fn nullable_enum_attr(&self, _ctx: impl ReadContext) -> Result<Nullable<SimpleEnum>, Error> {
Ok(self.data.borrow().nullable_enum_attr.clone())
}
fn nullable_struct<P: TLVBuilderParent>(
&self,
_ctx: impl ReadContext,
builder: NullableBuilder<P, SimpleStructBuilder<P>>,
) -> Result<P, Error> {
if let Some(s) = self.data.borrow().nullable_struct.as_opt_ref() {
let builder = builder.non_null()?;
builder
.a(s.a)?
.b(s.b)?
.c(s.c)?
.d(Octets(&s.d))?
.e(s.e.as_str())?
.f(s.f)?
.g(s.g)?
.h(s.h)?
.i(s.i)?
.end()
} else {
builder.null()
}
}
fn nullable_range_restricted_int_8_u(
&self,
_ctx: impl ReadContext,
) -> Result<Nullable<u8>, Error> {
Ok(self.data.borrow().nullable_range_restricted_int_8_u.clone())
}
fn nullable_range_restricted_int_8_s(
&self,
_ctx: impl ReadContext,
) -> Result<Nullable<i8>, Error> {
Ok(self.data.borrow().nullable_range_restricted_int_8_s.clone())
}
fn nullable_range_restricted_int_16_u(
&self,
_ctx: impl ReadContext,
) -> Result<Nullable<u16>, Error> {
Ok(self
.data
.borrow()
.nullable_range_restricted_int_16_u
.clone())
}
fn nullable_range_restricted_int_16_s(
&self,
_ctx: impl ReadContext,
) -> Result<Nullable<i16>, Error> {
Ok(self
.data
.borrow()
.nullable_range_restricted_int_16_s
.clone())
}
fn global_enum(&self, _ctx: impl ReadContext) -> Result<TestGlobalEnum, Error> {
Ok(self.data.borrow().global_enum)
}
fn global_struct<P: TLVBuilderParent>(
&self,
_ctx: impl ReadContext,
builder: TestGlobalStructBuilder<P>,
) -> Result<P, Error> {
let s = &self.data.borrow().global_struct;
builder
.name(s.name.as_str())?
.my_bitmap(s.my_bitmap.clone())?
.my_enum(s.my_enum.clone())?
.end()
}
fn nullable_global_enum(
&self,
_ctx: impl ReadContext,
) -> Result<Nullable<TestGlobalEnum>, Error> {
Ok(Nullable::some(self.data.borrow().global_enum))
}
fn nullable_global_struct<P: TLVBuilderParent>(
&self,
_ctx: impl ReadContext,
builder: NullableBuilder<P, TestGlobalStructBuilder<P>>,
) -> Result<P, Error> {
if let Some(s) = self.data.borrow().nullable_global_struct.as_opt_ref() {
let builder = builder.non_null()?;
builder
.name(s.name.as_str())?
.my_bitmap(s.my_bitmap.clone())?
.my_enum(s.my_enum.clone())?
.end()
} else {
builder.null()
}
}
fn set_boolean(&self, _ctx: impl WriteContext, value: bool) -> Result<(), Error> {
self.data.borrow_mut().boolean = value;
Ok(())
}
fn set_bitmap_8(&self, _ctx: impl WriteContext, value: Bitmap8MaskMap) -> Result<(), Error> {
self.data.borrow_mut().bitmap_8 = value;
Ok(())
}
fn set_bitmap_16(&self, _ctx: impl WriteContext, value: Bitmap16MaskMap) -> Result<(), Error> {
self.data.borrow_mut().bitmap_16 = value;
Ok(())
}
fn set_bitmap_32(&self, _ctx: impl WriteContext, value: Bitmap32MaskMap) -> Result<(), Error> {
self.data.borrow_mut().bitmap_32 = value;
Ok(())
}
fn set_bitmap_64(&self, _ctx: impl WriteContext, value: Bitmap64MaskMap) -> Result<(), Error> {
self.data.borrow_mut().bitmap_64 = value;
Ok(())
}
fn set_int_8_u(&self, _ctx: impl WriteContext, value: u8) -> Result<(), Error> {
self.data.borrow_mut().int_8_u = value;
Ok(())
}
fn set_int_16_u(&self, _ctx: impl WriteContext, value: u16) -> Result<(), Error> {
self.data.borrow_mut().int_16_u = value;
Ok(())
}
fn set_int_24_u(&self, _ctx: impl WriteContext, value: u32) -> Result<(), Error> {
self.data.borrow_mut().int_24_u = value;
Ok(())
}
fn set_int_32_u(&self, _ctx: impl WriteContext, value: u32) -> Result<(), Error> {
self.data.borrow_mut().int_32_u = value;
Ok(())
}
fn set_int_40_u(&self, _ctx: impl WriteContext, value: u64) -> Result<(), Error> {
self.data.borrow_mut().int_40_u = value;
Ok(())
}
fn set_int_48_u(&self, _ctx: impl WriteContext, value: u64) -> Result<(), Error> {
self.data.borrow_mut().int_48_u = value;
Ok(())
}
fn set_int_56_u(&self, _ctx: impl WriteContext, value: u64) -> Result<(), Error> {
self.data.borrow_mut().int_56_u = value;
Ok(())
}
fn set_int_64_u(&self, _ctx: impl WriteContext, value: u64) -> Result<(), Error> {
self.data.borrow_mut().int_64_u = value;
Ok(())
}
fn set_int_8_s(&self, _ctx: impl WriteContext, value: i8) -> Result<(), Error> {
self.data.borrow_mut().int_8_s = value;
Ok(())
}
fn set_int_16_s(&self, _ctx: impl WriteContext, value: i16) -> Result<(), Error> {
self.data.borrow_mut().int_16_s = value;
Ok(())
}
fn set_int_24_s(&self, _ctx: impl WriteContext, value: i32) -> Result<(), Error> {
self.data.borrow_mut().int_24_s = value;
Ok(())
}
fn set_int_32_s(&self, _ctx: impl WriteContext, value: i32) -> Result<(), Error> {
self.data.borrow_mut().int_32_s = value;
Ok(())
}
fn set_int_40_s(&self, _ctx: impl WriteContext, value: i64) -> Result<(), Error> {
self.data.borrow_mut().int_40_s = value;
Ok(())
}
fn set_int_48_s(&self, _ctx: impl WriteContext, value: i64) -> Result<(), Error> {
self.data.borrow_mut().int_48_s = value;
Ok(())
}
fn set_int_56_s(&self, _ctx: impl WriteContext, value: i64) -> Result<(), Error> {
self.data.borrow_mut().int_56_s = value;
Ok(())
}
fn set_int_64_s(&self, _ctx: impl WriteContext, value: i64) -> Result<(), Error> {
self.data.borrow_mut().int_64_s = value;
Ok(())
}
fn set_enum_8(&self, _ctx: impl WriteContext, value: u8) -> Result<(), Error> {
self.data.borrow_mut().enum_8 = value;
Ok(())
}
fn set_enum_16(&self, _ctx: impl WriteContext, value: u16) -> Result<(), Error> {
self.data.borrow_mut().enum_16 = value;
Ok(())
}
fn set_float_single(&self, _ctx: impl WriteContext, value: f32) -> Result<(), Error> {
self.data.borrow_mut().float_single = value;
Ok(())
}
fn set_float_double(&self, _ctx: impl WriteContext, value: f64) -> Result<(), Error> {
self.data.borrow_mut().float_double = value;
Ok(())
}
fn set_octet_string(&self, _ctx: impl WriteContext, value: OctetStr<'_>) -> Result<(), Error> {
self.data.borrow_mut().octet_string =
value.0.try_into().map_err(|_| ErrorCode::ConstraintError)?;
Ok(())
}
fn set_list_int_8_u(
&self,
_ctx: impl WriteContext,
value: ArrayAttributeWrite<TLVArray<'_, u8>, u8>,
) -> Result<(), Error> {
match value {
ArrayAttributeWrite::Replace(arr) => {
if arr.iter().count() > 16 {
return Err(ErrorCode::ConstraintError.into());
}
let mut data = self.data.borrow_mut();
data.list_int_8_u.clear();
for i in arr {
unwrap!(data.list_int_8_u.push(i?));
}
Ok(())
}
ArrayAttributeWrite::Add(item) => {
let mut data = self.data.borrow_mut();
if data.list_int_8_u.len() < 16 {
unwrap!(data.list_int_8_u.push(item));
Ok(())
} else {
Err(ErrorCode::ConstraintError.into())
}
}
ArrayAttributeWrite::Update(index, item) => {
let mut data = self.data.borrow_mut();
if index < data.list_int_8_u.len() as u16 {
data.list_int_8_u[index as usize] = item;
Ok(())
} else {
Err(ErrorCode::ConstraintError.into())
}
}
ArrayAttributeWrite::Remove(index) => {
let mut data = self.data.borrow_mut();
if index < data.list_int_8_u.len() as u16 {
let _ = data.list_int_8_u.remove(index as usize);
Ok(())
} else {
Err(ErrorCode::ConstraintError.into())
}
}
}
}
fn set_list_octet_string(
&self,
_ctx: impl WriteContext,
value: ArrayAttributeWrite<TLVArray<'_, OctetStr<'_>>, OctetStr<'_>>,
) -> Result<(), Error> {
match value {
ArrayAttributeWrite::Replace(arr) => {
if arr.iter().count() > 16 {
return Err(ErrorCode::ConstraintError.into());
}
let mut data = self.data.borrow_mut();
data.list_octet_string.clear();
for i in arr {
unwrap!(data
.list_octet_string
.push(i?.0.try_into().map_err(|_| ErrorCode::ConstraintError)?));
}
Ok(())
}
ArrayAttributeWrite::Add(item) => {
let mut data = self.data.borrow_mut();
if data.list_octet_string.len() < 16 {
unwrap!(data
.list_octet_string
.push(item.0.try_into().map_err(|_| ErrorCode::ConstraintError)?));
Ok(())
} else {
Err(ErrorCode::ConstraintError.into())
}
}
ArrayAttributeWrite::Update(index, item) => {
let mut data = self.data.borrow_mut();
if index < data.list_octet_string.len() as u16 {
data.list_octet_string[index as usize] =
item.0.try_into().map_err(|_| ErrorCode::ConstraintError)?;
Ok(())
} else {
Err(ErrorCode::ConstraintError.into())
}
}
ArrayAttributeWrite::Remove(index) => {
let mut data = self.data.borrow_mut();
if index < data.list_octet_string.len() as u16 {
let _ = data.list_octet_string.remove(index as usize);
Ok(())
} else {
Err(ErrorCode::ConstraintError.into())
}
}
}
}
fn set_list_struct_octet_string(
&self,
_ctx: impl WriteContext,
value: ArrayAttributeWrite<TLVArray<'_, TestListStructOctet<'_>>, TestListStructOctet<'_>>,
) -> Result<(), Error> {
match value {
ArrayAttributeWrite::Replace(arr) => {
if arr.iter().count() > 16 {
return Err(ErrorCode::ConstraintError.into());
}
let mut data = self.data.borrow_mut();
data.list_struct_octet_string.clear();
for i in arr {
let s = i?;
unwrap!(data
.list_struct_octet_string
.push(TestListStructOctetOwned {
member_1: s.member_1()?,
member_2: s
.member_2()?
.0
.try_into()
.map_err(|_| ErrorCode::ConstraintError)?,
}));
}
Ok(())
}
ArrayAttributeWrite::Add(item) => {
let mut data = self.data.borrow_mut();
if data.list_struct_octet_string.len() < 16 {
unwrap!(data
.list_struct_octet_string
.push(TestListStructOctetOwned {
member_1: item.member_1()?,
member_2: item
.member_2()?
.0
.try_into()
.map_err(|_| ErrorCode::ConstraintError)?,
}));
Ok(())
} else {
Err(ErrorCode::ConstraintError.into())
}
}
ArrayAttributeWrite::Update(index, item) => {
let mut data = self.data.borrow_mut();
if index < data.list_struct_octet_string.len() as u16 {
data.list_struct_octet_string[index as usize] = TestListStructOctetOwned {
member_1: item.member_1()?,
member_2: item
.member_2()?
.0
.try_into()
.map_err(|_| ErrorCode::ConstraintError)?,
};
Ok(())
} else {
Err(ErrorCode::ConstraintError.into())
}
}
ArrayAttributeWrite::Remove(index) => {
let mut data = self.data.borrow_mut();
if index < data.list_struct_octet_string.len() as u16 {
let _ = data.list_struct_octet_string.remove(index as usize);
Ok(())
} else {
Err(ErrorCode::ConstraintError.into())
}
}
}
}
fn set_long_octet_string(
&self,
_ctx: impl WriteContext,
value: OctetStr<'_>,
) -> Result<(), Error> {
self.data.borrow_mut().long_octet_string =
value.0.try_into().map_err(|_| ErrorCode::ConstraintError)?;
Ok(())
}
fn set_char_string(&self, _ctx: impl WriteContext, value: Utf8Str<'_>) -> Result<(), Error> {
self.data.borrow_mut().char_string =
value.try_into().map_err(|_| ErrorCode::ConstraintError)?;
Ok(())
}
fn set_long_char_string(
&self,
_ctx: impl WriteContext,
value: Utf8Str<'_>,
) -> Result<(), Error> {
self.data.borrow_mut().long_char_string =
value.try_into().map_err(|_| ErrorCode::ConstraintError)?;
Ok(())
}
fn set_epoch_us(&self, _ctx: impl WriteContext, value: u64) -> Result<(), Error> {
self.data.borrow_mut().epoch_us = value;
Ok(())
}
fn set_epoch_s(&self, _ctx: impl WriteContext, value: u32) -> Result<(), Error> {
self.data.borrow_mut().epoch_s = value;
Ok(())
}
fn set_vendor_id(&self, _ctx: impl WriteContext, value: u16) -> Result<(), Error> {
self.data.borrow_mut().vendor_id = value;
Ok(())
}
fn set_list_nullables_and_optionals_struct(
&self,
_ctx: impl WriteContext,
value: ArrayAttributeWrite<
TLVArray<'_, NullablesAndOptionalsStruct<'_>>,
NullablesAndOptionalsStruct<'_>,
>,
) -> Result<(), Error> {
fn to_owned<'a>(
s: &'a NullablesAndOptionalsStruct<'a>,
) -> impl Init<NullablesAndOptionalsStructOwned, Error> + 'a {
NullablesAndOptionalsStructOwned::init()
.into_fallible()
.chain(|o| o.update(s))
}
let no_space = || ErrorCode::ResourceExhausted.into();
match value {
ArrayAttributeWrite::Replace(arr) => {
if arr.iter().count() > 16 {
return Err(ErrorCode::ConstraintError.into());
}
let mut data = self.data.borrow_mut();
data.list_nullables_and_optionals_struct.clear();
for i in arr {
let s = i?;
data.list_nullables_and_optionals_struct
.push_init(to_owned(&s), no_space)?;
}
Ok(())
}
ArrayAttributeWrite::Add(item) => {
let mut data = self.data.borrow_mut();
if data.list_nullables_and_optionals_struct.len() < 16 {
data.list_nullables_and_optionals_struct
.push_init(to_owned(&item), no_space)
} else {
Err(ErrorCode::ConstraintError.into())
}
}
ArrayAttributeWrite::Update(index, item) => {
let mut data = self.data.borrow_mut();
if index < data.list_nullables_and_optionals_struct.len() as u16 {
data.list_nullables_and_optionals_struct[index as usize].update(&item)?;
Ok(())
} else {
Err(ErrorCode::ConstraintError.into())
}
}
ArrayAttributeWrite::Remove(index) => {
let mut data = self.data.borrow_mut();
if index < data.list_nullables_and_optionals_struct.len() as u16 {
let _ = data
.list_nullables_and_optionals_struct
.remove(index as usize);
Ok(())
} else {
Err(ErrorCode::ConstraintError.into())
}
}
}
}
fn set_enum_attr(&self, _ctx: impl WriteContext, value: SimpleEnum) -> Result<(), Error> {
self.data.borrow_mut().enum_attr = value;
Ok(())
}
fn set_struct_attr(
&self,
_ctx: impl WriteContext,
value: SimpleStruct<'_>,
) -> Result<(), Error> {
let mut data = self.data.borrow_mut();
let s = &mut data.struct_attr;
s.a = value.a()?;
s.b = value.b()?;
s.c = value.c()?;
s.d = value
.d()?
.0
.try_into()
.map_err(|_| ErrorCode::ConstraintError)?;
s.e = value
.e()?
.try_into()
.map_err(|_| ErrorCode::ConstraintError)?;
s.f = value.f()?;
s.g = value.g()?;
s.h = value.h()?;
Ok(())
}
fn set_range_restricted_int_8_u(
&self,
_ctx: impl WriteContext,
value: u8,
) -> Result<(), Error> {
const RANGE: core::ops::RangeInclusive<u8> = 20..=100;
if RANGE.contains(&value) {
self.data.borrow_mut().range_restricted_int_8_u = value;
} else {
Err(ErrorCode::ConstraintError)?;
}
Ok(())
}
fn set_range_restricted_int_8_s(
&self,
_ctx: impl WriteContext,
value: i8,
) -> Result<(), Error> {
const RANGE: core::ops::RangeInclusive<i8> = -40..=50;
if RANGE.contains(&value) {
self.data.borrow_mut().range_restricted_int_8_s = value;
} else {
Err(ErrorCode::ConstraintError)?;
}
Ok(())
}
fn set_range_restricted_int_16_u(
&self,
_ctx: impl WriteContext,
value: u16,
) -> Result<(), Error> {
const RANGE: core::ops::RangeInclusive<u16> = 100..=1000;
if RANGE.contains(&value) {
self.data.borrow_mut().range_restricted_int_16_u = value;
} else {
Err(ErrorCode::ConstraintError)?;
}
Ok(())
}
fn set_range_restricted_int_16_s(
&self,
_ctx: impl WriteContext,
value: i16,
) -> Result<(), Error> {
const RANGE: core::ops::RangeInclusive<i16> = -150..=200;
if RANGE.contains(&value) {
self.data.borrow_mut().range_restricted_int_16_s = value;
} else {
Err(ErrorCode::ConstraintError)?;
}
Ok(())
}
fn set_list_long_octet_string(
&self,
_ctx: impl WriteContext,
value: ArrayAttributeWrite<TLVArray<'_, OctetStr<'_>>, OctetStr<'_>>,
) -> Result<(), Error> {
match value {
ArrayAttributeWrite::Replace(arr) => {
if arr.iter().count() > 16 {
return Err(ErrorCode::ConstraintError.into());
}
let mut data = self.data.borrow_mut();
data.list_long_octet_string.clear();
for i in arr {
unwrap!(data
.list_long_octet_string
.push(i?.0.try_into().map_err(|_| ErrorCode::ConstraintError)?));
}
Ok(())
}
ArrayAttributeWrite::Add(item) => {
let mut data = self.data.borrow_mut();
if data.list_long_octet_string.len() < 16 {
unwrap!(data
.list_long_octet_string
.push(item.0.try_into().map_err(|_| ErrorCode::ConstraintError)?));
Ok(())
} else {
Err(ErrorCode::ConstraintError.into())
}
}
ArrayAttributeWrite::Update(index, item) => {
let mut data = self.data.borrow_mut();
if index < data.list_long_octet_string.len() as u16 {
data.list_long_octet_string[index as usize] =
item.0.try_into().map_err(|_| ErrorCode::ConstraintError)?;
Ok(())
} else {
Err(ErrorCode::ConstraintError.into())
}
}
ArrayAttributeWrite::Remove(index) => {
let mut data = self.data.borrow_mut();
if index < data.list_long_octet_string.len() as u16 {
let _ = data.list_long_octet_string.remove(index as usize);
Ok(())
} else {
Err(ErrorCode::ConstraintError.into())
}
}
}
}
fn set_list_fabric_scoped(
&self,
ctx: impl WriteContext,
value: ArrayAttributeWrite<TLVArray<'_, TestFabricScoped<'_>>, TestFabricScoped<'_>>,
) -> Result<(), Error> {
let fab_idx = NonZeroU8::new(ctx.attr().fab_idx).ok_or(ErrorCode::ConstraintError)?;
let mut data = self.data.borrow_mut();
let list = data
.list_fabric_scoped
.iter_mut()
.find(|(idx, _)| *idx == fab_idx)
.map(|(_, items)| items);
let list = if let Some(list) = list {
list
} else {
data.list_fabric_scoped
.push((fab_idx, Vec::new()))
.map_err(|_| ErrorCode::ResourceExhausted)?;
&mut data.list_fabric_scoped.last_mut().unwrap().1
};
match value {
ArrayAttributeWrite::Replace(array) => {
list.clear();
for i in array {
let s = i?;
list.push_init(TestFabricScopedOwned::init().into_fallible(), || {
ErrorCode::ResourceExhausted
})?;
list.last_mut().unwrap().update(&s)?;
}
}
ArrayAttributeWrite::Add(s) => {
list.push_init(TestFabricScopedOwned::init().into_fallible(), || {
ErrorCode::ResourceExhausted
})?;
list.last_mut().unwrap().update(&s)?;
}
ArrayAttributeWrite::Update(index, s) => {
if index as usize >= list.len() {
Err(ErrorCode::ConstraintError)?;
}
list[index as usize].update(&s)?;
}
ArrayAttributeWrite::Remove(index) => {
if index as usize >= list.len() {
Err(ErrorCode::ConstraintError)?;
}
let _ = list.remove(index as usize);
}
}
Ok(())
}
fn set_timed_write_boolean(&self, _ctx: impl WriteContext, value: bool) -> Result<(), Error> {
self.data.borrow_mut().timed_write_boolean = value;
Ok(())
}
fn set_general_error_boolean(
&self,
_ctx: impl WriteContext,
_value: bool,
) -> Result<(), Error> {
Err(ErrorCode::InvalidDataType.into())
}
fn set_cluster_error_boolean(
&self,
_ctx: impl WriteContext,
_value: bool,
) -> Result<(), Error> {
Err(ErrorCode::Invalid.into())
}
fn set_nullable_boolean(
&self,
_ctx: impl WriteContext,
value: Nullable<bool>,
) -> Result<(), Error> {
self.data.borrow_mut().nullable_boolean = value;
Ok(())
}
fn set_nullable_bitmap_8(
&self,
_ctx: impl WriteContext,
value: Nullable<Bitmap8MaskMap>,
) -> Result<(), Error> {
self.data.borrow_mut().nullable_bitmap_8 = value;
Ok(())
}
fn set_nullable_bitmap_16(
&self,
_ctx: impl WriteContext,
value: Nullable<Bitmap16MaskMap>,
) -> Result<(), Error> {
self.data.borrow_mut().nullable_bitmap_16 = value;
Ok(())
}
fn set_nullable_bitmap_32(
&self,
_ctx: impl WriteContext,
value: Nullable<Bitmap32MaskMap>,
) -> Result<(), Error> {
self.data.borrow_mut().nullable_bitmap_32 = value;
Ok(())
}
fn set_nullable_bitmap_64(
&self,
_ctx: impl WriteContext,
value: Nullable<Bitmap64MaskMap>,
) -> Result<(), Error> {
self.data.borrow_mut().nullable_bitmap_64 = value;
Ok(())
}
fn set_nullable_int_8_u(
&self,
_ctx: impl WriteContext,
value: Nullable<u8>,
) -> Result<(), Error> {
self.data.borrow_mut().nullable_int_8_u = value;
Ok(())
}
fn set_nullable_int_16_u(
&self,
_ctx: impl WriteContext,
value: Nullable<u16>,
) -> Result<(), Error> {
self.data.borrow_mut().nullable_int_16_u = value;
Ok(())
}
fn set_nullable_int_24_u(
&self,
_ctx: impl WriteContext,
value: Nullable<u32>,
) -> Result<(), Error> {
self.data.borrow_mut().nullable_int_24_u = value;
Ok(())
}
fn set_nullable_int_32_u(
&self,
_ctx: impl WriteContext,
value: Nullable<u32>,
) -> Result<(), Error> {
self.data.borrow_mut().nullable_int_32_u = value;
Ok(())
}
fn set_nullable_int_40_u(
&self,
_ctx: impl WriteContext,
value: Nullable<u64>,
) -> Result<(), Error> {
self.data.borrow_mut().nullable_int_40_u = value;
Ok(())
}
fn set_nullable_int_48_u(
&self,
_ctx: impl WriteContext,
value: Nullable<u64>,
) -> Result<(), Error> {
self.data.borrow_mut().nullable_int_48_u = value;
Ok(())
}
fn set_nullable_int_56_u(
&self,
_ctx: impl WriteContext,
value: Nullable<u64>,
) -> Result<(), Error> {
self.data.borrow_mut().nullable_int_56_u = value;
Ok(())
}
fn set_nullable_int_64_u(
&self,
_ctx: impl WriteContext,
value: Nullable<u64>,
) -> Result<(), Error> {
self.data.borrow_mut().nullable_int_64_u = value;
Ok(())
}
fn set_nullable_int_8_s(
&self,
_ctx: impl WriteContext,
value: Nullable<i8>,
) -> Result<(), Error> {
self.data.borrow_mut().nullable_int_8_s = value;
Ok(())
}
fn set_nullable_int_16_s(
&self,
_ctx: impl WriteContext,
value: Nullable<i16>,
) -> Result<(), Error> {
self.data.borrow_mut().nullable_int_16_s = value;
Ok(())
}
fn set_nullable_int_24_s(
&self,
_ctx: impl WriteContext,
value: Nullable<i32>,
) -> Result<(), Error> {
self.data.borrow_mut().nullable_int_24_s = value;
Ok(())
}
fn set_nullable_int_32_s(
&self,
_ctx: impl WriteContext,
value: Nullable<i32>,
) -> Result<(), Error> {
self.data.borrow_mut().nullable_int_32_s = value;
Ok(())
}
fn set_nullable_int_40_s(
&self,
_ctx: impl WriteContext,
value: Nullable<i64>,
) -> Result<(), Error> {
self.data.borrow_mut().nullable_int_40_s = value;
Ok(())
}
fn set_nullable_int_48_s(
&self,
_ctx: impl WriteContext,
value: Nullable<i64>,
) -> Result<(), Error> {
self.data.borrow_mut().nullable_int_48_s = value;
Ok(())
}
fn set_nullable_int_56_s(
&self,
_ctx: impl WriteContext,
value: Nullable<i64>,
) -> Result<(), Error> {
self.data.borrow_mut().nullable_int_56_s = value;
Ok(())
}
fn set_nullable_int_64_s(
&self,
_ctx: impl WriteContext,
value: Nullable<i64>,
) -> Result<(), Error> {
self.data.borrow_mut().nullable_int_64_s = value;
Ok(())
}
fn set_nullable_enum_8(
&self,
_ctx: impl WriteContext,
value: Nullable<u8>,
) -> Result<(), Error> {
self.data.borrow_mut().nullable_enum_8 = value;
Ok(())
}
fn set_nullable_enum_16(
&self,
_ctx: impl WriteContext,
value: Nullable<u16>,
) -> Result<(), Error> {
self.data.borrow_mut().nullable_enum_16 = value;
Ok(())
}
fn set_nullable_float_single(
&self,
_ctx: impl WriteContext,
value: Nullable<f32>,
) -> Result<(), Error> {
self.data.borrow_mut().nullable_float_single = value;
Ok(())
}
fn set_nullable_float_double(
&self,
_ctx: impl WriteContext,
value: Nullable<f64>,
) -> Result<(), Error> {
self.data.borrow_mut().nullable_float_double = value;
Ok(())
}
fn set_nullable_octet_string(
&self,
_ctx: impl WriteContext,
value: Nullable<OctetStr<'_>>,
) -> Result<(), Error> {
if let Some(value) = value.into_option() {
self.data.borrow_mut().nullable_octet_string =
Nullable::some(value.0.try_into().map_err(|_| ErrorCode::ConstraintError)?);
} else {
self.data.borrow_mut().nullable_octet_string = Nullable::none();
}
Ok(())
}
fn set_nullable_char_string(
&self,
_ctx: impl WriteContext,
value: Nullable<Utf8Str<'_>>,
) -> Result<(), Error> {
if let Some(value) = value.into_option() {
self.data.borrow_mut().nullable_char_string =
Nullable::some(value.try_into().map_err(|_| ErrorCode::ConstraintError)?);
} else {
self.data.borrow_mut().nullable_char_string = Nullable::none();
}
Ok(())
}
fn set_nullable_enum_attr(
&self,
_ctx: impl WriteContext,
value: Nullable<SimpleEnum>,
) -> Result<(), Error> {
self.data.borrow_mut().nullable_enum_attr = value;
Ok(())
}
fn set_nullable_struct(
&self,
_ctx: impl WriteContext,
value: Nullable<SimpleStruct<'_>>,
) -> Result<(), Error> {
if let Some(s) = value.into_option() {
let mut data = self.data.borrow_mut();
let ns = SimpleStructOwned {
a: s.a()?,
b: s.b()?,
c: s.c()?,
d: s.d()?
.0
.try_into()
.map_err(|_| ErrorCode::ConstraintError)?,
e: s.e()?.try_into().map_err(|_| ErrorCode::ConstraintError)?,
f: s.f()?,
g: s.g()?,
h: s.h()?,
i: s.i()?,
};
data.nullable_struct = Nullable::some(ns);
} else {
self.data.borrow_mut().nullable_struct = Nullable::none();
}
Ok(())
}
fn set_nullable_range_restricted_int_8_u(
&self,
_ctx: impl WriteContext,
value: Nullable<u8>,
) -> Result<(), Error> {
if let Some(value) = value.into_option() {
const RANGE: core::ops::RangeInclusive<u8> = 20..=100;
if RANGE.contains(&value) {
self.data.borrow_mut().nullable_range_restricted_int_8_u = Nullable::some(value);
} else {
Err(ErrorCode::ConstraintError)?;
}
} else {
self.data
.borrow_mut()
.nullable_range_restricted_int_8_u
.clear();
}
Ok(())
}
fn set_nullable_range_restricted_int_8_s(
&self,
_ctx: impl WriteContext,
value: Nullable<i8>,
) -> Result<(), Error> {
if let Some(value) = value.into_option() {
const RANGE: core::ops::RangeInclusive<i8> = -40..=50;
if RANGE.contains(&value) {
self.data.borrow_mut().nullable_range_restricted_int_8_s = Nullable::some(value);
} else {
Err(ErrorCode::ConstraintError)?;
}
} else {
self.data
.borrow_mut()
.nullable_range_restricted_int_8_s
.clear();
}
Ok(())
}
fn set_nullable_range_restricted_int_16_u(
&self,
_ctx: impl WriteContext,
value: Nullable<u16>,
) -> Result<(), Error> {
if let Some(value) = value.into_option() {
const RANGE: core::ops::RangeInclusive<u16> = 100..=1000;
if RANGE.contains(&value) {
self.data.borrow_mut().nullable_range_restricted_int_16_u = Nullable::some(value);
} else {
Err(ErrorCode::ConstraintError)?;
}
} else {
self.data
.borrow_mut()
.nullable_range_restricted_int_16_u
.clear();
}
Ok(())
}
fn set_nullable_range_restricted_int_16_s(
&self,
_ctx: impl WriteContext,
value: Nullable<i16>,
) -> Result<(), Error> {
if let Some(value) = value.into_option() {
const RANGE: core::ops::RangeInclusive<i16> = -150..=200;
if RANGE.contains(&value) {
self.data.borrow_mut().nullable_range_restricted_int_16_s = Nullable::some(value);
} else {
Err(ErrorCode::ConstraintError)?;
}
} else {
self.data
.borrow_mut()
.nullable_range_restricted_int_16_s
.clear();
}
Ok(())
}
fn set_global_enum(&self, _ctx: impl WriteContext, value: TestGlobalEnum) -> Result<(), Error> {
self.data.borrow_mut().global_enum = value;
Ok(())
}
fn set_global_struct(
&self,
_ctx: impl WriteContext,
value: TestGlobalStruct<'_>,
) -> Result<(), Error> {
self.data.borrow_mut().global_struct = TestGlobalStructOwned {
name: value
.name()?
.try_into()
.map_err(|_| ErrorCode::InvalidAction)?,
my_bitmap: value.my_bitmap()?,
my_enum: value.my_enum()?,
};
Ok(())
}
fn set_nullable_global_enum(
&self,
_ctx: impl WriteContext,
value: Nullable<TestGlobalEnum>,
) -> Result<(), Error> {
self.data.borrow_mut().nullable_global_enum = value;
Ok(())
}
fn set_nullable_global_struct(
&self,
_ctx: impl WriteContext,
value: Nullable<TestGlobalStruct<'_>>,
) -> Result<(), Error> {
if let Some(s) = value.into_option() {
let mut data = self.data.borrow_mut();
let ns = TestGlobalStructOwned {
name: s.name()?.try_into().map_err(|_| ErrorCode::InvalidAction)?,
my_bitmap: s.my_bitmap()?,
my_enum: s.my_enum()?,
};
data.nullable_global_struct = Nullable::some(ns);
} else {
self.data.borrow_mut().nullable_global_struct = Nullable::none();
}
Ok(())
}
fn handle_test(&self, _ctx: impl InvokeContext) -> Result<(), Error> {
Ok(())
}
fn handle_test_not_handled(&self, _ctx: impl InvokeContext) -> Result<(), Error> {
Err(ErrorCode::InvalidCommand.into())
}
fn handle_test_specific<P: TLVBuilderParent>(
&self,
_ctx: impl InvokeContext,
response: TestSpecificResponseBuilder<P>,
) -> Result<P, Error> {
response.return_value(7)?.end()
}
fn handle_test_add_arguments<P: TLVBuilderParent>(
&self,
_ctx: impl InvokeContext,
request: TestAddArgumentsRequest<'_>,
response: TestAddArgumentsResponseBuilder<P>,
) -> Result<P, Error> {
let result = request.arg_1()? as u16 + request.arg_2()? as u16;
if result <= u8::MAX as u16 {
response.return_value(result as _)?.end()
} else {
Err(ErrorCode::InvalidCommand.into())
}
}
fn handle_test_simple_argument_request<P: TLVBuilderParent>(
&self,
_ctx: impl InvokeContext,
request: TestSimpleArgumentRequestRequest<'_>,
response: TestSimpleArgumentResponseBuilder<P>,
) -> Result<P, Error> {
response.return_value(request.arg_1()? as _)?.end()
}
fn handle_test_struct_array_argument_request<P: TLVBuilderParent>(
&self,
_ctx: impl InvokeContext,
_request: TestStructArrayArgumentRequestRequest<'_>,
_response: TestStructArrayArgumentResponseBuilder<P>,
) -> Result<P, Error> {
unreachable!()
}
fn handle_test_struct_argument_request<P: TLVBuilderParent>(
&self,
_ctx: impl InvokeContext,
request: TestStructArgumentRequestRequest<'_>,
response: BooleanResponseBuilder<P>,
) -> Result<P, Error> {
let s = request.arg_1()?;
let result = s.a()? == 0
&& s.b()?
&& s.c()? == SimpleEnum::ValueB
&& s.d()?.0 == b"octet_string"
&& s.e()? == "char_string"
&& s.f()? == SimpleBitmap::VALUE_A
&& s.g()? == 0f32
&& s.h()? == 0f64;
response.value(result)?.end()
}
fn handle_test_nested_struct_argument_request<P: TLVBuilderParent>(
&self,
_ctx: impl InvokeContext,
request: TestNestedStructArgumentRequestRequest<'_>,
response: BooleanResponseBuilder<P>,
) -> Result<P, Error> {
let s = request.arg_1()?;
let result = s.a()? == 0 && s.b()? && {
let s = s.c()?;
s.a()? == 0
&& s.b()?
&& s.c()? == SimpleEnum::ValueB
&& s.d()?.0 == b"octet_string"
&& s.e()? == "char_string"
&& s.f()? == SimpleBitmap::VALUE_A
&& s.g()? == 0f32
&& s.h()? == 0f64
};
response.value(result)?.end()
}
fn handle_test_list_struct_argument_request<P: TLVBuilderParent>(
&self,
_ctx: impl InvokeContext,
request: TestListStructArgumentRequestRequest<'_>,
response: BooleanResponseBuilder<P>,
) -> Result<P, Error> {
let l = request.arg_1()?;
let mut result = l.iter().count() == 2;
if result {
let mut iter = l.iter();
let s1 = unwrap!(iter.next())?;
let s2 = unwrap!(iter.next())?;
result = s1.a()? == 0
&& s1.b()?
&& s1.c()? == SimpleEnum::ValueB
&& s1.d()?.0 == b"first_octet_string"
&& s1.e()? == "first_char_string"
&& s1.f()? == SimpleBitmap::VALUE_A
&& s1.g()? == 0f32
&& s1.h()? == 0f64
&& s2.a()? == 1
&& s2.b()?
&& s2.c()? == SimpleEnum::ValueC
&& s2.d()?.0 == b"second_octet_string"
&& s2.e()? == "second_char_string"
&& s2.f()? == SimpleBitmap::VALUE_A
&& s2.g()? == 0f32
&& s2.h()? == 0f64;
}
response.value(result)?.end()
}
fn handle_test_list_int_8_u_argument_request<P: TLVBuilderParent>(
&self,
_ctx: impl InvokeContext,
request: TestListInt8UArgumentRequestRequest<'_>,
response: BooleanResponseBuilder<P>,
) -> Result<P, Error> {
let l = request.arg_1()?;
let result = l.iter().count() == 9 && {
let mut result = true;
for (i, j) in l.iter().zip(1_u8..10) {
result = result || i? == j;
}
result
};
response.value(result)?.end()
}
fn handle_test_nested_struct_list_argument_request<P: TLVBuilderParent>(
&self,
_ctx: impl InvokeContext,
request: TestNestedStructListArgumentRequestRequest<'_>,
response: BooleanResponseBuilder<P>,
) -> Result<P, Error> {
let s = request.arg_1()?;
let result = s.a()? == 0
&& s.b()?
&& {
let ss = s.c()?;
ss.a()? == 0
&& ss.b()?
&& ss.c()? == SimpleEnum::ValueB
&& ss.d()?.0 == b"octet_string"
&& ss.e()? == "char_string"
&& ss.f()? == SimpleBitmap::VALUE_A
&& ss.g()? == 0f32
&& ss.h()? == 0f64
}
&& {
let l = s.d()?;
l.iter().count() == 2 && {
let mut iter = l.iter();
let ls1 = unwrap!(iter.next())?;
let ls2 = unwrap!(iter.next())?;
ls1.a()? == 1
&& ls1.b()?
&& ls1.c()? == SimpleEnum::ValueC
&& ls1.d()?.0 == b"nested_octet_string"
&& ls1.e()? == "nested_char_string"
&& ls1.f()? == SimpleBitmap::VALUE_A
&& ls1.g()? == 0f32
&& ls1.h()? == 0f64
&& ls2.a()? == 2
&& ls2.b()?
&& ls2.c()? == SimpleEnum::ValueC
&& ls2.d()?.0 == b"nested_octet_string"
&& ls2.e()? == "nested_char_string"
&& ls2.f()? == SimpleBitmap::VALUE_A
&& ls2.g()? == 0f32
&& ls2.h()? == 0f64
}
};
response.value(result)?.end()
}
fn handle_test_list_nested_struct_list_argument_request<P: TLVBuilderParent>(
&self,
_ctx: impl InvokeContext,
request: TestListNestedStructListArgumentRequestRequest<'_>,
response: BooleanResponseBuilder<P>,
) -> Result<P, Error> {
let l = request.arg_1()?;
let result = l.iter().count() == 1 && {
let s = unwrap!(l.iter().next())?;
s.a()? == 0
&& s.b()?
&& {
let c = s.c()?;
c.a()? == 0
&& c.b()?
&& c.c()? == SimpleEnum::ValueB
&& c.d()?.0 == b"octet_string"
&& c.e()? == "char_string"
&& c.f()? == SimpleBitmap::VALUE_A
&& c.g()? == 0f32
&& c.h()? == 0f64
}
&& {
let d = s.d()?;
d.iter().count() == 2 && {
let mut iter = d.iter();
let ls1 = unwrap!(iter.next())?;
let ls2 = unwrap!(iter.next())?;
ls1.a()? == 1
&& ls1.b()?
&& ls1.c()? == SimpleEnum::ValueC
&& ls1.d()?.0 == b"nested_octet_string"
&& ls1.e()? == "nested_char_string"
&& ls1.f()? == SimpleBitmap::VALUE_A
&& ls1.g()? == 0f32
&& ls1.h()? == 0f64
&& ls2.a()? == 2
&& ls2.b()?
&& ls2.c()? == SimpleEnum::ValueC
&& ls2.d()?.0 == b"nested_octet_string"
&& ls2.e()? == "nested_char_string"
&& ls2.f()? == SimpleBitmap::VALUE_A
&& ls2.g()? == 0f32
&& ls2.h()? == 0f64
}
}
&& {
let e = s.e()?;
e.iter().count() == 3 && {
let mut result = true;
for (i, j) in e.iter().zip(1_u32..4) {
result = result || i? == j;
}
result
}
}
&& {
let f = s.f()?;
f.iter().count() == 3 && {
const STRS: &[&[u8]] =
&[b"octet_string_1", b"octect_string_2", b"octet_string_3"];
let mut result = true;
for (i, j) in f.iter().zip(STRS.iter()) {
result = result || i?.0 == *j;
}
result
}
}
&& {
let g = s.g()?;
g.iter().count() == 2 && {
let mut result = true;
for (i, j) in g.iter().zip([0u8, 255]) {
result = result || i? == j;
}
result
}
}
};
response.value(result)?.end()
}
fn handle_test_list_int_8_u_reverse_request<P: TLVBuilderParent>(
&self,
_ctx: impl InvokeContext,
request: TestListInt8UReverseRequestRequest<'_>,
response: TestListInt8UReverseResponseBuilder<P>,
) -> Result<P, Error> {
// Iterating TLV containers backwards is not possible,
// so for once here we'll on-stack allocate a temp buffer
let l = request.arg_1()?;
let mut tmp = heapless::Vec::<u8, 16>::new();
for i in l.iter() {
unwrap!(tmp.push(i?));
}
let mut lo = response.arg_1()?;
for i in tmp.iter().rev() {
lo = lo.push(i)?;
}
lo.end()?.end()
}
fn handle_test_enums_request<P: TLVBuilderParent>(
&self,
_ctx: impl InvokeContext,
request: TestEnumsRequestRequest<'_>,
response: TestEnumsResponseBuilder<P>,
) -> Result<P, Error> {
response
.arg_1(request.arg_1()?)?
.arg_2(request.arg_2()?)?
.end()
}
fn handle_test_nullable_optional_request<P: TLVBuilderParent>(
&self,
_ctx: impl InvokeContext,
request: TestNullableOptionalRequestRequest<'_>,
response: TestNullableOptionalResponseBuilder<P>,
) -> Result<P, Error> {
response
.was_present(request.arg_1()?.is_some())?
.was_null(request.arg_1()?.as_ref().map(Nullable::is_none))?
.value(request.arg_1()?.and_then(|value| value.into_option()))?
.original_value(request.arg_1()?)?
.end()
}
fn handle_test_complex_nullable_optional_request<P: TLVBuilderParent>(
&self,
_ctx: impl InvokeContext,
request: TestComplexNullableOptionalRequestRequest<'_>,
response: TestComplexNullableOptionalResponseBuilder<P>,
) -> Result<P, Error> {
response
.nullable_int_was_null(request.nullable_int()?.is_none())?
.nullable_int_value(request.nullable_int()?.into_option())?
.optional_int_was_present(request.optional_int()?.is_some())?
.optional_int_value(request.optional_int()?)?
.nullable_optional_int_was_present(request.nullable_optional_int()?.is_some())?
.nullable_optional_int_was_null(
request
.nullable_optional_int()?
.as_ref()
.map(Nullable::is_none),
)?
.nullable_optional_int_value(
request
.nullable_optional_int()?
.and_then(Nullable::into_option),
)?
.nullable_string_was_null(request.nullable_string()?.is_none())?
.nullable_string_value(request.nullable_string()?.into_option())?
.optional_string_was_present(request.optional_string()?.is_some())?
.optional_string_value(request.optional_string()?)?
.nullable_optional_string_was_present(request.nullable_optional_string()?.is_some())?
.nullable_optional_string_was_null(
request
.nullable_optional_string()?
.as_ref()
.map(Nullable::is_none),
)?
.nullable_optional_string_value(
request
.nullable_optional_string()?
.and_then(Nullable::into_option),
)?
.nullable_struct_was_null(request.nullable_struct()?.is_none())?
.nullable_struct_value()?
.with_some(request.nullable_struct()?.into_option(), |i, o| {
o.a(i.a()?)?
.b(i.b()?)?
.c(i.c()?)?
.d(i.d()?)?
.e(i.e()?)?
.f(i.f()?)?
.g(i.g()?)?
.h(i.h()?)?
.i(i.i()?)?
.end()
})?
.optional_struct_was_present(request.optional_struct()?.is_some())?
.optional_struct_value()?
.with_some(request.optional_struct()?, |i, o| {
o.a(i.a()?)?
.b(i.b()?)?
.c(i.c()?)?
.d(i.d()?)?
.e(i.e()?)?
.f(i.f()?)?
.g(i.g()?)?
.h(i.h()?)?
.i(i.i()?)?
.end()
})?
.nullable_optional_struct_was_present(request.nullable_optional_struct()?.is_some())?
.nullable_optional_struct_was_null(
request
.nullable_optional_struct()?
.as_ref()
.map(Nullable::is_none),
)?
.nullable_optional_struct_value()?
.with_some(
request
.nullable_optional_struct()?
.and_then(Nullable::into_option),
|i, o| {
o.a(i.a()?)?
.b(i.b()?)?
.c(i.c()?)?
.d(i.d()?)?
.e(i.e()?)?
.f(i.f()?)?
.g(i.g()?)?
.h(i.h()?)?
.i(i.i()?)?
.end()
},
)?
.nullable_list_was_null(request.nullable_list()?.is_none())?
.nullable_list_value()?
.with_some(request.nullable_list()?.as_opt_ref(), |i, mut o| {
for i in i.iter() {
o = o.push(&i?)?;
}
o.end()
})?
.optional_list_was_present(request.optional_list()?.is_some())?
.optional_list_value()?
.with_some(request.optional_list()?, |i, mut o| {
for i in i.iter() {
o = o.push(&i?)?;
}
o.end()
})?
.nullable_optional_list_was_present(request.nullable_optional_list()?.is_some())?
.nullable_optional_list_was_null(
request
.nullable_optional_list()?
.as_ref()
.map(Nullable::is_none),
)?
.nullable_optional_list_value()?
.with_some(
request
.nullable_optional_list()?
.and_then(Nullable::into_option),
|i, mut o| {
for i in i.iter() {
o = o.push(&i?)?;
}
o.end()
},
)?
.end()
}
fn handle_simple_struct_echo_request<P: TLVBuilderParent>(
&self,
_ctx: impl InvokeContext,
request: SimpleStructEchoRequestRequest<'_>,
response: SimpleStructResponseBuilder<P>,
) -> Result<P, Error> {
let s = request.arg_1()?;
response
.arg_1()?
.a(s.a()?)?
.b(s.b()?)?
.c(s.c()?)?
.d(s.d()?)?
.e(s.e()?)?
.f(s.f()?)?
.g(s.g()?)?
.h(s.h()?)?
.i(s.i()?)?
.end()?
.end()
}
fn handle_timed_invoke_request(&self, _ctx: impl InvokeContext) -> Result<(), Error> {
Ok(())
}
fn handle_test_simple_optional_argument_request(
&self,
_ctx: impl InvokeContext,
request: TestSimpleOptionalArgumentRequestRequest<'_>,
) -> Result<(), Error> {
if request.arg_1()?.is_some() {
Ok(())
} else {
Err(ErrorCode::ConstraintError.into())
}
}
fn handle_test_emit_test_event_request<P: TLVBuilderParent>(
&self,
ctx: impl InvokeContext,
request: TestEmitTestEventRequestRequest<'_>,
response: TestEmitTestEventResponseBuilder<P>,
) -> Result<P, Error> {
let event_no = TestEvent::emit(&ctx, |tw| {
tw.arg_1(request.arg_1()?)?
.arg_2(request.arg_2()?)?
.arg_3(request.arg_3()?)?
// NOTE: Why are the remaining TestEvent fields not marked as optional in the IDL?
.arg_4()?
.a(0)?
.b(false)?
.c(SimpleEnum::ValueA)?
.d(Octets(&[]))?
.e("")?
.f(SimpleBitmap::empty())?
.g(0.0)?
.h(0.0)?
.i(None)?
.end()?
.arg_5()?
.end()?
.arg_6()?
.end()?
.end()
})?;
response.value(event_no)?.end()
}
fn handle_test_emit_test_fabric_scoped_event_request<P: TLVBuilderParent>(
&self,
_ctx: impl InvokeContext,
_request: TestEmitTestFabricScopedEventRequestRequest<'_>,
_response: TestEmitTestFabricScopedEventResponseBuilder<P>,
) -> Result<P, Error> {
todo!()
}
fn handle_test_unknown_command(&self, _ctx: impl InvokeContext) -> Result<(), Error> {
unreachable!()
}
fn handle_test_batch_helper_request<P: TLVBuilderParent>(
&self,
_ctx: impl InvokeContext,
request: TestBatchHelperRequestRequest<'_>,
response: TestBatchHelperResponseBuilder<P>,
) -> Result<P, Error> {
// Demonstrates how to skip the builder framework and write raw, unchecked TLV
let byte = request.fill_character()?;
let len = request.size_of_response_buffer()? as _;
let mut parent = response.unchecked_into_parent();
let writer = parent.writer();
writer.stri(
&TLVTag::Context(TestBatchHelperResponseTag::Buffer as _),
len,
core::iter::repeat_n(byte, len),
)?;
writer.end_container()?; // TestBatchHelperResponse struct
Ok(parent)
}
fn handle_test_second_batch_helper_request<P: TLVBuilderParent>(
&self,
_ctx: impl InvokeContext,
request: TestSecondBatchHelperRequestRequest<'_>,
response: TestBatchHelperResponseBuilder<P>,
) -> Result<P, Error> {
// Demonstrates how to skip the builder framework and write raw, unchecked TLV
let byte = request.fill_character()?;
let len = request.size_of_response_buffer()? as _;
let mut parent = response.unchecked_into_parent();
let writer = parent.writer();
writer.stri(
&TLVTag::Context(TestBatchHelperResponseTag::Buffer as _),
len,
core::iter::repeat_n(byte, len),
)?;
writer.end_container()?; // TestBatchHelperResponse struct
Ok(parent)
}
fn mei_int_8_u(&self, _ctx: impl ReadContext) -> Result<u8, Error> {
Ok(self.data.borrow().mei_int_8_u)
}
fn set_mei_int_8_u(&self, _ctx: impl WriteContext, value: u8) -> Result<(), Error> {
self.data.borrow_mut().mei_int_8_u = value;
Ok(())
}
fn handle_test_different_vendor_mei_request<P: TLVBuilderParent>(
&self,
ctx: impl InvokeContext,
request: TestDifferentVendorMeiRequestRequest<'_>,
response: TestDifferentVendorMeiResponseBuilder<P>,
) -> Result<P, Error> {
let arg = request.arg_1()?;
// Per the cluster spec, this command echoes `arg1` and emits a
// `TestDifferentVendorMeiEvent` whose `arg1` carries the same value;
// the response then surfaces the event's number for the caller to
// read back via `readEvent`. `TestUnitTestingClusterMei` step 7/8
// depend on the event being emitted with a non-zero (real) number.
let event_no = TestDifferentVendorMeiEvent::emit(&ctx, |tw| tw.arg_1(arg)?.end())?;
response.arg_1(arg)?.event_number(event_no)?.end()
}
fn handle_string_echo_request<P: TLVBuilderParent>(
&self,
_ctx: impl InvokeContext,
request: StringEchoRequestRequest<'_>,
response: StringEchoResponseBuilder<P>,
) -> Result<P, Error> {
response.payload(request.payload()?)?.end()
}
fn handle_global_echo_request<P: TLVBuilderParent>(
&self,
_ctx: impl InvokeContext,
request: GlobalEchoRequestRequest<'_>,
response: GlobalEchoResponseBuilder<P>,
) -> Result<P, Error> {
let s = request.field_1()?;
response
.field_1()?
.name(s.name()?)?
.my_bitmap(s.my_bitmap()?)?
.my_enum(s.my_enum()?)?
.end()?
.field_2(request.field_2()?)?
.end()
}
fn handle_test_check_command_flags(&self, _ctx: impl InvokeContext) -> Result<(), Error> {
todo!()
}
}