LCOV - code coverage report
Current view: top level - app/data-model - Encode.h (source / functions) Hit Total Coverage
Test: lcov_final.info Lines: 6 8 75.0 %
Date: 2024-02-15 08:20:41 Functions: 3 25 12.0 %

          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        2125 : CHIP_ERROR Encode(TLV::TLVWriter & writer, TLV::Tag tag, X x)
      53             : {
      54        2125 :     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           0 : CHIP_ERROR Encode(TLV::TLVWriter & writer, TLV::Tag tag, const X & x)
     116             : {
     117           0 :     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        5704 : CHIP_ERROR Encode(TLV::TLVWriter & writer, TLV::Tag tag, const Nullable<X> & x)
     181             : {
     182        5704 :     if (x.IsNull())
     183             :     {
     184        5700 :         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           4 :     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 1.14