Skip to content

Commit 593abde

Browse files
committed
Minor fixes and enhancements to v0.5.0 release.
- Fixed namespace-related errors that occur for user-defined conversions. - Can now specify a fallback value when extracting an object member during conversion. - Added Rpc::captureError which allows users to retrieve ERROR message details returned by a callee. - Variant-to-Variant conversion is now handled properly.
1 parent 4f9f6ad commit 593abde

File tree

12 files changed

+275
-42
lines changed

12 files changed

+275
-42
lines changed

cppwamp/include/cppwamp/conversion.hpp

Lines changed: 28 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -34,15 +34,15 @@
3434
void convertTo(ToVariantConverter&, const Type&)
3535
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ */
3636
//------------------------------------------------------------------------------
37-
#define CPPWAMP_CONVERSION_SPLIT_FREE(Type) \
38-
void convert(FromVariantConverter& c, Type& obj) \
39-
{ \
40-
convertFrom(c, obj); \
41-
} \
42-
\
43-
void convert(ToVariantConverter& c, Type& obj) \
44-
{ \
45-
convertTo(c, const_cast<const Type&>(obj)); \
37+
#define CPPWAMP_CONVERSION_SPLIT_FREE(Type) \
38+
inline void convert(::wamp::FromVariantConverter& c, Type& obj) \
39+
{ \
40+
convertFrom(c, obj); \
41+
} \
42+
\
43+
inline void convert(::wamp::ToVariantConverter& c, Type& obj) \
44+
{ \
45+
convertTo(c, const_cast<const Type&>(obj)); \
4646
}
4747

4848
//------------------------------------------------------------------------------
@@ -63,16 +63,16 @@ void convert(ToVariantConverter& c, Type& obj) \
6363
void CustomType::convertTo(ToVariantConverter&) const
6464
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ */
6565
//------------------------------------------------------------------------------
66-
#define CPPWAMP_CONVERSION_SPLIT_MEMBER(Type) \
67-
void convert(FromVariantConverter& c, Type& obj) \
68-
{ \
69-
ConversionAccess::convertFrom(c, obj); \
70-
} \
71-
\
72-
void convert(ToVariantConverter& c, Type& obj) \
73-
{ \
74-
const auto& constObj = obj; \
75-
ConversionAccess::convertTo(c, constObj); \
66+
#define CPPWAMP_CONVERSION_SPLIT_MEMBER(Type) \
67+
inline void convert(::wamp::FromVariantConverter& c, Type& obj) \
68+
{ \
69+
wamp::ConversionAccess::convertFrom(c, obj); \
70+
} \
71+
\
72+
inline void convert(::wamp::ToVariantConverter& c, Type& obj) \
73+
{ \
74+
const auto& constObj = obj; \
75+
wamp::ConversionAccess::convertTo(c, constObj); \
7676
}
7777

7878
namespace wamp
@@ -115,6 +115,10 @@ class ToVariantConverter
115115
template <typename T>
116116
ToVariantConverter& operator()(String key, T&& value);
117117

118+
/** Appends an object member to the variant. */
119+
template <typename T, typename U>
120+
ToVariantConverter& operator()(String key, T&& value, U&& ignored);
121+
118122
/** Returns a reference to the wrapped variant. */
119123
Variant& variant();
120124

@@ -160,6 +164,11 @@ class FromVariantConverter
160164
template <typename T>
161165
FromVariantConverter& operator()(const String& key, T& value);
162166

167+
/** Retrieves a member from an Object variant, with a fallback value
168+
if the member is not found. */
169+
template <typename T, typename U>
170+
FromVariantConverter& operator()(const String& key, T& value, U&& fallback);
171+
163172
/** Returns a constant reference to the wrapped variant. */
164173
const Variant& variant() const;
165174

cppwamp/include/cppwamp/dialoguedata.hpp

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -48,9 +48,15 @@ class Reason : public Options<Reason>
4848
class Error : public Options<Error>, public Payload<Error>
4949
{
5050
public:
51+
/** Constructs an empty error. */
52+
Error();
53+
5154
/** Converting constructor taking a reason URI. */
5255
Error(String reason);
5356

57+
/** Conversion to bool operator, returning false if the error is empty. */
58+
explicit operator bool() const;
59+
5460
/** Obtains the reason URI. */
5561
const String& reason() const;
5662

cppwamp/include/cppwamp/internal/client.hpp

Lines changed: 17 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -312,26 +312,28 @@ class Client : public ClientInterface, public Dialogue<TCodec, TTransport>
312312
virtual void call(Rpc&& rpc, AsyncHandler<Result>&& handler) override
313313
{
314314
using std::move;
315+
Error* errorPtr = rpc.error({});
316+
315317
if (!rpc.kwargs().empty())
316318
{
317319
callWithKwargsMsg_.at(2) = move(rpc.options({}));
318320
callWithKwargsMsg_.at(3) = move(rpc.procedure({}));
319321
callWithKwargsMsg_.at(4) = move(rpc.args({}));
320322
callWithKwargsMsg_.at(5) = move(rpc.kwargs({}));
321-
callProcedure(callWithKwargsMsg_, move(handler));
323+
callProcedure(callWithKwargsMsg_, errorPtr, move(handler));
322324
}
323325
else if (!rpc.args().empty())
324326
{
325327
callWithArgsMsg_.at(2) = move(rpc.options({}));
326328
callWithArgsMsg_.at(3) = move(rpc.procedure({}));
327329
callWithArgsMsg_.at(4) = move(rpc.args({}));
328-
callProcedure(callWithArgsMsg_, move(handler));
330+
callProcedure(callWithArgsMsg_, errorPtr, move(handler));
329331
}
330332
else
331333
{
332334
callMsg_.at(2) = move(rpc.options({}));
333335
callMsg_.at(3) = move(rpc.procedure({}));
334-
callProcedure(callMsg_, move(handler));
336+
callProcedure(callMsg_, errorPtr, move(handler));
335337
}
336338
}
337339

@@ -491,12 +493,22 @@ class Client : public ClientInterface, public Dialogue<TCodec, TTransport>
491493
}
492494
}
493495

494-
void callProcedure(Message& msg, AsyncHandler<Result>&& handler)
496+
void callProcedure(Message& msg, Error* errorPtr,
497+
AsyncHandler<Result>&& handler)
495498
{
496499
auto self = this->shared_from_this();
497500
this->request(msg,
498-
[this, self, handler](std::error_code ec, Message reply)
501+
[this, self, errorPtr, handler](std::error_code ec, Message reply)
499502
{
503+
if ((reply.type == WampMsgType::error) && (errorPtr != nullptr))
504+
{
505+
*errorPtr = Error(reply.as<String>(4));
506+
if (reply.size() >= 6)
507+
errorPtr->withArgList(reply.as<Array>(5));
508+
if (reply.size() >= 7)
509+
errorPtr->withKwargs(reply.as<Object>(6));
510+
}
511+
500512
if (checkReply<Result>(WampMsgType::result, ec, reply,
501513
SessionErrc::callError, handler))
502514
{

cppwamp/include/cppwamp/internal/conversion.ipp

Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -66,6 +66,16 @@ ToVariantConverter& ToVariantConverter::operator()(String key, T&& value)
6666
return *this;
6767
}
6868

69+
/** @details
70+
If the destination Variant is not already an Object, it will be transformed
71+
into an object and all previously stored values will be cleared.
72+
@post `this->variant().is<Object> == true` */
73+
template <typename T, typename U>
74+
ToVariantConverter& ToVariantConverter::operator()(String key, T&& value, U&&)
75+
{
76+
return operator()(std::move(key), std::forward<T>(value));
77+
}
78+
6979
inline Variant& ToVariantConverter::variant() {return var_;}
7080

7181

@@ -140,6 +150,19 @@ FromVariantConverter& FromVariantConverter::operator()(const String& key,
140150
return *this;
141151
}
142152

153+
template <typename T, typename U>
154+
FromVariantConverter& FromVariantConverter::operator()(const String& key,
155+
T& value, U&& fallback)
156+
{
157+
auto& obj = var_.as<Object>();
158+
auto kv = obj.find(key);
159+
if (kv != obj.end())
160+
kv->second.to(value);
161+
else
162+
value = std::forward<U>(fallback);
163+
return *this;
164+
}
165+
143166
inline const Variant& FromVariantConverter::variant() const {return var_;}
144167

145168

cppwamp/include/cppwamp/internal/dialoguedata.ipp

Lines changed: 8 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -11,18 +11,24 @@
1111
namespace wamp
1212
{
1313

14+
//------------------------------------------------------------------------------
1415
CPPWAMP_INLINE Reason::Reason(String uri) : uri_(std::move(uri)) {}
1516

1617
CPPWAMP_INLINE const String& Reason::uri() const {return uri_;}
1718

1819
CPPWAMP_INLINE String& Reason::uri(internal::PassKey)
1920
{return uri_;}
2021

22+
23+
//------------------------------------------------------------------------------
24+
CPPWAMP_INLINE Error::Error() {}
25+
2126
CPPWAMP_INLINE Error::Error(String reason) : reason_(std::move(reason)) {}
2227

2328
CPPWAMP_INLINE const String& Error::reason() const {return reason_;}
2429

25-
CPPWAMP_INLINE String& Error::reason(internal::PassKey)
26-
{return reason_;}
30+
CPPWAMP_INLINE Error::operator bool() const {return !reason_.empty();}
31+
32+
CPPWAMP_INLINE String& Error::reason(internal::PassKey) {return reason_;}
2733

2834
} // namespace wamp

cppwamp/include/cppwamp/internal/sessiondata.ipp

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -338,6 +338,12 @@ CPPWAMP_INLINE String& Procedure::uri(internal::PassKey) {return uri_;}
338338

339339
CPPWAMP_INLINE Rpc::Rpc(String procedure) : procedure_(std::move(procedure)) {}
340340

341+
CPPWAMP_INLINE Rpc& Rpc::captureError(Error& error)
342+
{
343+
error_ = &error;
344+
return *this;
345+
}
346+
341347
CPPWAMP_INLINE Rpc& Rpc::withDealerTimeout(Int milliseconds)
342348
{
343349
return withOption("timeout", milliseconds);
@@ -387,6 +393,8 @@ CPPWAMP_INLINE Rpc& Rpc::withDiscloseMe(bool disclosed)
387393

388394
CPPWAMP_INLINE String& Rpc::procedure(internal::PassKey) {return procedure_;}
389395

396+
CPPWAMP_INLINE Error* Rpc::error(internal::PassKey) {return error_;}
397+
390398

391399
//******************************************************************************
392400
// Result

cppwamp/include/cppwamp/internal/variant.ipp

Lines changed: 60 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -488,6 +488,33 @@ Variant Variant::convertFrom(const T& value)
488488
return v;
489489
}
490490

491+
//------------------------------------------------------------------------------
492+
template <typename T, Variant::EnableIfVariantArg<ValueTypeOf<T>>>
493+
Variant Variant::convertFrom(const T& variant)
494+
{
495+
return variant;
496+
}
497+
498+
//------------------------------------------------------------------------------
499+
template <typename T, Variant::DisableIfValidArg<T>>
500+
Variant Variant::convertFrom(const std::vector<T>& vec)
501+
{
502+
Variant::Array array;
503+
for (const auto& elem: vec)
504+
array.emplace_back(Variant::convertFrom(elem));
505+
return Variant(std::move(array));
506+
}
507+
508+
//------------------------------------------------------------------------------
509+
template <typename T, Variant::DisableIfValidArg<T>>
510+
Variant Variant::convertFrom(const std::map<String, T>& map)
511+
{
512+
Variant::Object object;
513+
for (const auto& kv: map)
514+
object.emplace(kv.first, Variant::convertFrom(kv.second));
515+
return Variant(std::move(object));
516+
}
517+
491518
//------------------------------------------------------------------------------
492519
template <typename T, Variant::EnableIfValidArg<T>>
493520
void Variant::convertTo(T& value) const
@@ -503,6 +530,39 @@ void Variant::convertTo(T& value) const
503530
convert(conv, value);
504531
}
505532

533+
//------------------------------------------------------------------------------
534+
template <typename T, Variant::EnableIfVariantArg<T>>
535+
void Variant::convertTo(T& variant) const
536+
{
537+
variant = *this;
538+
}
539+
540+
//------------------------------------------------------------------------------
541+
template <typename T, Variant::DisableIfValidArg<T>>
542+
void Variant::convertTo(std::vector<T>& vec) const
543+
{
544+
const auto& array = this->as<Array>();
545+
for (const auto& elem: array)
546+
{
547+
T value;
548+
elem.convertTo(value);
549+
vec.emplace_back(std::move(value));
550+
}
551+
}
552+
553+
//------------------------------------------------------------------------------
554+
template <typename T, Variant::DisableIfValidArg<T>>
555+
void Variant::convertTo(std::map<String, T>& map) const
556+
{
557+
const auto& object = this->as<Object>();
558+
for (const auto& kv: map)
559+
{
560+
T value;
561+
kv.second.convertTo(value);
562+
map.emplace(std::move(kv.first), std::move(value));
563+
}
564+
}
565+
506566
//------------------------------------------------------------------------------
507567
template <typename TField, typename V> TField& Variant::get(V&& variant)
508568
{

cppwamp/include/cppwamp/sessiondata.hpp

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -231,6 +231,10 @@ class Rpc : public Options<Rpc>, public Payload<Rpc>
231231
/** Converting constructor taking a procedure URI. */
232232
Rpc(String procedure);
233233

234+
/** Specifies the Error object in which to store call errors returned
235+
by the callee. */
236+
Rpc& captureError(Error& error);
237+
234238
/** Requests that the dealer cancels the call after the specified
235239
timeout duration. */
236240
Rpc& withDealerTimeout(Int milliseconds);
@@ -253,9 +257,11 @@ class Rpc : public Options<Rpc>, public Payload<Rpc>
253257

254258
private:
255259
String procedure_;
260+
Error* error_ = nullptr;
256261

257262
public:
258263
String& procedure(internal::PassKey); // Internal use only
264+
Error* error(internal::PassKey); // Internal use only
259265
};
260266

261267

cppwamp/include/cppwamp/variant.hpp

Lines changed: 25 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -113,7 +113,12 @@ class Variant
113113

114114
/** Metafunction used for disabling overloads for valid argument types. */
115115
template <typename T>
116-
using DisableIfValidArg = DisableIf<ArgTraits<ValueTypeOf<T>>::isValid>;
116+
using DisableIfValidArg = DisableIf<ArgTraits<ValueTypeOf<T>>::isValid ||
117+
isSameType<T, Variant>()>;
118+
119+
/** Metafunction used for enabling overloads for Variant arguments. */
120+
template <typename T>
121+
using EnableIfVariantArg = EnableIf<isSameType<T, Variant>()>;
117122

118123
/// @}
119124

@@ -256,7 +261,7 @@ class Variant
256261
/** Move-assigns from one variant into another. */
257262
Variant& operator=(Variant&& other) noexcept;
258263

259-
/** Assigns a value to variant. */
264+
/** Assigns a value to a variant. */
260265
template <typename T> Variant& operator=(T value);
261266

262267
/** Assigns an array variant to a variant. */
@@ -313,12 +318,30 @@ class Variant
313318
template <typename T, DisableIfValidArg<ValueTypeOf<T>> = 0>
314319
static Variant convertFrom(const T& value);
315320

321+
template <typename T, EnableIfVariantArg<ValueTypeOf<T>> = 0>
322+
static Variant convertFrom(const T& variant);
323+
324+
template <typename T, DisableIfValidArg<T> = 0>
325+
static Variant convertFrom(const std::vector<T>& vec);
326+
327+
template <typename T, DisableIfValidArg<T> = 0>
328+
static Variant convertFrom(const std::map<String, T>& map);
329+
316330
template <typename T, EnableIfValidArg<T> = 0>
317331
void convertTo(T& value) const;
318332

319333
template <typename T, DisableIfValidArg<T> = 0>
320334
void convertTo(T& value) const;
321335

336+
template <typename T, EnableIfVariantArg<T> = 0>
337+
void convertTo(T& variant) const;
338+
339+
template <typename T, DisableIfValidArg<T> = 0>
340+
void convertTo(std::vector<T>& vec) const;
341+
342+
template <typename T, DisableIfValidArg<T> = 0>
343+
void convertTo(std::map<String, T>& map) const;
344+
322345
template <typename TField, typename V> static TField& get(V&& variant);
323346

324347
static std::ostream& output(std::ostream& out, const Array& array);

cppwamp/include/cppwamp/version.hpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -20,7 +20,7 @@
2020
#define CPPWAMP_MINOR_VERSION 5
2121

2222
/// Patch version for backwards-compatible bug fixes.
23-
#define CPPWAMP_PATCH_VERSION 0
23+
#define CPPWAMP_PATCH_VERSION 1
2424

2525
/// Integer version number, computed as `(major*10000) + (minor*100) + patch`
2626
#define CPPWAMP_VERSION 500

0 commit comments

Comments
 (0)