File indexing completed on 2025-09-17 08:21:26
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 explicit 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 .withVolume(encoded.value("volume", GeometryIdentifier::Value{0u}))
0100 .withBoundary(encoded.value("boundary", GeometryIdentifier::Value{0u}))
0101 .withLayer(encoded.value("layer", GeometryIdentifier::Value{0u}))
0102 .withApproach(encoded.value("approach", GeometryIdentifier::Value{0u}))
0103 .withSensitive(
0104 encoded.value("sensitive", GeometryIdentifier::Value{0u}))
0105 .withExtra(encoded.value("extra", GeometryIdentifier::Value{0u}));
0106 }
0107
0108 private:
0109 static constexpr const char* kHeaderKey = "acts-geometry-hierarchy-map";
0110 static constexpr const char* kEntriesKey = "entries";
0111
0112
0113 static constexpr int kFormatVersion = 0;
0114
0115 std::string m_valueIdentifier;
0116 };
0117
0118
0119
0120
0121
0122 template <typename T, class decorator_t>
0123 struct missing_specialization : std::false_type {};
0124
0125
0126 template <class T, class decorator_t>
0127 void decorateJson([[maybe_unused]] const decorator_t* decorator,
0128 [[maybe_unused]] const T& src,
0129 [[maybe_unused]] nlohmann::json& dest) {
0130
0131 static_assert(
0132 missing_specialization<T, decorator_t>::value,
0133 "Explicit specialization needed for each decorator_t and src T");
0134 }
0135 template <class T, class decorator_t>
0136 void decorateJson([[maybe_unused]] const decorator_t* decorator,
0137 [[maybe_unused]] const T* src,
0138 [[maybe_unused]] nlohmann::json& dest) {
0139
0140 static_assert(
0141 missing_specialization<T, decorator_t>::value,
0142 "Explicit specialization needed for each decorator_t and src T");
0143 }
0144
0145 template <typename value_t, class decorator_t>
0146 nlohmann::json GeometryHierarchyMapJsonConverter<value_t, decorator_t>::toJson(
0147 const Container& container,
0148 [[maybe_unused]] const decorator_t* decorator) const {
0149
0150 nlohmann::json encoded = nlohmann::json::object();
0151 encoded[kHeaderKey] = nlohmann::json::object();
0152 encoded[kHeaderKey]["format-version"] = kFormatVersion;
0153 encoded[kHeaderKey]["value-identifier"] = m_valueIdentifier;
0154
0155 nlohmann::json entries = nlohmann::json::array();
0156 for (std::size_t i = 0; i < container.size(); ++i) {
0157 auto entry = encodeIdentifier(container.idAt(i));
0158 auto value_json = nlohmann::json(container.valueAt(i));
0159 if constexpr (!std::is_same_v<decorator_t, void>) {
0160 decorateJson(decorator, container.valueAt(i), value_json);
0161 }
0162 entry["value"] = std::move(value_json);
0163 entries.push_back(std::move(entry));
0164 }
0165 encoded[kEntriesKey] = std::move(entries);
0166 return encoded;
0167 }
0168
0169 template <typename value_t, class decorator_t>
0170 auto GeometryHierarchyMapJsonConverter<value_t, decorator_t>::fromJson(
0171 const nlohmann::json& encoded) const -> Container {
0172
0173 auto header = encoded.find(kHeaderKey);
0174 if (header == encoded.end()) {
0175 throw std::invalid_argument(
0176 "Missing header entry in json geometry hierarchy map");
0177 }
0178 if (header->at("format-version").get<int>() != kFormatVersion) {
0179 throw std::invalid_argument(
0180 "Invalid format version in json geometry hierarchy map");
0181 }
0182 if (header->at("value-identifier").get<std::string>() != m_valueIdentifier) {
0183 throw std::invalid_argument(
0184 "Inconsistent value identifier in Json geometry hierarchy map");
0185 }
0186
0187 if (!encoded.contains(kEntriesKey)) {
0188 throw std::invalid_argument(
0189 "Missing entries in json geometry hierarchy map");
0190 }
0191 std::vector<std::pair<GeometryIdentifier, Value>> elements;
0192 for (const auto& entry : encoded.at(kEntriesKey)) {
0193 auto id = decodeIdentifier(entry);
0194 auto value = entry.at("value").get<Value>();
0195 elements.emplace_back(id, std::move(value));
0196 }
0197 return elements;
0198 }
0199
0200 }