LBANN  0.103.0
LivermoreBigArtificialNeuralNetworkToolkit
impl.hpp
Go to the documentation of this file.
1 // Copyright (c) 2014-2023, Lawrence Livermore National Security, LLC.
3 // Produced at the Lawrence Livermore National Laboratory.
4 // Written by the LBANN Research Team (B. Van Essen, et al.) listed in
5 // the CONTRIBUTORS file. <lbann-dev@llnl.gov>
6 //
7 // LLNL-CODE-697807.
8 // All rights reserved.
9 //
10 // This file is part of LBANN: Livermore Big Artificial Neural Network
11 // Toolkit. For details, see http://software.llnl.gov/LBANN or
12 // https://github.com/LLNL/LBANN.
13 //
14 // Licensed under the Apache License, Version 2.0 (the "Licensee"); you
15 // may not use this file except in compliance with the License. You may
16 // obtain a copy of the License at:
17 //
18 // http://www.apache.org/licenses/LICENSE-2.0
19 //
20 // Unless required by applicable law or agreed to in writing, software
21 // distributed under the License is distributed on an "AS IS" BASIS,
22 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
23 // implied. See the License for the specific language governing
24 // permissions and limitations under the license.
26 #ifndef LBANN_UTILS_PROTOBUF_IMPL_HPP_INCLUDED
27 #define LBANN_UTILS_PROTOBUF_IMPL_HPP_INCLUDED
28 
29 #include "decl.hpp"
30 
32 
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>
38 
39 #include <type_traits>
40 
41 // Template definitions
42 namespace lbann {
43 namespace protobuf {
44 
45 namespace details {
46 
47 template <typename T>
48 struct PBCppTypePOD;
49 
50 template <typename T>
51 struct PBCppTypeS
52 {
53 private:
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>,
61 
62 public:
63  static auto constexpr value = type::type::value;
64 };
65 
66 template <typename T>
67 inline constexpr auto PBCppType = PBCppTypeS<T>::value;
68 
69 #define ADD_PB_CPPTYPE(TYPE, ENUMTYPE) \
70  template <> \
71  struct PBCppTypePOD<TYPE> \
72  { \
73  static constexpr auto value = \
74  google::protobuf::FieldDescriptor::CPPTYPE_##ENUMTYPE; \
75  }
76 ADD_PB_CPPTYPE(int32, INT32);
77 ADD_PB_CPPTYPE(int64, INT64);
78 ADD_PB_CPPTYPE(uint32, UINT32);
79 ADD_PB_CPPTYPE(uint64, UINT64);
80 ADD_PB_CPPTYPE(double, DOUBLE);
81 ADD_PB_CPPTYPE(float, FLOAT);
82 ADD_PB_CPPTYPE(std::string, STRING);
83 ADD_PB_CPPTYPE(bool, BOOL);
84 #undef ADD_PB_CPPTYPE
85 
89 template <typename T>
90 auto get_repeated_field_ref(google::protobuf::Message const& msg,
91  std::string const& field_name)
92 {
93  auto field_handle = msg.GetDescriptor()->FindFieldByName(field_name);
94  if (!field_handle)
96  "Field \"",
97  field_name,
98  "\" in message does not exist or has not been set. Message:\n{\n",
99  msg.DebugString(),
100  "}\n");
101  if (!field_handle->is_repeated())
102  LBANN_ERROR(
103  "Field \"",
104  field_name,
105  "\" in message does not refer to a repeated field. Message:\n{\n",
106  msg.DebugString(),
107  "}\n");
108  // The type is valid if it's an exact match. Enums are special,
109  // because they can match int32.
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))))
114  LBANN_ERROR("Field has incompatible type: \"",
115  field_handle->cpp_type_name(),
116  "\".");
117  return msg.GetReflection()->GetRepeatedFieldRef<T>(msg, field_handle);
118 }
119 
120 } // namespace details
121 } // namespace protobuf
122 } // namespace lbann
123 
124 template <typename T, typename ContainerT>
126  google::protobuf::RepeatedField<T>& field,
127  ContainerT const& values)
128 {
130  field.Clear();
131  field.Add(begin(values), end(values));
132 }
133 
139 template <typename ContainerT>
140 std::string lbann::protobuf::to_space_sep_string(ContainerT const& values)
141 {
142  if (values.empty())
143  return "";
144  std::ostringstream oss;
145  oss << *cbegin(values);
146  for (auto i = next(cbegin(values)); i != cend(values); ++i)
147  oss << " " << *i;
148  return oss.str();
149 }
150 
151 template <typename T>
152 auto lbann::protobuf::as_vector(google::protobuf::Message const& msg,
153  std::string const& field_name) -> std::vector<T>
154 {
155  auto&& field_ref = details::get_repeated_field_ref<T>(msg, field_name);
156  return std::vector<T>{field_ref.begin(), field_ref.end()};
157 }
158 
159 template <typename T>
160 auto lbann::protobuf::as_vector(google::protobuf::RepeatedField<T> const& rf)
161  -> std::vector<T>
162 {
163  return std::vector<T>{rf.cbegin(), rf.cend()};
164 }
165 
166 template <typename T>
167 auto lbann::protobuf::as_vector(google::protobuf::RepeatedPtrField<T> const& rf)
168  -> std::vector<T>
169 {
170  return std::vector<T>{rf.cbegin(), rf.cend()};
171 }
172 
173 template <typename OutT, typename InT>
174 auto lbann::protobuf::to_vector(google::protobuf::RepeatedField<InT> const& rf)
175  -> std::vector<OutT>
176 {
177  return std::vector<OutT>{rf.cbegin(), rf.cend()};
178 }
179 
180 template <typename T>
181 auto lbann::protobuf::as_set(google::protobuf::Message const& msg,
182  std::string const& field_name) -> std::set<T>
183 {
184  static_assert(
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()};
189 }
190 
191 template <typename T>
192 auto lbann::protobuf::as_set(google::protobuf::RepeatedField<T> const& rf)
193  -> std::set<T>
194 {
195  return std::set<T>{rf.cbegin(), rf.cend()};
196 }
197 
199  google::protobuf::RepeatedPtrField<std::string> const& rf)
200  -> std::set<std::string>
201 {
202  return std::set<std::string>{rf.cbegin(), rf.cend()};
203 }
204 
205 template <typename OutT, typename InT>
206 auto lbann::protobuf::to_set(google::protobuf::RepeatedField<InT> const& rf)
207  -> std::set<OutT>
208 {
209  return std::set<OutT>{rf.cbegin(), rf.cend()};
210 }
211 
212 template <typename T>
213 auto lbann::protobuf::as_unordered_set(google::protobuf::Message const& msg,
214  std::string const& field_name)
215  -> std::unordered_set<T>
216 {
217  static_assert(
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()};
222 }
223 
224 template <typename T>
226  google::protobuf::RepeatedField<T> const& rf) -> std::unordered_set<T>
227 {
228  return std::unordered_set<T>{rf.cbegin(), rf.cend()};
229 }
230 
232  google::protobuf::RepeatedPtrField<std::string> const& rf)
233  -> std::unordered_set<std::string>
234 {
235  return std::unordered_set<std::string>{rf.cbegin(), rf.cend()};
236 }
237 
238 template <typename OutT, typename InT>
240  google::protobuf::RepeatedField<InT> const& rf) -> std::unordered_set<OutT>
241 {
242  return std::unordered_set<OutT>{rf.cbegin(), rf.cend()};
243 }
244 
245 #endif // LBANN_UTILS_PROTOBUF_IMPL_HPP_INCLUDED
#define LBANN_ERROR(...)
Definition: exception.hpp:37
google::protobuf::int32 int32
Definition: decl.hpp:55
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.
Definition: impl.hpp:213
auto to_vector(google::protobuf::RepeatedField< InT > const &rf) -> std::vector< OutT >
Convert the repeated field to an STL vector of given type.
Definition: impl.hpp:174
std::string to_space_sep_string(ContainerT const &values)
Concatenate a container of strings into a single string. Elements are space separated.
Definition: impl.hpp:140
constexpr auto PBCppType
Definition: impl.hpp:67
google::protobuf::FieldDescriptor FD
Definition: impl.hpp:54
auto to_set(google::protobuf::RepeatedField< InT > const &) -> std::set< OutT >
Convert the repeated field to an STL set of given type.
Definition: impl.hpp:206
void assign_to_repeated(google::protobuf::RepeatedField< T > &field, ContainerT const &values)
Assign a range of values to a repeated protobuf field.
Definition: impl.hpp:125
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.
Definition: impl.hpp:90
google::protobuf::int64 int64
Definition: decl.hpp:56
google::protobuf::uint32 uint32
Definition: decl.hpp:60
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.
Definition: impl.hpp:181
google::protobuf::uint64 uint64
Definition: decl.hpp:61
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
Definition: impl.hpp:60
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.
Definition: impl.hpp:239
static auto constexpr value
Definition: impl.hpp:63
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.
Definition: impl.hpp:152