Matter SDK Coverage Report
Current view: top level - app/server-cluster - OptionalAttributeSet.h (source / functions) Coverage Total Hit
Test: SHA:97920baf58e6bf4a18be41e121e08f13676f36b0 Lines: 94.7 % 19 18
Test Date: 2025-08-17 07:11:11 Functions: 100.0 % 43 43

            Line data    Source code
       1              : /*
       2              :  *    Copyright (c) 2025 Project CHIP Authors
       3              :  *    All rights reserved.
       4              :  *
       5              :  *    Licensed under the Apache License, Version 2.0 (the "License");
       6              :  *    you may not use this file except in compliance with the License.
       7              :  *    You may obtain a copy of the License at
       8              :  *
       9              :  *        http://www.apache.org/licenses/LICENSE-2.0
      10              :  *
      11              :  *    Unless required by applicable law or agreed to in writing, software
      12              :  *    distributed under the License is distributed on an "AS IS" BASIS,
      13              :  *    WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
      14              :  *    See the License for the specific language governing permissions and
      15              :  *    limitations under the License.
      16              :  */
      17              : #pragma once
      18              : 
      19              : #include <cstdint>
      20              : #include <lib/core/DataModelTypes.h>
      21              : 
      22              : namespace chip {
      23              : namespace app {
      24              : namespace Internal {
      25              : 
      26              : // Compile-time helper to check if an ID is in a list of IDs.
      27              : template <AttributeId T, AttributeId... Ts>
      28              : struct IsOneOf;
      29              : 
      30              : template <AttributeId T, AttributeId Head, AttributeId... Tail>
      31              : struct IsOneOf<T, Head, Tail...>
      32              : {
      33              :     static constexpr bool value = (T == Head) || IsOneOf<T, Tail...>::value;
      34              : };
      35              : 
      36              : template <AttributeId T>
      37              : struct IsOneOf<T>
      38              : {
      39              :     static constexpr bool value = false;
      40              : };
      41              : 
      42              : } // namespace Internal
      43              : 
      44              : /// It is very common that a class has optional attributes. Such optional attributes
      45              : /// need checking for and also affect what attributes are being returned by
      46              : /// server cluster implementations
      47              : ///
      48              : /// This class implements the common case where attribute IDs can fit
      49              : /// within a 32-bit bitset as most attributes start with low IDs and are incremented
      50              : /// by one.
      51              : ///
      52              : /// NOTE: this will NOT work for all possible attributes/clusters, only for clusters
      53              : ///       whose optionnal attributes all have IDs under 32.
      54              : ///
      55              : /// The implementation of the class generally is a wrapper over a bitset with a
      56              : /// `IsSet()` method. Configurations should use the OptionalAttributeSet<...> class.
      57              : class AttributeSet
      58              : {
      59              : public:
      60            3 :     explicit AttributeSet(uint32_t initialValue) : mSetBits(initialValue) {}
      61              : 
      62           18 :     AttributeSet()                                       = default;
      63              :     AttributeSet(const AttributeSet & other)             = default;
      64              :     AttributeSet(AttributeSet && other)                  = default;
      65              :     AttributeSet & operator=(const AttributeSet & other) = default;
      66              :     AttributeSet & operator=(AttributeSet && other)      = default;
      67              : 
      68              :     // Checks if an attribute ID is set.
      69              :     //
      70              :     // NOTE: this does NOT validate that the ID is < 32 because all the Set functions
      71              :     //       generally are asserted on this (forceset as well as subclasses) and the
      72              :     //       initial value contructor uses a uint32_t bitmask as well.
      73              :     //
      74              :     // This MUST be called with id < 32.
      75          191 :     constexpr bool IsSet(AttributeId id) const { return (mSetBits & (1u << id)) != 0; }
      76              : 
      77              :     /// Exposes a "force attribute bit set" without extra validation,
      78              :     /// so that clusters can enforce specific bits to be set.
      79              :     ///
      80              :     /// This is NOT intended as a generic set, use `OptionalAttributeSet` to configure values.
      81              :     template <AttributeId id>
      82            9 :     constexpr AttributeSet & ForceSet()
      83              :     {
      84              :         static_assert(id < 32, "Attribute ID must be settable");
      85            9 :         return Set(id, true);
      86              :     }
      87              : 
      88              : protected:
      89           37 :     constexpr AttributeSet & Set(AttributeId id, bool value = true)
      90              :     {
      91           37 :         if (value)
      92              :         {
      93           37 :             mSetBits |= static_cast<uint32_t>((static_cast<uint32_t>(1) << id));
      94              :         }
      95              :         else
      96              :         {
      97            0 :             mSetBits &= ~static_cast<uint32_t>((static_cast<uint32_t>(1) << id));
      98              :         }
      99           37 :         return *this;
     100              :     }
     101              : 
     102              : private:
     103              :     uint32_t mSetBits = 0;
     104              : };
     105              : 
     106              : /// A specialization of AttributeSet that provides checked calls to `Set`.
     107              : ///
     108              : /// Specifically it requires that attributes are declared as part of the template
     109              : /// parameter pack.
     110              : ///
     111              : /// NOTE: this will NOT work for all possible attributes/clusters, only for clusters
     112              : ///       whose optional attributes all have IDs under 32. Static asserts are in place
     113              : ///       to ensure that arguments to the template are valid.
     114              : ///
     115              : /// Example usage:
     116              : ///
     117              : ///    namespace chip::app::Clusters::GeneralDiagnostics {
     118              : ///
     119              : ///    using OptionalAttributeSet = chip::app::OptionalAttributeSet<
     120              : ///        Attributes::TotalOperationalHours::Id,
     121              : ///        Attributes::BootReason::Id,
     122              : ///        Attributes::ActiveHardwareFaults::Id
     123              : ///    >;
     124              : ///
     125              : ///    } // namespace chip::app::Clusters::GeneralDiagnostics
     126              : ///
     127              : /// After this, one can:
     128              : ///
     129              : ///   GeneralDiagnostics::OptionalAttributeSet()
     130              : ///      .Set<GeneralDiagnostics::Attributes::TotalOperationalHours::Id>()
     131              : ///      .Set<GeneralDiagnostics::Attributes::BootReason::Id>();
     132              : ///
     133              : /// Cluster implementations can then store a
     134              : ///   Constructor(const GeneralDiagnostics::OptionalAttributeSet& optionalAttributeSet) :
     135              : ///   mOptionalAttributeSet(optionalAttributeSet) {...}
     136              : ///
     137              : /// where:
     138              : ///   const AttributeSet mOptionalAttributeSet;
     139              : template <AttributeId... OptionalAttributeIds>
     140              : class OptionalAttributeSet : public AttributeSet
     141              : {
     142              : public:
     143            3 :     explicit OptionalAttributeSet(uint32_t initialValue) : AttributeSet(initialValue & All()) {}
     144            7 :     OptionalAttributeSet(const AttributeSet & initialValue) : AttributeSet(initialValue) {}
     145           13 :     OptionalAttributeSet() = default;
     146              : 
     147              :     template <uint32_t ATTRIBUTE_ID>
     148           28 :     constexpr OptionalAttributeSet & Set(bool value = true)
     149              :     {
     150              :         static_assert(ATTRIBUTE_ID < 32, "Cluster attribute bits supports attributes up to 31");
     151              :         static_assert(Internal::IsOneOf<ATTRIBUTE_ID, OptionalAttributeIds...>::value, "attribute MUST be optional");
     152           28 :         (void) AttributeSet::Set(ATTRIBUTE_ID, value);
     153           28 :         return *this;
     154              :     }
     155              : 
     156            3 :     static constexpr uint32_t All()
     157              :     {
     158              :         if constexpr (sizeof...(OptionalAttributeIds) == 0)
     159              :         {
     160            1 :             return 0;
     161              :         }
     162              :         else
     163              :         {
     164            2 :             return ((1U << OptionalAttributeIds) | ...);
     165              :         }
     166              :     }
     167              : };
     168              : 
     169              : } // namespace app
     170              : } // namespace chip
        

Generated by: LCOV version 2.0-1