From c8defbf4a00419381357247f4533f0c63903af02 Mon Sep 17 00:00:00 2001 From: "Dr. Patrick Urbanke" Date: Sun, 29 Dec 2024 20:06:57 +0100 Subject: [PATCH] Added (basic) support for variants --- include/rfl/capnproto/schema/Type.hpp | 26 ++++++++++++--------- src/rfl/capnproto/Type.cpp | 11 +++++++++ src/rfl/capnproto/Writer.cpp | 4 ++-- src/rfl/capnproto/to_schema.cpp | 13 +++++++++-- tests/capnproto/test_variant.cpp | 33 +++++++++++++++++++++++++++ 5 files changed, 72 insertions(+), 15 deletions(-) create mode 100644 tests/capnproto/test_variant.cpp diff --git a/include/rfl/capnproto/schema/Type.hpp b/include/rfl/capnproto/schema/Type.hpp index 7050d12b..29245a74 100644 --- a/include/rfl/capnproto/schema/Type.hpp +++ b/include/rfl/capnproto/schema/Type.hpp @@ -41,17 +41,8 @@ struct Type { struct Data {}; - struct Optional { - rfl::Ref type; - }; - struct Text {}; - struct Struct { - std::string name; - std::vector> fields; - }; - struct List { rfl::Ref type; }; @@ -60,14 +51,27 @@ struct Type { rfl::Ref type; }; + struct Optional { + rfl::Ref type; + }; + struct Reference { std::string type_name; }; + struct Struct { + std::string name; + std::vector> fields; + }; + + struct Variant { + std::vector types; + }; + using ReflectionType = rfl::Variant; + UInt64, Float32, Float64, Data, Text, List, + /*Map,*/ Optional, Reference, Struct, Variant>; const auto& reflection() const { return value; } diff --git a/src/rfl/capnproto/Type.cpp b/src/rfl/capnproto/Type.cpp index 7032742a..6f6512fd 100644 --- a/src/rfl/capnproto/Type.cpp +++ b/src/rfl/capnproto/Type.cpp @@ -117,6 +117,13 @@ std::ostream& operator<<(std::ostream& _os, const Type::Struct& _s) { << " some @" << ix++ << " :" << *_r.type << ";" << std::endl << " none @" << ix++ << " :Void;" << std::endl << " }" << std::endl; + } else if constexpr (std::is_same()) { + _os << " " << name << " :union {" << std::endl; + for (size_t i = 0; i < _r.types.size(); ++i) { + _os << " option" << i + 1 << " @" << ix++ << " :" << _r.types[i] + << ";" << std::endl; + } + _os << " }" << std::endl; } else { _os << " " << name << " @" << ix++ << " :" << _r << ";" << std::endl; } @@ -129,6 +136,10 @@ std::ostream& operator<<(std::ostream& _os, const Type::List& _l) { return _os << "List(" << *_l.type << ")"; } +std::ostream& operator<<(std::ostream& _os, const Type::Variant& _v) { + return _os << "TODO"; +} + std::ostream& operator<<(std::ostream& _os, const Type::Reference& _r) { return _os << internal::strings::to_pascal_case(_r.type_name); } diff --git a/src/rfl/capnproto/Writer.cpp b/src/rfl/capnproto/Writer.cpp index 2f6a878b..abe5b520 100644 --- a/src/rfl/capnproto/Writer.cpp +++ b/src/rfl/capnproto/Writer.cpp @@ -108,7 +108,7 @@ Writer::OutputObjectType Writer::add_object_to_union( OutputUnionType* _parent) const noexcept { const auto field = _parent->val_.getSchema().getFields()[_index]; return OutputObjectType{ - _parent->val_.get(field).template as()}; + _parent->val_.init(field).template as()}; } Writer::OutputUnionType Writer::add_union_to_array( @@ -135,7 +135,7 @@ Writer::OutputUnionType Writer::add_union_to_union( const size_t _index, OutputUnionType* _parent) const noexcept { const auto field = _parent->val_.getSchema().getFields()[_index]; return OutputUnionType{ - _parent->val_.get(field).template as()}; + _parent->val_.init(field).template as()}; } Writer::OutputVarType Writer::add_null_to_array( diff --git a/src/rfl/capnproto/to_schema.cpp b/src/rfl/capnproto/to_schema.cpp index d5cf43a4..f07bb645 100644 --- a/src/rfl/capnproto/to_schema.cpp +++ b/src/rfl/capnproto/to_schema.cpp @@ -80,8 +80,12 @@ schema::Type type_to_capnproto_schema_type( return schema::Type{.value = schema::Type::Text{}}; } else if constexpr (std::is_same()) { - // TODO - return schema::Type{.value = schema::Type::Void{}}; + auto value = schema::Type::Variant{}; + for (const auto& type : _t.types_) { + value.types.push_back( + type_to_capnproto_schema_type(type, _definitions, _num_unnamed)); + } + return schema::Type{.value = value}; } else if constexpr (std::is_same()) { return type_to_capnproto_schema_type(*_t.type_, _definitions, @@ -115,9 +119,11 @@ schema::Type type_to_capnproto_schema_type( .value = schema::Type::Optional{ .type = Ref::make(type_to_capnproto_schema_type( *_t.type_, _definitions, _num_unnamed))}}; + } else if constexpr (std::is_same()) { return schema::Type{.value = schema::Type::Reference{.type_name = _t.name_}}; + } else if constexpr (std::is_same()) { // TODO return schema::Type{.value = schema::Type::Void{}}; @@ -126,15 +132,18 @@ schema::Type type_to_capnproto_schema_type( .values = Ref::make(type_to_capnproto_schema_type( *_t.value_type_, _definitions, _num_unnamed))}};*/ + } else if constexpr (std::is_same()) { return type_to_capnproto_schema_type( Type{parsing::schemaful::tuple_to_object(_t)}, _definitions, _num_unnamed); + } else if constexpr (std::is_same()) { return schema::Type{ .value = schema::Type::List{ .type = Ref::make(type_to_capnproto_schema_type( *_t.type_, _definitions, _num_unnamed))}}; + } else if constexpr (std::is_same()) { // Cap'n Proto knows no validation. return type_to_capnproto_schema_type(*_t.type_, _definitions, diff --git a/tests/capnproto/test_variant.cpp b/tests/capnproto/test_variant.cpp new file mode 100644 index 00000000..6ed47dc9 --- /dev/null +++ b/tests/capnproto/test_variant.cpp @@ -0,0 +1,33 @@ +#include +#include +#include +#include +#include + +#include "write_and_read.hpp" + +namespace test_variant { + +struct Circle { + double radius; +}; + +struct Rectangle { + double height; + double width; +}; + +struct Square { + double width; +}; + +struct Shapes { + std::variant root; +}; + +TEST(capnproto, test_variant) { + const auto r = Shapes{Rectangle{.height = 10, .width = 5}}; + + write_and_read(r); +} +} // namespace test_variant