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/rfl/time_point_parser.hpp"
35#include "ores.utility/uuid/tenant_id.hpp"
36
37// Forward declarations for enum types that need custom reflectors
38// to avoid GCC 15 std::min/max type deduction errors in rfl's
39// internal enum range detection.
40namespace ores::utility::serialization {
41 enum class error_code : std::uint16_t;
42}
43namespace ores::comms::messaging {
44 enum class compression_type : std::uint8_t;
45 enum class message_type : std::uint16_t;
46}
47
48namespace rfl {
49
55template<>
56struct Reflector<boost::uuids::uuid> {
57 using ReflType = std::string;
58
59 static boost::uuids::uuid to(const ReflType& str) {
60 return boost::lexical_cast<boost::uuids::uuid>(str);
61 }
62
63 static ReflType from(const boost::uuids::uuid& v) {
64 return boost::lexical_cast<std::string>(v);
65 }
66};
67
73template<>
74struct Reflector<ores::utility::uuid::tenant_id> {
75 using ReflType = std::string;
76
77 static ores::utility::uuid::tenant_id to(const ReflType& str) {
79 if (!result) {
80 throw std::runtime_error("Invalid tenant_id: " + result.error());
81 }
82 return *result;
83 }
84
85 static ReflType from(const ores::utility::uuid::tenant_id& v) {
86 return v.to_string();
87 }
88};
89
96template<>
97struct Reflector<std::optional<boost::uuids::uuid>> {
98 using ReflType = std::optional<std::string>;
99
100 static std::optional<boost::uuids::uuid> to(const ReflType& str) {
101 if (!str.has_value()) {
102 return std::nullopt;
103 }
104 return boost::lexical_cast<boost::uuids::uuid>(str.value());
105 }
106
107 static ReflType from(const std::optional<boost::uuids::uuid>& v) {
108 if (!v.has_value()) {
109 return std::nullopt;
110 }
111 return boost::lexical_cast<std::string>(v.value());
112 }
113};
114
120template<>
121struct Reflector<std::chrono::year_month_day> {
122 using ReflType = std::string;
123
124 static std::chrono::year_month_day to(const ReflType& str) {
125 int y{}, m{}, d{};
126 char sep1{}, sep2{};
127 std::istringstream ss(str);
128 ss.imbue(std::locale::classic());
129 if (!(ss >> y >> sep1 >> m >> sep2 >> d) || sep1 != '-' || sep2 != '-' || !ss.eof())
130 throw std::runtime_error("Invalid date format: " + str);
131 auto ymd = std::chrono::year{y} /
132 std::chrono::month{static_cast<unsigned>(m)} /
133 std::chrono::day{static_cast<unsigned>(d)};
134 if (!ymd.ok())
135 throw std::runtime_error("Invalid date value: " + str);
136 return ymd;
137 }
138
139 static ReflType from(const std::chrono::year_month_day& v) {
140 return std::format("{:%Y-%m-%d}", v);
141 }
142};
143
149template<>
150struct Reflector<boost::asio::ip::address> {
151 using ReflType = std::string;
152
153 static boost::asio::ip::address to(const ReflType& str) {
154 return boost::asio::ip::make_address(str);
155 }
156
157 static ReflType from(const boost::asio::ip::address& v) {
158 return v.to_string();
159 }
160};
161
168template<>
169struct Reflector<ores::comms::messaging::compression_type> {
170 using ReflType = std::uint8_t;
171
172 static ores::comms::messaging::compression_type to(const ReflType& v) {
173 // Valid values: none=0, zlib=1, gzip=2, bzip2=3
174 if (v > 3) {
175 throw std::runtime_error("Invalid value for compression_type enum: " +
176 std::to_string(v));
177 }
178 return static_cast<ores::comms::messaging::compression_type>(v);
179 }
180
181 static ReflType from(const ores::comms::messaging::compression_type& v) {
182 return static_cast<ReflType>(v);
183 }
184};
185
192template<>
193struct Reflector<ores::utility::serialization::error_code> {
194 using ReflType = std::uint16_t;
195
196 static ores::utility::serialization::error_code to(const ReflType& v) {
197 // Valid values: none=0x0000 through payload_incomplete=0x0019
198 if (v > 0x0019) {
199 throw std::runtime_error("Invalid value for error_code enum: " +
200 std::to_string(v));
201 }
202 return static_cast<ores::utility::serialization::error_code>(v);
203 }
204
205 static ReflType from(const ores::utility::serialization::error_code& v) {
206 return static_cast<ReflType>(v);
207 }
208};
209
216template<>
217struct Reflector<ores::comms::messaging::message_type> {
218 using ReflType = std::uint16_t;
219
220 static ores::comms::messaging::message_type to(const ReflType& v) {
221 // Valid values: 0x0001 to 0x5FFF (max subsystem range)
222 // More specific validation is done at the protocol layer
223 if (v == 0 || v > 0x5FFF) {
224 throw std::runtime_error("Invalid value for message_type enum: " +
225 std::to_string(v));
226 }
227 return static_cast<ores::comms::messaging::message_type>(v);
228 }
229
230 static ReflType from(const ores::comms::messaging::message_type& v) {
231 return static_cast<ReflType>(v);
232 }
233};
234
235}
236
237#endif
STL namespace.
ORE Studio - Graphical interface and data management for Open Source Risk Engine.
Definition pricing_engine_type.hpp:27
error_code
Error codes returned by service-layer request helpers.
Definition error_code.hpp:28
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