#pragma once namespace fluid { namespace client { struct ToFloatArray { static index allocSize(typename BufferT::type) { return 1; } template static std::enable_if_t< std::is_integral::value || std::is_floating_point::value, index> allocSize(T) { return 1; } static index allocSize(std::string s) { return asSigned(s.size()) + 1; } // put null char at end when we send static index allocSize(FluidTensor s) { index count = 0; for (auto& str : s) count += (str.size() + 1); return count; } template static index allocSize(FluidTensor s) { return s.size(); } template static std::tuple, index> allocSize(std::tuple&& t) { return allocSizeImpl(std::forward(t), std::index_sequence_for()); }; template static std::tuple, index> allocSizeImpl(std::tuple&& t, std::index_sequence) { index size{0}; std::array res; (void) std::initializer_list{ (res[Is] = size, size += ToFloatArray::allocSize(std::get(t)), 0)...}; return std::make_tuple(res, size); // array of offsets into allocated buffer & // total number of floats to alloc }; static void convert(float* f, typename BufferT::type buf) { f[0] = static_cast(buf.get())->bufnum(); } template static std::enable_if_t::value || std::is_floating_point::value> convert(float* f, T x) { f[0] = static_cast(x); } static void convert(float* f, std::string s) { std::copy(s.begin(), s.end(), f); f[s.size()] = 0; // terminate } static void convert(float* f, FluidTensor s) { for (auto& str : s) { std::copy(str.begin(), str.end(), f); f += str.size(); *f++ = 0; } } template static void convert(float* f, FluidTensor s) { static_assert(std::is_convertible::value, "Can't convert this to float output"); std::copy(s.begin(), s.end(), f); } template static void convert(float* f, std::tuple&& t, std::array offsets, std::index_sequence) { (void) std::initializer_list{ (convert(f + offsets[Is], std::get(t)), 0)...}; } }; } }