From 3ae3cda3421431ccad99987cc86bfb624c35b35e Mon Sep 17 00:00:00 2001 From: Ryan Lamb <4955475+kinyoklion@users.noreply.github.com> Date: Tue, 4 Apr 2023 13:28:07 -0700 Subject: [PATCH 1/6] feat: Add json serialization support for contexts. --- libs/common/include/attributes.hpp | 6 ++++++ libs/common/include/context.hpp | 4 ++++ libs/common/include/value.hpp | 4 ++++ libs/common/src/attributes.cpp | 19 +++++++++++++++++ libs/common/src/context.cpp | 6 ++++++ libs/common/src/value.cpp | 34 ++++++++++++++++++++++++++++++ libs/common/tests/value_test.cpp | 22 +++++++++++++++++++ 7 files changed, 95 insertions(+) diff --git a/libs/common/include/attributes.hpp b/libs/common/include/attributes.hpp index 28ec70574..f0d0f06b4 100644 --- a/libs/common/include/attributes.hpp +++ b/libs/common/include/attributes.hpp @@ -5,6 +5,7 @@ #include "attribute_reference.hpp" #include "value.hpp" +#include namespace launchdarkly { @@ -152,4 +153,9 @@ class Attributes { // Kinds are contained at the context level, not inside attributes. }; + +void tag_invoke(boost::json::value_from_tag const&, + boost::json::value& json_value, + Attributes const& attributes); + } // namespace launchdarkly diff --git a/libs/common/include/context.hpp b/libs/common/include/context.hpp index 54b2179fa..ed0a5a829 100644 --- a/libs/common/include/context.hpp +++ b/libs/common/include/context.hpp @@ -129,4 +129,8 @@ class Context { std::string make_canonical_key(); }; +void tag_invoke(boost::json::value_from_tag const&, + boost::json::value& json_value, + Context const& ld_context); + } // namespace launchdarkly diff --git a/libs/common/include/value.hpp b/libs/common/include/value.hpp index 006697278..5914a9950 100644 --- a/libs/common/include/value.hpp +++ b/libs/common/include/value.hpp @@ -433,4 +433,8 @@ class Value { Value tag_invoke(boost::json::value_to_tag const&, boost::json::value const&); +void tag_invoke(boost::json::value_from_tag const&, + boost::json::value& json_value, + Value const& ld_value); + } // namespace launchdarkly diff --git a/libs/common/src/attributes.cpp b/libs/common/src/attributes.cpp index 0c81812a8..f15f18d53 100644 --- a/libs/common/src/attributes.cpp +++ b/libs/common/src/attributes.cpp @@ -1,5 +1,7 @@ #include "attributes.hpp" +#include + namespace launchdarkly { std::string const& Attributes::key() const { @@ -22,4 +24,21 @@ AttributeReference::SetType const& Attributes::private_attributes() const { return private_attributes_; } +void tag_invoke(boost::json::value_from_tag const&, + boost::json::value& json_value, + Attributes const& attributes) { + auto& obj = json_value.emplace_object(); + + obj.emplace("key", attributes.key()); + if(!attributes.name().empty()) { + obj.emplace("name", attributes.name()); + } + if(attributes.anonymous()) { + obj.emplace("anonymous", attributes.anonymous()); + } + for(auto const& attr: attributes.custom_attributes().as_object()) { + obj.emplace(attr.first, boost::json::value_from(attr.second)); + } +} + } // namespace launchdarkly diff --git a/libs/common/src/context.cpp b/libs/common/src/context.cpp index b10fede8f..bfa679575 100644 --- a/libs/common/src/context.cpp +++ b/libs/common/src/context.cpp @@ -89,4 +89,10 @@ std::string Context::make_canonical_key() { return stream.str(); } +void tag_invoke(boost::json::value_from_tag const&, + boost::json::value& json_value, + Context const& ld_context) { + +} + } // namespace launchdarkly diff --git a/libs/common/src/value.cpp b/libs/common/src/value.cpp index 6042f12d5..69b9ff6c6 100644 --- a/libs/common/src/value.cpp +++ b/libs/common/src/value.cpp @@ -5,6 +5,8 @@ #include #include +#include + namespace launchdarkly { const Value Value::null_value_; @@ -255,6 +257,38 @@ Value tag_invoke(boost::json::value_to_tag const& unused, assert(!"All types need to be handled."); } +void tag_invoke(boost::json::value_from_tag const&, + boost::json::value& json_value, + Value const& ld_value) { + switch (ld_value.type()) { + case Value::Type::kNull: + json_value.emplace_null(); + break; + case Value::Type::kBool: + json_value.emplace_bool() = ld_value.as_bool(); + break; + case Value::Type::kNumber: + json_value.emplace_double() = ld_value.as_double(); + break; + case Value::Type::kString: + json_value.emplace_string() = ld_value.as_string(); + break; + case Value::Type::kObject: { + auto& obj = json_value.emplace_object(); + for (auto const& pair : ld_value.as_object()) { + obj.insert_or_assign(pair.first.c_str(), + boost::json::value_from(pair.second)); + } + } break; + case Value::Type::kArray: { + auto& arr = json_value.emplace_array(); + for (auto const& val : ld_value.as_array()) { + arr.push_back(boost::json::value_from(val)); + } + } break; + } +} + // NOLINTEND modernize-return-braced-init-list } // namespace launchdarkly diff --git a/libs/common/tests/value_test.cpp b/libs/common/tests/value_test.cpp index 624b5c0ac..595c7d484 100644 --- a/libs/common/tests/value_test.cpp +++ b/libs/common/tests/value_test.cpp @@ -246,4 +246,26 @@ TEST(ValueTests, FromBoostJson) { EXPECT_FALSE(ld_obj.as_object()["array"].as_array()[1].as_bool()); } +TEST(ValueTests, ToBoostJson) { + Value bool_val(true); + auto boost_bool = boost::json::value_from(bool_val); + EXPECT_TRUE(boost_bool.as_bool()); + + Value string_val("potato"); + auto boost_string = boost::json::value_from(string_val); + EXPECT_EQ("potato", boost_string.as_string()); + + Value number_val(3.14); + auto boost_number = boost::json::value_from(number_val); + EXPECT_EQ(3.14, boost_number.as_double()); + + Value arr_val{true, false, {"a", "b"}, Value::Object{{"string", "ham"}}}; + auto boost_arr = boost::json::value_from(arr_val); + EXPECT_TRUE(boost_arr.as_array().at(0).as_bool()); + EXPECT_FALSE(boost_arr.as_array().at(1).as_bool()); + EXPECT_EQ("a", boost_arr.as_array().at(2).as_array().at(0)); + EXPECT_EQ("b", boost_arr.as_array().at(2).as_array().at(1)); + EXPECT_EQ("ham", boost_arr.as_array().at(3).as_object().at("string")); +} + // NOLINTEND cppcoreguidelines-avoid-magic-numbers From c2794eac38b2c60e24378389622ba12c437c7120 Mon Sep 17 00:00:00 2001 From: Ryan Lamb <4955475+kinyoklion@users.noreply.github.com> Date: Wed, 5 Apr 2023 08:59:58 -0700 Subject: [PATCH 2/6] Context serialization and tests. --- libs/common/include/attributes.hpp | 2 +- libs/common/src/attributes.cpp | 23 +++++++++--- libs/common/src/context.cpp | 20 ++++++++++- libs/common/tests/attributes_test.cpp | 49 ++++++++++++++++++++++++++ libs/common/tests/context_tests.cpp | 50 +++++++++++++++++++++++++++ 5 files changed, 138 insertions(+), 6 deletions(-) diff --git a/libs/common/include/attributes.hpp b/libs/common/include/attributes.hpp index f0d0f06b4..d84602b20 100644 --- a/libs/common/include/attributes.hpp +++ b/libs/common/include/attributes.hpp @@ -3,9 +3,9 @@ #include #include +#include #include "attribute_reference.hpp" #include "value.hpp" -#include namespace launchdarkly { diff --git a/libs/common/src/attributes.cpp b/libs/common/src/attributes.cpp index f15f18d53..d13bdaa79 100644 --- a/libs/common/src/attributes.cpp +++ b/libs/common/src/attributes.cpp @@ -24,21 +24,36 @@ AttributeReference::SetType const& Attributes::private_attributes() const { return private_attributes_; } -void tag_invoke(boost::json::value_from_tag const&, +void tag_invoke(boost::json::value_from_tag const& unused, boost::json::value& json_value, Attributes const& attributes) { + boost::ignore_unused(unused); + auto& obj = json_value.emplace_object(); obj.emplace("key", attributes.key()); - if(!attributes.name().empty()) { + if (!attributes.name().empty()) { obj.emplace("name", attributes.name()); } - if(attributes.anonymous()) { + + if (attributes.anonymous()) { obj.emplace("anonymous", attributes.anonymous()); } - for(auto const& attr: attributes.custom_attributes().as_object()) { + + for (auto const& attr : attributes.custom_attributes().as_object()) { obj.emplace(attr.first, boost::json::value_from(attr.second)); } + + auto private_attributes = attributes.private_attributes(); + if (!private_attributes.empty()) { + obj.emplace("_meta", boost::json::object()); + auto& meta = obj.at("_meta").as_object(); + meta.emplace("privateAttributes", boost::json::array()); + auto& output_array = meta.at("privateAttributes").as_array(); + for (auto const& ref : private_attributes) { + output_array.push_back(boost::json::value(ref.redaction_name())); + } + } } } // namespace launchdarkly diff --git a/libs/common/src/context.cpp b/libs/common/src/context.cpp index bfa679575..9f62ce4d5 100644 --- a/libs/common/src/context.cpp +++ b/libs/common/src/context.cpp @@ -1,5 +1,7 @@ #include +#include + #include "context.hpp" namespace launchdarkly { @@ -92,7 +94,23 @@ std::string Context::make_canonical_key() { void tag_invoke(boost::json::value_from_tag const&, boost::json::value& json_value, Context const& ld_context) { - + if (ld_context.valid()) { + if (ld_context.kinds().size() == 1) { + auto kind = ld_context.kinds()[0].data(); + auto& obj = json_value.emplace_object() = + std::move(boost::json::value_from(ld_context.attributes(kind)) + .as_object()); + obj.emplace("kind", kind); + } else { + auto& obj = json_value.emplace_object(); + obj.emplace("kind", "multi"); + for (auto const& kind : ld_context.kinds()) { + obj.emplace(kind.data(), + boost::json::value_from( + ld_context.attributes(kind.data()))); + } + } + } } } // namespace launchdarkly diff --git a/libs/common/tests/attributes_test.cpp b/libs/common/tests/attributes_test.cpp index c45d25d0e..303487c96 100644 --- a/libs/common/tests/attributes_test.cpp +++ b/libs/common/tests/attributes_test.cpp @@ -1,5 +1,7 @@ #include +#include + #include "attributes.hpp" using launchdarkly::AttributeReference; @@ -101,3 +103,50 @@ TEST(AttributesTests, OStreamOperator) { "number(42)}})}", ProduceString(attributes2)); } + +TEST(AttributesTests, JsonSerializationtest) { + auto attributes_value = boost::json::value_from( + Attributes("the-key", std::nullopt, true, + Value(std::map({{"double", 4.2}})), + AttributeReference::SetType{"/potato", "/bacon"})); + + auto parsed_value = boost::json::parse( + "{" + "\"key\":\"the-key\"," + "\"anonymous\":true," + "\"double\":4.2," + "\"_meta\":{\"privateAttributes\": [\"/bacon\", \"/potato\"]}" + "}"); + + EXPECT_EQ(parsed_value, attributes_value); +} + +TEST(AttributesTests, JsonSerializationOmitsFalseAnonymous) { + auto attributes_value = boost::json::value_from( + Attributes("the-key", std::nullopt, false, + Value(std::map({{"double", 4.2}})), + AttributeReference::SetType{"/potato", "/bacon"})); + + auto parsed_value = boost::json::parse( + "{" + "\"key\":\"the-key\"," + "\"double\":4.2," + "\"_meta\":{\"privateAttributes\": [\"/bacon\", \"/potato\"]}" + "}"); + + EXPECT_EQ(parsed_value, attributes_value); +} + +TEST(AttributesTests, JsonSerializationOmitsMetaIfPrivateAttributesEmpty) { + auto attributes_value = boost::json::value_from( + Attributes("the-key", std::nullopt, false, + Value(std::map({{"double", 4.2}})))); + + auto parsed_value = boost::json::parse( + "{" + "\"key\":\"the-key\"," + "\"double\":4.2" + "}"); + + EXPECT_EQ(parsed_value, attributes_value); +} diff --git a/libs/common/tests/context_tests.cpp b/libs/common/tests/context_tests.cpp index e2acf6ad4..3c02f207f 100644 --- a/libs/common/tests/context_tests.cpp +++ b/libs/common/tests/context_tests.cpp @@ -1,5 +1,7 @@ #include +#include + #include "context_builder.hpp" using launchdarkly::Context; @@ -85,3 +87,51 @@ TEST(ContextTests, OstreamOperatorInvalidContext) { "#$#*(: \"The key for a context may not be empty.\"]", ProduceString(context)); } + +// The attributes_test covers most serialization conditions. +// So these tests are more for overall shape of single and multi-contexts. +TEST(ContextTests, JsonSerializeSingleContext) { + auto context_value = + boost::json::value_from(ContextBuilder() + .kind("user", "user-key") + .set("isCat", true) + .set_private("email", "cat@email.email") + .build()); + + auto parsed_value = boost::json::parse( + "{" + "\"kind\":\"user\"," + "\"key\":\"user-key\"," + "\"isCat\":true," + "\"email\":\"cat@email.email\"," + "\"_meta\":{\"privateAttributes\": [\"email\"]}" + "}"); + + EXPECT_EQ(parsed_value, context_value); +} + +TEST(ContextTests, JsonSerializeMultiContext) { + auto context_value = + boost::json::value_from(ContextBuilder() + .kind("user", "user-key") + .set("isCat", true) + .set_private("email", "cat@email.email") + .kind("org", "org-key") + .build()); + + auto parsed_value = boost::json::parse( + "{" + "\"kind\":\"multi\"," + "\"user\":{" + "\"key\":\"user-key\"," + "\"isCat\":true," + "\"email\":\"cat@email.email\"," + "\"_meta\":{\"privateAttributes\": [\"email\"]}" + "}," + "\"org\":{" + "\"key\":\"org-key\"" + "}" + "}"); + + EXPECT_EQ(parsed_value, context_value); +} From 2c0bed4291fe7a31cb08b3b6bc776b9faf6ceab6 Mon Sep 17 00:00:00 2001 From: Ryan Lamb <4955475+kinyoklion@users.noreply.github.com> Date: Wed, 5 Apr 2023 09:28:52 -0700 Subject: [PATCH 3/6] Move serialization into different files. --- libs/common/include/attributes.hpp | 5 -- libs/common/include/context.hpp | 4 - .../common/include/data/evaluation_reason.hpp | 11 --- .../common/include/data/evaluation_result.hpp | 11 --- .../include/serialization/json_attributes.hpp | 14 +++ .../include/serialization/json_context.hpp | 15 ++++ .../serialization/json_evaluation_reason.hpp | 16 ++++ .../serialization/json_evaluation_result.hpp | 16 ++++ .../include/serialization/json_value.hpp | 23 +++++ .../{ => serialization}/value_mapping.hpp | 0 libs/common/include/value.hpp | 13 --- libs/common/src/CMakeLists.txt | 7 +- libs/common/src/attributes.cpp | 32 ------- libs/common/src/context.cpp | 22 ----- libs/common/src/data/evaluation_reason.cpp | 41 +-------- libs/common/src/data/evaluation_result.cpp | 71 +-------------- .../src/serialization/json_attributes.cpp | 36 ++++++++ .../common/src/serialization/json_context.cpp | 26 ++++++ .../serialization/json_evaluation_reason.cpp | 44 ++++++++++ .../serialization/json_evaluation_result.cpp | 76 ++++++++++++++++ libs/common/src/serialization/json_value.cpp | 87 +++++++++++++++++++ libs/common/src/value.cpp | 83 ------------------ libs/common/src/value_mapping.cpp | 2 +- libs/common/tests/attributes_test.cpp | 13 ++- libs/common/tests/context_tests.cpp | 1 + libs/common/tests/evaluation_reason_test.cpp | 1 + libs/common/tests/evaluation_result_test.cpp | 1 + libs/common/tests/value_test.cpp | 1 + 28 files changed, 375 insertions(+), 297 deletions(-) create mode 100644 libs/common/include/serialization/json_attributes.hpp create mode 100644 libs/common/include/serialization/json_context.hpp create mode 100644 libs/common/include/serialization/json_evaluation_reason.hpp create mode 100644 libs/common/include/serialization/json_evaluation_result.hpp create mode 100644 libs/common/include/serialization/json_value.hpp rename libs/common/include/{ => serialization}/value_mapping.hpp (100%) create mode 100644 libs/common/src/serialization/json_attributes.cpp create mode 100644 libs/common/src/serialization/json_context.cpp create mode 100644 libs/common/src/serialization/json_evaluation_reason.cpp create mode 100644 libs/common/src/serialization/json_evaluation_result.cpp create mode 100644 libs/common/src/serialization/json_value.cpp diff --git a/libs/common/include/attributes.hpp b/libs/common/include/attributes.hpp index d84602b20..01db517e0 100644 --- a/libs/common/include/attributes.hpp +++ b/libs/common/include/attributes.hpp @@ -3,7 +3,6 @@ #include #include -#include #include "attribute_reference.hpp" #include "value.hpp" @@ -154,8 +153,4 @@ class Attributes { // Kinds are contained at the context level, not inside attributes. }; -void tag_invoke(boost::json::value_from_tag const&, - boost::json::value& json_value, - Attributes const& attributes); - } // namespace launchdarkly diff --git a/libs/common/include/context.hpp b/libs/common/include/context.hpp index ed0a5a829..54b2179fa 100644 --- a/libs/common/include/context.hpp +++ b/libs/common/include/context.hpp @@ -129,8 +129,4 @@ class Context { std::string make_canonical_key(); }; -void tag_invoke(boost::json::value_from_tag const&, - boost::json::value& json_value, - Context const& ld_context); - } // namespace launchdarkly diff --git a/libs/common/include/data/evaluation_reason.hpp b/libs/common/include/data/evaluation_reason.hpp index cb148e0d3..1133f4ddc 100644 --- a/libs/common/include/data/evaluation_reason.hpp +++ b/libs/common/include/data/evaluation_reason.hpp @@ -4,8 +4,6 @@ #include #include -#include - namespace launchdarkly { /** @@ -97,13 +95,4 @@ class EvaluationReason { std::optional big_segment_status_; }; -/** - * Method used by boost::json for converting a boost::json::value into a - * launchdarkly::EvaluationReason. - * @return A EvaluationReason representation of the boost::json::value. - */ -EvaluationReason tag_invoke( - boost::json::value_to_tag const& unused, - boost::json::value const& json_value); - } // namespace launchdarkly diff --git a/libs/common/include/data/evaluation_result.hpp b/libs/common/include/data/evaluation_result.hpp index fce0c7260..01742b53b 100644 --- a/libs/common/include/data/evaluation_result.hpp +++ b/libs/common/include/data/evaluation_result.hpp @@ -3,8 +3,6 @@ #include #include -#include - #include "evaluation_detail.hpp" namespace launchdarkly { @@ -68,13 +66,4 @@ class EvaluationResult { EvaluationDetail detail_; }; -/** - * Method used by boost::json for converting a boost::json::value into a - * launchdarkly::EvaluationResult. - * @return A EvaluationResult representation of the boost::json::value. - */ -EvaluationResult tag_invoke( - boost::json::value_to_tag const& unused, - boost::json::value const& json_value); - } // namespace launchdarkly diff --git a/libs/common/include/serialization/json_attributes.hpp b/libs/common/include/serialization/json_attributes.hpp new file mode 100644 index 000000000..b9c5476c3 --- /dev/null +++ b/libs/common/include/serialization/json_attributes.hpp @@ -0,0 +1,14 @@ +#pragma once + +#include +#include "attributes.hpp" + +namespace launchdarkly { +/** + * Method used by boost::json for converting launchdarkly::Attributes into a + * boost::json::value. + */ +void tag_invoke(boost::json::value_from_tag const&, + boost::json::value& json_value, + Attributes const& attributes); +} // namespace launchdarkly diff --git a/libs/common/include/serialization/json_context.hpp b/libs/common/include/serialization/json_context.hpp new file mode 100644 index 000000000..c212a697f --- /dev/null +++ b/libs/common/include/serialization/json_context.hpp @@ -0,0 +1,15 @@ +#pragma once + +#include + +#include "context.hpp" + +namespace launchdarkly { +/** + * Method used by boost::json for converting a launchdarkly::Context into a + * boost::json::value. + */ +void tag_invoke(boost::json::value_from_tag const&, + boost::json::value& json_value, + Context const& ld_context); +} // namespace launchdarkly diff --git a/libs/common/include/serialization/json_evaluation_reason.hpp b/libs/common/include/serialization/json_evaluation_reason.hpp new file mode 100644 index 000000000..150ad2854 --- /dev/null +++ b/libs/common/include/serialization/json_evaluation_reason.hpp @@ -0,0 +1,16 @@ +#pragma once + +#include + +#include "data/evaluation_reason.hpp" + +namespace launchdarkly { +/** + * Method used by boost::json for converting a boost::json::value into a + * launchdarkly::EvaluationReason. + * @return A EvaluationReason representation of the boost::json::value. + */ +EvaluationReason tag_invoke( + boost::json::value_to_tag const& unused, + boost::json::value const& json_value); +} // namespace launchdarkly diff --git a/libs/common/include/serialization/json_evaluation_result.hpp b/libs/common/include/serialization/json_evaluation_result.hpp new file mode 100644 index 000000000..8e510cd5f --- /dev/null +++ b/libs/common/include/serialization/json_evaluation_result.hpp @@ -0,0 +1,16 @@ +#pragma once + +#include + +#include "data/evaluation_result.hpp" + +namespace launchdarkly { +/** + * Method used by boost::json for converting a boost::json::value into a + * launchdarkly::EvaluationResult. + * @return A EvaluationResult representation of the boost::json::value. + */ +EvaluationResult tag_invoke( + boost::json::value_to_tag const& unused, + boost::json::value const& json_value); +} // namespace launchdarkly diff --git a/libs/common/include/serialization/json_value.hpp b/libs/common/include/serialization/json_value.hpp new file mode 100644 index 000000000..6e2e2d908 --- /dev/null +++ b/libs/common/include/serialization/json_value.hpp @@ -0,0 +1,23 @@ +#pragma once + +#include + +#include "value.hpp" + +namespace launchdarkly { +/** + * Method used by boost::json for converting a boost::json::value into a + * launchdarkly::Value. + * @return A Value representation of the boost::json::value. + */ +Value tag_invoke(boost::json::value_to_tag const&, + boost::json::value const&); + +/** + * Method used by boost::json for converting a launchdarkly::Value into a + * boost::json::value. + */ +void tag_invoke(boost::json::value_from_tag const&, + boost::json::value& json_value, + Value const& ld_value); +} // namespace launchdarkly diff --git a/libs/common/include/value_mapping.hpp b/libs/common/include/serialization/value_mapping.hpp similarity index 100% rename from libs/common/include/value_mapping.hpp rename to libs/common/include/serialization/value_mapping.hpp diff --git a/libs/common/include/value.hpp b/libs/common/include/value.hpp index 5914a9950..02ff8841c 100644 --- a/libs/common/include/value.hpp +++ b/libs/common/include/value.hpp @@ -7,7 +7,6 @@ #include #include -#include #include namespace launchdarkly { @@ -425,16 +424,4 @@ class Value { static const Value null_value_; }; -/** - * Method used by boost::json for converting a boost::json::value into a - * launchdarkly::Value. - * @return A Value representation of the boost::json::value. - */ -Value tag_invoke(boost::json::value_to_tag const&, - boost::json::value const&); - -void tag_invoke(boost::json::value_from_tag const&, - boost::json::value& json_value, - Value const& ld_value); - } // namespace launchdarkly diff --git a/libs/common/src/CMakeLists.txt b/libs/common/src/CMakeLists.txt index 51c01f8f8..77217f088 100644 --- a/libs/common/src/CMakeLists.txt +++ b/libs/common/src/CMakeLists.txt @@ -27,7 +27,12 @@ add_library(${LIBNAME} context_filter.cpp config/application_info.cpp lib.cpp - value_mapping.cpp) + value_mapping.cpp + serialization/json_attributes.cpp + serialization/json_context.cpp + serialization/json_evaluation_reason.cpp + serialization/json_evaluation_result.cpp + serialization/json_value.cpp) add_library(launchdarkly::common ALIAS ${LIBNAME}) diff --git a/libs/common/src/attributes.cpp b/libs/common/src/attributes.cpp index d13bdaa79..863f3403c 100644 --- a/libs/common/src/attributes.cpp +++ b/libs/common/src/attributes.cpp @@ -24,36 +24,4 @@ AttributeReference::SetType const& Attributes::private_attributes() const { return private_attributes_; } -void tag_invoke(boost::json::value_from_tag const& unused, - boost::json::value& json_value, - Attributes const& attributes) { - boost::ignore_unused(unused); - - auto& obj = json_value.emplace_object(); - - obj.emplace("key", attributes.key()); - if (!attributes.name().empty()) { - obj.emplace("name", attributes.name()); - } - - if (attributes.anonymous()) { - obj.emplace("anonymous", attributes.anonymous()); - } - - for (auto const& attr : attributes.custom_attributes().as_object()) { - obj.emplace(attr.first, boost::json::value_from(attr.second)); - } - - auto private_attributes = attributes.private_attributes(); - if (!private_attributes.empty()) { - obj.emplace("_meta", boost::json::object()); - auto& meta = obj.at("_meta").as_object(); - meta.emplace("privateAttributes", boost::json::array()); - auto& output_array = meta.at("privateAttributes").as_array(); - for (auto const& ref : private_attributes) { - output_array.push_back(boost::json::value(ref.redaction_name())); - } - } -} - } // namespace launchdarkly diff --git a/libs/common/src/context.cpp b/libs/common/src/context.cpp index 9f62ce4d5..a41b41593 100644 --- a/libs/common/src/context.cpp +++ b/libs/common/src/context.cpp @@ -91,26 +91,4 @@ std::string Context::make_canonical_key() { return stream.str(); } -void tag_invoke(boost::json::value_from_tag const&, - boost::json::value& json_value, - Context const& ld_context) { - if (ld_context.valid()) { - if (ld_context.kinds().size() == 1) { - auto kind = ld_context.kinds()[0].data(); - auto& obj = json_value.emplace_object() = - std::move(boost::json::value_from(ld_context.attributes(kind)) - .as_object()); - obj.emplace("kind", kind); - } else { - auto& obj = json_value.emplace_object(); - obj.emplace("kind", "multi"); - for (auto const& kind : ld_context.kinds()) { - obj.emplace(kind.data(), - boost::json::value_from( - ld_context.attributes(kind.data()))); - } - } - } -} - } // namespace launchdarkly diff --git a/libs/common/src/data/evaluation_reason.cpp b/libs/common/src/data/evaluation_reason.cpp index 2cdf0f849..51ecf77e0 100644 --- a/libs/common/src/data/evaluation_reason.cpp +++ b/libs/common/src/data/evaluation_reason.cpp @@ -1,5 +1,5 @@ #include "data/evaluation_reason.hpp" -#include "value_mapping.hpp" +#include "serialization/value_mapping.hpp" namespace launchdarkly { @@ -47,43 +47,4 @@ EvaluationReason::EvaluationReason( in_experiment_(in_experiment), big_segment_status_(std::move(big_segment_status)) {} -EvaluationReason tag_invoke( - boost::json::value_to_tag const& unused, - boost::json::value const& json_value) { - boost::ignore_unused(unused); - if (json_value.is_object()) { - auto json_obj = json_value.as_object(); - - auto* kind_iter = json_obj.find("kind"); - auto kind = - ValueOrDefault(kind_iter, json_obj.end(), "ERROR"); - - auto* error_kind_iter = json_obj.find("errorKind"); - auto error_kind = - ValueAsOpt(error_kind_iter, json_obj.end()); - - auto* rule_index_iter = json_obj.find("ruleIndex"); - auto rule_index = ValueAsOpt(rule_index_iter, json_obj.end()); - - auto* rule_id_iter = json_obj.find("ruleId"); - auto rule_id = ValueAsOpt(rule_id_iter, json_obj.end()); - - auto* prerequisite_key_iter = json_obj.find("prerequisiteKey"); - auto prerequisite_key = - ValueAsOpt(prerequisite_key_iter, json_obj.end()); - - auto* in_experiment_iter = json_obj.find("inExperiment"); - auto in_experiment = - ValueOrDefault(in_experiment_iter, json_obj.end(), false); - - auto* big_segment_status_iter = json_obj.find("bigSegmentStatus"); - auto big_segment_status = - ValueAsOpt(big_segment_status_iter, json_obj.end()); - - return {std::string(kind), error_kind, rule_index, rule_id, - prerequisite_key, in_experiment, big_segment_status}; - } - return {"ERROR", std::nullopt, 0, std::nullopt, - std::nullopt, false, std::nullopt}; -} } // namespace launchdarkly diff --git a/libs/common/src/data/evaluation_result.cpp b/libs/common/src/data/evaluation_result.cpp index aded6caad..2e2e76de3 100644 --- a/libs/common/src/data/evaluation_result.cpp +++ b/libs/common/src/data/evaluation_result.cpp @@ -1,5 +1,5 @@ #include "data/evaluation_result.hpp" -#include "value_mapping.hpp" +#include "serialization/value_mapping.hpp" #include @@ -45,73 +45,4 @@ EvaluationResult::EvaluationResult( debug_events_until_date_(debug_events_until_date), detail_(std::move(detail)) {} -EvaluationResult tag_invoke( - boost::json::value_to_tag const& unused, - boost::json::value const& json_value) { - boost::ignore_unused(unused); - if (json_value.is_object()) { - auto json_obj = json_value.as_object(); - - auto* version_iter = json_obj.find("version"); - auto version = ValueOrDefault(version_iter, json_obj.end(), 0UL); - - auto* flag_version_iter = json_obj.find("flagVersion"); - auto flag_version = - ValueAsOpt(flag_version_iter, json_obj.end()); - - auto* track_events_iter = json_obj.find("trackEvents"); - auto track_events = - ValueOrDefault(track_events_iter, json_obj.end(), false); - - auto* track_reason_iter = json_obj.find("trackReason"); - auto track_reason = - ValueOrDefault(track_reason_iter, json_obj.end(), false); - - auto* debug_events_until_date_iter = - json_obj.find("debugEventsUntilDate"); - - auto debug_events_until_date = - MapOpt, - uint64_t>(ValueAsOpt(debug_events_until_date_iter, - json_obj.end()), - [](auto value) { - return std::chrono::system_clock::time_point{ - std::chrono::milliseconds{value}}; - }); - - // Evaluation detail is directly de-serialized inline here. - // This is because the shape of the evaluation detail is different - // when deserializing FlagMeta. Primarily `variation` not - // `variationIndex`. - - auto* value_iter = json_obj.find("value"); - auto value = value_iter != json_obj.end() - ? boost::json::value_to(value_iter->value()) - : Value(); - - auto* variation_iter = json_obj.find("variation"); - auto variation = ValueAsOpt(variation_iter, json_obj.end()); - - auto* reason_iter = json_obj.find("reason"); - auto reason = - reason_iter != json_obj.end() - ? std::make_optional(boost::json::value_to( - reason_iter->value())) - : std::nullopt; - - return {version, - flag_version, - track_events, - track_reason, - debug_events_until_date, - EvaluationDetail(value, variation, reason)}; - } - // This would represent malformed JSON. - return {0, - 0, - false, - false, - std::nullopt, - EvaluationDetail(Value(), std::nullopt, std::nullopt)}; -} } // namespace launchdarkly diff --git a/libs/common/src/serialization/json_attributes.cpp b/libs/common/src/serialization/json_attributes.cpp new file mode 100644 index 000000000..4cd124dc8 --- /dev/null +++ b/libs/common/src/serialization/json_attributes.cpp @@ -0,0 +1,36 @@ +#include "serialization/json_attributes.hpp" +#include "serialization/json_value.hpp" + +namespace launchdarkly { +void tag_invoke(boost::json::value_from_tag const& unused, + boost::json::value& json_value, + Attributes const& attributes) { + boost::ignore_unused(unused); + + auto& obj = json_value.emplace_object(); + + obj.emplace("key", attributes.key()); + if (!attributes.name().empty()) { + obj.emplace("name", attributes.name()); + } + + if (attributes.anonymous()) { + obj.emplace("anonymous", attributes.anonymous()); + } + + for (auto const& attr : attributes.custom_attributes().as_object()) { + obj.emplace(attr.first, boost::json::value_from(attr.second)); + } + + auto private_attributes = attributes.private_attributes(); + if (!private_attributes.empty()) { + obj.emplace("_meta", boost::json::object()); + auto& meta = obj.at("_meta").as_object(); + meta.emplace("privateAttributes", boost::json::array()); + auto& output_array = meta.at("privateAttributes").as_array(); + for (auto const& ref : private_attributes) { + output_array.push_back(boost::json::value(ref.redaction_name())); + } + } +} +} // namespace launchdarkly diff --git a/libs/common/src/serialization/json_context.cpp b/libs/common/src/serialization/json_context.cpp new file mode 100644 index 000000000..6ac5e0945 --- /dev/null +++ b/libs/common/src/serialization/json_context.cpp @@ -0,0 +1,26 @@ +#include "serialization/json_context.hpp" +#include "serialization/json_attributes.hpp" + +namespace launchdarkly { +void tag_invoke(boost::json::value_from_tag const&, + boost::json::value& json_value, + Context const& ld_context) { + if (ld_context.valid()) { + if (ld_context.kinds().size() == 1) { + auto kind = ld_context.kinds()[0].data(); + auto& obj = json_value.emplace_object() = + std::move(boost::json::value_from(ld_context.attributes(kind)) + .as_object()); + obj.emplace("kind", kind); + } else { + auto& obj = json_value.emplace_object(); + obj.emplace("kind", "multi"); + for (auto const& kind : ld_context.kinds()) { + obj.emplace(kind.data(), + boost::json::value_from( + ld_context.attributes(kind.data()))); + } + } + } +} +} // namespace launchdarkly diff --git a/libs/common/src/serialization/json_evaluation_reason.cpp b/libs/common/src/serialization/json_evaluation_reason.cpp new file mode 100644 index 000000000..0a95798a0 --- /dev/null +++ b/libs/common/src/serialization/json_evaluation_reason.cpp @@ -0,0 +1,44 @@ +#include "serialization/json_evaluation_reason.hpp" +#include "serialization/value_mapping.hpp" + +namespace launchdarkly { +EvaluationReason tag_invoke( + boost::json::value_to_tag const& unused, + boost::json::value const& json_value) { + boost::ignore_unused(unused); + if (json_value.is_object()) { + auto json_obj = json_value.as_object(); + + auto* kind_iter = json_obj.find("kind"); + auto kind = + ValueOrDefault(kind_iter, json_obj.end(), "ERROR"); + + auto* error_kind_iter = json_obj.find("errorKind"); + auto error_kind = + ValueAsOpt(error_kind_iter, json_obj.end()); + + auto* rule_index_iter = json_obj.find("ruleIndex"); + auto rule_index = ValueAsOpt(rule_index_iter, json_obj.end()); + + auto* rule_id_iter = json_obj.find("ruleId"); + auto rule_id = ValueAsOpt(rule_id_iter, json_obj.end()); + + auto* prerequisite_key_iter = json_obj.find("prerequisiteKey"); + auto prerequisite_key = + ValueAsOpt(prerequisite_key_iter, json_obj.end()); + + auto* in_experiment_iter = json_obj.find("inExperiment"); + auto in_experiment = + ValueOrDefault(in_experiment_iter, json_obj.end(), false); + + auto* big_segment_status_iter = json_obj.find("bigSegmentStatus"); + auto big_segment_status = + ValueAsOpt(big_segment_status_iter, json_obj.end()); + + return {std::string(kind), error_kind, rule_index, rule_id, + prerequisite_key, in_experiment, big_segment_status}; + } + return {"ERROR", std::nullopt, 0, std::nullopt, + std::nullopt, false, std::nullopt}; +} +} // namespace launchdarkly diff --git a/libs/common/src/serialization/json_evaluation_result.cpp b/libs/common/src/serialization/json_evaluation_result.cpp new file mode 100644 index 000000000..f362df90e --- /dev/null +++ b/libs/common/src/serialization/json_evaluation_result.cpp @@ -0,0 +1,76 @@ +#include "serialization/json_evaluation_result.hpp" +#include "serialization/json_evaluation_reason.hpp" +#include "serialization/json_value.hpp" +#include "serialization/value_mapping.hpp" + +namespace launchdarkly { +EvaluationResult tag_invoke( + boost::json::value_to_tag const& unused, + boost::json::value const& json_value) { + boost::ignore_unused(unused); + if (json_value.is_object()) { + auto json_obj = json_value.as_object(); + + auto* version_iter = json_obj.find("version"); + auto version = ValueOrDefault(version_iter, json_obj.end(), 0UL); + + auto* flag_version_iter = json_obj.find("flagVersion"); + auto flag_version = + ValueAsOpt(flag_version_iter, json_obj.end()); + + auto* track_events_iter = json_obj.find("trackEvents"); + auto track_events = + ValueOrDefault(track_events_iter, json_obj.end(), false); + + auto* track_reason_iter = json_obj.find("trackReason"); + auto track_reason = + ValueOrDefault(track_reason_iter, json_obj.end(), false); + + auto* debug_events_until_date_iter = + json_obj.find("debugEventsUntilDate"); + + auto debug_events_until_date = + MapOpt, + uint64_t>(ValueAsOpt(debug_events_until_date_iter, + json_obj.end()), + [](auto value) { + return std::chrono::system_clock::time_point{ + std::chrono::milliseconds{value}}; + }); + + // Evaluation detail is directly de-serialized inline here. + // This is because the shape of the evaluation detail is different + // when deserializing FlagMeta. Primarily `variation` not + // `variationIndex`. + + auto* value_iter = json_obj.find("value"); + auto value = value_iter != json_obj.end() + ? boost::json::value_to(value_iter->value()) + : Value(); + + auto* variation_iter = json_obj.find("variation"); + auto variation = ValueAsOpt(variation_iter, json_obj.end()); + + auto* reason_iter = json_obj.find("reason"); + auto reason = + reason_iter != json_obj.end() + ? std::make_optional(boost::json::value_to( + reason_iter->value())) + : std::nullopt; + + return {version, + flag_version, + track_events, + track_reason, + debug_events_until_date, + EvaluationDetail(value, variation, reason)}; + } + // This would represent malformed JSON. + return {0, + 0, + false, + false, + std::nullopt, + EvaluationDetail(Value(), std::nullopt, std::nullopt)}; +} +} // namespace launchdarkly diff --git a/libs/common/src/serialization/json_value.cpp b/libs/common/src/serialization/json_value.cpp new file mode 100644 index 000000000..6b3a47f6e --- /dev/null +++ b/libs/common/src/serialization/json_value.cpp @@ -0,0 +1,87 @@ +#include "serialization/json_value.hpp" +#include "serialization/value_mapping.hpp" + +namespace launchdarkly { +// NOLINTBEGIN modernize-return-braced-init-list + +// Braced initializer list is not the same for a single item as the +// constructors. Replacing them with braced init lists would result in all types +// being lists. + +Value tag_invoke(boost::json::value_to_tag const& unused, + boost::json::value const& json_value) { + boost::ignore_unused(unused); + // The name of the function needs to be tag_invoke for boost::json. + + // The conditions in these switches explicitly use the constructors, because + // otherwise it is an init list, which is an array. + switch (json_value.kind()) { + case boost::json::kind::null: + return Value(); + case boost::json::kind::bool_: + return Value(json_value.as_bool()); + case boost::json::kind::int64: + return Value(json_value.to_number()); + case boost::json::kind::uint64: + return Value(json_value.to_number()); + case boost::json::kind::double_: + return Value(json_value.as_double()); + case boost::json::kind::string: + return Value(std::string(json_value.as_string())); + case boost::json::kind::array: { + auto vec = json_value.as_array(); + std::vector values; + for (auto const& item : vec) { + values.push_back(boost::json::value_to(item)); + } + return Value(values); + } + case boost::json::kind::object: { + auto map = json_value.as_object(); + std::map values; + for (auto const& pair : map) { + auto value = boost::json::value_to(pair.value()); + values.emplace(pair.key().data(), std::move(value)); + } + return Value(std::move(values)); + } + } + // The above switch is exhaustive, so this can only happen if a new + // type is added to boost::json::value. + assert(!"All types need to be handled."); +} + +void tag_invoke(boost::json::value_from_tag const&, + boost::json::value& json_value, + Value const& ld_value) { + switch (ld_value.type()) { + case Value::Type::kNull: + json_value.emplace_null(); + break; + case Value::Type::kBool: + json_value.emplace_bool() = ld_value.as_bool(); + break; + case Value::Type::kNumber: + json_value.emplace_double() = ld_value.as_double(); + break; + case Value::Type::kString: + json_value.emplace_string() = ld_value.as_string(); + break; + case Value::Type::kObject: { + auto& obj = json_value.emplace_object(); + for (auto const& pair : ld_value.as_object()) { + obj.insert_or_assign(pair.first.c_str(), + boost::json::value_from(pair.second)); + } + } break; + case Value::Type::kArray: { + auto& arr = json_value.emplace_array(); + for (auto const& val : ld_value.as_array()) { + arr.push_back(boost::json::value_from(val)); + } + } break; + } +} + +// NOLINTEND modernize-return-braced-init-list +} // namespace launchdarkly diff --git a/libs/common/src/value.cpp b/libs/common/src/value.cpp index 69b9ff6c6..d2a8a59b7 100644 --- a/libs/common/src/value.cpp +++ b/libs/common/src/value.cpp @@ -208,87 +208,4 @@ Value::Object::Iterator Value::Object::find(std::string const& key) const { return {map_.find(key)}; } -// NOLINTBEGIN modernize-return-braced-init-list - -// Braced initializer list is not the same for a single item as the -// constructors. Replacing them with braced init lists would result in all types -// being lists. - -Value tag_invoke(boost::json::value_to_tag const& unused, - boost::json::value const& json_value) { - boost::ignore_unused(unused); - // The name of the function needs to be tag_invoke for boost::json. - - // The conditions in these switches explicitly use the constructors, because - // otherwise it is an init list, which is an array. - switch (json_value.kind()) { - case boost::json::kind::null: - return Value(); - case boost::json::kind::bool_: - return Value(json_value.as_bool()); - case boost::json::kind::int64: - return Value(json_value.to_number()); - case boost::json::kind::uint64: - return Value(json_value.to_number()); - case boost::json::kind::double_: - return Value(json_value.as_double()); - case boost::json::kind::string: - return Value(std::string(json_value.as_string())); - case boost::json::kind::array: { - auto vec = json_value.as_array(); - std::vector values; - for (auto const& item : vec) { - values.push_back(boost::json::value_to(item)); - } - return Value(values); - } - case boost::json::kind::object: { - auto map = json_value.as_object(); - std::map values; - for (auto const& pair : map) { - auto value = boost::json::value_to(pair.value()); - values.emplace(pair.key().data(), std::move(value)); - } - return Value(std::move(values)); - } - } - // The above switch is exhaustive, so this can only happen if a new - // type is added to boost::json::value. - assert(!"All types need to be handled."); -} - -void tag_invoke(boost::json::value_from_tag const&, - boost::json::value& json_value, - Value const& ld_value) { - switch (ld_value.type()) { - case Value::Type::kNull: - json_value.emplace_null(); - break; - case Value::Type::kBool: - json_value.emplace_bool() = ld_value.as_bool(); - break; - case Value::Type::kNumber: - json_value.emplace_double() = ld_value.as_double(); - break; - case Value::Type::kString: - json_value.emplace_string() = ld_value.as_string(); - break; - case Value::Type::kObject: { - auto& obj = json_value.emplace_object(); - for (auto const& pair : ld_value.as_object()) { - obj.insert_or_assign(pair.first.c_str(), - boost::json::value_from(pair.second)); - } - } break; - case Value::Type::kArray: { - auto& arr = json_value.emplace_array(); - for (auto const& val : ld_value.as_array()) { - arr.push_back(boost::json::value_from(val)); - } - } break; - } -} - -// NOLINTEND modernize-return-braced-init-list - } // namespace launchdarkly diff --git a/libs/common/src/value_mapping.cpp b/libs/common/src/value_mapping.cpp index 6282b8db6..d08ed53bb 100644 --- a/libs/common/src/value_mapping.cpp +++ b/libs/common/src/value_mapping.cpp @@ -1,4 +1,4 @@ -#include "value_mapping.hpp" +#include "serialization/value_mapping.hpp" namespace launchdarkly { diff --git a/libs/common/tests/attributes_test.cpp b/libs/common/tests/attributes_test.cpp index 303487c96..3e68684da 100644 --- a/libs/common/tests/attributes_test.cpp +++ b/libs/common/tests/attributes_test.cpp @@ -3,11 +3,14 @@ #include #include "attributes.hpp" +#include "serialization/json_attributes.hpp" using launchdarkly::AttributeReference; using launchdarkly::Attributes; using launchdarkly::Value; +// NOLINTBEGIN cppcoreguidelines-avoid-magic-numbers + TEST(AttributesTests, CanGetBuiltInAttributesByReference) { Attributes attributes("the-key", "the-name", true, Value()); @@ -93,15 +96,15 @@ TEST(AttributesTests, OStreamOperator) { "[] custom: object({{int, number(42)}})}", ProduceString(attributes)); - Attributes attributes2("the-key", "the-name", true, - Value(std::map({{"int", 42}})), - AttributeReference::SetType{"/potato", "/bacon"}); + Attributes attributes_2("the-key", "the-name", true, + Value(std::map({{"int", 42}})), + AttributeReference::SetType{"/potato", "/bacon"}); EXPECT_EQ( "{key: string(the-key), name: string(the-name) anonymous: bool(true) " "private: [valid(/bacon), valid(/potato)] custom: object({{int, " "number(42)}})}", - ProduceString(attributes2)); + ProduceString(attributes_2)); } TEST(AttributesTests, JsonSerializationtest) { @@ -150,3 +153,5 @@ TEST(AttributesTests, JsonSerializationOmitsMetaIfPrivateAttributesEmpty) { EXPECT_EQ(parsed_value, attributes_value); } + +// NOLINTEND cppcoreguidelines-avoid-magic-numbers diff --git a/libs/common/tests/context_tests.cpp b/libs/common/tests/context_tests.cpp index 3c02f207f..aaa243b10 100644 --- a/libs/common/tests/context_tests.cpp +++ b/libs/common/tests/context_tests.cpp @@ -3,6 +3,7 @@ #include #include "context_builder.hpp" +#include "serialization/json_context.hpp" using launchdarkly::Context; using launchdarkly::ContextBuilder; diff --git a/libs/common/tests/evaluation_reason_test.cpp b/libs/common/tests/evaluation_reason_test.cpp index 2fc5c3129..dbb79f2fd 100644 --- a/libs/common/tests/evaluation_reason_test.cpp +++ b/libs/common/tests/evaluation_reason_test.cpp @@ -3,6 +3,7 @@ #include #include "data/evaluation_reason.hpp" +#include "serialization/json_evaluation_reason.hpp" using launchdarkly::EvaluationReason; diff --git a/libs/common/tests/evaluation_result_test.cpp b/libs/common/tests/evaluation_result_test.cpp index 2b99b3f52..65401ba21 100644 --- a/libs/common/tests/evaluation_result_test.cpp +++ b/libs/common/tests/evaluation_result_test.cpp @@ -3,6 +3,7 @@ #include #include "data/evaluation_result.hpp" +#include "serialization/json_evaluation_result.hpp" using launchdarkly::EvaluationResult; diff --git a/libs/common/tests/value_test.cpp b/libs/common/tests/value_test.cpp index 595c7d484..4729b5035 100644 --- a/libs/common/tests/value_test.cpp +++ b/libs/common/tests/value_test.cpp @@ -4,6 +4,7 @@ #include #include +#include "serialization/json_value.hpp" #include "value.hpp" #include From bf0302448ca1f18576a181d9ac6cc72ff3f36f0c Mon Sep 17 00:00:00 2001 From: Ryan Lamb <4955475+kinyoklion@users.noreply.github.com> Date: Wed, 5 Apr 2023 09:33:03 -0700 Subject: [PATCH 4/6] Remove boost json header from context and attributes. --- libs/common/src/attributes.cpp | 2 -- libs/common/src/context.cpp | 2 -- 2 files changed, 4 deletions(-) diff --git a/libs/common/src/attributes.cpp b/libs/common/src/attributes.cpp index 863f3403c..0c81812a8 100644 --- a/libs/common/src/attributes.cpp +++ b/libs/common/src/attributes.cpp @@ -1,7 +1,5 @@ #include "attributes.hpp" -#include - namespace launchdarkly { std::string const& Attributes::key() const { diff --git a/libs/common/src/context.cpp b/libs/common/src/context.cpp index a41b41593..b10fede8f 100644 --- a/libs/common/src/context.cpp +++ b/libs/common/src/context.cpp @@ -1,7 +1,5 @@ #include -#include - #include "context.hpp" namespace launchdarkly { From 2c027404458a09df2dbbd66ec0f092114c37c5e3 Mon Sep 17 00:00:00 2001 From: Ryan Lamb <4955475+kinyoklion@users.noreply.github.com> Date: Wed, 5 Apr 2023 09:34:26 -0700 Subject: [PATCH 5/6] Cleanup includes. --- libs/common/src/data/evaluation_reason.cpp | 1 - libs/common/src/data/evaluation_result.cpp | 1 - libs/common/src/value.cpp | 2 -- 3 files changed, 4 deletions(-) diff --git a/libs/common/src/data/evaluation_reason.cpp b/libs/common/src/data/evaluation_reason.cpp index 51ecf77e0..d164a76fe 100644 --- a/libs/common/src/data/evaluation_reason.cpp +++ b/libs/common/src/data/evaluation_reason.cpp @@ -1,5 +1,4 @@ #include "data/evaluation_reason.hpp" -#include "serialization/value_mapping.hpp" namespace launchdarkly { diff --git a/libs/common/src/data/evaluation_result.cpp b/libs/common/src/data/evaluation_result.cpp index 2e2e76de3..0045d9b28 100644 --- a/libs/common/src/data/evaluation_result.cpp +++ b/libs/common/src/data/evaluation_result.cpp @@ -1,5 +1,4 @@ #include "data/evaluation_result.hpp" -#include "serialization/value_mapping.hpp" #include diff --git a/libs/common/src/value.cpp b/libs/common/src/value.cpp index d2a8a59b7..55b1d5013 100644 --- a/libs/common/src/value.cpp +++ b/libs/common/src/value.cpp @@ -5,8 +5,6 @@ #include #include -#include - namespace launchdarkly { const Value Value::null_value_; From 4ce05481efc19e0de66e940e53ef51846c2b3215 Mon Sep 17 00:00:00 2001 From: Ryan Lamb <4955475+kinyoklion@users.noreply.github.com> Date: Wed, 5 Apr 2023 09:49:16 -0700 Subject: [PATCH 6/6] Rename EvaluationDetail to EvaluationDetailInternal --- ...ail.hpp => evaluation_detail_internal.hpp} | 4 +-- .../common/include/data/evaluation_result.hpp | 8 +++--- libs/common/src/CMakeLists.txt | 2 +- libs/common/src/data/evaluation_detail.cpp | 24 ------------------ .../src/data/evaluation_detail_internal.cpp | 25 +++++++++++++++++++ libs/common/src/data/evaluation_result.cpp | 4 +-- .../serialization/json_evaluation_result.cpp | 4 +-- 7 files changed, 36 insertions(+), 35 deletions(-) rename libs/common/include/data/{evaluation_detail.hpp => evaluation_detail_internal.hpp} (95%) delete mode 100644 libs/common/src/data/evaluation_detail.cpp create mode 100644 libs/common/src/data/evaluation_detail_internal.cpp diff --git a/libs/common/include/data/evaluation_detail.hpp b/libs/common/include/data/evaluation_detail_internal.hpp similarity index 95% rename from libs/common/include/data/evaluation_detail.hpp rename to libs/common/include/data/evaluation_detail_internal.hpp index d1a96593c..56ae7cbd3 100644 --- a/libs/common/include/data/evaluation_detail.hpp +++ b/libs/common/include/data/evaluation_detail_internal.hpp @@ -18,7 +18,7 @@ namespace launchdarkly { * For more information, see the [SDK reference guide] * (https://docs.launchdarkly.com/sdk/features/evaluation-reasons#TODO). */ -class EvaluationDetail { +class EvaluationDetailInternal { public: /** * The result of the flag evaluation. This will be either one of the flag's @@ -41,7 +41,7 @@ class EvaluationDetail { [[nodiscard]] std::optional> reason() const; - EvaluationDetail(Value value, + EvaluationDetailInternal(Value value, std::optional variation_index, std::optional reason); diff --git a/libs/common/include/data/evaluation_result.hpp b/libs/common/include/data/evaluation_result.hpp index 01742b53b..fa0604402 100644 --- a/libs/common/include/data/evaluation_result.hpp +++ b/libs/common/include/data/evaluation_result.hpp @@ -3,7 +3,7 @@ #include #include -#include "evaluation_detail.hpp" +#include "evaluation_detail_internal.hpp" namespace launchdarkly { @@ -45,7 +45,7 @@ class EvaluationResult { /** * Details of the flags evaluation. */ - [[nodiscard]] EvaluationDetail const& detail() const; + [[nodiscard]] EvaluationDetailInternal const& detail() const; EvaluationResult( uint64_t version, @@ -54,7 +54,7 @@ class EvaluationResult { bool track_reason, std::optional> debug_events_until_date, - EvaluationDetail detail); + EvaluationDetailInternal detail); private: uint64_t version_; @@ -63,7 +63,7 @@ class EvaluationResult { bool track_reason_; std::optional> debug_events_until_date_; - EvaluationDetail detail_; + EvaluationDetailInternal detail_; }; } // namespace launchdarkly diff --git a/libs/common/src/CMakeLists.txt b/libs/common/src/CMakeLists.txt index 77217f088..387e0b836 100644 --- a/libs/common/src/CMakeLists.txt +++ b/libs/common/src/CMakeLists.txt @@ -22,7 +22,7 @@ add_library(${LIBNAME} config/config_builder.cpp config/config.cpp data/evaluation_reason.cpp - data/evaluation_detail.cpp + data/evaluation_detail_internal.cpp data/evaluation_result.cpp context_filter.cpp config/application_info.cpp diff --git a/libs/common/src/data/evaluation_detail.cpp b/libs/common/src/data/evaluation_detail.cpp deleted file mode 100644 index ee4c23200..000000000 --- a/libs/common/src/data/evaluation_detail.cpp +++ /dev/null @@ -1,24 +0,0 @@ -#include "data/evaluation_detail.hpp" - -namespace launchdarkly { - -Value const& EvaluationDetail::value() const { - return value_; -} - -std::optional EvaluationDetail::variation_index() const { - return variation_index_; -} - -std::optional> -EvaluationDetail::reason() const { - return reason_; -} -EvaluationDetail::EvaluationDetail(Value value, - std::optional variation_index, - std::optional reason) - : value_(std::move(value)), - variation_index_(variation_index), - reason_(std::move(reason)) {} - -} // namespace launchdarkly diff --git a/libs/common/src/data/evaluation_detail_internal.cpp b/libs/common/src/data/evaluation_detail_internal.cpp new file mode 100644 index 000000000..2b5a01d75 --- /dev/null +++ b/libs/common/src/data/evaluation_detail_internal.cpp @@ -0,0 +1,25 @@ +#include "data/evaluation_detail_internal.hpp" + +namespace launchdarkly { + +Value const& EvaluationDetailInternal::value() const { + return value_; +} + +std::optional EvaluationDetailInternal::variation_index() const { + return variation_index_; +} + +std::optional> +EvaluationDetailInternal::reason() const { + return reason_; +} +EvaluationDetailInternal::EvaluationDetailInternal( + Value value, + std::optional variation_index, + std::optional reason) + : value_(std::move(value)), + variation_index_(variation_index), + reason_(std::move(reason)) {} + +} // namespace launchdarkly diff --git a/libs/common/src/data/evaluation_result.cpp b/libs/common/src/data/evaluation_result.cpp index 0045d9b28..bc196e4b1 100644 --- a/libs/common/src/data/evaluation_result.cpp +++ b/libs/common/src/data/evaluation_result.cpp @@ -25,7 +25,7 @@ EvaluationResult::debug_events_until_date() const { return debug_events_until_date_; } -EvaluationDetail const& EvaluationResult::detail() const { +EvaluationDetailInternal const& EvaluationResult::detail() const { return detail_; } @@ -36,7 +36,7 @@ EvaluationResult::EvaluationResult( bool track_reason, std::optional> debug_events_until_date, - EvaluationDetail detail) + EvaluationDetailInternal detail) : version_(version), flag_version_(flag_version), track_events_(track_events), diff --git a/libs/common/src/serialization/json_evaluation_result.cpp b/libs/common/src/serialization/json_evaluation_result.cpp index f362df90e..9d5291167 100644 --- a/libs/common/src/serialization/json_evaluation_result.cpp +++ b/libs/common/src/serialization/json_evaluation_result.cpp @@ -63,7 +63,7 @@ EvaluationResult tag_invoke( track_events, track_reason, debug_events_until_date, - EvaluationDetail(value, variation, reason)}; + EvaluationDetailInternal(value, variation, reason)}; } // This would represent malformed JSON. return {0, @@ -71,6 +71,6 @@ EvaluationResult tag_invoke( false, false, std::nullopt, - EvaluationDetail(Value(), std::nullopt, std::nullopt)}; + EvaluationDetailInternal(Value(), std::nullopt, std::nullopt)}; } } // namespace launchdarkly