From 14b8dfa5afe14a0023afc1e4d4109d48a0f24b6c Mon Sep 17 00:00:00 2001 From: Alfred Fuller Date: Sun, 11 Sep 2022 21:08:45 -0700 Subject: [PATCH] Fold Ensure.h into Create.h Differential Revision: D39377420 fbshipit-source-id: 1624e677074bc892124eb6edc073a4378e0a67db --- .../thrift/src/thrift/lib/cpp2/detail/FieldMask.h | 2 +- third-party/thrift/src/thrift/lib/cpp2/op/Create.h | 7 ++ .../thrift/src/thrift/lib/cpp2/op/CreateTest.cpp | 59 +++++++++- third-party/thrift/src/thrift/lib/cpp2/op/Ensure.h | 38 ------ .../src/thrift/lib/cpp2/op/detail/BasePatch.h | 80 ------------- .../thrift/src/thrift/lib/cpp2/op/detail/Copy.h | 2 +- .../thrift/src/thrift/lib/cpp2/op/detail/Create.h | 130 +++++++++++++++++++++ .../thrift/src/thrift/lib/cpp2/op/detail/Ensure.h | 77 ------------ third-party/thrift/src/thrift/test/CopyTest.cpp | 2 +- third-party/thrift/src/thrift/test/EnsureTest.cpp | 79 ------------- .../thrift/src/thrift/test/GetValueOrNullTest.cpp | 2 +- 11 files changed, 199 insertions(+), 279 deletions(-) delete mode 100644 third-party/thrift/src/thrift/lib/cpp2/op/Ensure.h delete mode 100644 third-party/thrift/src/thrift/lib/cpp2/op/detail/Ensure.h delete mode 100644 third-party/thrift/src/thrift/test/EnsureTest.cpp diff --git a/third-party/thrift/src/thrift/lib/cpp2/detail/FieldMask.h b/third-party/thrift/src/thrift/lib/cpp2/detail/FieldMask.h index 498abcb9668..a621ceacb90 100644 --- a/third-party/thrift/src/thrift/lib/cpp2/detail/FieldMask.h +++ b/third-party/thrift/src/thrift/lib/cpp2/detail/FieldMask.h @@ -19,7 +19,7 @@ #include #include #include -#include +#include #include #include #include diff --git a/third-party/thrift/src/thrift/lib/cpp2/op/Create.h b/third-party/thrift/src/thrift/lib/cpp2/op/Create.h index 32494eb2fad..800fb6190ac 100644 --- a/third-party/thrift/src/thrift/lib/cpp2/op/Create.h +++ b/third-party/thrift/src/thrift/lib/cpp2/op/Create.h @@ -37,6 +37,13 @@ namespace op { template FOLLY_INLINE_VARIABLE constexpr detail::Create create{}; +// Ensures the given field. If the field doesn't exist, emplaces the field. +// For example: +// // calls foo.field_ref().ensure() +// ensure(foo) +template +FOLLY_INLINE_VARIABLE constexpr detail::Ensure ensure{}; + } // namespace op } // namespace thrift } // namespace apache diff --git a/third-party/thrift/src/thrift/lib/cpp2/op/CreateTest.cpp b/third-party/thrift/src/thrift/lib/cpp2/op/CreateTest.cpp index b8d743de194..13367289621 100644 --- a/third-party/thrift/src/thrift/lib/cpp2/op/CreateTest.cpp +++ b/third-party/thrift/src/thrift/lib/cpp2/op/CreateTest.cpp @@ -16,17 +16,22 @@ #include #include +#include #include #include +#include #include #include #include +#include #include #include namespace apache::thrift::op { namespace { - +// TODO(afuller): Use testset instead. +using test::FieldRefStruct; +using test::SmartPointerStruct; using namespace apache::thrift::type; namespace testset = apache::thrift::test::testset; @@ -185,5 +190,57 @@ TEST(CreateTest, Container) { testCreate>(); } +template +void testEnsure(Obj obj, Ord ord) { + using Struct = decltype(obj); + using FieldTag = op::get_field_tag; + auto field = op::get(obj); + op::ensure(field, obj); + EXPECT_EQ(field, 0); + field = 2; + op::ensure(field, obj); // no-op + EXPECT_EQ(field, 2); +} + +template +void testEnsurePtr(Obj obj, Ord ord) { + using Struct = decltype(obj); + using FieldTag = op::get_field_tag; + auto& field = op::get(obj); + op::ensure(field, obj); + EXPECT_EQ(*field, 0); + if constexpr (thrift::detail::is_unique_ptr_v< + std::remove_reference_t>) { + field = std::make_unique(2); + } else { + field = std::make_shared(2); + } + op::ensure(field, obj); // no-op + EXPECT_EQ(*field, 2); +} + +TEST(EnsureTest, FieldRef) { + FieldRefStruct obj; + op::for_each_ordinal( + [&](auto fieldOrdinalTag) { testEnsure(obj, fieldOrdinalTag); }); +} + +TEST(EnsureTest, SmartPointer) { + SmartPointerStruct obj; + op::for_each_ordinal( + [&](auto fieldOrdinalTag) { testEnsurePtr(obj, fieldOrdinalTag); }); +} + +TEST(EnsureTest, Optional) { + FieldRefStruct obj; + using FieldTag = op::get_field_tag, FieldRefStruct>; + auto opt = obj.optional_i32_ref().to_optional(); + op::ensure(opt, obj); + EXPECT_EQ(*opt, 0); + opt = 2; + op::ensure(opt, obj); + EXPECT_EQ(*opt, 2); +} + } // namespace } // namespace apache::thrift::op diff --git a/third-party/thrift/src/thrift/lib/cpp2/op/Ensure.h b/third-party/thrift/src/thrift/lib/cpp2/op/Ensure.h deleted file mode 100644 index 246e53df4b4..00000000000 --- a/third-party/thrift/src/thrift/lib/cpp2/op/Ensure.h +++ /dev/null @@ -1,38 +0,0 @@ -/* - * Copyright (c) Meta Platforms, Inc. and affiliates. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -#pragma once - -#include -#include - -namespace apache { -namespace thrift { -namespace op { - -// TODO: move to Create.h -// Ensures the given field. If the field doesn't exist, emplaces the field. -// For example: -// // calls foo.field_ref().ensure() -// ensure(foo.field_ref(), foo) -// // constructs a smart pointer if doesn't exist. -// ensure(foo.smart_ptr_ref(), foo) -template -FOLLY_INLINE_VARIABLE constexpr detail::Ensure ensure{}; - -} // namespace op -} // namespace thrift -} // namespace apache diff --git a/third-party/thrift/src/thrift/lib/cpp2/op/detail/BasePatch.h b/third-party/thrift/src/thrift/lib/cpp2/op/detail/BasePatch.h index b045619a5b2..89514bbbd12 100644 --- a/third-party/thrift/src/thrift/lib/cpp2/op/detail/BasePatch.h +++ b/third-party/thrift/src/thrift/lib/cpp2/op/detail/BasePatch.h @@ -38,86 +38,6 @@ class bad_patch_access : public std::runtime_error { namespace detail { -// Helpers for detecting compatible optional types. -template -struct is_optional_type : std::false_type {}; -template -struct is_optional_type> : std::true_type {}; -template -struct is_optional_type> : std::true_type {}; -#ifdef THRIFT_HAS_OPTIONAL -template -struct is_optional_type> : std::true_type {}; -#endif - -template -using if_opt_type = std::enable_if_t::value, R>; -template -using if_not_opt_type = std::enable_if_t::value, R>; - -template -if_opt_type hasValue(const T& opt) { - return opt.has_value(); -} -template -bool hasValue(field_ref val) { - return !thrift::empty(*val); -} -template -bool hasValue(terse_field_ref val) { - return !thrift::empty(*val); -} - -// If the given field is absent/unset/void. -template -if_opt_type isAbsent(const T& opt) { - return !opt.has_value(); -} -template -constexpr bool isAbsent(union_field_ref opt) { - return opt.has_value(); -} -template -constexpr bool isAbsent(field_ref) { - return false; -} -template -constexpr bool isAbsent(terse_field_ref) { - return false; -} - -template -if_opt_type> resetValue(T&& opt) { - opt.reset(); -} -template -constexpr if_not_opt_type resetValue(T&&) {} - -// TODO: use op::clear and op::ensure to avoid duplication -template -if_opt_type> clearValue(T&& opt) { - opt.reset(); -} -template -if_not_opt_type clearValue(T& unn) { - thrift::clear(unn); -} - -template -if_opt_type ensureValue(T& opt) { - if (!opt.has_value()) { - opt.emplace(); - } -} -template -void ensureValue(field_ref val) { - val.ensure(); -} -template -void ensureValue(terse_field_ref) { - // A terse field doesn't have a set or unset state, so ensure is a noop. -} - template if_opt_type sameType(const T& opt1, const U& opt2) { return opt1.has_value() == opt2.has_value(); diff --git a/third-party/thrift/src/thrift/lib/cpp2/op/detail/Copy.h b/third-party/thrift/src/thrift/lib/cpp2/op/detail/Copy.h index cd380926a23..14942f892cf 100644 --- a/third-party/thrift/src/thrift/lib/cpp2/op/detail/Copy.h +++ b/third-party/thrift/src/thrift/lib/cpp2/op/detail/Copy.h @@ -17,7 +17,7 @@ #pragma once #include -#include +#include #include #include diff --git a/third-party/thrift/src/thrift/lib/cpp2/op/detail/Create.h b/third-party/thrift/src/thrift/lib/cpp2/op/detail/Create.h index 22bb237406d..6e1d4f25def 100644 --- a/third-party/thrift/src/thrift/lib/cpp2/op/detail/Create.h +++ b/third-party/thrift/src/thrift/lib/cpp2/op/detail/Create.h @@ -18,6 +18,7 @@ #include #include +#include #include #include #include @@ -27,6 +28,90 @@ namespace thrift { namespace op { namespace detail { +// Helpers for detecting compatible optional types. +template +struct is_optional_type : std::false_type {}; +template +struct is_optional_type> : std::true_type {}; +template +struct is_optional_type> : std::true_type {}; +#ifdef THRIFT_HAS_OPTIONAL +template +struct is_optional_type> : std::true_type {}; +#endif + +template +using if_opt_type = std::enable_if_t::value, R>; +template +using if_not_opt_type = std::enable_if_t::value, R>; + +template +if_opt_type hasValue(const T& opt) { + return opt.has_value(); +} +template +bool hasValue(field_ref val) { + return !thrift::empty(*val); +} +template +bool hasValue(terse_field_ref val) { + return !thrift::empty(*val); +} + +// If the given field is absent/unset/void. +template +if_opt_type isAbsent(const T& opt) { + return !opt.has_value(); +} +template +constexpr bool isAbsent(union_field_ref opt) { + return opt.has_value(); +} +template +constexpr bool isAbsent(field_ref) { + return false; +} +template +constexpr bool isAbsent(terse_field_ref) { + return false; +} + +template +if_opt_type> resetValue(T&& opt) { + opt.reset(); +} +template +constexpr if_not_opt_type resetValue(T&&) {} + +// TODO: use op::clear and op::ensure to avoid duplication +template +if_opt_type> clearValue(T&& opt) { + opt.reset(); +} +template +if_not_opt_type clearValue(T& unn) { + thrift::clear(unn); +} + +template +if_opt_type ensureValue(T& opt) { + if (!opt.has_value()) { + opt.emplace(); + } +} +template +void ensureValue(union_field_ref val) { + val.ensure(); +} +template +void ensureValue(field_ref val) { + val.ensure(); +} +template +void ensureValue(terse_field_ref) { + // A terse field doesn't have a set or unset state, so ensure is a noop. +} + template struct Create { static_assert(type::is_concrete_v, ""); @@ -37,6 +122,9 @@ struct Create { } }; +template +struct Ensure {}; + template struct Create> { using adapted_tag = type::adapted; @@ -80,6 +168,48 @@ struct Create< } }; +// TODO: support adapted field, smart pointers with custom allocators, and union +// TODO: return T& to get value from ensure method and accept a custom default +template +struct Ensure> { + using field_tag = type::field; + static_assert(type::is_concrete_v, ""); + template + void operator()(field_ref field_ref, Struct&) const { + field_ref.ensure(); + } + template + void operator()(optional_field_ref field_ref, Struct&) const { + field_ref.ensure(); + } + template + void operator()(optional_boxed_field_ref field_ref, Struct&) const { + field_ref.ensure(); + } + template + void operator()(terse_field_ref, Struct&) const { + // A terse field doesn't have a set or unset state, so ensure is a noop. + } + template + if_opt_type operator()(T& opt, Struct&) const { + if (!opt.has_value()) { + opt.emplace(); + } + } + + template + void operator()(std::unique_ptr& ptr, Struct&) const { + if (!ptr) { + ptr = std::make_unique(); + } + } + template + void operator()(std::shared_ptr& ptr, Struct&) const { + if (!ptr) { + ptr = std::make_shared(); + } + } +}; } // namespace detail } // namespace op } // namespace thrift diff --git a/third-party/thrift/src/thrift/lib/cpp2/op/detail/Ensure.h b/third-party/thrift/src/thrift/lib/cpp2/op/detail/Ensure.h deleted file mode 100644 index a4e4d534805..00000000000 --- a/third-party/thrift/src/thrift/lib/cpp2/op/detail/Ensure.h +++ /dev/null @@ -1,77 +0,0 @@ -/* - * Copyright (c) Meta Platforms, Inc. and affiliates. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -#pragma once - -#include -#include -#include -#include - -namespace apache { -namespace thrift { -namespace op { -namespace detail { - -template -struct Ensure {}; - -// TODO: support adapted field, smart pointers with custom allocators, and union -// TODO: return T& to get value from ensure method and accept a custom default -template -struct Ensure> { - using field_tag = type::field; - static_assert(type::is_concrete_v, ""); - template - void operator()(field_ref field_ref, Struct&) const { - field_ref.ensure(); - } - template - void operator()(optional_field_ref field_ref, Struct&) const { - field_ref.ensure(); - } - template - void operator()(optional_boxed_field_ref field_ref, Struct&) const { - field_ref.ensure(); - } - template - void operator()(terse_field_ref, Struct&) const { - // A terse field doesn't have a set or unset state, so ensure is a noop. - } - template - if_opt_type operator()(T& opt, Struct&) const { - if (!opt.has_value()) { - opt.emplace(); - } - } - - template - void operator()(std::unique_ptr& ptr, Struct&) const { - if (!ptr) { - ptr = std::make_unique(); - } - } - template - void operator()(std::shared_ptr& ptr, Struct&) const { - if (!ptr) { - ptr = std::make_shared(); - } - } -}; -} // namespace detail -} // namespace op -} // namespace thrift -} // namespace apache diff --git a/third-party/thrift/src/thrift/test/CopyTest.cpp b/third-party/thrift/src/thrift/test/CopyTest.cpp index 6d73e6014be..c08a236776c 100644 --- a/third-party/thrift/src/thrift/test/CopyTest.cpp +++ b/third-party/thrift/src/thrift/test/CopyTest.cpp @@ -16,7 +16,7 @@ #include #include -#include +#include #include #include diff --git a/third-party/thrift/src/thrift/test/EnsureTest.cpp b/third-party/thrift/src/thrift/test/EnsureTest.cpp deleted file mode 100644 index ac8b1dc87d6..00000000000 --- a/third-party/thrift/src/thrift/test/EnsureTest.cpp +++ /dev/null @@ -1,79 +0,0 @@ -/* - * Copyright (c) Meta Platforms, Inc. and affiliates. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -#include -#include -#include -#include -#include - -namespace apache::thrift::test { -namespace { - -template -void testEnsure(Obj obj, Ord ord) { - using Struct = decltype(obj); - using FieldTag = op::get_field_tag; - auto field = op::get(obj); - op::ensure(field, obj); - EXPECT_EQ(field, 0); - field = 2; - op::ensure(field, obj); // no-op - EXPECT_EQ(field, 2); -} - -template -void testEnsurePtr(Obj obj, Ord ord) { - using Struct = decltype(obj); - using FieldTag = op::get_field_tag; - auto& field = op::get(obj); - op::ensure(field, obj); - EXPECT_EQ(*field, 0); - if constexpr (detail::is_unique_ptr_v< - std::remove_reference_t>) { - field = std::make_unique(2); - } else { - field = std::make_shared(2); - } - op::ensure(field, obj); // no-op - EXPECT_EQ(*field, 2); -} - -TEST(EnsureTest, FieldRef) { - FieldRefStruct obj; - op::for_each_ordinal( - [&](auto fieldOrdinalTag) { testEnsure(obj, fieldOrdinalTag); }); -} - -TEST(EnsureTest, SmartPointer) { - SmartPointerStruct obj; - op::for_each_ordinal( - [&](auto fieldOrdinalTag) { testEnsurePtr(obj, fieldOrdinalTag); }); -} - -TEST(EnsureTest, Optional) { - FieldRefStruct obj; - using FieldTag = op::get_field_tag, FieldRefStruct>; - auto opt = obj.optional_i32_ref().to_optional(); - op::ensure(opt, obj); - EXPECT_EQ(*opt, 0); - opt = 2; - op::ensure(opt, obj); - EXPECT_EQ(*opt, 2); -} - -} // namespace -} // namespace apache::thrift::test diff --git a/third-party/thrift/src/thrift/test/GetValueOrNullTest.cpp b/third-party/thrift/src/thrift/test/GetValueOrNullTest.cpp index 2964535e0da..60d5850cbc7 100644 --- a/third-party/thrift/src/thrift/test/GetValueOrNullTest.cpp +++ b/third-party/thrift/src/thrift/test/GetValueOrNullTest.cpp @@ -18,7 +18,7 @@ #include #include #include -#include +#include #include #include -- 2.11.4.GIT