Skip to content

Commit

Permalink
add (cpp.experimental.lazy) annotation
Browse files Browse the repository at this point in the history
Summary:
This added `(cpp.experimental.lazy)` annotation to thrift C++ compiler. Currently there only affect is that

1. lazy field's data member will always be private
2. lazy field won't have setter/getter (this can be implemented in the future)

Reviewed By: vitaut

Differential Revision: D26715914

fbshipit-source-id: e1298bf372e2104c3faf7be03760072e14dc3e3d
  • Loading branch information
Mizuchi authored and facebook-github-bot committed Mar 4, 2021
1 parent 27547e2 commit 240b7fe
Show file tree
Hide file tree
Showing 19 changed files with 941 additions and 3 deletions.
12 changes: 11 additions & 1 deletion thrift/compiler/generate/t_mstch_cpp2_generator.cc
Expand Up @@ -37,6 +37,10 @@ bool field_has_isset(const t_field* field) {
!cpp2::is_explicit_ref(field);
}

bool field_is_lazy(const t_field* field) {
return field->has_annotation("cpp.experimental.lazy");
}

std::string const& get_cpp_template(const t_type* type) {
return type->get_annotation({"cpp.template", "cpp2.template"});
}
Expand Down Expand Up @@ -582,6 +586,7 @@ class mstch_cpp2_field : public mstch_field {
&mstch_cpp2_field::fatal_required_qualifier},
{"field:visibility", &mstch_cpp2_field::visibility},
{"field:metadata_name", &mstch_cpp2_field::metadata_name},
{"field:lazy?", &mstch_cpp2_field::lazy},
});
}
mstch::node name_hash() {
Expand All @@ -596,6 +601,9 @@ class mstch_cpp2_field : public mstch_field {
mstch::node cpp_ref() {
return cpp2::is_explicit_ref(field_);
}
mstch::node lazy() {
return field_is_lazy(field_);
}
mstch::node cpp_ref_unique() {
return cpp2::is_unique_ref(field_);
}
Expand Down Expand Up @@ -674,7 +682,9 @@ class mstch_cpp2_field : public mstch_field {
mstch::node visibility() {
auto req = field_->get_req();
bool isPrivate = true;
if (cpp2::is_ref(field_) || req == t_field::e_req::required) {
if (field_is_lazy(field_)) {
// Lazy field has to be private.
} else if (cpp2::is_ref(field_) || req == t_field::e_req::required) {
isPrivate = false;
} else if (req == t_field::e_req::optional) {
// Optional fields are always private.
Expand Down
Expand Up @@ -16,6 +16,7 @@

%><%#struct:fields?%><%#struct:fields%><%#field:type%><%#type:resolves_to_container_or_struct?%>
<%^type:no_getters_setters?%>
<%^field:lazy?%>
<%#field:optional?%><%^field:cpp_ref?%>
const <% > types/type%>* <%struct:name%>::get_<%field:cpp_name%>() const& {
return <%field:cpp_name%>_ref().has_value() ? std::addressof(<%field:cpp_name%>) : nullptr;
Expand All @@ -36,5 +37,6 @@ const <% > types/type%>& <%struct:name%>::get_<%field:cpp_name%>() const& {
}

<%/field:cpp_ref?%><%/field:optional?%>
<%/field:lazy?%>
<%/type:no_getters_setters?%>
<%/type:resolves_to_container_or_struct?%><%/field:type%><%/struct:fields%><%/struct:fields?%>
Expand Up @@ -14,7 +14,7 @@
See the License for the specific language governing permissions and
limitations under the License.

%><%#struct:fields%><%#field:type%><%^field:cpp_ref?%>
%><%#struct:fields%><%#field:type%><%^field:cpp_ref?%><%^field:lazy?%>
<%#type:resolves_to_base_or_enum?%>

<%^type:string_or_binary?%>
Expand Down Expand Up @@ -100,4 +100,4 @@ THRIFT_IGNORE_ISSET_USE_WARNING_END
return <%field:cpp_name%>;
}
<%/type:resolves_to_container_or_struct?%>
<%/field:cpp_ref?%><%/field:type%><%/struct:fields%>
<%/field:lazy?%><%/field:cpp_ref?%><%/field:type%><%/struct:fields%>
1 change: 1 addition & 0 deletions thrift/compiler/test/fixtures/lazy_deserialization/cmd
@@ -0,0 +1 @@
mstch_cpp2 src/simple.thrift
@@ -0,0 +1,6 @@
/**
* Autogenerated by Thrift for src/simple.thrift
*
* DO NOT EDIT UNLESS YOU ARE SURE THAT YOU KNOW WHAT YOU ARE DOING
* @generated
*/
@@ -0,0 +1,19 @@
/**
* Autogenerated by Thrift for src/simple.thrift
*
* DO NOT EDIT UNLESS YOU ARE SURE THAT YOU KNOW WHAT YOU ARE DOING
* @generated
*/
#pragma once

#include <thrift/lib/cpp2/gen/module_constants_h.h>

#include "thrift/compiler/test/fixtures/lazy_deserialization/gen-cpp2/simple_types.h"

namespace apache { namespace thrift { namespace test {

struct simple_constants {

};

}}} // apache::thrift::test
@@ -0,0 +1,35 @@
/**
* Autogenerated by Thrift for src/simple.thrift
*
* DO NOT EDIT UNLESS YOU ARE SURE THAT YOU KNOW WHAT YOU ARE DOING
* @generated
*/

#include "thrift/compiler/test/fixtures/lazy_deserialization/gen-cpp2/simple_data.h"

#include <thrift/lib/cpp2/gen/module_data_cpp.h>

namespace apache {
namespace thrift {

const std::array<folly::StringPiece, 4> TStructDataStorage<::apache::thrift::test::Foo>::fields_names = {{
"field1",
"field2",
"field3",
"field4",
}};
const std::array<int16_t, 4> TStructDataStorage<::apache::thrift::test::Foo>::fields_ids = {{
1,
2,
3,
4,
}};
const std::array<protocol::TType, 4> TStructDataStorage<::apache::thrift::test::Foo>::fields_types = {{
TType::T_STRING,
TType::T_STRING,
TType::T_LIST,
TType::T_LIST,
}};

} // namespace thrift
} // namespace apache
@@ -0,0 +1,22 @@
/**
* Autogenerated by Thrift for src/simple.thrift
*
* DO NOT EDIT UNLESS YOU ARE SURE THAT YOU KNOW WHAT YOU ARE DOING
* @generated
*/
#pragma once

#include <thrift/lib/cpp2/gen/module_data_h.h>

#include "thrift/compiler/test/fixtures/lazy_deserialization/gen-cpp2/simple_types.h"

namespace apache { namespace thrift {

template <> struct TStructDataStorage<::apache::thrift::test::Foo> {
static constexpr const std::size_t fields_size = 4;
static const std::array<folly::StringPiece, fields_size> fields_names;
static const std::array<int16_t, fields_size> fields_ids;
static const std::array<protocol::TType, fields_size> fields_types;
};

}} // apache::thrift
@@ -0,0 +1,28 @@
/**
* Autogenerated by Thrift for src/simple.thrift
*
* DO NOT EDIT UNLESS YOU ARE SURE THAT YOU KNOW WHAT YOU ARE DOING
* @generated
*/
#pragma once

#include "thrift/compiler/test/fixtures/lazy_deserialization/gen-cpp2/simple_metadata.h"
#include <thrift/lib/cpp2/visitation/for_each.h>

namespace apache {
namespace thrift {
namespace detail {

template <>
struct ForEachField<::apache::thrift::test::Foo> {
template <typename F, typename... T>
void operator()(FOLLY_MAYBE_UNUSED F&& f, FOLLY_MAYBE_UNUSED T&&... t) const {
f(0, static_cast<T&&>(t).field1_ref()...);
f(1, static_cast<T&&>(t).field2_ref()...);
f(2, static_cast<T&&>(t).field3_ref()...);
f(3, static_cast<T&&>(t).field4_ref()...);
}
};
} // namespace detail
} // namespace thrift
} // namespace apache
@@ -0,0 +1,53 @@
/**
* Autogenerated by Thrift for src/simple.thrift
*
* DO NOT EDIT UNLESS YOU ARE SURE THAT YOU KNOW WHAT YOU ARE DOING
* @generated
*/
#include <thrift/lib/cpp2/gen/module_metadata_cpp.h>
#include "thrift/compiler/test/fixtures/lazy_deserialization/gen-cpp2/simple_metadata.h"

namespace apache {
namespace thrift {
namespace detail {
namespace md {
using ThriftMetadata = ::apache::thrift::metadata::ThriftMetadata;
using ThriftPrimitiveType = ::apache::thrift::metadata::ThriftPrimitiveType;
using ThriftType = ::apache::thrift::metadata::ThriftType;
using ThriftService = ::apache::thrift::metadata::ThriftService;
using ThriftServiceContext = ::apache::thrift::metadata::ThriftServiceContext;
using ThriftFunctionGenerator = void (*)(ThriftMetadata&, ThriftService&);


const ::apache::thrift::metadata::ThriftStruct&
StructMetadata<::apache::thrift::test::Foo>::gen(ThriftMetadata& metadata) {
auto res = metadata.structs_ref()->emplace("simple.Foo", ::apache::thrift::metadata::ThriftStruct{});
if (!res.second) {
return res.first->second;
}
::apache::thrift::metadata::ThriftStruct& simple_Foo = res.first->second;
simple_Foo.name_ref() = "simple.Foo";
simple_Foo.is_union_ref() = false;
static const EncodedThriftField
simple_Foo_fields[] = {
std::make_tuple(1, "field1", false, std::make_unique<Primitive>(ThriftPrimitiveType::THRIFT_STRING_TYPE), std::vector<ThriftConstStruct>{}),
std::make_tuple(2, "field2", false, std::make_unique<Primitive>(ThriftPrimitiveType::THRIFT_STRING_TYPE), std::vector<ThriftConstStruct>{}),
std::make_tuple(3, "field3", false, std::make_unique<List>(std::make_unique<Primitive>(ThriftPrimitiveType::THRIFT_I32_TYPE)), std::vector<ThriftConstStruct>{}),
std::make_tuple(4, "field4", false, std::make_unique<List>(std::make_unique<Primitive>(ThriftPrimitiveType::THRIFT_I32_TYPE)), std::vector<ThriftConstStruct>{}),
};
for (const auto& f : simple_Foo_fields) {
::apache::thrift::metadata::ThriftField field;
field.id_ref() = std::get<0>(f);
field.name_ref() = std::get<1>(f);
field.is_optional_ref() = std::get<2>(f);
std::get<3>(f)->writeAndGenType(*field.type_ref(), metadata);
field.structured_annotations_ref() = std::get<4>(f);
simple_Foo.fields_ref()->push_back(std::move(field));
}
return res.first->second;
}

} // namespace md
} // namespace detail
} // namespace thrift
} // namespace apache
@@ -0,0 +1,26 @@
/**
* Autogenerated by Thrift for src/simple.thrift
*
* DO NOT EDIT UNLESS YOU ARE SURE THAT YOU KNOW WHAT YOU ARE DOING
* @generated
*/
#pragma once

#include <thrift/lib/cpp2/gen/module_metadata_h.h>
#include "thrift/compiler/test/fixtures/lazy_deserialization/gen-cpp2/simple_types.h"


namespace apache {
namespace thrift {
namespace detail {
namespace md {

template <>
class StructMetadata<::apache::thrift::test::Foo> {
public:
static const ::apache::thrift::metadata::ThriftStruct& gen(ThriftMetadata& metadata);
};
} // namespace md
} // namespace detail
} // namespace thrift
} // namespace apache
@@ -0,0 +1,130 @@
/**
* Autogenerated by Thrift for src/simple.thrift
*
* DO NOT EDIT UNLESS YOU ARE SURE THAT YOU KNOW WHAT YOU ARE DOING
* @generated
*/
#include "thrift/compiler/test/fixtures/lazy_deserialization/gen-cpp2/simple_types.h"
#include "thrift/compiler/test/fixtures/lazy_deserialization/gen-cpp2/simple_types.tcc"

#include <thrift/lib/cpp2/gen/module_types_cpp.h>

#include "thrift/compiler/test/fixtures/lazy_deserialization/gen-cpp2/simple_data.h"


namespace apache {
namespace thrift {
namespace detail {

void TccStructTraits<::apache::thrift::test::Foo>::translateFieldName(
folly::StringPiece _fname,
int16_t& fid,
apache::thrift::protocol::TType& _ftype) noexcept {
using data = apache::thrift::TStructDataStorage<::apache::thrift::test::Foo>;
static const st::translate_field_name_table table{
data::fields_size,
data::fields_names.data(),
data::fields_ids.data(),
data::fields_types.data()};
st::translate_field_name(_fname, fid, _ftype, table);
}

} // namespace detail
} // namespace thrift
} // namespace apache

namespace apache { namespace thrift { namespace test {

THRIFT_IGNORE_ISSET_USE_WARNING_BEGIN
Foo::Foo(apache::thrift::FragileConstructor, ::std::string field1__arg, ::std::string field2__arg, ::std::vector<int32_t> field3__arg, ::std::vector<int32_t> field4__arg) :
field1(std::move(field1__arg)),
field2(std::move(field2__arg)),
field3(std::move(field3__arg)),
field4(std::move(field4__arg)) {
__isset.field1 = true;
__isset.field2 = true;
__isset.field3 = true;
__isset.field4 = true;
}
THRIFT_IGNORE_ISSET_USE_WARNING_END
void Foo::__clear() {
// clear all fields
field1 = apache::thrift::StringTraits< std::string>::fromStringLiteral("");
field2 = apache::thrift::StringTraits< std::string>::fromStringLiteral("");
field3.clear();
field4.clear();
THRIFT_IGNORE_ISSET_USE_WARNING_BEGIN
__isset = {};
THRIFT_IGNORE_ISSET_USE_WARNING_END
}

bool Foo::operator==(const Foo& rhs) const {
(void)rhs;
auto& lhs = *this;
(void)lhs;
if (!(lhs.field1 == rhs.field1)) {
return false;
}
if (!(lhs.field2 == rhs.field2)) {
return false;
}
if (!(lhs.field3 == rhs.field3)) {
return false;
}
if (!(lhs.field4 == rhs.field4)) {
return false;
}
return true;
}

bool Foo::operator<(const Foo& rhs) const {
(void)rhs;
auto& lhs = *this;
(void)lhs;
if (!(lhs.field1 == rhs.field1)) {
return lhs.field1 < rhs.field1;
}
if (!(lhs.field2 == rhs.field2)) {
return lhs.field2 < rhs.field2;
}
if (!(lhs.field3 == rhs.field3)) {
return lhs.field3 < rhs.field3;
}
if (!(lhs.field4 == rhs.field4)) {
return lhs.field4 < rhs.field4;
}
return false;
}

const ::std::vector<int32_t>& Foo::get_field4() const& {
return field4;
}

::std::vector<int32_t> Foo::get_field4() && {
return std::move(field4);
}


void swap(Foo& a, Foo& b) {
using ::std::swap;
swap(a.field1_ref().value(), b.field1_ref().value());
swap(a.field2_ref().value(), b.field2_ref().value());
swap(a.field3_ref().value(), b.field3_ref().value());
swap(a.field4_ref().value(), b.field4_ref().value());
THRIFT_IGNORE_ISSET_USE_WARNING_BEGIN
swap(a.__isset, b.__isset);
THRIFT_IGNORE_ISSET_USE_WARNING_END
}

template void Foo::readNoXfer<>(apache::thrift::BinaryProtocolReader*);
template uint32_t Foo::write<>(apache::thrift::BinaryProtocolWriter*) const;
template uint32_t Foo::serializedSize<>(apache::thrift::BinaryProtocolWriter const*) const;
template uint32_t Foo::serializedSizeZC<>(apache::thrift::BinaryProtocolWriter const*) const;
template void Foo::readNoXfer<>(apache::thrift::CompactProtocolReader*);
template uint32_t Foo::write<>(apache::thrift::CompactProtocolWriter*) const;
template uint32_t Foo::serializedSize<>(apache::thrift::CompactProtocolWriter const*) const;
template uint32_t Foo::serializedSizeZC<>(apache::thrift::CompactProtocolWriter const*) const;



}}} // apache::thrift::test

0 comments on commit 240b7fe

Please sign in to comment.