Skip to content

Commit 6fbae55

Browse files
Mizuchifacebook-github-bot
authored andcommitted
Add customization to CppType and Adapter for RecursiveEncode
Summary: Currently RecursiveEncode cannot handle cpp type and adapted type. This diff added such support. Reviewed By: vitaut Differential Revision: D44309830 fbshipit-source-id: d7a10e9ef5c4114f15e443cf60e29ee969fd82bb
1 parent 48bbea1 commit 6fbae55

File tree

3 files changed

+98
-15
lines changed

3 files changed

+98
-15
lines changed

thrift/lib/cpp2/op/detail/Encode.h

Lines changed: 30 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -521,25 +521,37 @@ struct MapEncode {
521521
template <typename Key, typename Value>
522522
struct Encode<type::map<Key, Value>> : MapEncode<Key, Value> {};
523523

524-
template <typename T, typename Tag>
525-
struct Encode<type::cpp_type<T, Tag>> : Encode<Tag> {
524+
template <
525+
typename T,
526+
typename Tag,
527+
template <class...> class EncodeImpl = Encode>
528+
struct CppTypeEncode {
526529
template <class Protocol, class U>
527530
uint32_t operator()(Protocol& prot, const U& m) const {
528531
auto f = folly::if_constexpr<kIsStrongType<U, Tag>>(
529532
[](auto& v) { return static_cast<type::native_type<Tag>>(v); },
530533
folly::identity);
531-
return Encode<Tag>::operator()(prot, f(m));
534+
return EncodeImpl<Tag>{}(prot, f(m));
532535
}
533536
};
534537

535-
template <typename Adapter, typename Tag>
536-
struct Encode<type::adapted<Adapter, Tag>> {
538+
template <typename T, typename Tag>
539+
struct Encode<type::cpp_type<T, Tag>> : CppTypeEncode<T, Tag> {};
540+
541+
template <
542+
typename Adapter,
543+
typename Tag,
544+
template <class...> class EncodeImpl = Encode>
545+
struct AdaptedEncode {
537546
template <typename Protocol, typename U>
538547
uint32_t operator()(Protocol& prot, const U& m) const {
539-
return Encode<Tag>{}(prot, Adapter::toThrift(m));
548+
return EncodeImpl<Tag>{}(prot, Adapter::toThrift(m));
540549
}
541550
};
542551

552+
template <typename Adapter, typename Tag>
553+
struct Encode<type::adapted<Adapter, Tag>> : AdaptedEncode<Adapter, Tag> {};
554+
543555
template <typename>
544556
struct Decode;
545557

@@ -927,6 +939,18 @@ template <class T>
927939
struct RecursiveEncode<type::union_t<T>> : RecursiveEncode<type::struct_t<T>> {
928940
};
929941

942+
template <class T>
943+
struct RecursiveEncode<type::exception_t<T>>
944+
: RecursiveEncode<type::struct_t<T>> {};
945+
946+
template <typename T, typename Tag>
947+
struct RecursiveEncode<type::cpp_type<T, Tag>>
948+
: CppTypeEncode<T, Tag, RecursiveEncode> {};
949+
950+
template <typename Adapter, typename Tag>
951+
struct RecursiveEncode<type::adapted<Adapter, Tag>>
952+
: AdaptedEncode<Adapter, Tag, RecursiveEncode> {};
953+
930954
template <typename T>
931955
FOLLY_INLINE_VARIABLE constexpr RecursiveEncode<type::infer_tag<T>>
932956
recursive_encode{};

thrift/test/RecursiveEncode.thrift

Lines changed: 39 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,39 @@
1+
/*
2+
* Copyright (c) Meta Platforms, Inc. and affiliates.
3+
*
4+
* Licensed under the Apache License, Version 2.0 (the "License");
5+
* you may not use this file except in compliance with the License.
6+
* You may obtain a copy of the License at
7+
*
8+
* http://www.apache.org/licenses/LICENSE-2.0
9+
*
10+
* Unless required by applicable law or agreed to in writing, software
11+
* distributed under the License is distributed on an "AS IS" BASIS,
12+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13+
* See the License for the specific language governing permissions and
14+
* limitations under the License.
15+
*/
16+
17+
include "thrift/annotation/cpp.thrift"
18+
cpp_include "thrift/test/AdapterTest.h"
19+
cpp_include "<list>"
20+
21+
package "apache.org/thrift/test"
22+
23+
struct Foo {
24+
1: i32 field;
25+
}
26+
27+
typedef list<Foo> (cpp.type = "std::list<::apache::thrift::test::Foo>") FooList
28+
29+
@cpp.Adapter{name = "::apache::thrift::test::TemplatedTestAdapter"}
30+
struct Bar {
31+
1: i32 field;
32+
2: FooList foos;
33+
}
34+
35+
struct Baz {
36+
1: i32 field;
37+
@cpp.Adapter{name = "::apache::thrift::test::TemplatedTestAdapter"}
38+
2: Bar bar;
39+
}

thrift/test/RecursiveEncodeTest.cpp

Lines changed: 29 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -17,29 +17,31 @@
1717
#include <folly/portability/GTest.h>
1818
#include <thrift/lib/cpp2/op/Encode.h>
1919
#include <thrift/lib/cpp2/protocol/Serializer.h>
20+
#include <thrift/test/gen-cpp2/RecursiveEncode_types.h>
2021
#include <thrift/test/testset/Populator.h>
2122

2223
namespace apache::thrift::test {
2324

2425
namespace {
26+
template <typename SerializerT, typename T>
27+
void roundTripTest(T obj) {
28+
folly::IOBufQueue buffer;
29+
typename SerializerT::ProtocolWriter writer;
30+
writer.setOutput(&buffer);
31+
op::detail::recursive_encode<T>(writer, obj);
32+
T obj2 = SerializerT::template deserialize<T>(buffer.move().get());
33+
EXPECT_EQ(obj, obj2);
34+
}
2535

2636
template <typename T>
2737
class RecursiveEncodeTest : public testing::Test {
2838
private:
2939
std::mt19937 rng_;
3040

3141
protected:
32-
T populated() { return populated_if_not_adapted<T>(rng_); }
33-
3442
template <typename SerializerT>
3543
void testSerializer() {
36-
T obj = this->populated();
37-
folly::IOBufQueue buffer;
38-
typename SerializerT::ProtocolWriter writer;
39-
writer.setOutput(&buffer);
40-
op::detail::recursive_encode<T>(writer, obj);
41-
T obj2 = SerializerT::template deserialize<T>(buffer.move().get());
42-
EXPECT_EQ(obj, obj2);
44+
roundTripTest<SerializerT>(populated_if_not_adapted<T>(rng_));
4345
}
4446
};
4547

@@ -61,5 +63,23 @@ REGISTER_TYPED_TEST_CASE_P(RecursiveEncodeTest, Compact, Binary, SimpleJson);
6163

6264
THRIFT_INST_TESTSET_ALL(RecursiveEncodeTest);
6365

66+
TEST(RecursiveEncode, TestCustomType) {
67+
Baz baz;
68+
baz.field() = 10;
69+
auto& bar = baz.bar()->value.value;
70+
bar.field() = 20;
71+
72+
Foo foo1, foo2;
73+
foo1.field() = 30;
74+
foo2.field() = 40;
75+
76+
bar.foos()->push_back(foo1);
77+
bar.foos()->push_back(foo2);
78+
79+
roundTripTest<CompactSerializer>(baz);
80+
roundTripTest<BinarySerializer>(baz);
81+
roundTripTest<SimpleJSONSerializer>(baz);
82+
}
83+
6484
} // namespace
6585
} // namespace apache::thrift::test

0 commit comments

Comments
 (0)