[style] simplify checking conditional enum values (#10843)

This commit adds a compile time utility to check that enum values are in
order, which eliminates calculating the actual value of conditional enum
values in source code.
This commit is contained in:
Yakun Xu
2024-10-17 18:27:46 -07:00
committed by GitHub
parent deb35b0c25
commit a1474853d8
7 changed files with 168 additions and 107 deletions
+1
View File
@@ -743,6 +743,7 @@ openthread_core_files = [
"utils/slaac_address.hpp",
"utils/srp_client_buffers.cpp",
"utils/srp_client_buffers.hpp",
"utils/static_counter.hpp",
"utils/verhoeff_checksum.cpp",
"utils/verhoeff_checksum.hpp",
]
+15 -9
View File
@@ -38,6 +38,7 @@
#include "crypto/aes_ccm.hpp"
#include "crypto/sha256.hpp"
#include "instance/instance.hpp"
#include "utils/static_counter.hpp"
namespace ot {
namespace Mac {
@@ -2210,19 +2211,24 @@ const char *Mac::OperationToString(Operation aOperation)
#endif
};
static_assert(kOperationIdle == 0, "kOperationIdle value is incorrect");
static_assert(kOperationActiveScan == 1, "kOperationActiveScan value is incorrect");
static_assert(kOperationEnergyScan == 2, "kOperationEnergyScan value is incorrect");
static_assert(kOperationTransmitBeacon == 3, "kOperationTransmitBeacon value is incorrect");
static_assert(kOperationTransmitDataDirect == 4, "kOperationTransmitDataDirect value is incorrect");
static_assert(kOperationTransmitPoll == 5, "kOperationTransmitPoll value is incorrect");
static_assert(kOperationWaitingForData == 6, "kOperationWaitingForData value is incorrect");
struct OperationChecker
{
InitEnumValidatorCounter();
ValidateNextEnum(kOperationIdle);
ValidateNextEnum(kOperationActiveScan);
ValidateNextEnum(kOperationEnergyScan);
ValidateNextEnum(kOperationTransmitBeacon);
ValidateNextEnum(kOperationTransmitDataDirect);
ValidateNextEnum(kOperationTransmitPoll);
ValidateNextEnum(kOperationWaitingForData);
#if OPENTHREAD_FTD
static_assert(kOperationTransmitDataIndirect == 7, "kOperationTransmitDataIndirect value is incorrect");
ValidateNextEnum(kOperationTransmitDataIndirect);
#if OPENTHREAD_CONFIG_MAC_CSL_TRANSMITTER_ENABLE
static_assert(kOperationTransmitDataCsl == 8, "TransmitDataCsl value is incorrect");
ValidateNextEnum(kOperationTransmitDataCsl);
#endif
#endif
};
return kOperationStrings[aOperation];
}
+16 -21
View File
@@ -39,6 +39,7 @@
#include "common/code_utils.hpp"
#include "instance/instance.hpp"
#include "utils/static_counter.hpp"
namespace ot {
namespace Mac {
@@ -1010,32 +1011,26 @@ const char *SubMac::StateToString(State aState)
#endif
};
static_assert(kStateDisabled == 0, "kStateDisabled value is not correct");
static_assert(kStateSleep == 1, "kStateSleep value is not correct");
static_assert(kStateReceive == 2, "kStateReceive value is not correct");
static_assert(kStateCsmaBackoff == 3, "kStateCsmaBackoff value is not correct");
static_assert(kStateTransmit == 4, "kStateTransmit value is not correct");
static_assert(kStateEnergyScan == 5, "kStateEnergyScan value is not correct");
struct StateValueChecker
{
InitEnumValidatorCounter();
ValidateNextEnum(kStateDisabled);
ValidateNextEnum(kStateSleep);
ValidateNextEnum(kStateReceive);
ValidateNextEnum(kStateCsmaBackoff);
ValidateNextEnum(kStateTransmit);
ValidateNextEnum(kStateEnergyScan);
#if OPENTHREAD_CONFIG_MAC_ADD_DELAY_ON_NO_ACK_ERROR_BEFORE_RETRY
static_assert(kStateDelayBeforeRetx == 6, "kStateDelayBeforeRetx value is not correct");
ValidateNextEnum(kStateDelayBeforeRetx);
#endif
#if !OPENTHREAD_MTD && OPENTHREAD_CONFIG_MAC_CSL_TRANSMITTER_ENABLE
static_assert(kStateCslTransmit == 7, "kStateCslTransmit value is not correct");
ValidateNextEnum(kStateCslTransmit);
#endif
#if OPENTHREAD_CONFIG_MAC_CSL_RECEIVER_ENABLE
static_assert(kStateCslSample == 8, "kStateCslSample value is not correct");
#endif
#elif OPENTHREAD_CONFIG_MAC_CSL_RECEIVER_ENABLE
static_assert(kStateCslSample == 7, "kStateCslSample value is not correct");
#endif
#elif !OPENTHREAD_MTD && OPENTHREAD_CONFIG_MAC_CSL_TRANSMITTER_ENABLE
static_assert(kStateCslTransmit == 6, "kStateCslTransmit value is not correct");
#if OPENTHREAD_CONFIG_MAC_CSL_RECEIVER_ENABLE
static_assert(kStateCslSample == 7, "kStateCslSample value is not correct");
#endif
#elif OPENTHREAD_CONFIG_MAC_CSL_RECEIVER_ENABLE
static_assert(kStateCslSample == 6, "kStateCslSample value is not correct");
ValidateNextEnum(kStateCslSample);
#endif
};
return kStateStrings[aState];
}
+14 -12
View File
@@ -31,6 +31,7 @@
#if OPENTHREAD_CONFIG_DNS_CLIENT_ENABLE
#include "instance/instance.hpp"
#include "utils/static_counter.hpp"
/**
* @file
@@ -738,21 +739,22 @@ Client::Client(Instance &aInstance)
, mUserDidSetDefaultAddress(false)
#endif
{
static_assert(kIp6AddressQuery == 0, "kIp6AddressQuery value is not correct");
struct QueryTypeChecker
{
InitEnumValidatorCounter();
ValidateNextEnum(kIp6AddressQuery);
#if OPENTHREAD_CONFIG_DNS_CLIENT_NAT64_ENABLE
static_assert(kIp4AddressQuery == 1, "kIp4AddressQuery value is not correct");
ValidateNextEnum(kIp4AddressQuery);
#endif
#if OPENTHREAD_CONFIG_DNS_CLIENT_SERVICE_DISCOVERY_ENABLE
static_assert(kBrowseQuery == 2, "kBrowseQuery value is not correct");
static_assert(kServiceQuerySrvTxt == 3, "kServiceQuerySrvTxt value is not correct");
static_assert(kServiceQuerySrv == 4, "kServiceQuerySrv value is not correct");
static_assert(kServiceQueryTxt == 5, "kServiceQueryTxt value is not correct");
#endif
#elif OPENTHREAD_CONFIG_DNS_CLIENT_SERVICE_DISCOVERY_ENABLE
static_assert(kBrowseQuery == 1, "kBrowseQuery value is not correct");
static_assert(kServiceQuerySrvTxt == 2, "kServiceQuerySrvTxt value is not correct");
static_assert(kServiceQuerySrv == 3, "kServiceQuerySrv value is not correct");
static_assert(kServiceQueryTxt == 4, "kServiceQuerySrv value is not correct");
ValidateNextEnum(kBrowseQuery);
ValidateNextEnum(kServiceQuerySrvTxt);
ValidateNextEnum(kServiceQuerySrv);
ValidateNextEnum(kServiceQueryTxt);
#endif
};
#if OPENTHREAD_CONFIG_DNS_CLIENT_OVER_TCP_ENABLE
ClearAllBytes(mSendLink);
#endif
+16 -14
View File
@@ -34,6 +34,7 @@
#include "mesh_forwarder.hpp"
#include "instance/instance.hpp"
#include "utils/static_counter.hpp"
namespace ot {
@@ -1770,23 +1771,24 @@ const char *MeshForwarder::MessageActionToString(MessageAction aAction, Error aE
const char *string = kMessageActionStrings[aAction];
static_assert(kMessageReceive == 0, "kMessageReceive value is incorrect");
static_assert(kMessageTransmit == 1, "kMessageTransmit value is incorrect");
static_assert(kMessagePrepareIndirect == 2, "kMessagePrepareIndirect value is incorrect");
static_assert(kMessageDrop == 3, "kMessageDrop value is incorrect");
static_assert(kMessageReassemblyDrop == 4, "kMessageReassemblyDrop value is incorrect");
static_assert(kMessageEvict == 5, "kMessageEvict value is incorrect");
struct MessageActionChecker
{
InitEnumValidatorCounter();
ValidateNextEnum(kMessageReceive);
ValidateNextEnum(kMessageTransmit);
ValidateNextEnum(kMessagePrepareIndirect);
ValidateNextEnum(kMessageDrop);
ValidateNextEnum(kMessageReassemblyDrop);
ValidateNextEnum(kMessageEvict);
#if OPENTHREAD_CONFIG_DELAY_AWARE_QUEUE_MANAGEMENT_ENABLE
static_assert(kMessageMarkEcn == 6, "kMessageMarkEcn is incorrect");
static_assert(kMessageQueueMgmtDrop == 7, "kMessageQueueMgmtDrop is incorrect");
ValidateNextEnum(kMessageMarkEcn);
ValidateNextEnum(kMessageQueueMgmtDrop);
#endif
#if (OPENTHREAD_CONFIG_MAX_FRAMES_IN_DIRECT_TX_QUEUE > 0)
static_assert(kMessageFullQueueDrop == 8, "kMessageFullQueueDrop is incorrect");
#endif
#else
#if (OPENTHREAD_CONFIG_MAX_FRAMES_IN_DIRECT_TX_QUEUE > 0)
static_assert(kMessageFullQueueDrop == 6, "kMessageFullQueueDrop is incorrect");
#endif
ValidateNextEnum(kMessageFullQueueDrop);
#endif
};
if ((aAction == kMessageTransmit) && (aError != kErrorNone))
{
+40 -51
View File
@@ -34,6 +34,7 @@
#include "mle.hpp"
#include "instance/instance.hpp"
#include "utils/static_counter.hpp"
namespace ot {
namespace Mle {
@@ -4029,61 +4030,49 @@ const char *Mle::MessageTypeToString(MessageType aType)
#endif
};
static_assert(kTypeAdvertisement == 0, "kTypeAdvertisement value is incorrect");
static_assert(kTypeAnnounce == 1, "kTypeAnnounce value is incorrect");
static_assert(kTypeChildIdRequest == 2, "kTypeChildIdRequest value is incorrect");
static_assert(kTypeChildIdRequestShort == 3, "kTypeChildIdRequestShort value is incorrect");
static_assert(kTypeChildIdResponse == 4, "kTypeChildIdResponse value is incorrect");
static_assert(kTypeChildUpdateRequestAsChild == 5, "kTypeChildUpdateRequestAsChild value is incorrect");
static_assert(kTypeChildUpdateResponseAsChild == 6, "kTypeChildUpdateResponseAsChild value is incorrect");
static_assert(kTypeDataRequest == 7, "kTypeDataRequest value is incorrect");
static_assert(kTypeDataResponse == 8, "kTypeDataResponse value is incorrect");
static_assert(kTypeDiscoveryRequest == 9, "kTypeDiscoveryRequest value is incorrect");
static_assert(kTypeDiscoveryResponse == 10, "kTypeDiscoveryResponse value is incorrect");
static_assert(kTypeGenericDelayed == 11, "kTypeGenericDelayed value is incorrect");
static_assert(kTypeGenericUdp == 12, "kTypeGenericUdp value is incorrect");
static_assert(kTypeParentRequestToRouters == 13, "kTypeParentRequestToRouters value is incorrect");
static_assert(kTypeParentRequestToRoutersReeds == 14, "kTypeParentRequestToRoutersReeds value is incorrect");
static_assert(kTypeParentResponse == 15, "kTypeParentResponse value is incorrect");
struct MessageTypeChecker
{
InitEnumValidatorCounter();
ValidateNextEnum(kTypeAdvertisement);
ValidateNextEnum(kTypeAnnounce);
ValidateNextEnum(kTypeChildIdRequest);
ValidateNextEnum(kTypeChildIdRequestShort);
ValidateNextEnum(kTypeChildIdResponse);
ValidateNextEnum(kTypeChildUpdateRequestAsChild);
ValidateNextEnum(kTypeChildUpdateResponseAsChild);
ValidateNextEnum(kTypeDataRequest);
ValidateNextEnum(kTypeDataResponse);
ValidateNextEnum(kTypeDiscoveryRequest);
ValidateNextEnum(kTypeDiscoveryResponse);
ValidateNextEnum(kTypeGenericDelayed);
ValidateNextEnum(kTypeGenericUdp);
ValidateNextEnum(kTypeParentRequestToRouters);
ValidateNextEnum(kTypeParentRequestToRoutersReeds);
ValidateNextEnum(kTypeParentResponse);
#if OPENTHREAD_FTD
static_assert(kTypeAddressRelease == 16, "kTypeAddressRelease value is incorrect");
static_assert(kTypeAddressReleaseReply == 17, "kTypeAddressReleaseReply value is incorrect");
static_assert(kTypeAddressReply == 18, "kTypeAddressReply value is incorrect");
static_assert(kTypeAddressSolicit == 19, "kTypeAddressSolicit value is incorrect");
static_assert(kTypeChildUpdateRequestOfChild == 20, "kTypeChildUpdateRequestOfChild value is incorrect");
static_assert(kTypeChildUpdateResponseOfChild == 21, "kTypeChildUpdateResponseOfChild value is incorrect");
static_assert(kTypeChildUpdateResponseOfUnknownChild == 22, "kTypeChildUpdateResponseOfUnknownChild is incorrect");
static_assert(kTypeLinkAccept == 23, "kTypeLinkAccept value is incorrect");
static_assert(kTypeLinkAcceptAndRequest == 24, "kTypeLinkAcceptAndRequest value is incorrect");
static_assert(kTypeLinkReject == 25, "kTypeLinkReject value is incorrect");
static_assert(kTypeLinkRequest == 26, "kTypeLinkRequest value is incorrect");
static_assert(kTypeParentRequest == 27, "kTypeParentRequest value is incorrect");
ValidateNextEnum(kTypeAddressRelease);
ValidateNextEnum(kTypeAddressReleaseReply);
ValidateNextEnum(kTypeAddressReply);
ValidateNextEnum(kTypeAddressSolicit);
ValidateNextEnum(kTypeChildUpdateRequestOfChild);
ValidateNextEnum(kTypeChildUpdateResponseOfChild);
ValidateNextEnum(kTypeChildUpdateResponseOfUnknownChild);
ValidateNextEnum(kTypeLinkAccept);
ValidateNextEnum(kTypeLinkAcceptAndRequest);
ValidateNextEnum(kTypeLinkReject);
ValidateNextEnum(kTypeLinkRequest);
ValidateNextEnum(kTypeParentRequest);
#endif
#if OPENTHREAD_CONFIG_MLE_LINK_METRICS_INITIATOR_ENABLE || OPENTHREAD_CONFIG_MLE_LINK_METRICS_SUBJECT_ENABLE
static_assert(kTypeLinkMetricsManagementRequest == 28, "kTypeLinkMetricsManagementRequest value is incorrect)");
static_assert(kTypeLinkMetricsManagementResponse == 29, "kTypeLinkMetricsManagementResponse value is incorrect)");
static_assert(kTypeLinkProbe == 30, "kTypeLinkProbe value is incorrect)");
ValidateNextEnum(kTypeLinkMetricsManagementRequest);
ValidateNextEnum(kTypeLinkMetricsManagementResponse);
ValidateNextEnum(kTypeLinkProbe);
#endif
#if OPENTHREAD_CONFIG_TIME_SYNC_ENABLE
static_assert(kTypeTimeSync == 31, "kTypeTimeSync value is incorrect");
ValidateNextEnum(kTypeTimeSync);
#endif
#else
#if OPENTHREAD_CONFIG_TIME_SYNC_ENABLE
static_assert(kTypeTimeSync == 28, "kTypeTimeSync value is incorrect");
#endif
#endif
#else // OPENTHREAD_FTD
#if OPENTHREAD_CONFIG_MLE_LINK_METRICS_INITIATOR_ENABLE || OPENTHREAD_CONFIG_MLE_LINK_METRICS_SUBJECT_ENABLE
static_assert(kTypeLinkMetricsManagementRequest == 16, "kTypeLinkMetricsManagementRequest value is incorrect)");
static_assert(kTypeLinkMetricsManagementResponse == 17, "kTypeLinkMetricsManagementResponse value is incorrect)");
static_assert(kTypeLinkProbe == 18, "kTypeLinkProbe value is incorrect)");
#if OPENTHREAD_CONFIG_TIME_SYNC_ENABLE
static_assert(kTypeTimeSync == 19, "kTypeTimeSync value is incorrect");
#endif
#else
#if OPENTHREAD_CONFIG_TIME_SYNC_ENABLE
static_assert(kTypeTimeSync == 16, "kTypeTimeSync value is incorrect");
#endif
#endif
#endif // OPENTHREAD_FTD
};
return kMessageTypeStrings[aType];
}
+66
View File
@@ -0,0 +1,66 @@
/*
* Copyright (c) 2024, The OpenThread Authors.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* 3. Neither the name of the copyright holder nor the
* names of its contributors may be used to endorse or promote products
* derived from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
* LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
* POSSIBILITY OF SUCH DAMAGE.
*/
/**
* @file
* This file provides a compile time counter and utilities based on it.
*/
#ifndef OT_UTILS_STATIC_COUNTER_HPP_
#define OT_UTILS_STATIC_COUNTER_HPP_
namespace ot {
template <int N> struct StaticInt : public StaticInt<N - 1>
{
public:
static constexpr int kValue = N;
};
template <> struct StaticInt<0>
{
public:
static constexpr int kValue = 0;
};
#define StaticCounterInit(N) static constexpr StaticInt<N> StaticCounter(StaticInt<N>)
#define StaticCounterValue() decltype(StaticCounter(StaticInt<255>{}))::kValue
#define StaticCounterIncr() \
static constexpr StaticInt<StaticCounterValue() + 1> StaticCounter(StaticInt<StaticCounterValue() + 1>)
#define InitEnumValidatorCounter() StaticCounterInit(0)
#define ValidateNextEnum(kEnumartor) \
static_assert(kEnumartor == StaticCounterValue(), #kEnumartor " value is incorrect"); \
StaticCounterIncr()
} // namespace ot
#endif // OT_UTILS_STATIC_COUNTER_HPP_