Matter SDK Coverage Report
Current view: top level - app/data-model - Encode.h (source / functions) Coverage Total Hit
Test: SHA:b879ecb8e99e175eea0a293a888bda853da2b19c Lines: 100.0 % 8 8
Test Date: 2025-01-17 19:00:11 Functions: 14.3 % 28 4

            Line data    Source code
       1              : /*
       2              :  *
       3              :  *    Copyright (c) 2020-2021 Project CHIP Authors
       4              :  *    All rights reserved.
       5              :  *
       6              :  *    Licensed under the Apache License, Version 2.0 (the "License");
       7              :  *    you may not use this file except in compliance with the License.
       8              :  *    You may obtain a copy of the License at
       9              :  *
      10              :  *        http://www.apache.org/licenses/LICENSE-2.0
      11              :  *
      12              :  *    Unless required by applicable law or agreed to in writing, software
      13              :  *    distributed under the License is distributed on an "AS IS" BASIS,
      14              :  *    WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
      15              :  *    See the License for the specific language governing permissions and
      16              :  *    limitations under the License.
      17              :  */
      18              : 
      19              : #pragma once
      20              : 
      21              : #include <app/data-model/FabricScoped.h>
      22              : #include <app/data-model/Nullable.h>
      23              : #include <lib/core/DataModelTypes.h>
      24              : #include <lib/core/Optional.h>
      25              : #include <lib/core/TLV.h>
      26              : #include <protocols/interaction_model/Constants.h>
      27              : 
      28              : #include <type_traits>
      29              : 
      30              : namespace chip {
      31              : namespace app {
      32              : namespace DataModel {
      33              : 
      34              : namespace detail {
      35              : // A way to detect whether an enum has a kUnknownEnumValue value, for use in enable_if.
      36              : template <typename Enum, Enum value>
      37              : using VoidType = void;
      38              : 
      39              : template <typename, typename = void>
      40              : inline constexpr bool HasUnknownValue = false;
      41              : 
      42              : template <typename T>
      43              : inline constexpr bool HasUnknownValue<T, VoidType<T, T::kUnknownEnumValue>> = true;
      44              : } // namespace detail
      45              : 
      46              : /*
      47              :  * @brief
      48              :  * Set of overloaded encode methods that based on the type of cluster element passed in,
      49              :  * appropriately encodes them to TLV.
      50              :  */
      51              : template <typename X, typename std::enable_if_t<std::is_integral<X>::value, int> = 0>
      52         2176 : CHIP_ERROR Encode(TLV::TLVWriter & writer, TLV::Tag tag, X x)
      53              : {
      54         2176 :     return writer.Put(tag, x);
      55              : }
      56              : 
      57              : template <typename X, typename std::enable_if_t<std::is_floating_point<X>::value, int> = 0>
      58              : CHIP_ERROR Encode(TLV::TLVWriter & writer, TLV::Tag tag, X x)
      59              : {
      60              :     return writer.Put(tag, x);
      61              : }
      62              : 
      63              : template <typename X, typename std::enable_if_t<std::is_enum<X>::value && !detail::HasUnknownValue<X>, int> = 0>
      64              : CHIP_ERROR Encode(TLV::TLVWriter & writer, TLV::Tag tag, X x)
      65              : {
      66              :     return writer.Put(tag, x);
      67              : }
      68              : 
      69              : template <typename X, typename std::enable_if_t<std::is_enum<X>::value && detail::HasUnknownValue<X>, int> = 0>
      70              : CHIP_ERROR Encode(TLV::TLVWriter & writer, TLV::Tag tag, X x)
      71              : {
      72              : #if !CHIP_CONFIG_IM_ENABLE_ENCODING_SENTINEL_ENUM_VALUES
      73              :     if (x == X::kUnknownEnumValue)
      74              :     {
      75              :         return CHIP_IM_GLOBAL_STATUS(ConstraintError);
      76              :     }
      77              : #endif // !CHIP_CONFIG_IM_ENABLE_ENCODING_SENTINEL_ENUM_VALUES
      78              : 
      79              :     return writer.Put(tag, x);
      80              : }
      81              : 
      82              : template <typename X>
      83              : CHIP_ERROR Encode(TLV::TLVWriter & writer, TLV::Tag tag, BitFlags<X> x)
      84              : {
      85              :     return writer.Put(tag, x);
      86              : }
      87              : 
      88              : inline CHIP_ERROR Encode(TLV::TLVWriter & writer, TLV::Tag tag, ByteSpan x)
      89              : {
      90              :     return writer.Put(tag, x);
      91              : }
      92              : 
      93              : inline CHIP_ERROR Encode(TLV::TLVWriter & writer, TLV::Tag tag, Span<const char> x)
      94              : {
      95              :     return writer.PutString(tag, x);
      96              : }
      97              : 
      98              : /*
      99              :  * @brief
     100              :  *
     101              :  * This specific variant that encodes cluster objects (like non fabric-scoped structs, commands, events) to TLV
     102              :  * depends on the presence of an Encode method on the object. The signature of that method
     103              :  * is as follows:
     104              :  *
     105              :  * CHIP_ERROR <Object>::Encode(TLVWriter &writer, TLV::Tag tag) const;
     106              :  *
     107              :  *
     108              :  */
     109              : template <typename X,
     110              :           typename std::enable_if_t<
     111              :               std::is_class<X>::value &&
     112              :                   std::is_same<decltype(std::declval<X>().Encode(std::declval<TLV::TLVWriter &>(), std::declval<TLV::Tag>())),
     113              :                                CHIP_ERROR>::value,
     114              :               X> * = nullptr>
     115           36 : CHIP_ERROR Encode(TLV::TLVWriter & writer, TLV::Tag tag, const X & x)
     116              : {
     117           36 :     return x.Encode(writer, tag);
     118              : }
     119              : 
     120              : /*
     121              :  * @brief
     122              :  *
     123              :  * A way to encode fabric-scoped structs for a write that omits encoding the containing fabric index field.
     124              :  */
     125              : template <typename X,
     126              :           typename std::enable_if_t<std::is_class<X>::value &&
     127              :                                         std::is_same<decltype(std::declval<X>().EncodeForWrite(std::declval<TLV::TLVWriter &>(),
     128              :                                                                                                std::declval<TLV::Tag>())),
     129              :                                                      CHIP_ERROR>::value &&
     130              :                                         DataModel::IsFabricScoped<X>::value,
     131              :                                     X> * = nullptr>
     132              : CHIP_ERROR EncodeForWrite(TLV::TLVWriter & writer, TLV::Tag tag, const X & x)
     133              : {
     134              :     return x.EncodeForWrite(writer, tag);
     135              : }
     136              : 
     137              : /*
     138              :  * @brief
     139              :  *
     140              :  * A way to encode fabric-scoped structs for a read that always encodes the containing fabric index field.
     141              :  *
     142              :  * An accessing fabric index must be passed in to permit including/omitting sensitive fields based on a match with the fabric index
     143              :  * associated with the scoped struct.
     144              :  */
     145              : template <typename X,
     146              :           typename std::enable_if_t<
     147              :               std::is_class<X>::value &&
     148              :                   std::is_same<decltype(std::declval<X>().EncodeForRead(std::declval<TLV::TLVWriter &>(), std::declval<TLV::Tag>(),
     149              :                                                                         std::declval<FabricIndex>())),
     150              :                                CHIP_ERROR>::value &&
     151              :                   DataModel::IsFabricScoped<X>::value,
     152              :               X> * = nullptr>
     153              : CHIP_ERROR EncodeForRead(TLV::TLVWriter & writer, TLV::Tag tag, FabricIndex accessingFabricIndex, const X & x)
     154              : {
     155              :     return x.EncodeForRead(writer, tag, accessingFabricIndex);
     156              : }
     157              : 
     158              : /*
     159              :  * @brief
     160              :  *
     161              :  * Encodes an optional value (struct field, command field, event field).
     162              :  */
     163              : template <typename X>
     164              : CHIP_ERROR Encode(TLV::TLVWriter & writer, TLV::Tag tag, const Optional<X> & x)
     165              : {
     166              :     if (x.HasValue())
     167              :     {
     168              :         return Encode(writer, tag, x.Value());
     169              :     }
     170              :     // If no value, just do nothing.
     171              :     return CHIP_NO_ERROR;
     172              : }
     173              : 
     174              : /*
     175              :  * @brief
     176              :  *
     177              :  * Encodes a nullable value.
     178              :  */
     179              : template <typename X>
     180         5710 : CHIP_ERROR Encode(TLV::TLVWriter & writer, TLV::Tag tag, const Nullable<X> & x)
     181              : {
     182         5710 :     if (x.IsNull())
     183              :     {
     184         5705 :         return writer.PutNull(tag);
     185              :     }
     186              : 
     187              :     // Allow sending invalid values for nullables when
     188              :     // CONFIG_BUILD_FOR_HOST_UNIT_TEST is true, so we can test how the other side
     189              :     // responds.
     190              : #if !CONFIG_BUILD_FOR_HOST_UNIT_TEST
     191              :     if (!x.ExistingValueInEncodableRange())
     192              :     {
     193              :         return CHIP_IM_GLOBAL_STATUS(ConstraintError);
     194              :     }
     195              : #endif // !CONFIG_BUILD_FOR_HOST_UNIT_TEST
     196              : 
     197              :     // The -Wmaybe-uninitialized warning gets confused about the fact
     198              :     // that x.mValue is always initialized if x.IsNull() is not
     199              :     // true, so suppress it for our access to x.Value().
     200              : #pragma GCC diagnostic push
     201              : #if !defined(__clang__)
     202              : #pragma GCC diagnostic ignored "-Wmaybe-uninitialized"
     203              : #endif // !defined(__clang__)
     204            5 :     return Encode(writer, tag, x.Value());
     205              : #pragma GCC diagnostic pop
     206              : }
     207              : 
     208              : /*
     209              :  * @brief
     210              :  *
     211              :  * Encodes a nullable fabric-scoped struct for a write.
     212              :  */
     213              : template <typename X, std::enable_if_t<DataModel::IsFabricScoped<X>::value, bool> = true>
     214              : CHIP_ERROR EncodeForWrite(TLV::TLVWriter & writer, TLV::Tag tag, const Nullable<X> & x)
     215              : {
     216              :     if (x.IsNull())
     217              :     {
     218              :         return writer.PutNull(tag);
     219              :     }
     220              : 
     221              :     // The -Wmaybe-uninitialized warning gets confused about the fact
     222              :     // that x.mValue is always initialized if x.IsNull() is not
     223              :     // true, so suppress it for our access to x.Value().
     224              : #pragma GCC diagnostic push
     225              : #if !defined(__clang__)
     226              : #pragma GCC diagnostic ignored "-Wmaybe-uninitialized"
     227              : #endif // !defined(__clang__)
     228              :     return EncodeForWrite(writer, tag, x.Value());
     229              : #pragma GCC diagnostic pop
     230              : }
     231              : 
     232              : /*
     233              :  * @brief
     234              :  *
     235              :  * Encodes a nullable fabric-scoped struct for a read.
     236              :  */
     237              : template <typename X, std::enable_if_t<DataModel::IsFabricScoped<X>::value, bool> = true>
     238              : CHIP_ERROR EncodeForRead(TLV::TLVWriter & writer, TLV::Tag tag, FabricIndex accessingFabricIndex, const Nullable<X> & x)
     239              : {
     240              :     if (x.IsNull())
     241              :     {
     242              :         return writer.PutNull(tag);
     243              :     }
     244              : 
     245              :     // The -Wmaybe-uninitialized warning gets confused about the fact
     246              :     // that x.mValue is always initialized if x.IsNull() is not
     247              :     // true, so suppress it for our access to x.Value().
     248              : #pragma GCC diagnostic push
     249              : #if !defined(__clang__)
     250              : #pragma GCC diagnostic ignored "-Wmaybe-uninitialized"
     251              : #endif // !defined(__clang__)
     252              :     return EncodeForRead(writer, tag, accessingFabricIndex, x.Value());
     253              : #pragma GCC diagnostic pop
     254              : }
     255              : 
     256              : } // namespace DataModel
     257              : } // namespace app
     258              : } // namespace chip
        

Generated by: LCOV version 2.0-1