File indexing completed on 2025-01-18 09:27:42
0001
0002
0003
0004
0005
0006
0007
0008
0009 #pragma once
0010
0011 #include "Acts/Geometry/GeometryHierarchyMap.hpp"
0012 #include "Acts/Plugins/Json/ActsJson.hpp"
0013
0014 #include <stdexcept>
0015 #include <string>
0016 #include <type_traits>
0017
0018 namespace Acts {
0019
0020
0021
0022
0023
0024
0025
0026
0027
0028
0029
0030
0031
0032
0033
0034
0035 template <typename value_t,
0036 class decorator_t = void >
0037 class GeometryHierarchyMapJsonConverter {
0038 public:
0039 using Value = value_t;
0040 using Container = GeometryHierarchyMap<value_t>;
0041
0042
0043
0044
0045 GeometryHierarchyMapJsonConverter(std::string valueIdentifier)
0046 : m_valueIdentifier(std::move(valueIdentifier)) {
0047 if (m_valueIdentifier.empty()) {
0048 throw std::invalid_argument("Value identifier must be non-empty");
0049 }
0050 }
0051
0052
0053
0054
0055
0056
0057
0058 nlohmann::json toJson(const Container& container,
0059 const decorator_t* decorator) const;
0060
0061
0062
0063
0064
0065
0066 Container fromJson(const nlohmann::json& encoded) const;
0067
0068
0069
0070 static nlohmann::json encodeIdentifier(const GeometryIdentifier& id) {
0071 nlohmann::json encoded;
0072
0073 if (id.volume() != 0u) {
0074 encoded["volume"] = id.volume();
0075 }
0076 if (id.boundary() != 0u) {
0077 encoded["boundary"] = id.boundary();
0078 }
0079 if (id.layer() != 0u) {
0080 encoded["layer"] = id.layer();
0081 }
0082 if (id.approach() != 0u) {
0083 encoded["approach"] = id.approach();
0084 }
0085 if (id.sensitive() != 0u) {
0086 encoded["sensitive"] = id.sensitive();
0087 }
0088 if (id.extra() != 0u) {
0089 encoded["extra"] = id.extra();
0090 }
0091 return encoded;
0092 }
0093
0094
0095
0096
0097 static GeometryIdentifier decodeIdentifier(const nlohmann::json& encoded) {
0098 return GeometryIdentifier()
0099 .setVolume(encoded.value("volume", GeometryIdentifier::Value{0u}))
0100 .setBoundary(encoded.value("boundary", GeometryIdentifier::Value{0u}))
0101 .setLayer(encoded.value("layer", GeometryIdentifier::Value{0u}))
0102 .setApproach(encoded.value("approach", GeometryIdentifier::Value{0u}))
0103 .setSensitive(encoded.value("sensitive", GeometryIdentifier::Value{0u}))
0104 .setExtra(encoded.value("extra", GeometryIdentifier::Value{0u}));
0105 }
0106
0107 private:
0108 static constexpr const char* kHeaderKey = "acts-geometry-hierarchy-map";
0109 static constexpr const char* kEntriesKey = "entries";
0110
0111
0112 static constexpr int kFormatVersion = 0;
0113
0114 std::string m_valueIdentifier;
0115 };
0116
0117
0118
0119
0120
0121 template <typename T, class decorator_t>
0122 struct missing_specialization : std::false_type {};
0123
0124
0125 template <class T, class decorator_t>
0126 void decorateJson([[maybe_unused]] const decorator_t* decorator,
0127 [[maybe_unused]] const T& src,
0128 [[maybe_unused]] nlohmann::json& dest) {
0129
0130 static_assert(
0131 missing_specialization<T, decorator_t>::value,
0132 "Explicit specialization needed for each decorator_t and src T");
0133 }
0134 template <class T, class decorator_t>
0135 void decorateJson([[maybe_unused]] const decorator_t* decorator,
0136 [[maybe_unused]] const T* src,
0137 [[maybe_unused]] nlohmann::json& dest) {
0138
0139 static_assert(
0140 missing_specialization<T, decorator_t>::value,
0141 "Explicit specialization needed for each decorator_t and src T");
0142 }
0143
0144 template <typename value_t, class decorator_t>
0145 nlohmann::json GeometryHierarchyMapJsonConverter<value_t, decorator_t>::toJson(
0146 const Container& container,
0147 [[maybe_unused]] const decorator_t* decorator) const {
0148
0149 nlohmann::json encoded = nlohmann::json::object();
0150 encoded[kHeaderKey] = nlohmann::json::object();
0151 encoded[kHeaderKey]["format-version"] = kFormatVersion;
0152 encoded[kHeaderKey]["value-identifier"] = m_valueIdentifier;
0153
0154 nlohmann::json entries = nlohmann::json::array();
0155 for (std::size_t i = 0; i < container.size(); ++i) {
0156 auto entry = encodeIdentifier(container.idAt(i));
0157 auto value_json = nlohmann::json(container.valueAt(i));
0158 if constexpr (!std::is_same<decorator_t, void>::value) {
0159 decorateJson(decorator, container.valueAt(i), value_json);
0160 }
0161 entry["value"] = std::move(value_json);
0162 entries.push_back(std::move(entry));
0163 }
0164 encoded[kEntriesKey] = std::move(entries);
0165 return encoded;
0166 }
0167
0168 template <typename value_t, class decorator_t>
0169 auto GeometryHierarchyMapJsonConverter<value_t, decorator_t>::fromJson(
0170 const nlohmann::json& encoded) const -> Container {
0171
0172 auto header = encoded.find(kHeaderKey);
0173 if (header == encoded.end()) {
0174 throw std::invalid_argument(
0175 "Missing header entry in json geometry hierarchy map");
0176 }
0177 if (header->at("format-version").get<int>() != kFormatVersion) {
0178 throw std::invalid_argument(
0179 "Invalid format version in json geometry hierarchy map");
0180 }
0181 if (header->at("value-identifier").get<std::string>() != m_valueIdentifier) {
0182 throw std::invalid_argument(
0183 "Inconsistent value identifier in Json geometry hierarchy map");
0184 }
0185
0186 if (!encoded.contains(kEntriesKey)) {
0187 throw std::invalid_argument(
0188 "Missing entries in json geometry hierarchy map");
0189 }
0190 std::vector<std::pair<GeometryIdentifier, Value>> elements;
0191 for (const auto& entry : encoded.at(kEntriesKey)) {
0192 auto id = decodeIdentifier(entry);
0193 auto value = entry.at("value").get<Value>();
0194 elements.emplace_back(id, std::move(value));
0195 }
0196 return elements;
0197 }
0198
0199 }