File: indexed_rename_key_test.cpp

package info (click to toggle)
glaze 6.5.1-1
  • links: PTS, VCS
  • area: main
  • in suites: forky
  • size: 7,948 kB
  • sloc: cpp: 121,839; sh: 99; ansic: 26; makefile: 13
file content (151 lines) | stat: -rw-r--r-- 3,849 bytes parent folder | download | duplicates (2)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
#include <iostream>

#include "glaze/glaze.hpp"

namespace mylib
{
   enum struct MyEnum { First, Second };
   enum struct MyFlag { Yes, No };
} // namespace mylib

namespace glz
{
   template <>
   struct meta<mylib::MyEnum>
   {
      using enum mylib::MyEnum;
      static constexpr auto value = enumerate(First, Second);
   };

   template <>
   struct meta<mylib::MyFlag>
   {
      using enum mylib::MyFlag;
      static constexpr auto value = enumerate(Yes, No);
   };
} // namespace glz

// Test struct using automatic reflection
namespace test1
{
   struct AppContext
   {
      int num{};
      mylib::MyEnum e{};
      mylib::MyFlag f{};
   };
} // namespace test1

// Use indexed rename_key to automatically use enum type names as keys
template <>
struct glz::meta<test1::AppContext>
{
   template <size_t Index>
   static constexpr auto rename_key()
   {
      // Get the member type at this index
      using MemberType = glz::member_type_t<test1::AppContext, Index>;

      // If it's an enum, use the type name; otherwise use the member name
      if constexpr (std::is_enum_v<MemberType>) {
         return glz::name_v<MemberType>;
      }
      else {
         return glz::member_nameof<Index, test1::AppContext>;
      }
   }
};

// Test with custom short names (strip namespace)
namespace test2
{
   struct AppContext
   {
      int num{};
      mylib::MyEnum e{};
      mylib::MyFlag f{};
   };
} // namespace test2

template <>
struct glz::meta<test2::AppContext>
{
   template <size_t Index>
   static constexpr auto rename_key()
   {
      using MemberType = glz::member_type_t<test2::AppContext, Index>;

      if constexpr (std::is_enum_v<MemberType>) {
         // Strip namespace from enum type name
         constexpr auto full_name = glz::name_v<MemberType>;
         constexpr size_t pos = full_name.rfind("::");
         return (pos == std::string_view::npos) ? full_name : full_name.substr(pos + 2);
      }
      else {
         return glz::member_nameof<Index, test2::AppContext>;
      }
   }
};

// Test that it works with non-enum types too
namespace test3
{
   struct Point
   {
      double x{};
      double y{};
   };
} // namespace test3

// Transform all keys to uppercase
template <>
struct glz::meta<test3::Point>
{
   template <size_t Index>
   static constexpr auto rename_key()
   {
      constexpr auto name = glz::member_nameof<Index, test3::Point>;
      if constexpr (name == "x")
         return "X";
      else if constexpr (name == "y")
         return "Y";
      else
         return name;
   }
};

int main()
{
   std::cout << "=== Test 1: Enum type names (full) ===\n";
   test1::AppContext obj1{42, mylib::MyEnum::Second, mylib::MyFlag::Yes};
   std::string json1 = glz::write_json(obj1).value_or("error");
   std::cout << json1 << '\n';

   bool test1_pass = (json1 == R"({"num":42,"mylib::MyEnum":"Second","mylib::MyFlag":"Yes"})");
   std::cout << (test1_pass ? "✓ PASS" : "✗ FAIL") << "\n\n";

   std::cout << "=== Test 2: Enum type names (short) ===\n";
   test2::AppContext obj2{42, mylib::MyEnum::Second, mylib::MyFlag::Yes};
   std::string json2 = glz::write_json(obj2).value_or("error");
   std::cout << json2 << '\n';

   bool test2_pass = (json2 == R"({"num":42,"MyEnum":"Second","MyFlag":"Yes"})");
   std::cout << (test2_pass ? "✓ PASS" : "✗ FAIL") << "\n\n";

   std::cout << "=== Test 3: Generic key transformation ===\n";
   test3::Point obj3{3.14, 2.71};
   std::string json3 = glz::write_json(obj3).value_or("error");
   std::cout << json3 << '\n';

   bool test3_pass = (json3 == R"({"X":3.14,"Y":2.71})");
   std::cout << (test3_pass ? "✓ PASS" : "✗ FAIL") << "\n\n";

   if (test1_pass && test2_pass && test3_pass) {
      std::cout << "All tests passed!\n";
      return 0;
   }
   else {
      std::cout << "Some tests failed!\n";
      return 1;
   }
}