From 1cbd92dc577ce8888405175d3e936fda96fb905c Mon Sep 17 00:00:00 2001
From: Felix Weiglhofer <weiglhofer@fias.uni-frankfurt.de>
Date: Fri, 2 Jun 2023 12:15:24 +0000
Subject: [PATCH] algo: Allow reading enums as strings from YAML.

---
 algo/base/RecoParams.h      | 30 ++++++++++++++++++++++++++----
 algo/base/config/Yaml.h     | 13 ++++++++++++-
 algo/params/RecoParams.yaml |  8 +++-----
 3 files changed, 41 insertions(+), 10 deletions(-)

diff --git a/algo/base/RecoParams.h b/algo/base/RecoParams.h
index ed9a7e79f2..184e78a1e5 100644
--- a/algo/base/RecoParams.h
+++ b/algo/base/RecoParams.h
@@ -8,6 +8,7 @@
 
 #include "Prelude.h"
 #include "config/Property.h"
+#include "util/SerializableEnum.h"
 
 namespace cbm::algo
 {
@@ -16,12 +17,12 @@ namespace cbm::algo
    * @brief RecoParams contains all parameters to configure reconstruction
    */
   struct RecoParams {
-    enum SortMode : u8
+    enum class SortMode : u8
     {
-      SortBlockSort        = 0,
-      SortCUBSegmentedSort = 1,
+      BlockSort        = 0,
+      CUBSegmentedSort = 1,
     };
-    enum UnpackMode : u8
+    enum class UnpackMode : u8
     {
       CPU,
       XPU,
@@ -96,6 +97,27 @@ namespace cbm::algo
     static constexpr auto Properties = std::make_tuple(config::Property(&RecoParams::sts, "sts", "STS reco settings"));
   };
 
+  template<>
+  struct EnumIsSerializable<RecoParams::SortMode> : std::true_type {
+  };
+
+  template<>
+  inline const EnumDict_t<RecoParams::SortMode>& EnumDict<RecoParams::SortMode> = {
+    {"BlockSort", RecoParams::SortMode::BlockSort},
+    {"CUBSegmentedSort", RecoParams::SortMode::CUBSegmentedSort},
+  };
+
+  template<>
+  struct EnumIsSerializable<RecoParams::UnpackMode> : std::true_type {
+  };
+
+  template<>
+  inline const EnumDict_t<RecoParams::UnpackMode>& EnumDict<RecoParams::UnpackMode> = {
+    {"CPU", RecoParams::UnpackMode::CPU},
+    {"XPU", RecoParams::UnpackMode::XPU},
+  };
+
+
 };  // namespace cbm::algo
 
 #endif  // CBM_ALGO_BASE_RECOPARAMS_H
diff --git a/algo/base/config/Yaml.h b/algo/base/config/Yaml.h
index 1697a23be1..cbdd7a2f9a 100644
--- a/algo/base/config/Yaml.h
+++ b/algo/base/config/Yaml.h
@@ -13,6 +13,7 @@
 #include "BaseTypes.h"
 #include "Prelude.h"
 #include "Property.h"
+#include "util/SerializableEnum.h"
 
 namespace cbm::algo::config
 {
@@ -28,10 +29,15 @@ namespace cbm::algo::config
   {
     using Type = std::remove_cv_t<std::remove_reference_t<T>>;
 
+    static_assert(!IsEnum<T> || EnumIsSerializable<Type>::value, "Enum must be serializable");
+
+
     // TODO: error handling
     if constexpr (IsBaseType<Type>) { return node.as<Type>(); }
     else if constexpr (IsEnum<Type>) {
-      return static_cast<Type>(node.as<std::underlying_type_t<Type>>());
+      std::optional<T> maybet = FromString<T>(node.as<std::string>());
+      if (!maybet) { throw std::runtime_error(fmt::format("Invalid enum value: {}", node.as<std::string>())); }
+      return *maybet;
     }
     else if constexpr (IsVector<Type>) {
       Type vector;
@@ -117,7 +123,12 @@ namespace cbm::algo::config
     template<typename T>
     void DoDump(const T& object, YAML::Emitter& ss, std::optional<YAML::EMITTER_MANIP> formatEntries = {})
     {
+      static_assert(!IsEnum<T> || EnumIsSerializable<T>::value, "Enum must be serializable");
+
       if constexpr (IsBaseType<T>) { ss << object; }
+      else if constexpr (IsEnum<T>) {
+        ss << ToString<T>(object);
+      }
       else if constexpr (IsVector<T> || IsArray<T>) {
         ss << YAML::BeginSeq;
         for (const auto& element : object) {
diff --git a/algo/params/RecoParams.yaml b/algo/params/RecoParams.yaml
index b69e5db5ea..e23a50bc39 100644
--- a/algo/params/RecoParams.yaml
+++ b/algo/params/RecoParams.yaml
@@ -1,10 +1,8 @@
 ---
 sts:
-  # 0: block_sort, 1: cub
-  digiSortMode: 0
-  clusterSortMode: 0
-  # 0: cpu, 1: xpu
-  unpackMode: 0
+  digiSortMode: BlockSort
+  clusterSortMode: BlockSort
+  unpackMode: CPU
   findClustersMultiKernels: 1
   timeCutDigiAbs: -1
   timeCutDigiSig: 3
-- 
GitLab