3 #include <ozo/type_traits.h>
4 #include <ozo/io/send.h>
5 #include <ozo/io/recv.h>
6 #include <boost/hana/adapt_struct.hpp>
7 #include <boost/hana/size.hpp>
8 #include <boost/hana/fold.hpp>
9 #include <boost/fusion/adapted/struct/adapt_struct.hpp>
10 #include <boost/range/numeric.hpp>
11 #include <boost/range/algorithm/for_each.hpp>
16 struct fit_array_size_impl {
17 static void apply(T& array,
size_type count) { array.resize(count); }
61 fit_array_size_impl<T>::apply(array, count);
66 namespace ozo::detail {
69 BOOST_HANA_DEFINE_STRUCT(pg_array,
70 (std::int32_t, dimensions_count),
71 (std::int32_t, dataoffset),
76 struct pg_array_dimension {
77 BOOST_HANA_DEFINE_STRUCT(pg_array_dimension,
85 namespace ozo::detail {
88 struct size_of_array_impl {
89 constexpr
static size_type data_size(
const T& v) {
91 if constexpr (StaticSize<typename T::value_type>) {
98 static constexpr
auto apply(
const T& v) {
99 constexpr
const auto header_size = hana::unpack(
100 hana::members(pg_array{}),
101 [] (
const auto& ...x) {
return (
sizeof(x) + ... + 0); });
103 constexpr
const auto dimension_header_size = hana::unpack(
104 hana::members(pg_array_dimension{}),
105 [] (
const auto& ...x) {
return (
sizeof(x) + ... + 0); });
107 return header_size + dimension_header_size + data_size(v);
111 template <
typename T>
112 struct size_of_impl_dispatcher<T,
Require<
Array<T>>> {
using type = size_of_array_impl<std::decay_t<T>>; };
114 template <
typename T>
115 struct send_array_impl {
116 template <
typename O
idMap>
117 static ostream& apply(ostream& out,
const OidMap& oid_map,
const T& in) {
118 using value_type =
typename T::value_type;
119 write(out, pg_array {1, 0, type_oid<value_type>(oid_map)});
120 write(out, pg_array_dimension {std::int32_t(std::size(in)), 0});
121 boost::for_each(in, [&] (
const auto& v) {
send_data_frame(out, oid_map, v);});
126 template <
typename T>
127 struct send_impl_dispatcher<T,
Require<
Array<T>>> {
using type = send_array_impl<std::decay_t<T>>; };
129 template <
typename T>
130 struct recv_array_impl {
133 template <
typename O
idMap>
134 static istream& apply(istream& in,
size_type,
const OidMap& oids, out_type& out) {
135 pg_array array_header;
136 pg_array_dimension dim_header;
138 read(in, array_header);
140 if (array_header.dimensions_count > 1) {
142 "multiply dimension count is not supported: "
143 + std::to_string(array_header.dimensions_count));
146 using item_type = unwrap_type<typename out_type::value_type>;
148 if (!accepts_oid<item_type>(oids, array_header.elemtype)) {
150 "unexpected oid " + std::to_string(array_header.elemtype)
151 +
" for element type of " + boost::core::demangle(
typeid(item_type).name()));
154 if (array_header.dimensions_count < 1) {
158 read(in, dim_header);
160 if (dim_header.size == 0) {
166 for (
auto& item : out) {
173 template <
typename T>
174 struct recv_impl_dispatcher<T,
Require<
Array<T>>> {
using type = recv_array_impl<std::decay_t<T>>; };