Leosac  0.8.0
Open Source Access Control
ExtensibleSerializer.hpp
Go to the documentation of this file.
1 /*
2  Copyright (C) 2014-2016 Leosac
3 
4  This file is part of Leosac.
5 
6  Leosac is free software: you can redistribute it and/or modify
7  it under the terms of the GNU Affero General Public License as published by
8  the Free Software Foundation, either version 3 of the License, or
9  (at your option) any later version.
10 
11  Leosac is distributed in the hope that it will be useful,
12  but WITHOUT ANY WARRANTY; without even the implied warranty of
13  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14  GNU Affero General Public License for more details.
15 
16  You should have received a copy of the GNU Affero General Public License
17  along with this program. If not, see <http://www.gnu.org/licenses/>.
18 */
19 
20 #pragma once
21 
22 #include "tools/AssertCast.hpp"
23 #include <boost/type_index.hpp>
24 #include <map>
25 #include <mutex>
26 #include <type_traits>
27 
28 namespace Leosac
29 {
52 template <typename SerializedT, typename ObjectT, typename... AdditionalArgs>
54 {
55  public:
56  SerializedT serialize(const ObjectT &input, AdditionalArgs &&... args) const
57  {
58  std::lock_guard<decltype(mutex_)> lg(mutex_);
59 
60  auto type_index = boost::typeindex::type_id_runtime(input);
61  auto itr = serializers_.find(type_index);
62  if (itr != serializers_.end())
63  {
64  // Invoke the adapter we stored in the map.
65  // The wrapper will invoke the user-defined callable.
66  return itr->second(input, std::forward<AdditionalArgs>(args)...);
67  }
68  ASSERT_LOG(false, "Cannot find an appropriate serializer for " +
69  type_index.pretty_name());
70  return {};
71  }
72 
76  using SerializationCallable =
77  std::function<SerializedT(const ObjectT &, AdditionalArgs &&...)>;
78 
82  template <typename T, typename Callable>
83  void register_serializer(Callable &&callable)
84  {
85  static_assert(std::is_base_of<ObjectT, T>::value,
86  "T is not a subclass of ObjectT");
87 
88  std::lock_guard<decltype(mutex_)> lg(mutex_);
89  auto type_index = boost::typeindex::type_id<T>();
90  ASSERT_LOG(serializers_.count(type_index) == 0,
91  "Already got a serializer for this type of object.");
92 
93  // This is an adapter that wraps the user function. This allows us to
94  // store uniform function objects.
95  auto wrapper = [callable](const ObjectT &base_obj,
96  AdditionalArgs &&... args) -> SerializedT {
97  // This cast is safe, because we'll only pick this serializer when
98  // the typeid of the base type (ObjectT) match T.
99  const T &concrete_object = reinterpret_cast<const T &>(base_obj);
100 
101  // Extra runtime safety check.
102  const T &extra_safety = assert_cast<const T &>(base_obj);
103  ASSERT_LOG(std::addressof(concrete_object) ==
104  std::addressof(extra_safety),
105  "Memory error.");
106  return callable(concrete_object, std::forward<AdditionalArgs>(args)...);
107  };
108  serializers_[type_index] = wrapper;
109  };
110 
111  template <typename T>
113  {
114  std::lock_guard<decltype(mutex_)> lg(mutex_);
115 
116  auto type_index = boost::typeindex::type_id<T>();
117  serializers_.erase(type_index);
118  }
119 
120  private:
121  mutable std::recursive_mutex mutex_;
122  std::map<boost::typeindex::type_index, SerializationCallable> serializers_;
123 };
124 }
Leosac::ExtensibleSerializer::mutex_
std::recursive_mutex mutex_
Definition: ExtensibleSerializer.hpp:121
ASSERT_LOG
#define ASSERT_LOG(cond, msg)
Definition: log.hpp:190
Leosac::ExtensibleSerializer::serializers_
std::map< boost::typeindex::type_index, SerializationCallable > serializers_
Definition: ExtensibleSerializer.hpp:122
Leosac
This is the header file for a generated source file, GitSHA1.cpp.
Definition: APIStatusCode.hpp:22
Leosac::ExtensibleSerializer::SerializationCallable
std::function< SerializedT(const ObjectT &, AdditionalArgs &&...)> SerializationCallable
Callable type for serialization.
Definition: ExtensibleSerializer.hpp:77
Leosac::ExtensibleSerializer
Provides dynamic serializers management for a given object's hierarchy.
Definition: ExtensibleSerializer.hpp:53
Leosac::ExtensibleSerializer::unregister_serializer
void unregister_serializer()
Definition: ExtensibleSerializer.hpp:112
Leosac::ExtensibleSerializer::register_serializer
void register_serializer(Callable &&callable)
Register a serializer for T.
Definition: ExtensibleSerializer.hpp:83
Leosac::ExtensibleSerializer::serialize
SerializedT serialize(const ObjectT &input, AdditionalArgs &&... args) const
Definition: ExtensibleSerializer.hpp:56
AssertCast.hpp