CppWAMP
C++11 client library for the WAMP protocol
All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Macros Pages
payload.hpp
Go to the documentation of this file.
1 /*------------------------------------------------------------------------------
2  Copyright Butterfly Energy Systems 2014-2015, 2022.
3  Distributed under the Boost Software License, Version 1.0.
4  http://www.boost.org/LICENSE_1_0.txt
5 ------------------------------------------------------------------------------*/
6 
7 #ifndef CPPWAMP_PAYLOAD_HPP
8 #define CPPWAMP_PAYLOAD_HPP
9 
10 //------------------------------------------------------------------------------
14 //------------------------------------------------------------------------------
15 
16 #include <initializer_list>
17 #include <ostream>
18 #include <sstream>
19 #include <tuple>
20 #include <utility>
21 #include "api.hpp"
22 #include "options.hpp"
23 #include "internal/integersequence.hpp"
24 
25 namespace wamp
26 {
27 
28 //------------------------------------------------------------------------------
31 //------------------------------------------------------------------------------
32 template <typename TDerived, typename TMessage>
33 class CPPWAMP_API Payload : public Options<TDerived, TMessage>
34 {
35 public:
37  template <typename... Ts>
38  TDerived& withArgs(Ts&&... args);
39 
41  template <typename... Ts>
42  TDerived& withArgsTuple(const std::tuple<Ts...>& tuple);
43 
46  TDerived& withArgList(Array args);
47 
49  TDerived& withKwargs(Object kwargs);
50 
52  const Array& args() const &;
53 
55  Array args() &&;
56 
58  const Object& kwargs() const &;
59 
61  Object kwargs() &&;
62 
64  Variant& operator[](size_t index);
65 
67  const Variant& operator[](size_t index) const;
68 
70  Variant& operator[](const String& keyword);
71 
73  template <typename... Ts>
74  size_t convertTo(Ts&... values) const;
75 
77  template <typename... Ts>
78  size_t convertToTuple(std::tuple<Ts...>& tuple) const;
79 
82  template <typename... Ts>
83  size_t moveTo(Ts&... values);
84 
86  template <typename... Ts>
87  size_t moveToTuple(std::tuple<Ts...>& tuple);
88 
89 protected:
91  template <typename... TArgs>
92  explicit Payload(TArgs&&... args);
93 
94 private:
96 
97  CPPWAMP_HIDDEN static void bundle(Array&);
98 
99  template <typename T, typename... Ts>
100  CPPWAMP_HIDDEN static void bundle(Array& array, T&& head, Ts&&... tail);
101 
102  template <typename TTuple, int... Seq>
103  CPPWAMP_HIDDEN static Array
104  bundleFromTuple(TTuple&& tuple, internal::IntegerSequence<Seq...>);
105 
106  CPPWAMP_HIDDEN static void unbundleTo(const Array&, size_t&);
107 
108  template <typename T, typename... Ts>
109  CPPWAMP_HIDDEN static void unbundleTo(const Array& array, size_t& index,
110  T& head, Ts&... tail);
111 
112  template <size_t I, typename... Ts>
113  CPPWAMP_HIDDEN static size_t unbundleToTuple(
114  const Array&, std::tuple<Ts...>& tuple, std::true_type);
115 
116  template <size_t I, typename... Ts>
117  CPPWAMP_HIDDEN static size_t unbundleToTuple(
118  const Array&, std::tuple<Ts...>& tuple, std::false_type);
119 
120  CPPWAMP_HIDDEN static void unbundleAs(Array&, size_t&);
121 
122  template <typename T, typename... Ts>
123  CPPWAMP_HIDDEN static void unbundleAs(Array& array, size_t& index, T& head,
124  Ts&... tail);
125 
126  template <size_t I, typename... Ts>
127  CPPWAMP_HIDDEN static size_t unbundleAsTuple(
128  const Array&, std::tuple<Ts...>& tuple, std::true_type);
129 
130  template <size_t I, typename... Ts>
131  CPPWAMP_HIDDEN static size_t unbundleAsTuple(
132  const Array&, std::tuple<Ts...>& tuple, std::false_type);
133 };
134 
135 
136 //******************************************************************************
137 // Payload implementation
138 //******************************************************************************
139 
140 //------------------------------------------------------------------------------
144 //------------------------------------------------------------------------------
145 template <typename D, typename M>
146 template <typename... Ts>
147 D& Payload<D,M>::withArgs(Ts&&... args)
148 {
149  Array array;
150  bundle(array, std::forward<Ts>(args)...);
151  return withArgList(std::move(array));
152 }
153 
154 //------------------------------------------------------------------------------
158 //------------------------------------------------------------------------------
159 template <typename D, typename M>
160 template <typename... Ts>
161 D& Payload<D,M>::withArgsTuple(const std::tuple<Ts...>& tuple)
162 {
163  using Seq = typename internal::GenIntegerSequence<sizeof...(Ts)>::type;
164  return withArgList(bundleFromTuple(tuple, Seq{}));
165 }
166 
167 //------------------------------------------------------------------------------
169 //------------------------------------------------------------------------------
170 template <typename D, typename M>
172 {
173  this->message().args() = std::move(list);
174  return static_cast<D&>(*this);
175 }
176 
177 //------------------------------------------------------------------------------
179 //------------------------------------------------------------------------------
180 template <typename D, typename M>
182 {
183  this->message().kwargs() = std::move(map);
184  return static_cast<D&>(*this);
185 }
186 
187 //------------------------------------------------------------------------------
188 template <typename D, typename M>
189 const Array& Payload<D,M>::args() const &
190 {
191  return this->message().args();
192 }
193 
194 //------------------------------------------------------------------------------
201 //------------------------------------------------------------------------------
202 template <typename D, typename M>
204 {
205  auto& array = this->message().args();
206  Array result(std::move(array));
207  array.clear();
208  return result;
209 }
210 
211 //------------------------------------------------------------------------------
212 template <typename D, typename M>
213 const Object& Payload<D,M>::kwargs() const &
214 {
215  return this->message().kwargs();
216 }
217 
218 //------------------------------------------------------------------------------
225 //------------------------------------------------------------------------------
226 template <typename D, typename M>
228 {
229  auto& object = this->message().kwargs();
230  Object result(std::move(object));
231  object.clear();
232  return result;
233 }
234 
235 //------------------------------------------------------------------------------
240 //------------------------------------------------------------------------------
241 template <typename D, typename M>
243 {
244  return this->message().args().at(index);
245 }
246 
247 //------------------------------------------------------------------------------
252 //------------------------------------------------------------------------------
253 template <typename D, typename M>
254 const Variant& Payload<D,M>::operator[](size_t index) const
255 {
256  return this->message().args().at(index);
257 }
258 
259 //------------------------------------------------------------------------------
263 //------------------------------------------------------------------------------
264 template <typename D, typename M>
265 Variant& Payload<D,M>::operator[](const std::string& keyword)
266 {
267  return this->message().kwargs()[keyword];
268 }
269 
270 //------------------------------------------------------------------------------
285 //------------------------------------------------------------------------------
286 template <typename D, typename M>
287 template <typename... Ts>
288 size_t Payload<D,M>::convertTo(Ts&... values) const
289 {
290  size_t index = 0;
291  unbundleTo(args(), index, values...);
292  return index;
293 }
294 
295 template <typename D, typename M>
296 template <typename... Ts>
297 size_t Payload<D, M>::convertToTuple(std::tuple<Ts...>& tuple) const
298 {
299  using More = std::integral_constant<bool, sizeof...(Ts) != 0>;
300  return unbundleToTuple<0>(args(), tuple, More{});
301 }
302 
303 //------------------------------------------------------------------------------
319 //------------------------------------------------------------------------------
320 template <typename D, typename M>
321 template <typename... Ts>
322 size_t Payload<D,M>::moveTo(Ts&... values)
323 {
324  size_t index = 0;
325  unbundleAs(this->message().args(), index, values...);
326  return index;
327 }
328 
329 //------------------------------------------------------------------------------
330 template <typename D, typename M>
331 template <typename... Ts>
332 size_t Payload<D,M>::moveToTuple(std::tuple<Ts...>& tuple)
333 {
334  using More = std::integral_constant<bool, sizeof...(Ts) != 0>;
335  return unbundleAsTuple<0>(args(), tuple, More{});
336 }
337 
338 //------------------------------------------------------------------------------
339 template <typename D, typename M>
340 template <typename... TArgs>
341 Payload<D,M>::Payload(TArgs&&... args)
342  : Base(std::forward<TArgs>(args)...)
343 {}
344 
345 //------------------------------------------------------------------------------
346 template <typename D, typename M>
347 void Payload<D,M>::bundle(Array&) {}
348 
349 template <typename D, typename M>
350 template <typename T, typename... Ts>
351 void Payload<D,M>::bundle(Array& array, T&& head, Ts&&... tail)
352 {
353  array.emplace_back(Variant::from(std::forward<T>(head)));
354  bundle(array, tail...);
355 }
356 
357 //------------------------------------------------------------------------------
358 template <typename D, typename M>
359 template <typename TTuple, int... Seq>
360 Array Payload<D,M>::bundleFromTuple(TTuple&& tuple,
361  internal::IntegerSequence<Seq...>)
362 {
363  return Array{Variant::from(std::get<Seq>(std::forward<TTuple>(tuple)))...};
364 }
365 
366 //------------------------------------------------------------------------------
367 template <typename D, typename M>
368 void Payload<D,M>::unbundleTo(const Array&, size_t&) {}
369 
370 template <typename D, typename M>
371 template <typename T, typename... Ts>
372 void Payload<D,M>::unbundleTo(const Array& array, size_t& index, T& head,
373  Ts&... tail)
374 {
375  if (index < array.size())
376  {
377  try
378  {
379  head = array[index].to<T>();
380  }
381  catch (const error::Conversion& e)
382  {
383  std::ostringstream oss;
384  oss << "Payload element at index " << index
385  << " is not convertible to the target type: " << e.what();
386  throw error::Conversion(oss.str());
387  }
388 
389  unbundleTo(array, ++index, tail...);
390  }
391 }
392 
393 //------------------------------------------------------------------------------
394 template <typename D, typename M>
395 template <size_t I, typename... Ts>
396 size_t Payload<D,M>::unbundleToTuple(
397  const Array& array, std::tuple<Ts...>& tuple, std::true_type)
398 {
399  if (I < array.size())
400  {
401  using T = NthTypeOf<I, Ts...>;
402  try
403  {
404  std::get<I>(tuple) = array[I].to<T>();
405  }
406  catch (const error::Conversion& e)
407  {
408  std::ostringstream oss;
409  oss << "Payload element at index " << I
410  << " is not convertible to the target type: " << e.what();
411  throw error::Conversion(oss.str());
412  }
413 
414  using More = std::integral_constant<bool, I+1 != sizeof...(Ts)>;
415  return unbundleToTuple<I+1, Ts...>(array, tuple, More{});
416  }
417  return I;
418 }
419 
420 template <typename D, typename M>
421 template <size_t I, typename... Ts>
422 size_t Payload<D,M>::unbundleToTuple(
423  const Array& array, std::tuple<Ts...>& tuple, std::false_type)
424 {
425  return I;
426 }
427 
428 //------------------------------------------------------------------------------
429 template <typename D, typename M>
430 void Payload<D,M>::unbundleAs(Array&, size_t&) {}
431 
432 template <typename D, typename M>
433 template <typename T, typename... Ts>
434 void Payload<D,M>::unbundleAs(Array& array, size_t& index, T& head, Ts&... tail)
435 {
436  if (index < array.size())
437  {
438  auto& arg = array[index];
439  if (!arg.template is<T>())
440  {
441  std::ostringstream oss;
442  oss << "Payload element of type " << typeNameOf(arg)
443  << " at index " << index
444  << " is not of type: " << typeNameOf<T>();
445  throw error::Access(oss.str());
446  }
447  head = std::move(arg.as<T>());
448  unbundleAs(array, ++index, tail...);
449  }
450 }
451 
452 //------------------------------------------------------------------------------
453 template <typename D, typename M>
454 template <size_t I, typename... Ts>
455 size_t Payload<D,M>::unbundleAsTuple(
456  const Array& array, std::tuple<Ts...>& tuple, std::true_type)
457 {
458  if (I < array.size())
459  {
460  using T = NthTypeOf<I, Ts...>;
461  auto& arg = array[I];
462  if (!arg.template is<T>())
463  {
464  std::ostringstream oss;
465  oss << "Payload element of type " << typeNameOf(arg)
466  << " at index " << I
467  << " is not of type: " << typeNameOf<T>();
468  throw error::Access(oss.str());
469  }
470  std::get<I>(tuple) = std::move(arg.as<T>());
471  using More = std::integral_constant<bool, I+1 != sizeof...(Ts)>;
472  return unbundleAsTuple<I+1, Ts...>(array, tuple, More{});
473  }
474  return I;
475 }
476 
477 template <typename D, typename M>
478 template <size_t I, typename... Ts>
479 size_t Payload<D,M>::unbundleAsTuple(
480  const Array& array, std::tuple<Ts...>& tuple, std::false_type)
481 {
482  return I;
483 }
484 
485 } // namespace wamp
486 
487 #endif // CPPWAMP_PAYLOAD_HPP
wamp::Payload::convertTo
size_t convertTo(Ts &... values) const
Converts the payload's positional arguments to the given value types.
Definition: payload.hpp:288
wamp::Payload::withArgsTuple
TDerived & withArgsTuple(const std::tuple< Ts... > &tuple)
Sets the positional arguments for this payload from a tuple.
wamp::Payload::withArgs
TDerived & withArgs(Ts &&... args)
Sets the positional arguments for this payload.
wamp::Variant
Discriminated union container that represents a JSON value.
Definition: variant.hpp:134
wamp::Payload::operator[]
Variant & operator[](size_t index)
Accesses a positional argument by index.
Definition: payload.hpp:242
api.hpp
Defines macros related to exporting/importing APIs.
wamp::TypeId::array
@ array
For Variant::Array.
wamp::Payload::withKwargs
TDerived & withKwargs(Object kwargs)
Sets the keyword arguments for this payload.
Definition: payload.hpp:181
wamp::Payload
Wrapper around a WAMP message containing payload arguments and an options dictionary.
Definition: payload.hpp:33
wamp::Object
std::map< String, Variant > Object
Variant bound type for maps of variants.
Definition: variantdefs.hpp:52
wamp::Payload::withArgList
TDerived & withArgList(Array args)
Sets the positional arguments for this payload from an array of variants.
Definition: payload.hpp:171
wamp
Definition: anyhandler.hpp:36
wamp::Variant::at
Variant & at(SizeType index)
Accesses an array element by index.
Definition: variant.ipp:287
wamp::Payload::moveTo
size_t moveTo(Ts &... values)
Moves the payload's positional arguments to the given value references.
Definition: payload.hpp:322
wamp::Payload::args
const Array & args() const &
Accesses the constant list of positional arguments.
Definition: payload.hpp:189
wamp::Array
std::vector< Variant > Array
Variant bound type for arrays of variants.
Definition: variantdefs.hpp:51
wamp::Options
Wrapper around a WAMP message containing an options dictionary.
Definition: options.hpp:29
wamp::Payload::Payload
Payload(TArgs &&... args)
Constructor taking message construction aruments.
Definition: payload.hpp:341
options.hpp
Contains the declaration of the Options class.
wamp::Payload::kwargs
const Object & kwargs() const &
Accesses the constant map of keyword arguments.
Definition: payload.hpp:213
wamp::Payload::moveToTuple
size_t moveToTuple(std::tuple< Ts... > &tuple)
Moves the payload's positional arguments to the given std::tuple.
Definition: payload.hpp:332
wamp::String
std::string String
Variant bound type for text strings.
Definition: variantdefs.hpp:50
wamp::Variant::from
static Variant from(TValue &&value)
Constructs a variant from a custom type.
Definition: variant.hpp:744
wamp::NthTypeOf
typename std::tuple_element< N, std::tuple< Ts... > >::type NthTypeOf
Metafunction that obtains the Nth type of a parameter pack.
Definition: traits.hpp:106
wamp::Payload::convertToTuple
size_t convertToTuple(std::tuple< Ts... > &tuple) const
Converts the payload's positional arguments to the given std::tuple.
Definition: payload.hpp:297