ESPResSo
Extensible Simulation Package for Research on Soft Matter Systems
Loading...
Searching...
No Matches
packed_variant.hpp
Go to the documentation of this file.
1/*
2 * Copyright (C) 2020-2022 The ESPResSo project
3 *
4 * This file is part of ESPResSo.
5 *
6 * ESPResSo is free software: you can redistribute it and/or modify
7 * it under the terms of the GNU 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 * ESPResSo 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 General Public License for more details.
15 *
16 * You should have received a copy of the GNU General Public License
17 * along with this program. If not, see <http://www.gnu.org/licenses/>.
18 */
19
20#pragma once
21
22#include "ObjectId.hpp"
23#include "Variant.hpp"
24
28
29#include <boost/serialization/access.hpp>
30#include <boost/serialization/string.hpp>
31#include <boost/serialization/vector.hpp>
32
33#include <algorithm>
34#include <cstddef>
35#include <filesystem>
36#include <functional>
37#include <string>
38#include <unordered_map>
39#include <utility>
40#include <variant>
41#include <vector>
42
43namespace ScriptInterface {
44/**
45 * @brief Packed version of @ref Variant.
46 *
47 * When packing variants by @ref PackVisitor, objects of type
48 * @ref ObjectRef are packed as @ref ObjectId. Other than that,
49 * all other types allowed in @ref Variant also appear here.
50 */
52
53using PackedMap = std::vector<std::pair<std::string, PackedVariant>>;
54
55/**
56 * @brief Visitor that converts a Variant to a @ref PackedVariant.
57 *
58 * While packing, keeps track of all the @ref ObjectRef values that
59 * were encountered and stores them. This also keeps the
60 * referees alive if there are no other owners.
61 */
63private:
64 mutable std::unordered_map<ObjectId, ObjectRef> m_objects;
65
66public:
67 /** @brief Map of objects whose references were replaced by ids. */
68 auto const &objects() const { return m_objects; }
69
70 /* For the vector, we recurse into each element. */
71 PackedVariant operator()(const std::vector<Variant> &vec) const {
72 std::vector<PackedVariant> ret(vec.size());
73
74 std::ranges::transform(vec, ret.begin(), [this](const Variant &v) {
75 return std::visit(*this, v);
76 });
77
78 return ret;
79 }
80
81 /* For the map, we recurse into each element. */
82 template <typename K>
83 PackedVariant operator()(const std::unordered_map<K, Variant> &map) const {
84 std::unordered_map<K, PackedVariant> ret{};
85
86 for (auto const &[key, variant] : map) {
87 ret.emplace(key, std::visit(*this, variant));
88 }
89
90 return ret;
91 }
92
93 /* For object references we store the object reference, and
94 * replace it by just an id. */
96 auto const oid = ObjectId(so_ptr.get());
97 m_objects[oid] = so_ptr;
98
99 return oid;
100 }
101
102 /* Regular value are just verbatim copied into the result. */
103 template <class T> PackedVariant operator()(T &&val) const {
104 return std::forward<T>(val);
105 }
106};
107
108/**
109 * @brief Visitor that converts a @ref PackedVariant to a @ref Variant.
110 *
111 * ObjectId are replaced according to the provided object map.
112 */
114 std::unordered_map<ObjectId, ObjectRef> const &objects;
115
116 explicit UnpackVisitor(std::unordered_map<ObjectId, ObjectRef> const &objects)
117 : objects(objects) {}
118
119 /* For the vector, we recurse into each element. */
120 Variant operator()(const std::vector<PackedVariant> &vec) const {
121 std::vector<Variant> ret(vec.size());
122
123 std::ranges::transform(vec, ret.begin(), [this](const PackedVariant &v) {
124 return std::visit(*this, v);
125 });
126
127 return ret;
128 }
129
130 /* For the map, we recurse into each element. */
131 template <typename K>
132 Variant operator()(const std::unordered_map<K, PackedVariant> &map) const {
133 std::unordered_map<K, Variant> ret{};
134
135 for (auto const &[key, packed_variant] : map) {
136 ret.emplace(key, std::visit(*this, packed_variant));
137 }
138
139 return ret;
140 }
141
142 /* Regular value are just verbatim copied into the result. */
143 template <class T> Variant operator()(T &&val) const {
144 return std::forward<T>(val);
145 }
146
147 /* For object id's they are replaced by references according to the map. */
148 Variant operator()(const ObjectId &id) const { return objects.at(id); }
149};
150
151/**
152 * @brief Transform a Variant to a @ref PackedVariant
153 *
154 * Applies @ref PackVisitor to a @ref Variant.
155 *
156 * @param v Input @ref Variant
157 * @return Packed variant.
158 */
159inline PackedVariant pack(const Variant &v) {
160 return std::visit(PackVisitor(), v);
161}
162
163/**
164 * @brief Unpack a @ref PackedVariant.
165 *
166 * Applies @ref UnpackVisitor to a @ref Variant.
167 *
168 * @param v Packed @ref Variant.
169 * @param objects Map of ids to reference.
170 * @return Transformed variant.
171 */
173 std::unordered_map<ObjectId, ObjectRef> const &objects) {
174 return std::visit(UnpackVisitor(objects), v);
175}
176
177/**
178 * @brief Pack a @ref VariantMap.
179 *
180 * Applies @ref pack to every value in the
181 * input map.
182 */
183inline PackedMap pack(const VariantMap &v) {
184 PackedMap ret(v.size());
185
186 std::ranges::transform(v, ret.begin(), [](auto const &kv) {
187 return std::pair<std::string, PackedVariant>{kv.first, pack(kv.second)};
188 });
189
190 return ret;
191}
192
193/**
194 * @brief Unpack a @ref PackedMap.
195 *
196 * Applies @ref unpack to every value in the
197 * input map.
198 */
199inline VariantMap
201 std::unordered_map<ObjectId, ObjectRef> const &objects) {
203
204 std::ranges::transform(
205 v, std::inserter(ret, ret.end()),
206 [&objects](auto const &kv) -> std::pair<std::string, Variant> {
207 return {kv.first, unpack(kv.second, objects)};
208 });
209
210 return ret;
211}
212} // namespace ScriptInterface
cudaStream_t stream[1]
CUDA streams for parallel computing on CPU and GPU.
PackedVariant pack(const Variant &v)
Transform a Variant to a PackedVariant.
std::shared_ptr< ObjectHandle > ObjectRef
Definition Variant.hpp:121
std::unordered_map< std::string, Variant > VariantMap
Definition Variant.hpp:133
std::vector< std::pair< std::string, PackedVariant > > PackedMap
Variant unpack(const PackedVariant &v, std::unordered_map< ObjectId, ObjectRef > const &objects)
Unpack a PackedVariant.
Strongly typed integer type to hold a unique identifier for a ObjectHandle object,...
Definition ObjectId.hpp:37
Visitor that converts a Variant to a PackedVariant.
PackedVariant operator()(const ObjectRef &so_ptr) const
PackedVariant operator()(T &&val) const
PackedVariant operator()(const std::unordered_map< K, Variant > &map) const
PackedVariant operator()(const std::vector< Variant > &vec) const
auto const & objects() const
Map of objects whose references were replaced by ids.
Visitor that converts a PackedVariant to a Variant.
UnpackVisitor(std::unordered_map< ObjectId, ObjectRef > const &objects)
Variant operator()(const ObjectId &id) const
Variant operator()(const std::vector< PackedVariant > &vec) const
Variant operator()(T &&val) const
Variant operator()(const std::unordered_map< K, PackedVariant > &map) const
std::unordered_map< ObjectId, ObjectRef > const & objects
Recursive variant implementation.
Definition Variant.hpp:84