ORE Studio 0.0.4
Loading...
Searching...
No Matches
reflectors.hpp
1/* -*- mode: c++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*-
2 *
3 * Copyright (C) 2025 Marco Craveiro <marco.craveiro@gmail.com>
4 *
5 * This program is free software; you can redistribute it and/or modify it under
6 * the terms of the GNU General Public License as published by the Free Software
7 * Foundation; either version 3 of the License, or (at your option) any later
8 * version.
9 *
10 * This program is distributed in the hope that it will be useful, but WITHOUT
11 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
12 * FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
13 * details.
14 *
15 * You should have received a copy of the GNU General Public License along with
16 * this program; if not, write to the Free Software Foundation, Inc., 51
17 * Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
18 *
19 */
20#ifndef ORES_UTILITY_RFL_REFLECTORS_HPP
21#define ORES_UTILITY_RFL_REFLECTORS_HPP
22
23#include <string>
24#include <chrono>
25#include <optional>
26#include <sstream>
27#include <cstdint>
28#include <stdexcept>
29#include <boost/uuid/uuid.hpp>
30#include <boost/uuid/uuid_io.hpp>
31#include <boost/lexical_cast.hpp>
32#include <boost/asio/ip/address.hpp>
33#include <rfl.hpp>
34#include "ores.utility/uuid/tenant_id.hpp"
35
36// Forward declarations for enum types that need custom reflectors
37// to avoid GCC 15 std::min/max type deduction errors in rfl's
38// internal enum range detection.
39namespace ores::utility::serialization {
40 enum class error_code : std::uint16_t;
41}
42namespace ores::comms::messaging {
43 enum class compression_type : std::uint8_t;
44 enum class message_type : std::uint16_t;
45}
46
47namespace rfl {
48
54template<>
55struct Reflector<boost::uuids::uuid> {
56 using ReflType = std::string;
57
58 static boost::uuids::uuid to(const ReflType& str) {
59 return boost::lexical_cast<boost::uuids::uuid>(str);
60 }
61
62 static ReflType from(const boost::uuids::uuid& v) {
63 return boost::lexical_cast<std::string>(v);
64 }
65};
66
72template<>
73struct Reflector<ores::utility::uuid::tenant_id> {
74 using ReflType = std::string;
75
76 static ores::utility::uuid::tenant_id to(const ReflType& str) {
78 if (!result) {
79 throw std::runtime_error("Invalid tenant_id: " + result.error());
80 }
81 return *result;
82 }
83
84 static ReflType from(const ores::utility::uuid::tenant_id& v) {
85 return v.to_string();
86 }
87};
88
95template<>
96struct Reflector<std::optional<boost::uuids::uuid>> {
97 using ReflType = std::optional<std::string>;
98
99 static std::optional<boost::uuids::uuid> to(const ReflType& str) {
100 if (!str.has_value()) {
101 return std::nullopt;
102 }
103 return boost::lexical_cast<boost::uuids::uuid>(str.value());
104 }
105
106 static ReflType from(const std::optional<boost::uuids::uuid>& v) {
107 if (!v.has_value()) {
108 return std::nullopt;
109 }
110 return boost::lexical_cast<std::string>(v.value());
111 }
112};
113
124template<>
125struct Reflector<std::chrono::system_clock::time_point> {
126 using ReflType = std::string;
127
136 static std::chrono::system_clock::time_point to(const ReflType& str) {
137 // Parse ISO 8601 format: "YYYY-MM-DD HH:MM:SS"
138 std::tm tm = {};
139 std::istringstream ss(str);
140 ss >> std::get_time(&tm, "%Y-%m-%d %H:%M:%S");
141
142 auto tp = std::chrono::system_clock::from_time_t(std::mktime(&tm));
143 return tp;
144 }
145
153 static ReflType from(const std::chrono::system_clock::time_point& v) {
154 // The time_point is already in the "system clock" which is UTC.
155 // We format it directly. The format specifiers are:
156 // %F -> YYYY-MM-DD
157 // %T -> HH:MM:SS
158 // We add 'Z' to explicitly mark it as UTC, which is best practice.
159 return std::format("{:%F %T}Z", v);
160 }
161};
162
168template<>
169struct Reflector<boost::asio::ip::address> {
170 using ReflType = std::string;
171
172 static boost::asio::ip::address to(const ReflType& str) {
173 return boost::asio::ip::make_address(str);
174 }
175
176 static ReflType from(const boost::asio::ip::address& v) {
177 return v.to_string();
178 }
179};
180
187template<>
188struct Reflector<ores::comms::messaging::compression_type> {
189 using ReflType = std::uint8_t;
190
191 static ores::comms::messaging::compression_type to(const ReflType& v) {
192 // Valid values: none=0, zlib=1, gzip=2, bzip2=3
193 if (v > 3) {
194 throw std::runtime_error("Invalid value for compression_type enum: " +
195 std::to_string(v));
196 }
197 return static_cast<ores::comms::messaging::compression_type>(v);
198 }
199
200 static ReflType from(const ores::comms::messaging::compression_type& v) {
201 return static_cast<ReflType>(v);
202 }
203};
204
211template<>
212struct Reflector<ores::utility::serialization::error_code> {
213 using ReflType = std::uint16_t;
214
215 static ores::utility::serialization::error_code to(const ReflType& v) {
216 // Valid values: none=0x0000 through payload_incomplete=0x0019
217 if (v > 0x0019) {
218 throw std::runtime_error("Invalid value for error_code enum: " +
219 std::to_string(v));
220 }
221 return static_cast<ores::utility::serialization::error_code>(v);
222 }
223
224 static ReflType from(const ores::utility::serialization::error_code& v) {
225 return static_cast<ReflType>(v);
226 }
227};
228
235template<>
236struct Reflector<ores::comms::messaging::message_type> {
237 using ReflType = std::uint16_t;
238
239 static ores::comms::messaging::message_type to(const ReflType& v) {
240 // Valid values: 0x0001 to 0x5FFF (max subsystem range)
241 // More specific validation is done at the protocol layer
242 if (v == 0 || v > 0x5FFF) {
243 throw std::runtime_error("Invalid value for message_type enum: " +
244 std::to_string(v));
245 }
246 return static_cast<ores::comms::messaging::message_type>(v);
247 }
248
249 static ReflType from(const ores::comms::messaging::message_type& v) {
250 return static_cast<ReflType>(v);
251 }
252};
253
254}
255
256#endif
STL namespace.
ORE Studio - Graphical interface and data management for Open Source Risk Engine.
Definition image.hpp:29
error_code
Error codes returned by service-layer request helpers.
Definition error_code.hpp:28
static std::chrono::system_clock::time_point to(const ReflType &str)
Parses a string into a time_point.
Definition reflectors.hpp:136
static ReflType from(const std::chrono::system_clock::time_point &v)
Formats a time_point into a string.
Definition reflectors.hpp:153
A strongly-typed wrapper around a UUID representing a tenant identifier.
Definition tenant_id.hpp:66
std::string to_string() const
Converts the tenant_id to its string representation.
Definition tenant_id.cpp:81
static std::expected< tenant_id, std::string > from_string(std::string_view str)
Creates a tenant_id from a string representation.
Definition tenant_id.cpp:57