3 #include <ozo/type_traits.h>
4 #include <ozo/io/send.h>
5 #include <ozo/io/recv.h>
6 #include <ozo/io/size_of.h>
7 #include <boost/hana/adapt_struct.hpp>
8 #include <boost/hana/members.hpp>
9 #include <boost/hana/size.hpp>
10 #include <boost/hana/fold.hpp>
11 #include <boost/fusion/adapted/struct/adapt_struct.hpp>
12 #include <boost/fusion/include/fold.hpp>
14 namespace ozo::detail {
17 BOOST_HANA_DEFINE_STRUCT(pg_composite,
28 constexpr
auto size_of(
const pg_composite&) noexcept {
29 return size_constant<
sizeof(std::int32_t)>{};
33 constexpr
auto fields_number(
const T& v) -> Require<FusionSequence<T>&&!HanaStruct<T>,
size_type> {
38 constexpr
auto fields_number(
const T& v) -> Require<HanaStruct<T>,
size_type> {
39 return size_type(hana::value(hana::size(hana::members(v))));
43 constexpr
auto data_size(
const T& v) -> Require<FusionSequence<T>&&!HanaStruct<T>,
size_type> {
45 [&] (
auto r,
const auto& item) {
return r +
frame_size(item); });
49 constexpr
auto data_size(
const T& v) -> Require<HanaStruct<T>,
size_type>{
50 return hana::unpack(hana::members(v),
51 [&] (
const auto& ...x) {
return (
frame_size(x) + ... + 0); });
55 struct size_of_composite {
56 static constexpr
auto apply(
const T& v) {
58 constexpr
const auto header_size =
size_of(detail::pg_composite{});
59 return header_size + data_size(v);
63 template <
typename T,
typename Func>
64 constexpr
auto for_each_member(T&& v, Func&& f) -> Require<FusionSequence<T>&&!HanaStruct<T>> {
65 fusion::for_each(std::forward<T>(v), std::forward<Func>(f));
68 template <
typename T,
typename Func>
69 constexpr
auto for_each_member(T&& v, Func&& f) -> Require<HanaStruct<T>>{
70 hana::for_each(hana::members(std::forward<T>(v)), std::forward<Func>(f));
74 struct size_of_impl_dispatcher<T,
Require<
Composite<T>>> {
using type = size_of_composite<std::decay_t<T>>; };
77 struct send_composite_impl {
78 template <
typename O
idMap>
79 static ostream& apply(ostream& out,
const OidMap& oid_map,
const T& in) {
80 write(out, pg_composite{fields_number(in)});
81 for_each_member(in, [&] (
const auto& v) {
89 struct send_impl_dispatcher<T,
Require<
Composite<T>>> {
using type = send_composite_impl<std::decay_t<T>>; };
92 inline Require<Composite<T>> read_and_verify_header(istream& in,
const T& v) {
95 if (header.count != fields_number(v)) {
97 "incoming composite fields count " + std::to_string(header.count)
98 +
" does not match fields count " + std::to_string(fields_number(v))
99 +
" of type " + boost::core::demangle(
typeid(v).name()));
103 template <
typename T>
104 struct recv_fusion_adapted_composite_impl {
105 template <
typename O
idMap>
106 static istream& apply(istream& in,
size_type,
const OidMap& oid_map, T& out) {
107 read_and_verify_header(in, out);
108 fusion::for_each(out, [&] (
auto& v) {
115 template <
typename T>
116 struct recv_hana_adapted_composite_impl {
117 template <
typename O
idMap>
118 static istream& apply(istream& in,
size_type,
const OidMap& oid_map, T& out) {
119 read_and_verify_header(in, out);
120 hana::for_each(hana::keys(out), [&in, &out, &oid_map](
auto key) {
121 recv_frame(in, oid_map, hana::at_key(out, key));
127 template <
typename T>
129 using type = recv_fusion_adapted_composite_impl<std::decay_t<T>>;
132 template <
typename T>
134 using type = recv_hana_adapted_composite_impl<std::decay_t<T>>;