diff --git a/libs/client-sdk/include/launchdarkly/client_side/bindings/c/sdk.h b/libs/client-sdk/include/launchdarkly/client_side/bindings/c/sdk.h index e45ba26ad..7ed7a4830 100644 --- a/libs/client-sdk/include/launchdarkly/client_side/bindings/c/sdk.h +++ b/libs/client-sdk/include/launchdarkly/client_side/bindings/c/sdk.h @@ -501,9 +501,23 @@ enum LDDataSourceStatus_State { * SDK key will never become valid), or because the SDK client was * explicitly shut down. */ - LD_DATASOURCESTATUS_STATE_SHUTDOWN = 4 + LD_DATASOURCESTATUS_STATE_SHUTDOWN = 4, + + LD_DATASOURCESTATUS_STATE_UNUSED_MAXVALUE = + INT32_MAX /* Used to ensure the underlying type is + * at least 32 bits. */ }; +/** + * @param state The state to convert to a string. + * @param default_if_unknown The default string to return if the state is not + * recognized. + * @return Returns the name of the given LDDataSourceStatus_State. + */ +LD_EXPORT(char const*) +LDDataSourceStatus_State_Name(enum LDDataSourceStatus_State state, + char const* default_if_unknown); + /** * Get an enumerated value representing the overall current state of the data * source. diff --git a/libs/client-sdk/include/launchdarkly/client_side/data_source_status.hpp b/libs/client-sdk/include/launchdarkly/client_side/data_source_status.hpp index 4c14572c5..6909ecdd1 100644 --- a/libs/client-sdk/include/launchdarkly/client_side/data_source_status.hpp +++ b/libs/client-sdk/include/launchdarkly/client_side/data_source_status.hpp @@ -2,6 +2,7 @@ #include #include +#include #include #include #include @@ -15,7 +16,7 @@ namespace launchdarkly::client_side::data_sources { /** * Enumeration of possible data source states. */ -enum class DataSourceState { +enum class DataSourceState : std::int32_t { /** * The initial state of the data source when the SDK is being * initialized. @@ -62,15 +63,17 @@ enum class DataSourceState { * SDK key will never become valid), or because the SDK client was * explicitly shut down. */ - kShutdown = 4, - - // BackgroundDisabled, - - // TODO: A plugin of sorts would likely be required to implement - // network availability. - // kNetworkUnavailable, + kShutdown = 4 }; +/** + * + * @return Returns the name of the given DataSourceState as a string. If + * the enum value is not recognized, the default string value is returned. + */ +char const* GetDataSourceStateName(DataSourceState state, + char const* default_if_unknown); + using DataSourceStatus = common::data_sources::DataSourceStatusBase; diff --git a/libs/client-sdk/src/bindings/c/sdk.cpp b/libs/client-sdk/src/bindings/c/sdk.cpp index da070b98e..078a4ba55 100644 --- a/libs/client-sdk/src/bindings/c/sdk.cpp +++ b/libs/client-sdk/src/bindings/c/sdk.cpp @@ -352,6 +352,14 @@ LDDataSourceStatus_GetState(LDDataSourceStatus status) { TO_DATASOURCESTATUS(status)->State()); } +LD_EXPORT(char const*) +LDDataSourceStatus_State_Name(enum LDDataSourceStatus_State state, + char const* default_if_unknown) { + return GetDataSourceStateName( + static_cast(state), + default_if_unknown); +} + LD_EXPORT(LDDataSourceStatus_ErrorInfo) LDDataSourceStatus_GetLastError(LDDataSourceStatus status) { LD_ASSERT_NOT_NULL(status); diff --git a/libs/client-sdk/src/data_sources/data_source_status.cpp b/libs/client-sdk/src/data_sources/data_source_status.cpp index 437b5b357..98446622d 100644 --- a/libs/client-sdk/src/data_sources/data_source_status.cpp +++ b/libs/client-sdk/src/data_sources/data_source_status.cpp @@ -4,26 +4,27 @@ namespace launchdarkly::client_side::data_sources { -std::ostream& operator<<(std::ostream& out, - DataSourceStatus::DataSourceState const& state) { +char const* GetDataSourceStateName(DataSourceState state, + char const* default_if_unknown) { switch (state) { case DataSourceStatus::DataSourceState::kInitializing: - out << "INITIALIZING"; - break; + return "INITIALIZING"; case DataSourceStatus::DataSourceState::kValid: - out << "VALID"; - break; + return "VALID"; case DataSourceStatus::DataSourceState::kInterrupted: - out << "INTERRUPTED"; - break; + return "INTERRUPTED"; case DataSourceStatus::DataSourceState::kSetOffline: - out << "OFFLINE"; - break; + return "OFFLINE"; case DataSourceStatus::DataSourceState::kShutdown: - out << "SHUTDOWN"; - break; + return "SHUTDOWN"; + default: + return default_if_unknown; } +} +std::ostream& operator<<(std::ostream& out, + DataSourceStatus::DataSourceState const& state) { + out << GetDataSourceStateName(state, "UNKNOWN"); return out; } diff --git a/libs/client-sdk/tests/client_c_bindings_test.cpp b/libs/client-sdk/tests/client_c_bindings_test.cpp index 42f5dac0c..0fb2ec44f 100644 --- a/libs/client-sdk/tests/client_c_bindings_test.cpp +++ b/libs/client-sdk/tests/client_c_bindings_test.cpp @@ -80,8 +80,9 @@ TEST(ClientBindings, RegisterFlagListener) { } void StatusListenerFunction(LDDataSourceStatus status, void* user_data) { - EXPECT_EQ(LD_DATASOURCESTATUS_STATE_OFFLINE, - LDDataSourceStatus_GetState(status)); + auto const state = LDDataSourceStatus_GetState(status); + EXPECT_EQ(LD_DATASOURCESTATUS_STATE_OFFLINE, state); + EXPECT_STREQ("OFFLINE", LDDataSourceStatus_State_Name(state, "unknown")); } // This test registers a listener. It doesn't use the listener, but it @@ -194,3 +195,24 @@ TEST(ClientBindings, ComplexDataSourceStatus) { LDDataSourceStatus_ErrorInfo_Free(info); } + +TEST(ClientBindings, TestDataSourceStatusStateName) { + ASSERT_STREQ(LDDataSourceStatus_State_Name(LD_DATASOURCESTATUS_STATE_VALID, + "unknown"), + "VALID"); + ASSERT_STREQ(LDDataSourceStatus_State_Name( + LD_DATASOURCESTATUS_STATE_OFFLINE, "unknown"), + "OFFLINE"); + ASSERT_STREQ(LDDataSourceStatus_State_Name( + LD_DATASOURCESTATUS_STATE_INITIALIZING, "unknown"), + "INITIALIZING"); + ASSERT_STREQ(LDDataSourceStatus_State_Name( + LD_DATASOURCESTATUS_STATE_SHUTDOWN, "unknown"), + "SHUTDOWN"); + ASSERT_STREQ(LDDataSourceStatus_State_Name( + LD_DATASOURCESTATUS_STATE_INTERRUPTED, "unknown"), + "INTERRUPTED"); + ASSERT_STREQ(LDDataSourceStatus_State_Name( + LD_DATASOURCESTATUS_STATE_UNUSED_MAXVALUE, "unknown"), + "unknown"); +}