cxxmcp 1.2.4
C++ MCP SDK
Loading...
Searching...
No Matches
reflect.hpp
Go to the documentation of this file.
1// Copyright (c) 2025 [caomengxuan666]
2
3#pragma once
4
18
19#include <cstdint>
20#include <map>
21#include <optional>
22#include <string>
23#include <string_view>
24#include <tuple>
25#include <type_traits>
26#include <variant>
27#include <vector>
28
31
32namespace mcp::protocol {
33
34// ---------------------------------------------------------------------------
35// Field descriptor
36// ---------------------------------------------------------------------------
37
40template <typename Struct, typename Field>
42 const char* wire_name;
43 Field Struct::* pointer;
44 using field_type = Field;
45 using struct_type = Struct;
46 core::Result<core::Unit> (*post_validate)(const Field&) = nullptr;
47 bool absent_as_monostate = false;
48 bool absent_as_default = false;
49};
50
55template <typename Struct>
57 Json Struct::* pointer;
58 std::vector<std::string> own_keys;
59 using field_type = Json;
60 using struct_type = Struct;
61};
62
65template <typename Struct, typename Field>
67 const char* wire_name;
68 Field Struct::* pointer;
69 using field_type = Field;
70 using struct_type = Struct;
71};
72
74template <typename Struct, typename Field>
75constexpr FieldDescriptor<Struct, Field> field(const char* wire_name,
76 Field Struct::* pointer) {
77 return {wire_name, pointer, nullptr};
78}
79
81template <typename Struct, typename Field>
83 const char* wire_name, Field Struct::* pointer,
84 core::Result<core::Unit> (*validator)(const Field&)) {
85 return {wire_name, pointer, validator};
86}
87
89template <typename Struct>
91 std::vector<std::string> own_keys) {
92 return {pointer, std::move(own_keys)};
93}
94
96template <typename Struct, typename Field>
98 const char* wire_name, Field Struct::* pointer) {
99 return {wire_name, pointer};
100}
101
102// ---------------------------------------------------------------------------
103// Utility type traits
104// ---------------------------------------------------------------------------
105
107template <typename T>
108struct is_optional : std::false_type {};
109
110template <typename T>
111struct is_optional<std::optional<T>> : std::true_type {};
112
113template <typename T>
114inline constexpr bool is_optional_v = is_optional<T>::value;
115
117template <typename T>
118struct is_nullable_variant : std::false_type {};
119
120template <typename... Ts>
121struct is_nullable_variant<std::variant<Ts...>>
122 : std::disjunction<std::is_same<Ts, std::monostate>...> {};
123
124template <typename T>
125inline constexpr bool is_nullable_variant_v = is_nullable_variant<T>::value;
126
133template <typename Struct, typename Field>
135 const char* wire_name, Field Struct::* pointer) {
136 static_assert(is_nullable_variant_v<Field>,
137 "nullable_field requires a std::variant containing "
138 "std::monostate");
139 return {wire_name, pointer, nullptr, true};
140}
141
144template <typename Struct, typename Field>
146 const char* wire_name, Field Struct::* pointer) {
147 return {wire_name, pointer, nullptr, false, true};
148}
149
151template <typename T, typename = void>
152struct has_extensions_member : std::false_type {};
153
154template <typename T>
156 T, std::void_t<decltype(std::declval<T>().extensions)>>
157 : std::bool_constant<
158 std::is_same_v<decltype(std::declval<T>().extensions), Json>> {};
159
160template <typename T>
161inline constexpr bool has_extensions_member_v = has_extensions_member<T>::value;
162
163// ---------------------------------------------------------------------------
164// SFINAE: detect optional known_keys() on Reflect<T>
165// ---------------------------------------------------------------------------
166
167namespace detail {
168template <typename T, typename = void>
169struct has_intrusive_fields : std::false_type {};
170
171template <typename T>
172struct has_intrusive_fields<T, std::void_t<decltype(T::cxxmcp_fields())>>
173 : std::true_type {};
174
175template <typename T>
176inline constexpr bool has_intrusive_fields_v = has_intrusive_fields<T>::value;
177
178template <typename T, typename = void>
179struct has_known_keys : std::false_type {};
180
181template <typename T>
182struct has_known_keys<T, std::void_t<decltype(T::known_keys())>>
183 : std::true_type {};
184
187template <typename S, typename F>
188void push_wire_name(std::vector<std::string>& keys,
189 const FieldDescriptor<S, F>& fd) {
190 keys.push_back(fd.wire_name);
191}
192template <typename S, typename F>
193void push_wire_name(std::vector<std::string>& keys,
194 const DeserializeOnlyField<S, F>& fd) {
195 keys.push_back(fd.wire_name);
196}
197template <typename S>
198void push_wire_name(std::vector<std::string>&, const ExtensionsField<S>&) {}
199} // namespace detail
200
201// ---------------------------------------------------------------------------
202// Primary Reflect template (unspecialized types are not reflectable)
203// ---------------------------------------------------------------------------
204
208template <typename T>
209struct Reflect {
210 static constexpr bool defined = false;
211};
212
213template <typename T>
214auto reflect_fields();
215
219template <typename T>
220std::vector<std::string> extract_known_keys() {
221 std::vector<std::string> keys;
222 std::apply(
223 [&keys](const auto&... fds) { (detail::push_wire_name(keys, fds), ...); },
224 reflect_fields<T>());
225 return keys;
226}
227
228// ---------------------------------------------------------------------------
229// Type trait: detect whether a type has a Reflect specialization
230// ---------------------------------------------------------------------------
231
233template <typename T, typename = void>
234struct has_reflect : std::false_type {};
235
236template <typename T>
237struct has_reflect<T, std::void_t<decltype(Reflect<T>::defined)>>
238 : std::bool_constant<Reflect<T>::defined ||
239 detail::has_intrusive_fields_v<T>> {};
240
241template <typename T>
242inline constexpr bool has_reflect_v = has_reflect<T>::value;
243
249template <typename T>
251 if constexpr (Reflect<T>::defined) {
252 return Reflect<T>::fields();
253 } else {
254 return T::cxxmcp_fields();
255 }
256}
257
258// Forward declarations for reflect_to_json / reflect_from_json.
259template <typename T>
260Json reflect_to_json(const T& obj);
261template <typename T>
262core::Result<T> reflect_from_json(const Json& json);
263
264// ---------------------------------------------------------------------------
265// JsonFieldTraits: primary template for scalars (int64, double, bool)
266// ---------------------------------------------------------------------------
267
273template <typename T, typename Enable = void>
275 static void serialize(Json& json, const char* key, const T& value) {
276 json[key] = value;
277 }
278
279 static bool deserialize(const Json& json, const char* key, T& target) {
280 if (!json.contains(key)) {
281 return false;
282 }
283 const auto& val = json.at(key);
284 if constexpr (std::is_same_v<T, bool>) {
285 if (!val.is_boolean()) {
286 return false;
287 }
288 } else if constexpr (std::is_floating_point_v<T>) {
289 if (!val.is_number()) {
290 return false;
291 }
292 } else if constexpr (std::is_integral_v<T>) {
293 if (!val.is_number_integer()) {
294 return false;
295 }
296 }
297 target = val.get<T>();
298 return true;
299 }
300};
301
303template <typename T>
304struct JsonFieldTraits<T, std::enable_if_t<has_reflect_v<T>>> {
305 static void serialize(Json& json, const char* key, const T& value) {
306 json[key] = reflect_to_json(value);
307 }
308
309 static bool deserialize(const Json& json, const char* key, T& target) {
310 if (!json.contains(key)) {
311 return false;
312 }
313 auto value = reflect_from_json<T>(json.at(key));
314 if (!value) {
315 return false;
316 }
317 target = std::move(*value);
318 return true;
319 }
320};
321
322// ---------------------------------------------------------------------------
323// Traits for std::string (omit empty on serialize, no default on deserialize)
324// ---------------------------------------------------------------------------
325
326template <>
327struct JsonFieldTraits<std::string> {
328 static void serialize(Json& json, const char* key, const std::string& value) {
329 json[key] = value;
330 }
331
332 static bool deserialize(const Json& json, const char* key,
333 std::string& target) {
334 if (!json.contains(key)) {
335 return false;
336 }
337 if (!json.at(key).is_string()) {
338 return false;
339 }
340 target = json.at(key).get<std::string>();
341 return true;
342 }
343};
344
345// ---------------------------------------------------------------------------
346// Traits for Json (raw JSON passthrough)
347// ---------------------------------------------------------------------------
348
349template <>
351 static void serialize(Json& json, const char* key, const Json& value) {
352 if (!value.is_null() && !value.empty()) {
353 json[key] = value;
354 }
355 }
356
357 static bool deserialize(const Json& json, const char* key, Json& target) {
358 if (!json.contains(key)) {
359 return false;
360 }
361 target = json.at(key);
362 return true;
363 }
364};
365
366template <>
368 static void serialize(Json& json, const char* key, IconTheme value) {
369 json[key] = std::string(icon_theme_to_string(value));
370 }
371
372 static bool deserialize(const Json& json, const char* key,
373 IconTheme& target) {
374 if (!json.contains(key) || !json.at(key).is_string()) {
375 return false;
376 }
377 auto value = icon_theme_from_string(json.at(key).get<std::string>());
378 if (!value.has_value()) {
379 return false;
380 }
381 target = *value;
382 return true;
383 }
384};
385
386// ---------------------------------------------------------------------------
387// Note: JsonFieldTraits<Icon> and JsonFieldTraits<std::vector<Icon>> are no
388// longer needed. Icon uses Reflect<Icon> (in types_reflect.hpp) via the
389// generic vector<T> trait and reflect_to_json/reflect_from_json.
390// ---------------------------------------------------------------------------
391
392// ---------------------------------------------------------------------------
393// Traits for std::optional<T>
394// ---------------------------------------------------------------------------
395
396template <typename T>
397struct JsonFieldTraits<std::optional<T>> {
398 static void serialize(Json& json, const char* key,
399 const std::optional<T>& value) {
400 if (value.has_value()) {
401 JsonFieldTraits<T>::serialize(json, key, *value);
402 }
403 }
404
405 static bool deserialize(const Json& json, const char* key,
406 std::optional<T>& target) {
407 if (!json.contains(key)) {
408 return true; // optional: missing is OK
409 }
410 T inner{};
411 if (!JsonFieldTraits<T>::deserialize(json, key, inner)) {
412 return false;
413 }
414 target = std::move(inner);
415 return true;
416 }
417};
418
419// ---------------------------------------------------------------------------
420// Traits for std::optional<Json> (e.g. `_meta`)
421// ---------------------------------------------------------------------------
422
423template <>
424struct JsonFieldTraits<std::optional<Json>> {
425 static void serialize(Json& json, const char* key,
426 const std::optional<Json>& value) {
427 if (value.has_value() && !value->is_null()) {
428 json[key] = *value;
429 }
430 }
431
432 static bool deserialize(const Json& json, const char* key,
433 std::optional<Json>& target) {
434 if (!json.contains(key)) {
435 return true;
436 }
437 target = json.at(key);
438 return true;
439 }
440};
441
442// ---------------------------------------------------------------------------
443// Traits for std::vector<T> (omit empty, recurse elements)
444// ---------------------------------------------------------------------------
445
446template <typename T>
447struct JsonFieldTraits<std::vector<T>> {
448 static void serialize(Json& json, const char* key,
449 const std::vector<T>& value) {
450 if (value.empty()) {
451 return;
452 }
453 json[key] = Json::array();
454 for (const auto& item : value) {
455 Json element = Json::object();
456 JsonFieldTraits<T>::serialize(element, "_item", item);
457 json[key].push_back(std::move(element["_item"]));
458 }
459 }
460
461 static bool deserialize(const Json& json, const char* key,
462 std::vector<T>& target) {
463 if (!json.contains(key)) {
464 return true; // missing vector = empty
465 }
466 if (!json.at(key).is_array()) {
467 return false;
468 }
469 target.clear();
470 target.reserve(json.at(key).size());
471 for (const auto& item : json.at(key)) {
472 T element{};
473 // For nested DTOs, pass the item directly
474 if constexpr (has_reflect_v<T>) {
475 auto result = reflect_from_json<T>(item);
476 if (!result) {
477 return false;
478 }
479 target.push_back(std::move(*result));
480 } else {
481 // For scalars, extract directly
482 element = item.get<T>();
483 target.push_back(std::move(element));
484 }
485 }
486 return true;
487 }
488};
489
490// ---------------------------------------------------------------------------
491// Traits for std::vector<std::string>
492// ---------------------------------------------------------------------------
493
494template <>
495struct JsonFieldTraits<std::vector<std::string>> {
496 static void serialize(Json& json, const char* key,
497 const std::vector<std::string>& value) {
498 if (value.empty()) {
499 return;
500 }
501 json[key] = value;
502 }
503
504 static bool deserialize(const Json& json, const char* key,
505 std::vector<std::string>& target) {
506 if (!json.contains(key)) {
507 return true;
508 }
509 if (!json.at(key).is_array()) {
510 return false;
511 }
512 target.reserve(json.at(key).size());
513 for (const auto& item : json.at(key)) {
514 if (!item.is_string()) {
515 return false;
516 }
517 target.push_back(item.get<std::string>());
518 }
519 return true;
520 }
521};
522
523// ---------------------------------------------------------------------------
524// Traits for std::map<std::string, std::string> (string-to-string maps)
525// ---------------------------------------------------------------------------
526
527template <>
528struct JsonFieldTraits<std::map<std::string, std::string>> {
529 static void serialize(Json& json, const char* key,
530 const std::map<std::string, std::string>& value) {
531 if (value.empty()) {
532 return;
533 }
534 json[key] = Json::object();
535 for (const auto& [k, v] : value) {
536 json[key][k] = v;
537 }
538 }
539
540 static bool deserialize(const Json& json, const char* key,
541 std::map<std::string, std::string>& target) {
542 if (!json.contains(key)) {
543 return true; // missing map = empty
544 }
545 if (!json.at(key).is_object()) {
546 return false;
547 }
548 target.clear();
549 for (const auto& [k, v] : json.at(key).items()) {
550 if (!v.is_string()) {
551 return false;
552 }
553 target[k] = v.get<std::string>();
554 }
555 return true;
556 }
557};
558
559// ---------------------------------------------------------------------------
560// Traits for std::variant<std::monostate, std::int64_t> (nullable int)
561// ---------------------------------------------------------------------------
562
563template <>
564struct JsonFieldTraits<std::variant<std::monostate, std::int64_t>> {
565 static void serialize(Json& json, const char* key,
566 const std::variant<std::monostate, std::int64_t>& val) {
567 if (std::holds_alternative<std::int64_t>(val)) {
568 json[key] = std::get<std::int64_t>(val);
569 } else {
570 json[key] = nullptr;
571 }
572 }
573
574 static bool deserialize(const Json& json, const char* key,
575 std::variant<std::monostate, std::int64_t>& target) {
576 if (!json.contains(key)) {
577 target = std::monostate{};
578 return true;
579 }
580 if (json.at(key).is_null()) {
581 target = std::monostate{};
582 return true;
583 }
584 if (json.at(key).is_number_integer()) {
585 target = json.at(key).get<std::int64_t>();
586 return true;
587 }
588 return false;
589 }
590};
591
592// ---------------------------------------------------------------------------
593// Traits for std::variant<int64_t, std::string> (RequestId / ProgressToken)
594// ---------------------------------------------------------------------------
595
596template <>
597struct JsonFieldTraits<std::variant<std::int64_t, std::string>> {
598 static void serialize(Json& json, const char* key,
599 const std::variant<std::int64_t, std::string>& val) {
600 json[key] = std::visit([](const auto& v) { return Json(v); }, val);
601 }
602
603 static bool deserialize(const Json& json, const char* key,
604 std::variant<std::int64_t, std::string>& target) {
605 if (!json.contains(key)) {
606 return false;
607 }
608 const auto& val = json.at(key);
609 if (val.is_number_integer()) {
610 target = val.get<std::int64_t>();
611 return true;
612 }
613 if (val.is_string()) {
614 target = val.get<std::string>();
615 return true;
616 }
617 return false;
618 }
619};
620
621// ---------------------------------------------------------------------------
622// Generic fold-expression helpers for serialize/deserialize one field
623// ---------------------------------------------------------------------------
624
626template <typename Struct, typename Field>
627void serialize_one(Json& json, const Struct& obj,
629 JsonFieldTraits<Field>::serialize(json, fd.wire_name, obj.*(fd.pointer));
630}
631
633template <typename Struct, typename Field>
634void serialize_one(Json&, const Struct&,
636
638template <typename Struct>
639void serialize_one(Json& json, const Struct& obj,
640 const ExtensionsField<Struct>& fd) {
641 append_json_extensions(json, obj.*(fd.pointer));
642}
643
648template <typename Struct, typename Field>
649bool deserialize_one(const Json& json, Struct& obj,
651 core::Result<core::Unit>& status) {
652 const bool present = json.contains(fd.wire_name);
653 if (!present) {
654 if (fd.absent_as_default) {
655 obj.*(fd.pointer) = Field{};
656 status = core::Unit{};
657 return true;
658 }
659 // For optional types, absent is fine. Nullable variants must opt in
660 // explicitly with nullable_field(); otherwise they are required fields.
661 if constexpr (is_optional_v<Field>) {
662 return true;
663 }
664 if constexpr (is_nullable_variant_v<Field>) {
665 if (fd.absent_as_monostate) {
666 obj.*(fd.pointer) = Field{std::monostate{}};
667 status = core::Unit{};
668 return true;
669 }
670 }
671 status = mcp::core::unexpected(core::Error{
672 static_cast<int>(ErrorCode::InvalidRequest),
673 "missing required field '" + std::string(fd.wire_name) + "'",
674 {}});
675 return false;
676 }
677 Field temp{};
678 if (!JsonFieldTraits<Field>::deserialize(json, fd.wire_name, temp)) {
679 status = mcp::core::unexpected(
680 core::Error{static_cast<int>(ErrorCode::InvalidRequest),
681 "invalid field '" + std::string(fd.wire_name) + "'",
682 {}});
683 return false;
684 }
685 if (fd.post_validate) {
686 auto validation = fd.post_validate(temp);
687 if (!validation) {
688 status = mcp::core::unexpected(validation.error());
689 return false;
690 }
691 }
692 obj.*(fd.pointer) = std::move(temp);
693 status = core::Unit{};
694 return true;
695}
696
698template <typename Struct>
699bool deserialize_one(const Json&, Struct&, const ExtensionsField<Struct>&,
701 return true;
702}
703
705template <typename Struct, typename Field>
706bool deserialize_one(const Json& json, Struct& obj,
708 core::Result<core::Unit>& status) {
709 if constexpr (is_optional_v<Field>) {
710 JsonFieldTraits<Field>::deserialize(json, fd.wire_name, obj.*(fd.pointer));
711 status = core::Unit{};
712 return true;
713 } else {
714 return deserialize_one(
715 json, obj,
716 FieldDescriptor<Struct, Field>{fd.wire_name, fd.pointer, nullptr},
717 status);
718 }
719}
720
721// ---------------------------------------------------------------------------
722// reflect_to_json / reflect_from_json
723// ---------------------------------------------------------------------------
724
728template <typename T>
729Json reflect_to_json(const T& obj) {
730 static_assert(has_reflect_v<T>,
731 "Reflect<T> must be specialized for this type");
732 Json json = Json::object();
733
734 // Serialize each field.
735 std::apply([&](const auto&... fds) { (serialize_one(json, obj, fds), ...); },
736 reflect_fields<T>());
737
738 // Merge extension members last (they fill gaps left by typed fields).
739 if constexpr (has_extensions_member_v<T>) {
740 append_json_extensions(json, obj.extensions);
741 }
742 return json;
743}
744
749template <typename T>
751 static_assert(has_reflect_v<T>,
752 "Reflect<T> must be specialized for this type");
753 if (!json.is_object()) {
754 return mcp::core::unexpected(
755 core::Error{static_cast<int>(ErrorCode::InvalidRequest),
756 "expected a JSON object",
757 {}});
758 }
759
760 T obj{};
762
763 // Early-exit fold: on first error, skip remaining fields.
764 std::apply(
765 [&](const auto&... fds) {
766 auto one = [&](const auto& fd) {
767 if (status) {
768 deserialize_one(json, obj, fd, status);
769 }
770 };
771 (one(fds), ...);
772 },
773 reflect_fields<T>());
774
775 if (!status) {
776 return mcp::core::unexpected(status.error());
777 }
778
779 // Collect unknown keys into extensions.
780 if constexpr (has_extensions_member_v<T>) {
781 auto known = [] {
782 if constexpr (detail::has_known_keys<Reflect<T>>::value) {
783 return Reflect<T>::known_keys();
784 } else {
785 return extract_known_keys<T>();
786 }
787 }();
788 obj.extensions = collect_json_extensions(json, known);
789 }
790
791 return obj;
792}
793
794// ---------------------------------------------------------------------------
795// CXXMCP_REFLECT: one-line Reflect<T> specialization
796// ---------------------------------------------------------------------------
797
798#define CXXMCP_REFL_IMPL_1(T, f1) \
799 template <> \
800 struct mcp::protocol::Reflect<T> { \
801 static constexpr bool defined = true; \
802 static auto fields() { return std::make_tuple(field(#f1, &T::f1)); } \
803 };
804
805#define CXXMCP_REFL_IMPL_2(T, f1, f2) \
806 template <> \
807 struct mcp::protocol::Reflect<T> { \
808 static constexpr bool defined = true; \
809 static auto fields() { \
810 return std::make_tuple(field(#f1, &T::f1), field(#f2, &T::f2)); \
811 } \
812 };
813
814#define CXXMCP_REFL_IMPL_3(T, f1, f2, f3) \
815 template <> \
816 struct mcp::protocol::Reflect<T> { \
817 static constexpr bool defined = true; \
818 static auto fields() { \
819 return std::make_tuple(field(#f1, &T::f1), field(#f2, &T::f2), \
820 field(#f3, &T::f3)); \
821 } \
822 };
823
824#define CXXMCP_REFL_IMPL_4(T, f1, f2, f3, f4) \
825 template <> \
826 struct mcp::protocol::Reflect<T> { \
827 static constexpr bool defined = true; \
828 static auto fields() { \
829 return std::make_tuple(field(#f1, &T::f1), field(#f2, &T::f2), \
830 field(#f3, &T::f3), field(#f4, &T::f4)); \
831 } \
832 };
833
834#define CXXMCP_REFL_IMPL_5(T, f1, f2, f3, f4, f5) \
835 template <> \
836 struct mcp::protocol::Reflect<T> { \
837 static constexpr bool defined = true; \
838 static auto fields() { \
839 return std::make_tuple(field(#f1, &T::f1), field(#f2, &T::f2), \
840 field(#f3, &T::f3), field(#f4, &T::f4), \
841 field(#f5, &T::f5)); \
842 } \
843 };
844
845#define CXXMCP_REFL_IMPL_6(T, f1, f2, f3, f4, f5, f6) \
846 template <> \
847 struct mcp::protocol::Reflect<T> { \
848 static constexpr bool defined = true; \
849 static auto fields() { \
850 return std::make_tuple(field(#f1, &T::f1), field(#f2, &T::f2), \
851 field(#f3, &T::f3), field(#f4, &T::f4), \
852 field(#f5, &T::f5), field(#f6, &T::f6)); \
853 } \
854 };
855
856#define CXXMCP_REFL_IMPL_7(T, f1, f2, f3, f4, f5, f6, f7) \
857 template <> \
858 struct mcp::protocol::Reflect<T> { \
859 static constexpr bool defined = true; \
860 static auto fields() { \
861 return std::make_tuple(field(#f1, &T::f1), field(#f2, &T::f2), \
862 field(#f3, &T::f3), field(#f4, &T::f4), \
863 field(#f5, &T::f5), field(#f6, &T::f6), \
864 field(#f7, &T::f7)); \
865 } \
866 };
867
868#define CXXMCP_REFL_IMPL_8(T, f1, f2, f3, f4, f5, f6, f7, f8) \
869 template <> \
870 struct mcp::protocol::Reflect<T> { \
871 static constexpr bool defined = true; \
872 static auto fields() { \
873 return std::make_tuple(field(#f1, &T::f1), field(#f2, &T::f2), \
874 field(#f3, &T::f3), field(#f4, &T::f4), \
875 field(#f5, &T::f5), field(#f6, &T::f6), \
876 field(#f7, &T::f7), field(#f8, &T::f8)); \
877 } \
878 };
879
880#define CXXMCP_REFL_IMPL_9(T, f1, f2, f3, f4, f5, f6, f7, f8, f9) \
881 template <> \
882 struct mcp::protocol::Reflect<T> { \
883 static constexpr bool defined = true; \
884 static auto fields() { \
885 return std::make_tuple( \
886 field(#f1, &T::f1), field(#f2, &T::f2), field(#f3, &T::f3), \
887 field(#f4, &T::f4), field(#f5, &T::f5), field(#f6, &T::f6), \
888 field(#f7, &T::f7), field(#f8, &T::f8), field(#f9, &T::f9)); \
889 } \
890 };
891
892#define CXXMCP_REFL_IMPL_10(T, f1, f2, f3, f4, f5, f6, f7, f8, f9, f10) \
893 template <> \
894 struct mcp::protocol::Reflect<T> { \
895 static constexpr bool defined = true; \
896 static auto fields() { \
897 return std::make_tuple(field(#f1, &T::f1), field(#f2, &T::f2), \
898 field(#f3, &T::f3), field(#f4, &T::f4), \
899 field(#f5, &T::f5), field(#f6, &T::f6), \
900 field(#f7, &T::f7), field(#f8, &T::f8), \
901 field(#f9, &T::f9), field(#f10, &T::f10)); \
902 } \
903 };
904
905#define CXXMCP_REFL_IMPL_11(T, f1, f2, f3, f4, f5, f6, f7, f8, f9, f10, f11) \
906 template <> \
907 struct mcp::protocol::Reflect<T> { \
908 static constexpr bool defined = true; \
909 static auto fields() { \
910 return std::make_tuple( \
911 field(#f1, &T::f1), field(#f2, &T::f2), field(#f3, &T::f3), \
912 field(#f4, &T::f4), field(#f5, &T::f5), field(#f6, &T::f6), \
913 field(#f7, &T::f7), field(#f8, &T::f8), field(#f9, &T::f9), \
914 field(#f10, &T::f10), field(#f11, &T::f11)); \
915 } \
916 };
917
918#define CXXMCP_REFL_IMPL_12(T, f1, f2, f3, f4, f5, f6, f7, f8, f9, f10, f11, \
919 f12) \
920 template <> \
921 struct mcp::protocol::Reflect<T> { \
922 static constexpr bool defined = true; \
923 static auto fields() { \
924 return std::make_tuple( \
925 field(#f1, &T::f1), field(#f2, &T::f2), field(#f3, &T::f3), \
926 field(#f4, &T::f4), field(#f5, &T::f5), field(#f6, &T::f6), \
927 field(#f7, &T::f7), field(#f8, &T::f8), field(#f9, &T::f9), \
928 field(#f10, &T::f10), field(#f11, &T::f11), field(#f12, &T::f12)); \
929 } \
930 };
931
932#define CXXMCP_REFL_IMPL_13(T, f1, f2, f3, f4, f5, f6, f7, f8, f9, f10, f11, \
933 f12, f13) \
934 template <> \
935 struct mcp::protocol::Reflect<T> { \
936 static constexpr bool defined = true; \
937 static auto fields() { \
938 return std::make_tuple( \
939 field(#f1, &T::f1), field(#f2, &T::f2), field(#f3, &T::f3), \
940 field(#f4, &T::f4), field(#f5, &T::f5), field(#f6, &T::f6), \
941 field(#f7, &T::f7), field(#f8, &T::f8), field(#f9, &T::f9), \
942 field(#f10, &T::f10), field(#f11, &T::f11), field(#f12, &T::f12), \
943 field(#f13, &T::f13)); \
944 } \
945 };
946
947#define CXXMCP_REFL_IMPL_14(T, f1, f2, f3, f4, f5, f6, f7, f8, f9, f10, f11, \
948 f12, f13, f14) \
949 template <> \
950 struct mcp::protocol::Reflect<T> { \
951 static constexpr bool defined = true; \
952 static auto fields() { \
953 return std::make_tuple( \
954 field(#f1, &T::f1), field(#f2, &T::f2), field(#f3, &T::f3), \
955 field(#f4, &T::f4), field(#f5, &T::f5), field(#f6, &T::f6), \
956 field(#f7, &T::f7), field(#f8, &T::f8), field(#f9, &T::f9), \
957 field(#f10, &T::f10), field(#f11, &T::f11), field(#f12, &T::f12), \
958 field(#f13, &T::f13), field(#f14, &T::f14)); \
959 } \
960 };
961
962#define CXXMCP_REFL_IMPL_15(T, f1, f2, f3, f4, f5, f6, f7, f8, f9, f10, f11, \
963 f12, f13, f14, f15) \
964 template <> \
965 struct mcp::protocol::Reflect<T> { \
966 static constexpr bool defined = true; \
967 static auto fields() { \
968 return std::make_tuple( \
969 field(#f1, &T::f1), field(#f2, &T::f2), field(#f3, &T::f3), \
970 field(#f4, &T::f4), field(#f5, &T::f5), field(#f6, &T::f6), \
971 field(#f7, &T::f7), field(#f8, &T::f8), field(#f9, &T::f9), \
972 field(#f10, &T::f10), field(#f11, &T::f11), field(#f12, &T::f12), \
973 field(#f13, &T::f13), field(#f14, &T::f14), field(#f15, &T::f15)); \
974 } \
975 };
976
977#define CXXMCP_REFL_IMPL_16(T, f1, f2, f3, f4, f5, f6, f7, f8, f9, f10, f11, \
978 f12, f13, f14, f15, f16) \
979 template <> \
980 struct mcp::protocol::Reflect<T> { \
981 static constexpr bool defined = true; \
982 static auto fields() { \
983 return std::make_tuple( \
984 field(#f1, &T::f1), field(#f2, &T::f2), field(#f3, &T::f3), \
985 field(#f4, &T::f4), field(#f5, &T::f5), field(#f6, &T::f6), \
986 field(#f7, &T::f7), field(#f8, &T::f8), field(#f9, &T::f9), \
987 field(#f10, &T::f10), field(#f11, &T::f11), field(#f12, &T::f12), \
988 field(#f13, &T::f13), field(#f14, &T::f14), field(#f15, &T::f15), \
989 field(#f16, &T::f16)); \
990 } \
991 };
992
993// Internal dispatch by selecting the implementation from the argument list.
994#define CXXMCP_REFLECT_CHOOSER(_1, _2, _3, _4, _5, _6, _7, _8, _9, _10, _11, \
995 _12, _13, _14, _15, _16, NAME, ...) \
996 NAME
997#define CXXMCP_REFLECT_EXPAND(expr) expr
998
1007#define CXXMCP_REFLECT(Type, ...) \
1008 using ::mcp::protocol::Reflect; \
1009 using ::mcp::protocol::field; \
1010 CXXMCP_REFLECT_EXPAND(CXXMCP_REFLECT_CHOOSER( \
1011 __VA_ARGS__, CXXMCP_REFL_IMPL_16, CXXMCP_REFL_IMPL_15, \
1012 CXXMCP_REFL_IMPL_14, CXXMCP_REFL_IMPL_13, CXXMCP_REFL_IMPL_12, \
1013 CXXMCP_REFL_IMPL_11, CXXMCP_REFL_IMPL_10, CXXMCP_REFL_IMPL_9, \
1014 CXXMCP_REFL_IMPL_8, CXXMCP_REFL_IMPL_7, CXXMCP_REFL_IMPL_6, \
1015 CXXMCP_REFL_IMPL_5, CXXMCP_REFL_IMPL_4, CXXMCP_REFL_IMPL_3, \
1016 CXXMCP_REFL_IMPL_2, CXXMCP_REFL_IMPL_1)(Type, __VA_ARGS__))
1017
1018#define CXXMCP_REFL_SELF_IMPL_1(T, f1) \
1019 static auto cxxmcp_fields() { \
1020 return std::make_tuple(::mcp::protocol::field(#f1, &T::f1)); \
1021 }
1022
1023#define CXXMCP_REFL_SELF_IMPL_2(T, f1, f2) \
1024 static auto cxxmcp_fields() { \
1025 return std::make_tuple(::mcp::protocol::field(#f1, &T::f1), \
1026 ::mcp::protocol::field(#f2, &T::f2)); \
1027 }
1028
1029#define CXXMCP_REFL_SELF_IMPL_3(T, f1, f2, f3) \
1030 static auto cxxmcp_fields() { \
1031 return std::make_tuple(::mcp::protocol::field(#f1, &T::f1), \
1032 ::mcp::protocol::field(#f2, &T::f2), \
1033 ::mcp::protocol::field(#f3, &T::f3)); \
1034 }
1035
1036#define CXXMCP_REFL_SELF_IMPL_4(T, f1, f2, f3, f4) \
1037 static auto cxxmcp_fields() { \
1038 return std::make_tuple(::mcp::protocol::field(#f1, &T::f1), \
1039 ::mcp::protocol::field(#f2, &T::f2), \
1040 ::mcp::protocol::field(#f3, &T::f3), \
1041 ::mcp::protocol::field(#f4, &T::f4)); \
1042 }
1043
1044#define CXXMCP_REFL_SELF_IMPL_5(T, f1, f2, f3, f4, f5) \
1045 static auto cxxmcp_fields() { \
1046 return std::make_tuple(::mcp::protocol::field(#f1, &T::f1), \
1047 ::mcp::protocol::field(#f2, &T::f2), \
1048 ::mcp::protocol::field(#f3, &T::f3), \
1049 ::mcp::protocol::field(#f4, &T::f4), \
1050 ::mcp::protocol::field(#f5, &T::f5)); \
1051 }
1052
1053#define CXXMCP_REFL_SELF_IMPL_6(T, f1, f2, f3, f4, f5, f6) \
1054 static auto cxxmcp_fields() { \
1055 return std::make_tuple(::mcp::protocol::field(#f1, &T::f1), \
1056 ::mcp::protocol::field(#f2, &T::f2), \
1057 ::mcp::protocol::field(#f3, &T::f3), \
1058 ::mcp::protocol::field(#f4, &T::f4), \
1059 ::mcp::protocol::field(#f5, &T::f5), \
1060 ::mcp::protocol::field(#f6, &T::f6)); \
1061 }
1062
1063#define CXXMCP_REFL_SELF_IMPL_7(T, f1, f2, f3, f4, f5, f6, f7) \
1064 static auto cxxmcp_fields() { \
1065 return std::make_tuple(::mcp::protocol::field(#f1, &T::f1), \
1066 ::mcp::protocol::field(#f2, &T::f2), \
1067 ::mcp::protocol::field(#f3, &T::f3), \
1068 ::mcp::protocol::field(#f4, &T::f4), \
1069 ::mcp::protocol::field(#f5, &T::f5), \
1070 ::mcp::protocol::field(#f6, &T::f6), \
1071 ::mcp::protocol::field(#f7, &T::f7)); \
1072 }
1073
1074#define CXXMCP_REFL_SELF_IMPL_8(T, f1, f2, f3, f4, f5, f6, f7, f8) \
1075 static auto cxxmcp_fields() { \
1076 return std::make_tuple(::mcp::protocol::field(#f1, &T::f1), \
1077 ::mcp::protocol::field(#f2, &T::f2), \
1078 ::mcp::protocol::field(#f3, &T::f3), \
1079 ::mcp::protocol::field(#f4, &T::f4), \
1080 ::mcp::protocol::field(#f5, &T::f5), \
1081 ::mcp::protocol::field(#f6, &T::f6), \
1082 ::mcp::protocol::field(#f7, &T::f7), \
1083 ::mcp::protocol::field(#f8, &T::f8)); \
1084 }
1085
1086#define CXXMCP_REFL_SELF_IMPL_9(T, f1, f2, f3, f4, f5, f6, f7, f8, f9) \
1087 static auto cxxmcp_fields() { \
1088 return std::make_tuple(::mcp::protocol::field(#f1, &T::f1), \
1089 ::mcp::protocol::field(#f2, &T::f2), \
1090 ::mcp::protocol::field(#f3, &T::f3), \
1091 ::mcp::protocol::field(#f4, &T::f4), \
1092 ::mcp::protocol::field(#f5, &T::f5), \
1093 ::mcp::protocol::field(#f6, &T::f6), \
1094 ::mcp::protocol::field(#f7, &T::f7), \
1095 ::mcp::protocol::field(#f8, &T::f8), \
1096 ::mcp::protocol::field(#f9, &T::f9)); \
1097 }
1098
1099#define CXXMCP_REFL_SELF_IMPL_10(T, f1, f2, f3, f4, f5, f6, f7, f8, f9, f10) \
1100 static auto cxxmcp_fields() { \
1101 return std::make_tuple(::mcp::protocol::field(#f1, &T::f1), \
1102 ::mcp::protocol::field(#f2, &T::f2), \
1103 ::mcp::protocol::field(#f3, &T::f3), \
1104 ::mcp::protocol::field(#f4, &T::f4), \
1105 ::mcp::protocol::field(#f5, &T::f5), \
1106 ::mcp::protocol::field(#f6, &T::f6), \
1107 ::mcp::protocol::field(#f7, &T::f7), \
1108 ::mcp::protocol::field(#f8, &T::f8), \
1109 ::mcp::protocol::field(#f9, &T::f9), \
1110 ::mcp::protocol::field(#f10, &T::f10)); \
1111 }
1112
1113#define CXXMCP_REFL_SELF_IMPL_11(T, f1, f2, f3, f4, f5, f6, f7, f8, f9, f10, \
1114 f11) \
1115 static auto cxxmcp_fields() { \
1116 return std::make_tuple(::mcp::protocol::field(#f1, &T::f1), \
1117 ::mcp::protocol::field(#f2, &T::f2), \
1118 ::mcp::protocol::field(#f3, &T::f3), \
1119 ::mcp::protocol::field(#f4, &T::f4), \
1120 ::mcp::protocol::field(#f5, &T::f5), \
1121 ::mcp::protocol::field(#f6, &T::f6), \
1122 ::mcp::protocol::field(#f7, &T::f7), \
1123 ::mcp::protocol::field(#f8, &T::f8), \
1124 ::mcp::protocol::field(#f9, &T::f9), \
1125 ::mcp::protocol::field(#f10, &T::f10), \
1126 ::mcp::protocol::field(#f11, &T::f11)); \
1127 }
1128
1129#define CXXMCP_REFL_SELF_IMPL_12(T, f1, f2, f3, f4, f5, f6, f7, f8, f9, f10, \
1130 f11, f12) \
1131 static auto cxxmcp_fields() { \
1132 return std::make_tuple(::mcp::protocol::field(#f1, &T::f1), \
1133 ::mcp::protocol::field(#f2, &T::f2), \
1134 ::mcp::protocol::field(#f3, &T::f3), \
1135 ::mcp::protocol::field(#f4, &T::f4), \
1136 ::mcp::protocol::field(#f5, &T::f5), \
1137 ::mcp::protocol::field(#f6, &T::f6), \
1138 ::mcp::protocol::field(#f7, &T::f7), \
1139 ::mcp::protocol::field(#f8, &T::f8), \
1140 ::mcp::protocol::field(#f9, &T::f9), \
1141 ::mcp::protocol::field(#f10, &T::f10), \
1142 ::mcp::protocol::field(#f11, &T::f11), \
1143 ::mcp::protocol::field(#f12, &T::f12)); \
1144 }
1145
1146#define CXXMCP_REFL_SELF_IMPL_13(T, f1, f2, f3, f4, f5, f6, f7, f8, f9, f10, \
1147 f11, f12, f13) \
1148 static auto cxxmcp_fields() { \
1149 return std::make_tuple(::mcp::protocol::field(#f1, &T::f1), \
1150 ::mcp::protocol::field(#f2, &T::f2), \
1151 ::mcp::protocol::field(#f3, &T::f3), \
1152 ::mcp::protocol::field(#f4, &T::f4), \
1153 ::mcp::protocol::field(#f5, &T::f5), \
1154 ::mcp::protocol::field(#f6, &T::f6), \
1155 ::mcp::protocol::field(#f7, &T::f7), \
1156 ::mcp::protocol::field(#f8, &T::f8), \
1157 ::mcp::protocol::field(#f9, &T::f9), \
1158 ::mcp::protocol::field(#f10, &T::f10), \
1159 ::mcp::protocol::field(#f11, &T::f11), \
1160 ::mcp::protocol::field(#f12, &T::f12), \
1161 ::mcp::protocol::field(#f13, &T::f13)); \
1162 }
1163
1164#define CXXMCP_REFL_SELF_IMPL_14(T, f1, f2, f3, f4, f5, f6, f7, f8, f9, f10, \
1165 f11, f12, f13, f14) \
1166 static auto cxxmcp_fields() { \
1167 return std::make_tuple(::mcp::protocol::field(#f1, &T::f1), \
1168 ::mcp::protocol::field(#f2, &T::f2), \
1169 ::mcp::protocol::field(#f3, &T::f3), \
1170 ::mcp::protocol::field(#f4, &T::f4), \
1171 ::mcp::protocol::field(#f5, &T::f5), \
1172 ::mcp::protocol::field(#f6, &T::f6), \
1173 ::mcp::protocol::field(#f7, &T::f7), \
1174 ::mcp::protocol::field(#f8, &T::f8), \
1175 ::mcp::protocol::field(#f9, &T::f9), \
1176 ::mcp::protocol::field(#f10, &T::f10), \
1177 ::mcp::protocol::field(#f11, &T::f11), \
1178 ::mcp::protocol::field(#f12, &T::f12), \
1179 ::mcp::protocol::field(#f13, &T::f13), \
1180 ::mcp::protocol::field(#f14, &T::f14)); \
1181 }
1182
1183#define CXXMCP_REFL_SELF_IMPL_15(T, f1, f2, f3, f4, f5, f6, f7, f8, f9, f10, \
1184 f11, f12, f13, f14, f15) \
1185 static auto cxxmcp_fields() { \
1186 return std::make_tuple(::mcp::protocol::field(#f1, &T::f1), \
1187 ::mcp::protocol::field(#f2, &T::f2), \
1188 ::mcp::protocol::field(#f3, &T::f3), \
1189 ::mcp::protocol::field(#f4, &T::f4), \
1190 ::mcp::protocol::field(#f5, &T::f5), \
1191 ::mcp::protocol::field(#f6, &T::f6), \
1192 ::mcp::protocol::field(#f7, &T::f7), \
1193 ::mcp::protocol::field(#f8, &T::f8), \
1194 ::mcp::protocol::field(#f9, &T::f9), \
1195 ::mcp::protocol::field(#f10, &T::f10), \
1196 ::mcp::protocol::field(#f11, &T::f11), \
1197 ::mcp::protocol::field(#f12, &T::f12), \
1198 ::mcp::protocol::field(#f13, &T::f13), \
1199 ::mcp::protocol::field(#f14, &T::f14), \
1200 ::mcp::protocol::field(#f15, &T::f15)); \
1201 }
1202
1203#define CXXMCP_REFL_SELF_IMPL_16(T, f1, f2, f3, f4, f5, f6, f7, f8, f9, f10, \
1204 f11, f12, f13, f14, f15, f16) \
1205 static auto cxxmcp_fields() { \
1206 return std::make_tuple(::mcp::protocol::field(#f1, &T::f1), \
1207 ::mcp::protocol::field(#f2, &T::f2), \
1208 ::mcp::protocol::field(#f3, &T::f3), \
1209 ::mcp::protocol::field(#f4, &T::f4), \
1210 ::mcp::protocol::field(#f5, &T::f5), \
1211 ::mcp::protocol::field(#f6, &T::f6), \
1212 ::mcp::protocol::field(#f7, &T::f7), \
1213 ::mcp::protocol::field(#f8, &T::f8), \
1214 ::mcp::protocol::field(#f9, &T::f9), \
1215 ::mcp::protocol::field(#f10, &T::f10), \
1216 ::mcp::protocol::field(#f11, &T::f11), \
1217 ::mcp::protocol::field(#f12, &T::f12), \
1218 ::mcp::protocol::field(#f13, &T::f13), \
1219 ::mcp::protocol::field(#f14, &T::f14), \
1220 ::mcp::protocol::field(#f15, &T::f15), \
1221 ::mcp::protocol::field(#f16, &T::f16)); \
1222 }
1223
1224#define CXXMCP_REFLECT_SELF_CHOOSER(_1, _2, _3, _4, _5, _6, _7, _8, _9, _10, \
1225 _11, _12, _13, _14, _15, _16, NAME, ...) \
1226 NAME
1227
1240#define CXXMCP_REFLECT_SELF(Type, ...) \
1241 CXXMCP_REFLECT_EXPAND(CXXMCP_REFLECT_SELF_CHOOSER( \
1242 __VA_ARGS__, CXXMCP_REFL_SELF_IMPL_16, CXXMCP_REFL_SELF_IMPL_15, \
1243 CXXMCP_REFL_SELF_IMPL_14, CXXMCP_REFL_SELF_IMPL_13, \
1244 CXXMCP_REFL_SELF_IMPL_12, CXXMCP_REFL_SELF_IMPL_11, \
1245 CXXMCP_REFL_SELF_IMPL_10, CXXMCP_REFL_SELF_IMPL_9, \
1246 CXXMCP_REFL_SELF_IMPL_8, CXXMCP_REFL_SELF_IMPL_7, \
1247 CXXMCP_REFL_SELF_IMPL_6, CXXMCP_REFL_SELF_IMPL_5, \
1248 CXXMCP_REFL_SELF_IMPL_4, CXXMCP_REFL_SELF_IMPL_3, \
1249 CXXMCP_REFL_SELF_IMPL_2, CXXMCP_REFL_SELF_IMPL_1)(Type, __VA_ARGS__))
1250
1251// ---------------------------------------------------------------------------
1252// Compile-time reflection completeness check
1253// ---------------------------------------------------------------------------
1254
1269#define CXXMCP_REFLECT_CHECK(Struct, expected_count) \
1270 static_assert( \
1271 std::tuple_size_v< \
1272 decltype(::mcp::protocol::Reflect<Struct>::fields())> == \
1273 (expected_count), \
1274 "Reflect<" #Struct \
1275 ">::fields() has " \
1276 "a different number of descriptors than expected (" #expected_count \
1277 "). Update the count or add/remove field descriptors.")
1278
1279} // namespace mcp::protocol
void push_wire_name(std::vector< std::string > &keys, const FieldDescriptor< S, F > &fd)
Overloads that extract wire_name from field descriptors.
Definition reflect.hpp:188
Shared JSON, JSON-RPC, error, cancellation, and progress model types.
std::string_view icon_theme_to_string(IconTheme theme) noexcept
Converts an icon theme enum to the lowercase wire value.
Definition types.hpp:259
void append_json_extensions(Json &json, const Json &extensions)
Flattens extension members into a JSON object without overwriting typed fields.
Definition types.hpp:358
IconTheme
Preferred icon variant for clients with light or dark surfaces.
Definition types.hpp:151
std::optional< IconTheme > icon_theme_from_string(std::string_view value) noexcept
Parses a lowercase icon theme wire value.
Definition types.hpp:270
nlohmann::json Json
JSON value type used by all protocol DTOs.
Definition types.hpp:28
Json collect_json_extensions(const Json &json, std::initializer_list< std::string_view > known_keys)
Collects unknown object members so typed DTOs can preserve future protocol fields and vendor extensio...
Definition types.hpp:320
constexpr FieldDescriptor< Struct, Field > field(const char *wire_name, Field Struct::*pointer)
Creates a FieldDescriptor with wire name and pointer-to-member.
Definition reflect.hpp:75
std::vector< std::string > extract_known_keys()
Extracts known wire names from the fields() tuple at runtime.
Definition reflect.hpp:220
constexpr FieldDescriptor< Struct, Field > defaulted_field(const char *wire_name, Field Struct::*pointer)
Creates a FieldDescriptor whose missing wire value keeps the C++ default value.
Definition reflect.hpp:145
constexpr FieldDescriptor< Struct, Field > nullable_field(const char *wire_name, Field Struct::*pointer)
Creates a FieldDescriptor whose missing wire value maps to std::monostate.
Definition reflect.hpp:134
ExtensionsField< Struct > extensions_field(Json Struct::*pointer, std::vector< std::string > own_keys)
Creates an ExtensionsField descriptor.
Definition reflect.hpp:90
auto reflect_fields()
Returns the field descriptors for a reflectable type.
Definition reflect.hpp:250
void serialize_one(Json &json, const Struct &obj, const FieldDescriptor< Struct, Field > &fd)
Serializes a single field into the JSON object.
Definition reflect.hpp:627
constexpr DeserializeOnlyField< Struct, Field > deserialize_only(const char *wire_name, Field Struct::*pointer)
Creates a DeserializeOnlyField descriptor.
Definition reflect.hpp:97
Json reflect_to_json(const T &obj)
Serializes a DTO to JSON using its Reflect<T> trait.
Definition reflect.hpp:729
constexpr FieldDescriptor< Struct, Field > validated_field(const char *wire_name, Field Struct::*pointer, core::Result< core::Unit >(*validator)(const Field &))
Creates a FieldDescriptor with a post-deserialization validator.
Definition reflect.hpp:82
bool deserialize_one(const Json &json, Struct &obj, const FieldDescriptor< Struct, Field > &fd, core::Result< core::Unit > &status)
Deserializes a single field from the JSON object.
Definition reflect.hpp:649
core::Result< T > reflect_from_json(const Json &json)
Deserializes a DTO from JSON using its Reflect<T> trait.
Definition reflect.hpp:750
Shared result and error primitives used by the public cxxmcp SDK.
std::monostate Unit
Success value for operations that only need to report failure.
Definition result.hpp:55
tl::expected< T, Error > Result
Alias for the SDK result type.
Definition result.hpp:64
Structured error returned by fallible SDK operations.
Definition result.hpp:35
Tag-only field descriptor for fields that are populated during deserialization only (e....
Definition reflect.hpp:66
Tag-only field descriptor for the extensions member.
Definition reflect.hpp:56
Describes a single DTO field: its JSON wire name, pointer-to-member, and optional post-deserializatio...
Definition reflect.hpp:41
Type-specific serialization and deserialization logic.
Definition reflect.hpp:274
Primary template.
Definition reflect.hpp:209
Definition reflect.hpp:179
Detects whether a type has an extensions member of type Json.
Definition reflect.hpp:152
Detects whether Reflect<T> is specialized for a given type.
Definition reflect.hpp:234
Detects std::variant containing std::monostate (nullable on wire).
Definition reflect.hpp:118
Detects std::optional<T>.
Definition reflect.hpp:108