From c1b09e43c27dc5938ae2492b7e53771c3f645791 Mon Sep 17 00:00:00 2001 From: qicosmos Date: Mon, 1 Jul 2024 15:43:35 +0800 Subject: [PATCH 1/7] base version --- iguana/pb_writer.hpp | 221 +++++++++++++++++++++++++++++++++++++++++++ test/test_pb.cpp | 53 +++++++++++ 2 files changed, 274 insertions(+) diff --git a/iguana/pb_writer.hpp b/iguana/pb_writer.hpp index 9e7bbe5e..18514cd5 100644 --- a/iguana/pb_writer.hpp +++ b/iguana/pb_writer.hpp @@ -205,6 +205,206 @@ IGUANA_INLINE void to_pb_impl(Type&& t, It&& it, uint32_t*& sz_ptr) { encode_numeric_field(t, it); } } + +template +IGUANA_INLINE constexpr std::string_view get_type_string() { + if constexpr (std::is_integral_v) { + if constexpr (sizeof(T) <= 4) { + return "int32"; + } + else { + return "int64"; + } + } + else if constexpr (std::is_same_v || + std::is_same_v) { + return "string"; + } + else if constexpr (std::is_floating_point_v) { + return type_string(); + } + else if constexpr (std::is_enum_v) { + // TODO: maybe let user define the enum name and value + return "int32"; + } + else { + constexpr auto str_type_name = type_string(); + constexpr size_t pos = str_type_name.rfind("::"); + if constexpr (pos != std::string_view::npos) { + if constexpr (detail::is_signed_varint_v || detail::is_fixed_v) { + constexpr size_t pos = str_type_name.rfind("::") + 2; + return str_type_name.substr(pos, str_type_name.size() - pos - 2); + } + else { + return str_type_name.substr(pos); + } + } + else { + return str_type_name; + } + } +} + +template +IGUANA_INLINE void numeric_to_proto(Stream& out, std::string_view field_name, + uint32_t field_no) { + constexpr auto name = get_type_string(); + out.append(name).append(" "); + out.append(field_name) + .append(" = ") + .append(std::to_string(field_no)) + .append(";\n"); +} + +template +IGUANA_INLINE void build_proto_field(Stream& out, std::string_view str_type, + std::string_view field_name, + uint32_t field_no) { + for (size_t i = 0; i < space_count; i++) { + out.append(" "); + } + + if (!str_type.empty()) { + out.append(str_type); + } + + out.append(" ") + .append(field_name) + .append(" = ") + .append(std::to_string(field_no)) + .append(";\n"); +} + +template +IGUANA_INLINE void build_sub_proto(Map& map, std::string_view str_type, + std::string& sub_str); + +template +IGUANA_INLINE void to_proto_impl( + Stream& out, std::unordered_map& map, + std::string_view field_name = "", uint32_t field_no = 0) { + std::string sub_str; + using T = std::remove_const_t>; + if constexpr (is_reflection_v || is_custom_reflection_v) { + constexpr auto name = get_name(); + out.append("message ").append(name).append(" {\n"); + static constexpr auto tuple = get_members_tuple(); + constexpr size_t SIZE = std::tuple_size_v>; + + for_each_n( + [&out, &sub_str, &map](auto i) mutable { + using field_type = + std::tuple_element_t>; + constexpr auto value = std::get(tuple); + + using U = typename field_type::value_type; + if constexpr (is_reflection_v) { + constexpr auto str_type = type_string(); + build_proto_field( + out, str_type, + {value.field_name.data(), value.field_name.size()}, + value.field_no); + + build_sub_proto(map, str_type, sub_str); + } + else if constexpr (variant_v) { + constexpr size_t var_size = std::variant_size_v; + using sub_type = typename field_type::sub_type; + + constexpr auto offset = + get_variant_index(); + + if (offset == 0) { + out.append(" oneof "); + out.append(value.field_name.data(), value.field_name.size()) + .append(" {\n"); + } + + constexpr auto str_type = get_type_string(); + std::string field_name = " one_of_"; + field_name.append(str_type); + + out.append(" "); + build_proto_field(out, str_type, field_name, value.field_no); + + if constexpr (is_reflection_v) { + build_sub_proto(map, str_type, sub_str); + } + + if (offset == var_size - 1) { + out.append(" }\n"); + } + } + else { + to_proto_impl(out, map, + {value.field_name.data(), value.field_name.size()}, + value.field_no); + } + }, + std::make_index_sequence{}); + out.append("}\r\n\r\n"); + } + else if constexpr (is_sequence_container::value) { + out.append(" repeated"); + using item_type = typename T::value_type; + + if constexpr (is_lenprefix_v) { + // non-packed + if constexpr (is_reflection_v) { + constexpr auto str_type = get_type_string(); + build_proto_field(out, str_type, field_name, field_no); + + build_sub_proto(map, str_type, sub_str); + } + else { + to_proto_impl(out, map, field_name, field_no); + } + } + else { + out.append(" "); + numeric_to_proto(out, field_name, field_no); + } + } + else if constexpr (is_map_container::value) { + out.append(" map<"); + using first_type = typename T::key_type; + using second_type = typename T::mapped_type; + + constexpr auto str_first = get_type_string(); + constexpr auto str_second = get_type_string(); + out.append(str_first).append(", ").append(str_second).append(">"); + + build_proto_field<1>(out, "", field_name, field_no); + + if constexpr (is_reflection_v) { + constexpr auto str_type = type_string(); + build_sub_proto(map, str_type, sub_str); + } + } + else if constexpr (optional_v) { + to_proto_impl( + out, map, {field_name.data(), field_name.size()}, field_no); + } + else if constexpr (std::is_same_v || + std::is_same_v) { + build_proto_field(out, "string ", field_name, field_no); + } + else { + out.append(" "); + numeric_to_proto(out, field_name, field_no); + } +} + +template +IGUANA_INLINE void build_sub_proto(Map& map, std::string_view str_type, + std::string& sub_str) { + if (map.find(str_type) == map.end()) { + to_proto_impl(sub_str, map); + map.emplace(str_type, std::move(sub_str)); + } +} + } // namespace detail template @@ -216,6 +416,27 @@ IGUANA_INLINE void to_pb(T& t, Stream& out) { detail::to_pb_impl<0>(t, &out[0], sz_ptr); } +template +IGUANA_INLINE void to_proto(Stream& out, bool add_header = true, + std::string_view ns = "") { + if (add_header) { + constexpr std::string_view crlf = "\r\n\r\n"; + out.append(R"(syntax = "proto3";)").append(crlf); + if (!ns.empty()) { + out.append("package ").append(ns).append(";").append(crlf); + } + + out.append(R"(option optimize_for = SPEED;)").append(crlf); + out.append(R"(option cc_enable_arenas = true;)").append(crlf); + } + + std::unordered_map map; + detail::to_proto_impl(out, map); + for (auto& [k, s] : map) { + out.append(s); + } +} + template IGUANA_INLINE void to_pb_adl(iguana_adl_t* p, T& t, Stream& out) { to_pb(t, out); diff --git a/test/test_pb.cpp b/test/test_pb.cpp index bf784338..37fbae61 100644 --- a/test/test_pb.cpp +++ b/test/test_pb.cpp @@ -1,5 +1,6 @@ #include #include +#include #define DOCTEST_CONFIG_IMPLEMENT #include "doctest.h" @@ -237,7 +238,59 @@ struct numer_st PUBLIC(numer_st) { }; REFLECTION(numer_st, a, b, c); +struct person PUBLIC(person) { + person() = default; + person(int32_t a, std::string b, int c, double d) + : id(a), name(std::move(b)), age(c), salary(d) {} + int32_t id; + std::string name; + int age; + double salary; +}; +REFLECTION(person, id, name, age, salary); + +struct vector_t { + int id; + std::variant variant; + std::vector ids; + std::vector pairs; + std::vector strs; + std::map map; + std::string name; + std::optional op_val; +}; +REFLECTION(vector_t, id, variant, ids, pairs, strs, map, name, op_val); + TEST_CASE("test reflection") { + { + std::string str; + iguana::to_proto(str, true, "pb"); + std::cout << str; + } + { + std::string str; + iguana::to_proto(str, true, "pb"); + std::cout << str; + } + { + std::string str; + iguana::to_proto(str, true, "pb"); + std::cout << str; + + iguana::to_proto(str, false); + std::cout << str; + + iguana::to_proto(str, false); + std::cout << str; + + iguana::to_proto(str, false); + std::cout << str; + } + { + std::string str; + iguana::to_proto(str); + std::cout << str; + } { auto t = iguana::create_instance("nest1"); std::vector fields_name = t->get_fields_name(); From 31980a963dbde463d4f0c47365707b585dee8762 Mon Sep 17 00:00:00 2001 From: qicosmos Date: Mon, 1 Jul 2024 17:16:03 +0800 Subject: [PATCH 2/7] to proto --- iguana/pb_writer.hpp | 33 +++++++++++++++++++++++++-------- iguana/reflection.hpp | 2 +- test/test_pb.cpp | 42 ++++++++++++++++++++++++++++++++++-------- 3 files changed, 60 insertions(+), 17 deletions(-) diff --git a/iguana/pb_writer.hpp b/iguana/pb_writer.hpp index 18514cd5..ba43c55a 100644 --- a/iguana/pb_writer.hpp +++ b/iguana/pb_writer.hpp @@ -223,10 +223,6 @@ IGUANA_INLINE constexpr std::string_view get_type_string() { else if constexpr (std::is_floating_point_v) { return type_string(); } - else if constexpr (std::is_enum_v) { - // TODO: maybe let user define the enum name and value - return "int32"; - } else { constexpr auto str_type_name = type_string(); constexpr size_t pos = str_type_name.rfind("::"); @@ -390,6 +386,28 @@ IGUANA_INLINE void to_proto_impl( std::is_same_v) { build_proto_field(out, "string ", field_name, field_no); } + else if constexpr (enum_v) { + constexpr auto str_type = get_type_string(); + static constexpr auto enum_to_str = get_enum_map>(); + if constexpr (bool_v) { + build_proto_field(out, "int32", field_name, field_no); + } + else { + build_proto_field(out, str_type, field_name, field_no); + if (map.find(str_type) == map.end()) { + sub_str.append("enum ").append(str_type).append(" {\n"); + for (auto& [k, field_name] : enum_to_str) { + sub_str.append(" ") + .append({field_name.data(), field_name.size()}) + .append(" = ") + .append(std::to_string(static_cast>(k))) + .append(";\n"); + } + sub_str.append("}\r\n\r\n"); + map.emplace(str_type, std::move(sub_str)); + } + } + } else { out.append(" "); numeric_to_proto(out, field_name, field_no); @@ -416,10 +434,9 @@ IGUANA_INLINE void to_pb(T& t, Stream& out) { detail::to_pb_impl<0>(t, &out[0], sz_ptr); } -template -IGUANA_INLINE void to_proto(Stream& out, bool add_header = true, - std::string_view ns = "") { - if (add_header) { +template +IGUANA_INLINE void to_proto(Stream& out, std::string_view ns = "") { + if (gen_header) { constexpr std::string_view crlf = "\r\n\r\n"; out.append(R"(syntax = "proto3";)").append(crlf); if (!ns.empty()) { diff --git a/iguana/reflection.hpp b/iguana/reflection.hpp index d5029d7b..ceb605a4 100644 --- a/iguana/reflection.hpp +++ b/iguana/reflection.hpp @@ -846,7 +846,7 @@ constexpr inline auto build_fields(T t, S &s, uint32_t &index) { return build_variant_fields(t, s, I + 1, std::make_index_sequence{}); } else { - uint32_t field_no = (I == index) ? (I + 1) : (I + index); + uint32_t field_no = (I == index) ? (I + 1) : (2 + index); index++; return std::tuple(field_t{t, field_no, s}); } diff --git a/test/test_pb.cpp b/test/test_pb.cpp index 37fbae61..903c8b80 100644 --- a/test/test_pb.cpp +++ b/test/test_pb.cpp @@ -249,8 +249,18 @@ struct person PUBLIC(person) { }; REFLECTION(person, id, name, age, salary); +enum Color { Red = 1, Black = 2, Green = 4 }; + +namespace iguana { +template <> +struct enum_value { + constexpr static std::array value = {1, 2, 4}; +}; +} // namespace iguana + struct vector_t { int id; + Color color; std::variant variant; std::vector ids; std::vector pairs; @@ -259,38 +269,54 @@ struct vector_t { std::string name; std::optional op_val; }; -REFLECTION(vector_t, id, variant, ids, pairs, strs, map, name, op_val); +REFLECTION(vector_t, id, color, variant, ids, pairs, strs, map, name, op_val); -TEST_CASE("test reflection") { +TEST_CASE("struct to proto") { { std::string str; - iguana::to_proto(str, true, "pb"); + iguana::to_proto(str, "pb"); std::cout << str; + CHECK(str.find(R"(syntax = "proto3";)") != std::string::npos); + CHECK(str.find("message vector_t") != std::string::npos); + CHECK(str.find("map map = 9;") != std::string::npos); + CHECK(str.find("Green = 4;") != std::string::npos); } { std::string str; - iguana::to_proto(str, true, "pb"); + iguana::to_proto(str, "pb"); std::cout << str; + CHECK(str.find("message_t z = 3;") != std::string::npos); + CHECK(str.find("message message_t") != std::string::npos); + CHECK(str.find("pair_t t = 2;") != std::string::npos); + CHECK(str.find("message pair_t") != std::string::npos); } { std::string str; - iguana::to_proto(str, true, "pb"); + iguana::to_proto(str, "pb"); std::cout << str; + CHECK(str.find("sint64 z = 3;") != std::string::npos); - iguana::to_proto(str, false); + iguana::to_proto(str); std::cout << str; + CHECK(str.find("fixed64 z = 3;") != std::string::npos); - iguana::to_proto(str, false); + iguana::to_proto(str); std::cout << str; + CHECK(str.find("sfixed64 z = 3;") != std::string::npos); - iguana::to_proto(str, false); + iguana::to_proto(str); std::cout << str; + CHECK(str.find("pair_t t = 2;") != std::string::npos); } { std::string str; iguana::to_proto(str); std::cout << str; + CHECK(str.find("int32 age = 3;") != std::string::npos); } +} + +TEST_CASE("test reflection") { { auto t = iguana::create_instance("nest1"); std::vector fields_name = t->get_fields_name(); From 6ec2d2362be429f63c00a959c799813cbba4b3ea Mon Sep 17 00:00:00 2001 From: qicosmos Date: Mon, 1 Jul 2024 17:27:22 +0800 Subject: [PATCH 3/7] proto file --- iguana/pb_writer.hpp | 10 ++++++++++ test/test_pb.cpp | 18 ++++++++++++++++++ 2 files changed, 28 insertions(+) diff --git a/iguana/pb_writer.hpp b/iguana/pb_writer.hpp index ba43c55a..42e4109a 100644 --- a/iguana/pb_writer.hpp +++ b/iguana/pb_writer.hpp @@ -454,6 +454,16 @@ IGUANA_INLINE void to_proto(Stream& out, std::string_view ns = "") { } } +template +IGUANA_INLINE void to_proto_file(Stream& stream, std::string_view ns = "") { + if (!stream.is_open()) { + return; + } + std::string out; + to_proto(out, ns); + stream.write(out.data(), out.size()); +} + template IGUANA_INLINE void to_pb_adl(iguana_adl_t* p, T& t, Stream& out) { to_pb(t, out); diff --git a/test/test_pb.cpp b/test/test_pb.cpp index 903c8b80..f6692c51 100644 --- a/test/test_pb.cpp +++ b/test/test_pb.cpp @@ -1,7 +1,11 @@ +#include +#include #include #include #include +#include "iguana/pb_writer.hpp" + #define DOCTEST_CONFIG_IMPLEMENT #include "doctest.h" #include "iguana/iguana.hpp" @@ -280,6 +284,20 @@ TEST_CASE("struct to proto") { CHECK(str.find("message vector_t") != std::string::npos); CHECK(str.find("map map = 9;") != std::string::npos); CHECK(str.find("Green = 4;") != std::string::npos); + + std::ofstream file("test_vector.proto", std::ios::binary); + iguana::to_proto_file(file, "pb"); + file.sync_with_stdio(true); + file.flush(); + file.close(); + + size_t size = std::filesystem::file_size("test_vector.proto"); + std::ifstream in("test_vector.proto", std::ios::binary); + std::string read_str; + read_str.resize(size); + in.read(read_str.data(), size); + CHECK(read_str.find("map map = 9;") != std::string::npos); + CHECK(read_str.find("Green = 4;") != std::string::npos); } { std::string str; From a58f09cffc36947740e9cb697f36535bfa557ab3 Mon Sep 17 00:00:00 2001 From: qicosmos Date: Mon, 1 Jul 2024 17:42:16 +0800 Subject: [PATCH 4/7] fix enum for proto3 --- iguana/pb_writer.hpp | 3 +++ test/test_pb.cpp | 4 ++-- 2 files changed, 5 insertions(+), 2 deletions(-) diff --git a/iguana/pb_writer.hpp b/iguana/pb_writer.hpp index 42e4109a..632d0c99 100644 --- a/iguana/pb_writer.hpp +++ b/iguana/pb_writer.hpp @@ -393,6 +393,9 @@ IGUANA_INLINE void to_proto_impl( build_proto_field(out, "int32", field_name, field_no); } else { + static_assert(enum_to_str.size() > 0, "empty enum not allowed"); + static_assert(enum_to_str.begin()->first == 0, + "the first enum value must be zero in proto3"); build_proto_field(out, str_type, field_name, field_no); if (map.find(str_type) == map.end()) { sub_str.append("enum ").append(str_type).append(" {\n"); diff --git a/test/test_pb.cpp b/test/test_pb.cpp index f6692c51..daf312ab 100644 --- a/test/test_pb.cpp +++ b/test/test_pb.cpp @@ -253,12 +253,12 @@ struct person PUBLIC(person) { }; REFLECTION(person, id, name, age, salary); -enum Color { Red = 1, Black = 2, Green = 4 }; +enum Color { Red = 0, Black = 2, Green = 4 }; namespace iguana { template <> struct enum_value { - constexpr static std::array value = {1, 2, 4}; + constexpr static std::array value = {0, 2, 4}; }; } // namespace iguana From 93a5b93102d0796dcbe2ae88bd24c9b5fe754fbc Mon Sep 17 00:00:00 2001 From: qicosmos Date: Mon, 1 Jul 2024 18:16:47 +0800 Subject: [PATCH 5/7] fix type --- iguana/pb_writer.hpp | 25 +++++++++++++++++++------ 1 file changed, 19 insertions(+), 6 deletions(-) diff --git a/iguana/pb_writer.hpp b/iguana/pb_writer.hpp index 632d0c99..ae0fe73e 100644 --- a/iguana/pb_writer.hpp +++ b/iguana/pb_writer.hpp @@ -209,11 +209,24 @@ IGUANA_INLINE void to_pb_impl(Type&& t, It&& it, uint32_t*& sz_ptr) { template IGUANA_INLINE constexpr std::string_view get_type_string() { if constexpr (std::is_integral_v) { - if constexpr (sizeof(T) <= 4) { - return "int32"; + if constexpr (std::is_same_v) { + return "bool"; + } + else if constexpr (sizeof(T) <= 4) { + if constexpr (std::is_unsigned_v) { + return "uint32"; + } + else { + return "int32"; + } } else { - return "int64"; + if constexpr (std::is_unsigned_v) { + return "uint64"; + } + else { + return "int64"; + } } } else if constexpr (std::is_same_v || @@ -227,8 +240,8 @@ IGUANA_INLINE constexpr std::string_view get_type_string() { constexpr auto str_type_name = type_string(); constexpr size_t pos = str_type_name.rfind("::"); if constexpr (pos != std::string_view::npos) { + constexpr size_t pos = str_type_name.rfind("::") + 2; if constexpr (detail::is_signed_varint_v || detail::is_fixed_v) { - constexpr size_t pos = str_type_name.rfind("::") + 2; return str_type_name.substr(pos, str_type_name.size() - pos - 2); } else { @@ -296,7 +309,7 @@ IGUANA_INLINE void to_proto_impl( using U = typename field_type::value_type; if constexpr (is_reflection_v) { - constexpr auto str_type = type_string(); + constexpr auto str_type = get_type_string(); build_proto_field( out, str_type, {value.field_name.data(), value.field_name.size()}, @@ -374,7 +387,7 @@ IGUANA_INLINE void to_proto_impl( build_proto_field<1>(out, "", field_name, field_no); if constexpr (is_reflection_v) { - constexpr auto str_type = type_string(); + constexpr auto str_type = get_type_string(); build_sub_proto(map, str_type, sub_str); } } From f7bd683629da9b6684654703ae3a8d2e8b336e04 Mon Sep 17 00:00:00 2001 From: qicosmos Date: Mon, 1 Jul 2024 18:36:13 +0800 Subject: [PATCH 6/7] enum name --- iguana/pb_writer.hpp | 9 +++++++-- test/proto/unittest_proto3.h | 13 +++++++++++++ test/test_proto3.cpp | 11 +++++++++++ 3 files changed, 31 insertions(+), 2 deletions(-) diff --git a/iguana/pb_writer.hpp b/iguana/pb_writer.hpp index ae0fe73e..fadc6c3e 100644 --- a/iguana/pb_writer.hpp +++ b/iguana/pb_writer.hpp @@ -407,14 +407,19 @@ IGUANA_INLINE void to_proto_impl( } else { static_assert(enum_to_str.size() > 0, "empty enum not allowed"); - static_assert(enum_to_str.begin()->first == 0, + static_assert((int)(enum_to_str.begin()->first) == 0, "the first enum value must be zero in proto3"); build_proto_field(out, str_type, field_name, field_no); if (map.find(str_type) == map.end()) { sub_str.append("enum ").append(str_type).append(" {\n"); for (auto& [k, field_name] : enum_to_str) { + std::string_view name{field_name.data(), field_name.size()}; + size_t pos = name.rfind("::"); + if (pos != std::string_view::npos) { + name = name.substr(pos + 2); + } sub_str.append(" ") - .append({field_name.data(), field_name.size()}) + .append(name) .append(" = ") .append(std::to_string(static_cast>(k))) .append(";\n"); diff --git a/test/proto/unittest_proto3.h b/test/proto/unittest_proto3.h index 4311e986..603affab 100644 --- a/test/proto/unittest_proto3.h +++ b/test/proto/unittest_proto3.h @@ -311,6 +311,19 @@ REFLECTION(bench_int32, a, b, c, d); } // namespace stpb +namespace iguana { +template <> +struct enum_value { + constexpr static std::array value = {0, 2, 4}; +}; + +template <> +struct enum_value { + constexpr static std::array value = {0, 1, 2, 123456, -1}; +}; + +} // namespace iguana + inline auto create_person() { stpb::person p{432798, std::string(1024, 'A'), 24, 65536.42}; return p; diff --git a/test/test_proto3.cpp b/test/test_proto3.cpp index c5227686..2a50d0aa 100644 --- a/test/test_proto3.cpp +++ b/test/test_proto3.cpp @@ -1,3 +1,6 @@ +#include + +#include "iguana/pb_writer.hpp" #define DOCTEST_CONFIG_IMPLEMENT #include "doctest.h" #include "iguana/iguana.hpp" @@ -294,6 +297,14 @@ TEST_CASE("test RepeatIguanaTypeMsg") { } TEST_CASE("test NestedMsg") { + { + std::string str; + iguana::to_proto(str, "test"); + std::cout << str; + + std::ofstream out("NestedMsg.proto", std::ios::binary); + iguana::to_proto_file(out, "test"); + } { stpb::NestedMsg se_st{ /* base_msg */ stpb::BaseTypeMsg{100, 200, 300, 400, 31.4f, 62.8, false, From d26edb9744699b2972d90efafaf95274d8644df2 Mon Sep 17 00:00:00 2001 From: qicosmos Date: Tue, 2 Jul 2024 09:34:45 +0800 Subject: [PATCH 7/7] gcc8 --- iguana/pb_writer.hpp | 7 ++++++- test/test_pb.cpp | 3 +++ test/test_proto3.cpp | 3 +++ 3 files changed, 12 insertions(+), 1 deletion(-) diff --git a/iguana/pb_writer.hpp b/iguana/pb_writer.hpp index fadc6c3e..4c39305a 100644 --- a/iguana/pb_writer.hpp +++ b/iguana/pb_writer.hpp @@ -206,6 +206,8 @@ IGUANA_INLINE void to_pb_impl(Type&& t, It&& it, uint32_t*& sz_ptr) { } } +#if defined(__clang__) || defined(_MSC_VER) || \ + (defined(__GNUC__) && __GNUC__ > 8) template IGUANA_INLINE constexpr std::string_view get_type_string() { if constexpr (std::is_integral_v) { @@ -443,7 +445,7 @@ IGUANA_INLINE void build_sub_proto(Map& map, std::string_view str_type, map.emplace(str_type, std::move(sub_str)); } } - +#endif } // namespace detail template @@ -455,6 +457,8 @@ IGUANA_INLINE void to_pb(T& t, Stream& out) { detail::to_pb_impl<0>(t, &out[0], sz_ptr); } +#if defined(__clang__) || defined(_MSC_VER) || \ + (defined(__GNUC__) && __GNUC__ > 8) template IGUANA_INLINE void to_proto(Stream& out, std::string_view ns = "") { if (gen_header) { @@ -484,6 +488,7 @@ IGUANA_INLINE void to_proto_file(Stream& stream, std::string_view ns = "") { to_proto(out, ns); stream.write(out.data(), out.size()); } +#endif template IGUANA_INLINE void to_pb_adl(iguana_adl_t* p, T& t, Stream& out) { diff --git a/test/test_pb.cpp b/test/test_pb.cpp index daf312ab..85e27988 100644 --- a/test/test_pb.cpp +++ b/test/test_pb.cpp @@ -275,6 +275,8 @@ struct vector_t { }; REFLECTION(vector_t, id, color, variant, ids, pairs, strs, map, name, op_val); +#if defined(__clang__) || defined(_MSC_VER) || \ + (defined(__GNUC__) && __GNUC__ > 8) TEST_CASE("struct to proto") { { std::string str; @@ -333,6 +335,7 @@ TEST_CASE("struct to proto") { CHECK(str.find("int32 age = 3;") != std::string::npos); } } +#endif TEST_CASE("test reflection") { { diff --git a/test/test_proto3.cpp b/test/test_proto3.cpp index 2a50d0aa..2612b16e 100644 --- a/test/test_proto3.cpp +++ b/test/test_proto3.cpp @@ -297,6 +297,8 @@ TEST_CASE("test RepeatIguanaTypeMsg") { } TEST_CASE("test NestedMsg") { +#if defined(__clang__) || defined(_MSC_VER) || \ + (defined(__GNUC__) && __GNUC__ > 8) { std::string str; iguana::to_proto(str, "test"); @@ -305,6 +307,7 @@ TEST_CASE("test NestedMsg") { std::ofstream out("NestedMsg.proto", std::ios::binary); iguana::to_proto_file(out, "test"); } +#endif { stpb::NestedMsg se_st{ /* base_msg */ stpb::BaseTypeMsg{100, 200, 300, 400, 31.4f, 62.8, false,