@@ -100,6 +100,29 @@ struct EndpointEntryCount : public PersistentData<kPersistentBufferEntryCountByt
100
100
}
101
101
};
102
102
103
+ // Prevent mutations from happening in TableEntryData::Serialize
104
+ // If we just used a raw reference for TableEntryData::mEntry, C++ allows us
105
+ // to mutate mEntry.mStorageId & mEntry.mStorageData in TableEntryData::Serialize
106
+ // without having to do a const_cast; as an example, if we were to accidentally introduce
107
+ // the following code in TableEntryData::Serialize (a const method):
108
+ //
109
+ // this->mEntry->mStorageData = StorageData();
110
+ //
111
+ // If TableEntryData::mEntry is a reference, it allows this with no compilation error;
112
+ // But with ConstCorrectRef, we get a compile-time error that TableEntryData::mEntry->mStorageData
113
+ // cannot be modified because it is a const value
114
+ template <typename T>
115
+ class ConstCorrectRef
116
+ {
117
+ T & mRef ;
118
+
119
+ public:
120
+ inline ConstCorrectRef (T & ref) : mRef(ref) {}
121
+
122
+ inline const T * operator ->() const { return &mRef ; }
123
+ inline T * operator ->() { return &mRef ; }
124
+ };
125
+
103
126
template <class StorageId , class StorageData >
104
127
struct TableEntryData : DataAccessor
105
128
{
@@ -110,7 +133,7 @@ struct TableEntryData : DataAccessor
110
133
FabricIndex fabric_index = kUndefinedFabricIndex ;
111
134
EntryIndex index = 0 ;
112
135
bool first = true ;
113
- Data::TableEntry<StorageId, StorageData> & mEntry ;
136
+ ConstCorrectRef< Data::TableEntry<StorageId, StorageData>> mEntry ;
114
137
115
138
TableEntryData (EndpointId endpoint, FabricIndex fabric, TableEntry & entry, EntryIndex idx = 0 ) :
116
139
endpoint_id (endpoint), fabric_index(fabric), index(idx), mEntry (entry)
@@ -124,16 +147,16 @@ struct TableEntryData : DataAccessor
124
147
return CHIP_NO_ERROR;
125
148
}
126
149
127
- void Clear () override { this ->mEntry . mStorageData .Clear (); }
150
+ void Clear () override { this ->mEntry -> mStorageData .Clear (); }
128
151
129
152
CHIP_ERROR Serialize (TLV::TLVWriter & writer) const override
130
153
{
131
154
TLV::TLVType container;
132
155
ReturnErrorOnFailure (writer.StartContainer (TLV::AnonymousTag (), TLV::kTLVType_Structure , container));
133
156
134
- ReturnErrorOnFailure (Serializer::SerializeId (writer, this ->mEntry . mStorageId ));
157
+ ReturnErrorOnFailure (Serializer::SerializeId (writer, this ->mEntry -> mStorageId ));
135
158
136
- ReturnErrorOnFailure (Serializer::SerializeData (writer, this ->mEntry . mStorageData ));
159
+ ReturnErrorOnFailure (Serializer::SerializeData (writer, this ->mEntry -> mStorageData ));
137
160
138
161
return writer.EndContainer (container);
139
162
}
@@ -145,9 +168,9 @@ struct TableEntryData : DataAccessor
145
168
TLV::TLVType container;
146
169
ReturnErrorOnFailure (reader.EnterContainer (container));
147
170
148
- ReturnErrorOnFailure (Serializer::DeserializeId (reader, this ->mEntry . mStorageId ));
171
+ ReturnErrorOnFailure (Serializer::DeserializeId (reader, this ->mEntry -> mStorageId ));
149
172
150
- ReturnErrorOnFailure (Serializer::DeserializeData (reader, this ->mEntry . mStorageData ));
173
+ ReturnErrorOnFailure (Serializer::DeserializeData (reader, this ->mEntry -> mStorageData ));
151
174
152
175
return reader.ExitContainer (container);
153
176
}
0 commit comments