26 #ifndef LBANN_UTILS_PROTOBUF_IMPL_HPP_INCLUDED 27 #define LBANN_UTILS_PROTOBUF_IMPL_HPP_INCLUDED 33 #include <google/protobuf/any.pb.h> 34 #include <google/protobuf/descriptor.h> 35 #include <google/protobuf/message.h> 36 #include <google/protobuf/reflection.h> 37 #include <h2/meta/core/ValueAsType.hpp> 39 #include <type_traits> 54 using FD = google::protobuf::FieldDescriptor;
55 using type = std::conditional<
56 std::is_base_of_v<google::protobuf::Message, T>,
57 h2::meta::ValueAsType<FD::CppType, FD::CPPTYPE_MESSAGE>,
58 std::conditional_t<std::is_enum_v<T>,
59 h2::meta::ValueAsType<FD::CppType, FD::CPPTYPE_ENUM>,
63 static auto constexpr
value = type::type::value;
69 #define ADD_PB_CPPTYPE(TYPE, ENUMTYPE) \ 71 struct PBCppTypePOD<TYPE> \ 73 static constexpr auto value = \ 74 google::protobuf::FieldDescriptor::CPPTYPE_##ENUMTYPE; \ 91 std::string
const& field_name)
93 auto field_handle = msg.GetDescriptor()->FindFieldByName(field_name);
98 "\" in message does not exist or has not been set. Message:\n{\n",
101 if (!field_handle->is_repeated())
105 "\" in message does not refer to a repeated field. Message:\n{\n",
110 if (!((field_handle->cpp_type() == PBCppType<T>) ||
111 ((field_handle->cpp_type() ==
112 google::protobuf::FieldDescriptor::CPPTYPE_ENUM) &&
113 (PBCppType<T> == google::protobuf::FieldDescriptor::CPPTYPE_INT32))))
115 field_handle->cpp_type_name(),
117 return msg.GetReflection()->GetRepeatedFieldRef<T>(msg, field_handle);
124 template <
typename T,
typename ContainerT>
126 google::protobuf::RepeatedField<T>& field,
127 ContainerT
const& values)
131 field.Add(begin(values), end(values));
139 template <
typename ContainerT>
144 std::ostringstream oss;
145 oss << *cbegin(values);
146 for (
auto i = next(cbegin(values)); i != cend(values); ++i)
151 template <
typename T>
153 std::string
const& field_name) -> std::vector<T>
155 auto&& field_ref = details::get_repeated_field_ref<T>(msg, field_name);
156 return std::vector<T>{field_ref.begin(), field_ref.end()};
159 template <
typename T>
163 return std::vector<T>{rf.cbegin(), rf.cend()};
166 template <
typename T>
170 return std::vector<T>{rf.cbegin(), rf.cend()};
173 template <
typename OutT,
typename InT>
177 return std::vector<OutT>{rf.cbegin(), rf.cend()};
180 template <
typename T>
182 std::string
const& field_name) -> std::set<T>
185 !std::is_base_of_v<google::protobuf::Message, T>,
186 "Messages are not weakly ordered; they cannot be added to a set.");
187 auto&& field_ref = details::get_repeated_field_ref<T>(msg, field_name);
188 return std::set<T>{field_ref.begin(), field_ref.end()};
191 template <
typename T>
195 return std::set<T>{rf.cbegin(), rf.cend()};
199 google::protobuf::RepeatedPtrField<std::string>
const& rf)
200 -> std::set<std::string>
202 return std::set<std::string>{rf.cbegin(), rf.cend()};
205 template <
typename OutT,
typename InT>
209 return std::set<OutT>{rf.cbegin(), rf.cend()};
212 template <
typename T>
214 std::string
const& field_name)
215 -> std::unordered_set<T>
218 !std::is_base_of_v<google::protobuf::Message, T>,
219 "Messages are not hashable; they cannot be added to an unordered_set.");
220 auto&& field_ref = details::get_repeated_field_ref<T>(msg, field_name);
221 return std::unordered_set<T>{field_ref.begin(), field_ref.end()};
224 template <
typename T>
226 google::protobuf::RepeatedField<T>
const& rf) -> std::unordered_set<T>
228 return std::unordered_set<T>{rf.cbegin(), rf.cend()};
232 google::protobuf::RepeatedPtrField<std::string>
const& rf)
233 -> std::unordered_set<std::string>
235 return std::unordered_set<std::string>{rf.cbegin(), rf.cend()};
238 template <
typename OutT,
typename InT>
240 google::protobuf::RepeatedField<InT>
const& rf) -> std::unordered_set<OutT>
242 return std::unordered_set<OutT>{rf.cbegin(), rf.cend()};
245 #endif // LBANN_UTILS_PROTOBUF_IMPL_HPP_INCLUDED
google::protobuf::int32 int32
auto as_unordered_set(google::protobuf::Message const &msg, std::string const &field_name) -> std::unordered_set< T >
Extract the values from the named field as an unordered_set.
auto to_vector(google::protobuf::RepeatedField< InT > const &rf) -> std::vector< OutT >
Convert the repeated field to an STL vector of given type.
std::string to_space_sep_string(ContainerT const &values)
Concatenate a container of strings into a single string. Elements are space separated.
google::protobuf::FieldDescriptor FD
auto to_set(google::protobuf::RepeatedField< InT > const &) -> std::set< OutT >
Convert the repeated field to an STL set of given type.
void assign_to_repeated(google::protobuf::RepeatedField< T > &field, ContainerT const &values)
Assign a range of values to a repeated protobuf field.
auto get_repeated_field_ref(google::protobuf::Message const &msg, std::string const &field_name)
Common code to extract a repeated field reference from a message.
google::protobuf::int64 int64
google::protobuf::uint32 uint32
auto as_set(google::protobuf::Message const &msg, std::string const &field_name) -> std::set< T >
Extract the values from the named field as a set.
google::protobuf::uint64 uint64
std::conditional< std::is_base_of_v< google::protobuf::Message, T >, h2::meta::ValueAsType< FD::CppType, FD::CPPTYPE_MESSAGE >, std::conditional_t< std::is_enum_v< T >, h2::meta::ValueAsType< FD::CppType, FD::CPPTYPE_ENUM >, PBCppTypePOD< T > >> type
ADD_PB_CPPTYPE(int32, INT32)
auto to_unordered_set(google::protobuf::RepeatedField< InT > const &) -> std::unordered_set< OutT >
Convert the repeated field to an STL unordered_set of given type.
static auto constexpr value
auto as_vector(google::protobuf::Message const &msg, std::string const &field_name) -> std::vector< T >
Extract the values from the named field as a vector.