@@ -662,6 +662,19 @@ decltype(auto) CustomReadField(TypeList<LocalType> param,
662
662
return read_dest.update ([&](auto & value) { ReadOne<0 >(param, invoke_context, input, value); });
663
663
}
664
664
665
+ // ! Overload CustomReadField to serialize objects that have CustomReadMessage
666
+ // ! overloads. Defining a CustomReadMessage overload is simpler than defining a
667
+ // ! CustomReadField overload because it only requires defining a normal
668
+ // ! function, not a template function, but less flexible.
669
+ template <typename LocalType, typename Reader, typename ReadDest>
670
+ decltype (auto ) CustomReadField(TypeList<LocalType>, Priority<2 >, InvokeContext& invoke_context, Reader&& reader,
671
+ ReadDest&& read_dest,
672
+ decltype (CustomReadMessage(invoke_context, reader.get(),
673
+ std::declval<LocalType&>()))* enable = nullptr )
674
+ {
675
+ return read_dest.update ([&](auto & value) { if (reader.has ()) CustomReadMessage (invoke_context, reader.get (), value); });
676
+ }
677
+
665
678
template <typename ... LocalTypes, typename ... Args>
666
679
decltype (auto ) ReadField(TypeList<LocalTypes...>, Args&&... args)
667
680
{
@@ -719,6 +732,17 @@ bool CustomHasValue(InvokeContext& invoke_context, Values&&... value)
719
732
return true ;
720
733
}
721
734
735
+ // ! Overload CustomBuildField to serialize objects that have CustomBuildMessage
736
+ // ! overloads. Defining a CustomBuildMessage overload is simpler than defining a
737
+ // ! CustomBuildField overload because it only requires defining a normal
738
+ // ! function, not a template function, but less flexible.
739
+ template <typename LocalType, typename Value, typename Output>
740
+ void CustomBuildField (TypeList<LocalType>, Priority<2 >, InvokeContext& invoke_context, Value&& value, Output&& output,
741
+ decltype (CustomBuildMessage(invoke_context, value, std::move(output.get())))* enable = nullptr)
742
+ {
743
+ CustomBuildMessage (invoke_context, value, std::move (output.init ()));
744
+ }
745
+
722
746
template <typename ... LocalTypes, typename Context, typename ... Values, typename Output>
723
747
void BuildField (TypeList<LocalTypes...>, Context& context, Output&& output, Values&&... values)
724
748
{
@@ -1389,10 +1413,61 @@ struct ServerExcept : Parent
1389
1413
}
1390
1414
};
1391
1415
1416
+ // ! Helper for CustomPassField below. Call Accessor::get method if it has one,
1417
+ // ! otherwise return capnp::Void.
1418
+ template <typename Accessor, typename Message>
1419
+ decltype (auto ) MaybeGet(Message&& message, decltype (Accessor::get(message))* enable = nullptr)
1420
+ {
1421
+ return Accessor::get (message);
1422
+ }
1423
+
1424
+ template <typename Accessor>
1425
+ ::capnp::Void MaybeGet (...)
1426
+ {
1427
+ return {};
1428
+ }
1429
+
1430
+ // ! Helper for CustomPassField below. Call Accessor::init method if it has one,
1431
+ // ! otherwise do nothing.
1432
+ template <typename Accessor, typename Message>
1433
+ decltype (auto ) MaybeInit(Message&& message, decltype (Accessor::get(message))* enable = nullptr)
1434
+ {
1435
+ return Accessor::init (message);
1436
+ }
1437
+
1438
+ template <typename Accessor>
1439
+ ::capnp::Void MaybeInit (...)
1440
+ {
1441
+ return {};
1442
+ }
1443
+
1444
+ // ! Overload CustomPassField to serialize objects that have CustomPassMessage
1445
+ // ! overloads. Defining a CustomPassMessage overload is simpler than defining a
1446
+ // ! CustomPassField overload because it only requires defining a normal
1447
+ // ! function, not a template function, but less flexible.
1448
+ template <typename Accessor, typename ... LocalTypes, typename ServerContext, typename Fn, typename ... Args>
1449
+ auto CustomPassField (TypeList<LocalTypes...>, ServerContext& server_context, Fn&& fn, Args&&... args)
1450
+ -> decltype(CustomPassMessage(server_context, MaybeGet<Accessor>(server_context.call_context.getParams()),
1451
+ MaybeGet<Accessor>(server_context.call_context.getResults()), nullptr))
1452
+ {
1453
+ CustomPassMessage (server_context, MaybeGet<Accessor>(server_context.call_context .getParams ()),
1454
+ MaybeInit<Accessor>(server_context.call_context .getResults ()),
1455
+ [&](LocalTypes... param) { fn.invoke (server_context, std::forward<Args>(args)..., param...); });
1456
+ }
1457
+
1392
1458
template <class Accessor >
1393
1459
void CustomPassField ();
1394
1460
1395
1461
// ! PassField override calling CustomPassField function, if it exists.
1462
+ // ! Defining a CustomPassField or CustomPassMessage overload is useful for
1463
+ // ! input/output parameters. If an overload is not defined these parameters will
1464
+ // ! just be deserialized on the server side with ReadField into a temporary
1465
+ // ! variable, then the server method will be called passing the temporary
1466
+ // ! variable as a parameter, then the temporary variable will be serialized and
1467
+ // ! sent back to the client with BuildField. But if a PassField or PassMessage
1468
+ // ! overload is defined, the overload is called with a callback to invoke and
1469
+ // ! pass parameters to the server side function, and run arbitrary code before
1470
+ // ! and after invoking the function.
1396
1471
template <typename Accessor, typename ... Args>
1397
1472
auto PassField (Priority<2 >, Args&&... args) -> decltype(CustomPassField<Accessor>(std::forward<Args>(args)...))
1398
1473
{
0 commit comments