5 #include <mutils/macro_utils.hpp> 6 #include <mutils/mutils.hpp> 7 #include <mutils/tuple_extras.hpp> 8 #include <mutils/type_utils.hpp> 17 struct DeserializationManager;
35 virtual std::size_t
to_bytes(
char* v)
const = 0;
47 const std::function<
void(
char const*
const, std::size_t)>&)
const = 0;
146 : registered_v(
std::move(o.registered_v)) {}
149 registered_v.emplace_back(ctx);
158 template <
typename T>
160 for(
auto& candidate : registered_v) {
161 if(
auto* t = dynamic_cast<T*>(candidate))
164 assert(
false &&
"Error: no registered manager exists");
172 template <
typename T>
174 for(
auto& candidate : registered_v) {
175 if(
auto* t = dynamic_cast<T*>(candidate))
178 assert(
false &&
"Error: no registered manager exists");
187 template <
typename T>
189 for(
auto& candidate : registered_v) {
190 if(dynamic_cast<T const*>(candidate))
200 template <typename T, restrict2(std::is_pod<T>::value)>
217 template <
typename... T>
218 std::size_t
bytes_size(
const std::tuple<T...>& t);
223 template <
typename T,
typename V>
231 std::size_t
bytes_size(
const std::vector<bool>& v);
233 template <
typename T>
236 static const auto typenonce_size =
bytes_size(
237 type_name<std::vector<T>>());)
if(std::is_pod<T>::value)
return v
240 +
sizeof(
int) whenmutilsdebug(+typenonce_size);
245 return accum +
sizeof(int) whenmutilsdebug(+typenonce_size);
253 template <
typename T>
255 if(std::is_pod<T>::value)
256 return list.size() *
bytes_size(list.back()) +
sizeof(
int);
259 for(
const auto& e : list)
261 return accum +
sizeof(int);
268 template <
typename T>
270 int size =
sizeof(int);
281 template <
typename K,
typename V>
283 int size =
sizeof(int);
284 for(
const auto& p : m) {
294 template <
typename... T>
298 template <
typename... T>
300 return std::apply(bytes_size_helper<T...>, t);
309 template <
typename F,
typename BR,
typename... Args>
310 std::enable_if_t<std::is_pod<BR>::value>
post_object(
const F& f,
const BR& br,
312 f(std::forward<Args>(args)..., (
char*)&br,
sizeof(BR));
315 void post_object(
const std::function<
void(
char const*
const, std::size_t)>& f,
329 template <typename T, restrict(std::is_pod<T>::value)>
346 std::size_t
to_bytes(
const std::string& b,
char* v);
353 template <
typename T>
354 std::enable_if_t<std::is_base_of<ByteRepresentable CMA T>::value,
365 template <
typename T>
366 std::enable_if_t<std::is_pod<T>::value, std::unique_ptr<std::decay_t<T>>>
374 template <
typename T>
375 std::enable_if_t<std::is_base_of<ByteRepresentable CMA std::decay_t<T>>::value,
382 template <
typename T>
383 std::enable_if_t<std::is_base_of<ByteRepresentable CMA std::decay_t<T>>::value,
390 return std::decay_t<T>::from_bytes_noalloc_const(ctx, v);
401 template <
typename T>
405 template <
typename T>
415 template <
typename T,
typename F>
427 : size(size), data(data) {}
430 assert(
false &&
"revisit this");
431 std::memcpy(v, data, size);
442 template <
typename DSM>
443 static std::unique_ptr<marshalled>
from_bytes(DSM
const*
const,
445 static_assert(std::is_same<DSM, void>::value && !std::is_same<DSM, void>::value,
446 "Do not deserialize into a marshalled. please.");
475 std::function<void(char const* const, std::size_t)>
480 void post_object(
const std::function<
void(
char const*
const, std::size_t)>& f,
481 const std::string& str);
483 template <
typename T,
typename V>
484 void post_object(
const std::function<
void(
char const*
const, std::size_t)>& f,
485 const std::pair<T, V>& pair) {
490 template <
typename... T>
492 const std::function<
void(
char const*
const, std::size_t)>& f,
497 template <
typename... T>
498 void post_object(
const std::function<
void(
char const*
const, std::size_t)>& f,
499 const std::tuple<T...>& t) {
501 std::apply([f](T... args) {
502 post_object_helper(f, args...);
507 void post_object(
const std::function<
void(
char const*
const, std::size_t)>& f,
508 const std::vector<bool>& vec);
510 template <
typename T>
511 void post_object(
const std::function<
void(
char const*
const, std::size_t)>& f,
512 const std::vector<T>& vec) {
513 whenmutilsdebug(
post_object(f, type_name<std::vector<T>>());)
int size = vec.size();
514 f((
char*)&size,
sizeof(size));
515 if(std::is_pod<T>::value) {
516 std::size_t size = vec.size() *
bytes_size(vec.back());
517 f((
char*)vec.data(), size);
519 for(
const auto& e : vec) {
525 template <
typename T>
526 void post_object(
const std::function<
void(
char const*
const, std::size_t)>& f,
527 const std::list<T>& list) {
528 int size = list.size();
529 f((
char*)&size,
sizeof(size));
530 for(
const auto& e : list) {
535 template <
typename T>
536 void post_object(
const std::function<
void(
char const*
const, std::size_t)>& f,
537 const std::set<T>& s) {
539 f((
char*)&size,
sizeof(size));
540 for(
const auto& a : s) {
545 template <
typename K,
typename V>
546 void post_object(
const std::function<
void(
char const*
const, std::size_t)>& f,
547 const std::map<K, V>& map) {
548 int size = map.size();
549 f((
char*)&size,
sizeof(size));
550 for(
const auto& pair : map) {
565 template <typename T, restrict(std::is_pod<T>::value)>
567 auto res = std::memcpy(v, &t,
sizeof(T));
573 std::size_t
to_bytes(
const std::vector<bool>& vec,
char* v);
575 template <
typename T>
576 std::size_t
to_bytes(
const std::vector<T>& vec,
char* v) {
578 std::size_t index = 0;
583 template <
typename T>
584 std::size_t
to_bytes(
const std::list<T>& list,
char* buffer) {
586 std::size_t offset = 0;
591 template <
typename T,
typename V>
592 std::size_t
to_bytes(
const std::pair<T, V>& pair,
char* buffer) {
593 std::size_t index = 0;
598 template <
typename... T>
599 std::size_t
to_bytes(
const std::tuple<T...>& tuple,
char* buffer) {
600 std::size_t index = 0;
605 template <
typename T>
606 std::size_t
to_bytes(
const std::set<T>& s,
char* _v) {
607 std::size_t index = 0;
613 template <
typename K,
typename V>
614 std::size_t
to_bytes(
const std::map<K, V>& m,
char* buffer) {
615 std::size_t index = 0;
626 template <
typename T>
629 ensure_registered(e, dm);
632 template <
typename L,
typename R>
634 ensure_registered(v.first, dm);
635 ensure_registered(v.second, dm);
638 template <
typename T>
641 ensure_registered(e, dm);
644 template <
typename T>
647 ensure_registered(e, dm);
654 template <
typename T>
655 std::unique_ptr<type_check<std::is_integral, T>>
657 return std::make_unique<T>(std::stoll(std::string{v, length}));
660 template <
typename T>
661 std::unique_ptr<type_check<std::is_floating_point, T>>
663 return std::make_unique<T>(std::stold(std::string{v, length}));
673 struct is_string<const std::string> : std::true_type {};
675 template <
typename T>
676 std::unique_ptr<type_check<is_string, T>>
678 return std::make_unique<T>(std::string{v, length});
682 template <
typename T>
683 std::enable_if_t<std::is_pod<T>::value, std::unique_ptr<std::decay_t<T>>>
685 using T2 = std::decay_t<T>;
687 auto t = std::make_unique<T2>(*(T2*)v);
694 template <
typename T>
698 using T2 = std::decay_t<T>;
702 template <
typename T>
706 using T2 = std::decay_t<T>;
716 template <
typename T,
typename U>
717 struct is_pair<std::pair<T, U>> : std::true_type {};
729 template <
typename T>
730 struct is_list<std::list<T>> : std::true_type {};
735 template <
typename K,
typename V>
736 struct is_map<std::map<K, V>> : std::true_type {};
738 template <
typename T>
742 return std::make_unique<T>(v);
745 template <
typename T>
753 template <
typename T>
756 int size = ((
int*)_v)[0];
757 const char* v = _v +
sizeof(int);
758 auto r = std::make_unique<std::set<typename T::key_type>>();
759 for(
int i = 0; i < size; ++i) {
760 auto e = from_bytes<typename T::key_type>(ctx, v);
767 template <
typename T>
774 template <
typename T>
777 using ft =
typename T::first_type;
778 using st =
typename T::second_type;
779 auto fst = from_bytes_noalloc<ft>(ctx, v);
780 return std::make_unique<std::pair<ft, st>>(
781 *fst, *from_bytes_noalloc<st>(ctx, v +
bytes_size(*fst)));
784 template <
typename L>
786 const char* buffer) {
787 using elem =
typename L::value_type;
788 int size = ((
int*)buffer)[0];
789 const char* buf_ptr = buffer +
sizeof(int);
790 std::unique_ptr<std::list<elem>> return_list{
new L()};
791 for(
int i = 0; i < size; ++i) {
794 return_list->push_back(*item);
796 return std::move(return_list);
799 template <
typename T>
806 template <
typename T>
810 template <
typename TupleType, std::
size_t N>
812 using ElementType =
typename std::tuple_element<N, TupleType>::type;
813 ElementType e(*from_bytes<ElementType>(ctx, v));
814 auto t = std::make_tuple<ElementType>(std::move(e));
815 if constexpr((N + 1) == std::tuple_size<TupleType>::value) {
818 return std::tuple_cat(t, from_bytes_helper<TupleType, N + 1>(ctx, v +
bytes_size(std::get<0>(t))));
822 template <
typename T>
824 return std::make_unique<T>(std::move(from_bytes_helper<T, 0>(ctx, v)));
828 template <
typename T>
829 std::enable_if_t<is_vector<T>::value, std::unique_ptr<T>>
832 const static std::string typenonce = type_name<T>();
833 const auto typenonce_size =
bytes_size(typenonce);
834 auto remote_string = *from_bytes<std::string>(ctx, v);
835 if(typenonce != remote_string) {
836 std::cout << typenonce << std::endl
838 std::cout << remote_string << std::endl;
840 assert(typenonce == v);
841 assert(typenonce == remote_string);
844 using member =
typename T::value_type;
845 if(std::is_same<bool, member>::value) {
846 return boolvec_from_bytes<T>(ctx, v);
847 }
else if(std::is_pod<member>::value && !std::is_same<bool, member>::value) {
848 member
const*
const start = (member*)(v +
sizeof(
int));
849 const int size = ((
int*)v)[0];
850 return std::unique_ptr<T>{
new T{start, start + size}};
852 int size = ((
int*)v)[0];
853 auto* v2 = v +
sizeof(int);
854 std::size_t accumulated_offset = 0;
855 std::unique_ptr<std::vector<member>> accum{
new T()};
856 for(
int i = 0; i < size; ++i) {
857 std::unique_ptr<member> item = from_bytes<member>(ctx, v2 + accumulated_offset);
859 accum->push_back(*item);
865 template <
typename T>
872 template <
typename T>
873 std::enable_if_t<is_map<T>::value, std::unique_ptr<T>>
875 using key_t =
typename T::key_type;
876 using value_t =
typename T::mapped_type;
877 int size = ((
int*)buffer)[0];
878 const char* buf_ptr = buffer +
sizeof(int);
880 auto new_map = std::make_unique<T>();
881 for(
int i = 0; i < size; ++i) {
886 new_map->emplace(*key, *value);
888 return std::move(new_map);
891 template <
typename T>
907 template <
typename T,
typename... Rest>
908 std::size_t
to_bytes_v(
char* buf,
const T& first,
const Rest&... rest) {
910 return size +
to_bytes_v(buf + size, rest...);
915 template <
typename T,
typename... Rest>
917 std::unique_ptr<T>& first, Rest&... rest) {
918 first = from_bytes<T>(dsm, buf);
925 template <
typename T,
typename... Rest>
934 template <
typename T,
typename... Rest>
941 template <
typename T,
typename... Rest>
943 char const*
const buf,
957 typename std::chrono::high_resolution_clock::time_point
start_time;
959 #ifdef SERIALIZATION_STATS 960 inline auto& get_dsr_info() {
965 template <
typename F,
typename R,
typename... Args>
967 const F& fun, std::function<R(Args...)>
const*
const) {
968 #ifdef SERIALIZATION_STATS 970 using namespace chrono;
971 static thread_local
auto deserialize_and_run_start = high_resolution_clock::now();
972 static thread_local
auto callfunc_time = deserialize_and_run_start;
973 struct on_function_end {
975 auto& r = get_dsr_info();
976 r.start_time = deserialize_and_run_start;
977 r.to_callfunc = callfunc_time - deserialize_and_run_start;
978 r.to_exit = high_resolution_clock::now() - deserialize_and_run_start;
982 deserialize_and_run_start = high_resolution_clock::now();
984 using result_t = std::result_of_t<F(Args...)>;
985 static_assert(std::is_same<result_t, R>::value,
986 "Error: function types mismatch.");
987 using fun_t = std::function<result_t(Args...)>;
990 std::is_convertible<F, fun_t>::value,
991 "Error: type mismatch on function and target deserialialized type");
995 std::get<0>(args_tuple) = dsm;
996 std::get<1>(args_tuple) = v;
999 using from_bytes_type = std::size_t (*)(DeserializationManager*,
const char*,
1001 from_bytes_type from_bytes_noalloc_concrete =
1002 [](DeserializationManager* d,
const char* c,
1007 callFunc(from_bytes_noalloc_concrete, args_tuple);
1010 [&fun](
const auto&,
const auto&,
auto&... ctx_ptrs) {
1011 #ifdef SERIALIZATION_STATS 1012 callfunc_time = high_resolution_clock::now();
1014 return fun(*ctx_ptrs...);
1019 template <
typename F>
1022 using fun_t = std::decay_t<decltype(convert(fun))>;
1023 return deserialize_and_run<F>(dsm, v, fun, (fun_t*)
nullptr);
std::enable_if_t< std::is_base_of< ByteRepresentable CMA T >::value, std::unique_ptr< T > > from_bytes(DeserializationManager *ctx, char const *v)
Calls T::from_bytes(ctx,v) when T is a ByteRepresentable.
std::size_t from_bytes_noalloc_v(DeserializationManager *, char const *const)
void post_object_helper(const std::function< void(char const *const, std::size_t)> &f, const T &... t)
DeserializationManager(RemoteDeserialization_v rv)
bool registered() const
checks to see if a context of type T has been registered with this DeserializationManager.
std::enable_if_t< std::is_base_of< ByteRepresentable CMA std::decay_t< T > >::value, context_ptr< T > > from_bytes_noalloc(DeserializationManager *ctx, const char *v, context_ptr< std::decay_t< T >>=context_ptr< std::decay_t< T >>{})
Calls T::from_bytes_noalloc(ctx,v) when T is a ByteRepresentable.
std::size_t from_bytes_v(DeserializationManager *, char const *const)
std::size_t bytes_size() const
the size of the marshalled representation of this object.
std::size_t to_bytes_v(char *)
For Serializing and Deserializing many objects at once.
virtual ~RemoteDeserializationContext()
virtual void post_object(const std::function< void(char const *const, std::size_t)> &) const =0
Pass a pointer to a buffer containing this class's marshalled representation into the function f...
A non-POD type which wishes to mark itself byte representable should extend this class.
virtual std::size_t to_bytes(char *v) const =0
Write this class's marshalled representation into the array found at v.
virtual std::size_t bytes_size() const =0
the size of the marshalled representation of this object.
std::unique_ptr< T, ContextDeleter< T > > context_ptr
std::chrono::nanoseconds to_exit
The manager for any RemoteDeserializationContexts.
T & mgr()
Lookup the context registered at this DeserializationManager whose type is T.
context_ptr< type_check< is_map, T > > from_bytes_noalloc(DeserializationManager *ctx, char const *v, context_ptr< T >=context_ptr< T >{})
RemoteDeserialization_v registered_v
Various registered managers.
RemoteDeserializationContext()
std::unique_ptr< type_check< std::is_integral, T > > from_string(DeserializationManager *, char const *v, std::size_t length)
std::size_t from_bytes_noalloc_v_nc(DeserializationManager *dsm, char *buf, context_ptr< T > &first, context_ptr< Rest > &... rest)
std::chrono::high_resolution_clock::time_point start_time
auto from_bytes_helper(DeserializationManager *ctx, char const *v)
const T & mgr() const
As the above, but const.
std::unique_ptr< T > boolvec_from_bytes(DeserializationManager *ctx, char const *v)
marshalled(decltype(size) size, decltype(data) data)
DeserializationManager(DeserializationManager &&o)
auto deserialize_and_run(DeserializationManager *dsm, char *v, const F &fun)
Calls mutils::from_bytes_noalloc<T>(ctx,v), dereferences the result, and passes it to fun...
The "marshalled" type is a wrapper for already-serialized types;.
std::vector< RemoteDeserializationContext_p > RemoteDeserialization_v
std::size_t to_bytes(char *v) const
Write this class's marshalled representation into the array found at v.
std::chrono::nanoseconds to_callfunc
std::enable_if_t< is_map< T >::value, std::unique_ptr< T > > from_bytes(DeserializationManager *ctx, char const *buffer)
virtual ~ByteRepresentable()
static std::unique_ptr< marshalled > from_bytes(DSM const *const, char const *const)
std::size_t bytes_size_helper(const T &... t)
Sums the size of each element of the tuple.
std::function< void(char const *const, std::size_t)> post_to_buffer(std::size_t &index, char *dest_buf)
Serialization is also implemented for the following STL types: vector pair string set...
If a class which implements ByteRepresentable requires a context in order to correctly deserialize...
DeserializationManager & register_ctx(RemoteDeserializationContext_p ctx)