Skip to content

Commit c50c591

Browse files
Post merge cleanup 36229 ember buffer encode (project-chip#36266)
* Use chip::app::IsSignedAttributeType * Fix up put as well as naming for null value and comment * Fix up nullable tests * Test that you cannot decode a null value for non-nullable double and single * Allow NAN for non-nullable floating points * Add test case for non nullable bool * Restyle * Add a header for efr32 * Update src/app/codegen-data-model-provider/EmberAttributeDataBuffer.cpp Co-authored-by: Boris Zbarsky <bzbarsky@apple.com> * Update src/app/codegen-data-model-provider/EmberAttributeDataBuffer.cpp Co-authored-by: Boris Zbarsky <bzbarsky@apple.com> * Remove extra comment * Replace switch with if * Comment fix * Another try to make efr32 build of tests happy * Move includes around, to try to work around issues within efr32 compiles... * more updates, this time local efr32 compiles --------- Co-authored-by: Boris Zbarsky <bzbarsky@apple.com>
1 parent e7729d9 commit c50c591

File tree

3 files changed

+62
-40
lines changed

3 files changed

+62
-40
lines changed

src/app/codegen-data-model-provider/EmberAttributeDataBuffer.cpp

+17-38
Original file line numberDiff line numberDiff line change
@@ -384,29 +384,22 @@ CHIP_ERROR EmberAttributeDataBuffer::EncodeInteger(chip::TLV::TLVWriter & writer
384384

385385
uint8_t raw_bytes[8];
386386

387-
bool isSigned = (mAttributeType == ZCL_INT8S_ATTRIBUTE_TYPE) //
388-
|| (mAttributeType == ZCL_INT16S_ATTRIBUTE_TYPE) //
389-
|| (mAttributeType == ZCL_INT24S_ATTRIBUTE_TYPE) //
390-
|| (mAttributeType == ZCL_INT32S_ATTRIBUTE_TYPE) //
391-
|| (mAttributeType == ZCL_INT40S_ATTRIBUTE_TYPE) //
392-
|| (mAttributeType == ZCL_INT48S_ATTRIBUTE_TYPE) //
393-
|| (mAttributeType == ZCL_INT56S_ATTRIBUTE_TYPE) //
394-
|| (mAttributeType == ZCL_INT64S_ATTRIBUTE_TYPE);
387+
const bool isSigned = IsSignedAttributeType(mAttributeType);
395388

396389
unsigned byteCount;
397-
uint64_t nullValue;
390+
uint64_t nullValueAsU64;
398391

399392
if (isSigned)
400393
{
401394
const SignedDecodeInfo info = GetSignedDecodeInfo(mAttributeType);
402395
byteCount = info.byteCount;
403-
nullValue = static_cast<uint64_t>(info.minValue); // just a bit cast for easy compare
396+
nullValueAsU64 = static_cast<uint64_t>(info.minValue);
404397
}
405398
else
406399
{
407400
const UnsignedDecodeInfo info = GetUnsignedDecodeInfo(mAttributeType);
408401
byteCount = info.byteCount;
409-
nullValue = info.maxValue;
402+
nullValueAsU64 = info.maxValue;
410403
}
411404

412405
VerifyOrDie(sizeof(raw_bytes) >= byteCount);
@@ -445,36 +438,21 @@ CHIP_ERROR EmberAttributeDataBuffer::EncodeInteger(chip::TLV::TLVWriter & writer
445438
value.uint_value = (value.uint_value & ~0xFFULL) | raw_bytes[i];
446439
}
447440

448-
if (mIsNullable && (value.uint_value == nullValue))
441+
// We place the null value as either int_value or uint_value into a union that is
442+
// bit-formatted as both int64 and uint64. When we define the nullValue,
443+
// it is bitcast into u64 hence this comparison. This is ugly, however this
444+
// code prioritizes code size over readability here.
445+
if (mIsNullable && (value.uint_value == nullValueAsU64))
449446
{
450-
// MaxValue is used for NULL setting
451447
return writer.PutNull(tag);
452448
}
453449

454-
switch (mAttributeType)
450+
if (isSigned)
455451
{
456-
case ZCL_INT8U_ATTRIBUTE_TYPE: // Unsigned 8-bit integer
457-
return writer.Put(tag, static_cast<uint8_t>(value.uint_value));
458-
case ZCL_INT16U_ATTRIBUTE_TYPE: // Unsigned 16-bit integer
459-
return writer.Put(tag, static_cast<uint16_t>(value.uint_value));
460-
case ZCL_INT24U_ATTRIBUTE_TYPE: // Unsigned 24-bit integer
461-
case ZCL_INT32U_ATTRIBUTE_TYPE: // Unsigned 32-bit integer
462-
return writer.Put(tag, static_cast<uint32_t>(value.uint_value));
463-
case ZCL_INT40U_ATTRIBUTE_TYPE: // Unsigned 40-bit integer
464-
case ZCL_INT48U_ATTRIBUTE_TYPE: // Unsigned 48-bit integer
465-
case ZCL_INT56U_ATTRIBUTE_TYPE: // Signed 56-bit integer
466-
case ZCL_INT64U_ATTRIBUTE_TYPE: // Signed 64-bit integer
467-
return writer.Put(tag, static_cast<uint64_t>(value.uint_value));
468-
case ZCL_INT8S_ATTRIBUTE_TYPE: // Signed 8-bit integer
469-
return writer.Put(tag, static_cast<int8_t>(value.int_value));
470-
case ZCL_INT16S_ATTRIBUTE_TYPE: // Signed 16-bit integer
471-
return writer.Put(tag, static_cast<int16_t>(value.int_value));
472-
case ZCL_INT24S_ATTRIBUTE_TYPE: // Signed 24-bit integer
473-
case ZCL_INT32S_ATTRIBUTE_TYPE: // Signed 32-bit integer
474-
return writer.Put(tag, static_cast<int32_t>(value.int_value));
475-
default:
476-
return writer.Put(tag, static_cast<int64_t>(value.int_value));
452+
return writer.Put(tag, value.int_value);
477453
}
454+
455+
return writer.Put(tag, value.uint_value);
478456
}
479457

480458
CHIP_ERROR EmberAttributeDataBuffer::Encode(chip::TLV::TLVWriter & writer, TLV::Tag tag) const
@@ -497,10 +475,11 @@ CHIP_ERROR EmberAttributeDataBuffer::Encode(chip::TLV::TLVWriter & writer, TLV::
497475
case 1:
498476
return writer.PutBoolean(tag, value != 0);
499477
case 0xFF:
478+
VerifyOrReturnError(mIsNullable, CHIP_ERROR_INVALID_ARGUMENT);
500479
return writer.PutNull(tag);
501480
default:
502481
// Unknown types
503-
return CHIP_ERROR_INCORRECT_STATE;
482+
return CHIP_ERROR_INVALID_ARGUMENT;
504483
}
505484
}
506485
case ZCL_INT8U_ATTRIBUTE_TYPE: // Unsigned 8-bit integer
@@ -531,7 +510,7 @@ CHIP_ERROR EmberAttributeDataBuffer::Encode(chip::TLV::TLVWriter & writer, TLV::
531510
{
532511
return endianReader.StatusCode();
533512
}
534-
if (NumericAttributeTraits<float>::IsNullValue(value.value))
513+
if (mIsNullable && NumericAttributeTraits<float>::IsNullValue(value.value))
535514
{
536515
return writer.PutNull(tag);
537516
}
@@ -548,7 +527,7 @@ CHIP_ERROR EmberAttributeDataBuffer::Encode(chip::TLV::TLVWriter & writer, TLV::
548527
{
549528
return endianReader.StatusCode();
550529
}
551-
if (NumericAttributeTraits<double>::IsNullValue(value.value))
530+
if (mIsNullable && NumericAttributeTraits<double>::IsNullValue(value.value))
552531
{
553532
return writer.PutNull(tag);
554533
}

src/app/codegen-data-model-provider/EmberAttributeDataBuffer.h

+1-1
Original file line numberDiff line numberDiff line change
@@ -85,7 +85,7 @@ class EmberAttributeDataBuffer
8585
/// Takes into account internal mIsNullable.
8686
CHIP_ERROR DecodeSignedInteger(chip::TLV::TLVReader & reader, EndianWriter & writer);
8787

88-
/// Encodes the UNSIGNED integer into `writer`.
88+
/// Encodes the given integer into `writer`.
8989
/// Takes into account internal mIsNullable.
9090
CHIP_ERROR EncodeInteger(chip::TLV::TLVWriter & writer, TLV::Tag tag, EndianReader & reader) const;
9191

src/app/codegen-data-model-provider/tests/TestEmberAttributeDataBuffer.cpp

+44-1
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,8 @@
1616
*/
1717
#include <pw_unit_test/framework.h>
1818

19+
#include <cmath>
20+
1921
#include <app/codegen-data-model-provider/EmberAttributeDataBuffer.h>
2022

2123
#include <app-common/zap-generated/attribute-type.h>
@@ -107,6 +109,28 @@ bool IsEqual(const T & a, const T & b)
107109
return a == b;
108110
}
109111

112+
template <>
113+
bool IsEqual<float>(const float & a, const float & b)
114+
{
115+
if (std::isnan(a) && std::isnan(b))
116+
{
117+
return true;
118+
}
119+
120+
return a == b;
121+
}
122+
123+
template <>
124+
bool IsEqual<double>(const double & a, const double & b)
125+
{
126+
if (std::isnan(a) && std::isnan(b))
127+
{
128+
return true;
129+
}
130+
131+
return a == b;
132+
}
133+
110134
template <>
111135
bool IsEqual<ByteSpan>(const ByteSpan & a, const ByteSpan & b)
112136
{
@@ -756,7 +780,7 @@ TEST(TestEmberAttributeBuffer, TestDecodeFailures)
756780
{
757781
// Bad boolean data
758782
EncodeTester tester(CreateFakeMeta(ZCL_BOOLEAN_ATTRIBUTE_TYPE, false /* nullable */));
759-
EXPECT_EQ(tester.TryDecode<bool>(true, { 123 }), CHIP_ERROR_INCORRECT_STATE);
783+
EXPECT_EQ(tester.TryDecode<bool>(true, { 123 }), CHIP_ERROR_INVALID_ARGUMENT);
760784
}
761785
}
762786

@@ -1097,6 +1121,13 @@ TEST(TestEmberAttributeBuffer, TestDecodeBool)
10971121
EXPECT_TRUE(tester.TryDecode<DataModel::Nullable<bool>>(false, { 0 }).IsSuccess());
10981122
EXPECT_TRUE(tester.TryDecode<DataModel::Nullable<bool>>(DataModel::NullNullable, { 0xFF }).IsSuccess());
10991123
}
1124+
1125+
{
1126+
// Boolean that is NOT nullable
1127+
EncodeTester tester(CreateFakeMeta(ZCL_BOOLEAN_ATTRIBUTE_TYPE, false /* nullable */));
1128+
EXPECT_EQ(tester.TryDecode<DataModel::Nullable<bool>>(DataModel::NullNullable, { 0xFF }), CHIP_ERROR_INVALID_ARGUMENT);
1129+
EXPECT_EQ(tester.TryDecode<bool>(true, { 0xFF }), CHIP_ERROR_INVALID_ARGUMENT);
1130+
}
11001131
}
11011132

11021133
TEST(TestEmberAttributeBuffer, TestDecodeFloatingPoint)
@@ -1120,6 +1151,12 @@ TEST(TestEmberAttributeBuffer, TestDecodeFloatingPoint)
11201151
EXPECT_TRUE(tester.TryDecode<DataModel::Nullable<float>>(DataModel::NullNullable, { 0, 0, 0xC0, 0x7F }).IsSuccess());
11211152
}
11221153

1154+
{
1155+
EncodeTester tester(CreateFakeMeta(ZCL_SINGLE_ATTRIBUTE_TYPE, false /* nullable */));
1156+
// non-nullable float
1157+
EXPECT_TRUE(tester.TryDecode<float>(std::nanf("0"), { 0, 0, 0xC0, 0x7F }).IsSuccess());
1158+
}
1159+
11231160
{
11241161
EncodeTester tester(CreateFakeMeta(ZCL_DOUBLE_ATTRIBUTE_TYPE, false /* nullable */));
11251162
EXPECT_TRUE(tester.TryDecode<double>(123.55, { 0x33, 0x33, 0x33, 0x33, 0x33, 0xE3, 0x5E, 0x40 }).IsSuccess());
@@ -1133,4 +1170,10 @@ TEST(TestEmberAttributeBuffer, TestDecodeFloatingPoint)
11331170
EXPECT_TRUE(
11341171
tester.TryDecode<DataModel::Nullable<double>>(DataModel::NullNullable, { 0, 0, 0, 0, 0, 0, 0xF8, 0x7F }).IsSuccess());
11351172
}
1173+
1174+
{
1175+
EncodeTester tester(CreateFakeMeta(ZCL_DOUBLE_ATTRIBUTE_TYPE, false /* nullable */));
1176+
// non-nullable double
1177+
EXPECT_TRUE(tester.TryDecode<double>(std::nan("0"), { 0, 0, 0, 0, 0, 0, 0xF8, 0x7F }).IsSuccess());
1178+
}
11361179
}

0 commit comments

Comments
 (0)