Commit 31bf72dc authored by Branislav Katreniak's avatar Branislav Katreniak

capnp-c++: implement asGeneric method for outer template contexts

https://github.com/sandstorm-io/capnproto/issues/334
parent 965a7ff2
...@@ -805,6 +805,7 @@ TEST(Capability, Generics) { ...@@ -805,6 +805,7 @@ TEST(Capability, Generics) {
test::TestGenerics<TestAllTypes>::Interface<>::Client castClient = client.asGeneric<>(); test::TestGenerics<TestAllTypes>::Interface<>::Client castClient = client.asGeneric<>();
test::TestGenerics<TestAllTypes>::Interface<TestAllTypes>::Client castClient2 = test::TestGenerics<TestAllTypes>::Interface<TestAllTypes>::Client castClient2 =
client.asGeneric<TestAllTypes>(); client.asGeneric<TestAllTypes>();
test::TestGenerics<>::Interface<List<uint32_t>>::Client castClient3 = client.asTestGenericsGeneric<>();
} }
TEST(Capability, Generics2) { TEST(Capability, Generics2) {
......
...@@ -571,8 +571,8 @@ private: ...@@ -571,8 +571,8 @@ private:
TemplateContext(): parent(nullptr) {} TemplateContext(): parent(nullptr) {}
explicit TemplateContext(schema::Node::Reader node) explicit TemplateContext(schema::Node::Reader node)
: parent(nullptr), node(node) {} : parent(nullptr), node(node) {}
TemplateContext(const TemplateContext& parent, schema::Node::Reader node) TemplateContext(const TemplateContext& parent, kj::StringPtr name, schema::Node::Reader node)
: parent(parent), node(node) {} : parent(parent), name(name), node(node) {}
bool hasParams() const { bool hasParams() const {
return node.getParameters().size() > 0; return node.getParameters().size() > 0;
...@@ -580,6 +580,10 @@ private: ...@@ -580,6 +580,10 @@ private:
bool isGeneric() const { bool isGeneric() const {
return node.getIsGeneric(); return node.getIsGeneric();
} }
kj::Maybe<const TemplateContext&> getParent() const {
return parent;
}
kj::StringPtr getName() const { return name; }
kj::StringTree decl(bool withDefaults, kj::StringPtr suffix = nullptr) const { kj::StringTree decl(bool withDefaults, kj::StringPtr suffix = nullptr) const {
// "template <typename T, typename U>" for this type. Includes default assignments // "template <typename T, typename U>" for this type. Includes default assignments
...@@ -665,6 +669,7 @@ private: ...@@ -665,6 +669,7 @@ private:
private: private:
kj::Maybe<const TemplateContext&> parent; kj::Maybe<const TemplateContext&> parent;
kj::StringPtr name;
schema::Node::Reader node; schema::Node::Reader node;
}; };
...@@ -1719,6 +1724,56 @@ private: ...@@ -1719,6 +1724,56 @@ private:
// ----------------------------------------------------------------- // -----------------------------------------------------------------
enum class AsGenericRole { READER, BUILDER, CLIENT };
kj::StringTree makeAsGenericDef(AsGenericRole role, const TemplateContext& templateContext,
kj::StringPtr type, kj::String innerType = kj::String()) {
if (!templateContext.isGeneric()) {
return kj::StringTree();
}
kj::StringTree self, up;
if (templateContext.hasParams()) {
auto returnType = [&]() {
return kj::strTree(type, templateContext.args("2"), innerType);
};
kj::StringTree asGeneric = kj::strTree("as", innerType.size() ? type : "", "Generic()");
switch (role) {
case AsGenericRole::READER:
self = kj::strTree(
" ", templateContext.decl(true, "2"),
" typename ", returnType(), "::Reader ", kj::mv(asGeneric), " {\n"
" return typename ", returnType(), "::Reader(_reader);\n"
" }\n"
"\n");
break;
case AsGenericRole::BUILDER:
self = kj::strTree(
" ", templateContext.decl(true, "2"),
" typename ", returnType(), "::Builder ", kj::mv(asGeneric), " {\n"
" return typename ", returnType(), "::Builder(_builder);\n"
" }\n"
"\n");
break;
case AsGenericRole::CLIENT:
self = kj::strTree(
" ", templateContext.decl(true, "2"),
" typename ", returnType(), "::Client ", kj::mv(asGeneric), " {\n"
" return castAs<", innerType.size() ? "typename " : "", returnType(), ">();\n"
" }\n"
"\n");
break;
}
}
KJ_IF_MAYBE(p, templateContext.getParent()) {
up = makeAsGenericDef(role, *p, p->getName(), kj::strTree(
templateContext.hasParams() ? "::template " : "::", type,
templateContext.args()).flatten());
}
return kj::strTree(kj::mv(self), kj::mv(up));
}
// -----------------------------------------------------------------
struct StructText { struct StructText {
kj::StringTree outerTypeDecl; kj::StringTree outerTypeDecl;
kj::StringTree outerTypeDef; kj::StringTree outerTypeDef;
...@@ -1749,13 +1804,7 @@ private: ...@@ -1749,13 +1804,7 @@ private:
" }\n" " }\n"
"#endif // !CAPNP_LITE\n" "#endif // !CAPNP_LITE\n"
"\n", "\n",
templateContext.isGeneric() ? kj::strTree( makeAsGenericDef(AsGenericRole::READER, templateContext, unqualifiedParentType),
" ", templateContext.decl(true, "2"),
" typename ", unqualifiedParentType, templateContext.args("2"), "::Reader asGeneric() {\n"
" return typename ", unqualifiedParentType, templateContext.args("2"),
"::Reader(_reader);\n"
" }\n"
"\n") : kj::strTree(),
isUnion ? kj::strTree(" inline Which which() const;\n") : kj::strTree(), isUnion ? kj::strTree(" inline Which which() const;\n") : kj::strTree(),
kj::mv(methodDecls), kj::mv(methodDecls),
"private:\n" "private:\n"
...@@ -1793,13 +1842,7 @@ private: ...@@ -1793,13 +1842,7 @@ private:
" inline ::kj::StringTree toString() const { return asReader().toString(); }\n" " inline ::kj::StringTree toString() const { return asReader().toString(); }\n"
"#endif // !CAPNP_LITE\n" "#endif // !CAPNP_LITE\n"
"\n", "\n",
templateContext.isGeneric() ? kj::strTree( makeAsGenericDef(AsGenericRole::BUILDER, templateContext, unqualifiedParentType),
" ", templateContext.decl(true, "2"),
" typename ", unqualifiedParentType, templateContext.args("2"), "::Builder asGeneric() {\n"
" return typename ", unqualifiedParentType, templateContext.args("2"),
"::Builder(_builder);\n"
" }\n"
"\n") : kj::strTree(),
isUnion ? kj::strTree(" inline Which which();\n") : kj::strTree(), isUnion ? kj::strTree(" inline Which which();\n") : kj::strTree(),
kj::mv(methodDecls), kj::mv(methodDecls),
"private:\n" "private:\n"
...@@ -2251,12 +2294,7 @@ private: ...@@ -2251,12 +2294,7 @@ private:
" Client& operator=(Client& other);\n" " Client& operator=(Client& other);\n"
" Client& operator=(Client&& other);\n" " Client& operator=(Client&& other);\n"
"\n", "\n",
templateContext.isGeneric() ? kj::strTree( makeAsGenericDef(AsGenericRole::CLIENT, templateContext, name),
" ", templateContext.decl(true, "2"),
" typename ", name, templateContext.args("2"), "::Client asGeneric() {\n"
" return castAs<", name, templateContext.args("2"), ">();\n"
" }\n"
"\n") : kj::strTree(),
KJ_MAP(m, methods) { return kj::mv(m.clientDecls); }, KJ_MAP(m, methods) { return kj::mv(m.clientDecls); },
"\n" "\n"
"protected:\n" "protected:\n"
...@@ -2498,7 +2536,7 @@ private: ...@@ -2498,7 +2536,7 @@ private:
} }
auto hexId = kj::hex(proto.getId()); auto hexId = kj::hex(proto.getId());
TemplateContext templateContext(parentTemplateContext, proto); TemplateContext templateContext(parentTemplateContext, name, proto);
auto subScope = kj::str(scope, name, templateContext.args(), "::"); auto subScope = kj::str(scope, name, templateContext.args(), "::");
......
...@@ -1821,6 +1821,22 @@ TEST(Encoding, Generics) { ...@@ -1821,6 +1821,22 @@ TEST(Encoding, Generics) {
initTestMessage(root.initInner().initFoo()); initTestMessage(root.initInner().initFoo());
checkTestMessage(reader.getInner().getFoo()); checkTestMessage(reader.getInner().getFoo());
{
auto typed = root.getInner();
test::TestGenerics<>::Inner::Reader generic = typed.asTestGenericsGeneric<>();
checkTestMessage(generic.getFoo().getAs<TestAllTypes>());
test::TestGenerics<TestAllTypes>::Inner::Reader halfGeneric = typed.asTestGenericsGeneric<TestAllTypes>();
checkTestMessage(halfGeneric.getFoo());
}
{
auto typed = root.getInner().asReader();
test::TestGenerics<>::Inner::Reader generic = typed.asTestGenericsGeneric<>();
checkTestMessage(generic.getFoo().getAs<TestAllTypes>());
test::TestGenerics<TestAllTypes>::Inner::Reader halfGeneric = typed.asTestGenericsGeneric<TestAllTypes>();
checkTestMessage(halfGeneric.getFoo());
}
root.initInner2().setBaz("foo"); root.initInner2().setBaz("foo");
EXPECT_EQ("foo", reader.getInner2().getBaz()); EXPECT_EQ("foo", reader.getInner2().getBaz());
......
...@@ -232,8 +232,9 @@ public: ...@@ -232,8 +232,9 @@ public:
} }
#endif // !CAPNP_LITE #endif // !CAPNP_LITE
typename SaveParams::Reader asGeneric() { template <typename SturdyRef2 = ::capnp::AnyPointer, typename Owner2 = ::capnp::AnyPointer>
return typename SaveParams::Reader(_reader); typename Persistent<SturdyRef2, Owner2>::SaveParams::Reader asPersistentGeneric() {
return typename Persistent<SturdyRef2, Owner2>::SaveParams::Reader(_reader);
} }
inline bool hasSealFor() const; inline bool hasSealFor() const;
...@@ -268,8 +269,9 @@ public: ...@@ -268,8 +269,9 @@ public:
inline ::kj::StringTree toString() const { return asReader().toString(); } inline ::kj::StringTree toString() const { return asReader().toString(); }
#endif // !CAPNP_LITE #endif // !CAPNP_LITE
typename SaveParams::Builder asGeneric() { template <typename SturdyRef2 = ::capnp::AnyPointer, typename Owner2 = ::capnp::AnyPointer>
return typename SaveParams::Builder(_builder); typename Persistent<SturdyRef2, Owner2>::SaveParams::Builder asPersistentGeneric() {
return typename Persistent<SturdyRef2, Owner2>::SaveParams::Builder(_builder);
} }
inline bool hasSealFor(); inline bool hasSealFor();
...@@ -326,8 +328,9 @@ public: ...@@ -326,8 +328,9 @@ public:
} }
#endif // !CAPNP_LITE #endif // !CAPNP_LITE
typename SaveResults::Reader asGeneric() { template <typename SturdyRef2 = ::capnp::AnyPointer, typename Owner2 = ::capnp::AnyPointer>
return typename SaveResults::Reader(_reader); typename Persistent<SturdyRef2, Owner2>::SaveResults::Reader asPersistentGeneric() {
return typename Persistent<SturdyRef2, Owner2>::SaveResults::Reader(_reader);
} }
inline bool hasSturdyRef() const; inline bool hasSturdyRef() const;
...@@ -362,8 +365,9 @@ public: ...@@ -362,8 +365,9 @@ public:
inline ::kj::StringTree toString() const { return asReader().toString(); } inline ::kj::StringTree toString() const { return asReader().toString(); }
#endif // !CAPNP_LITE #endif // !CAPNP_LITE
typename SaveResults::Builder asGeneric() { template <typename SturdyRef2 = ::capnp::AnyPointer, typename Owner2 = ::capnp::AnyPointer>
return typename SaveResults::Builder(_builder); typename Persistent<SturdyRef2, Owner2>::SaveResults::Builder asPersistentGeneric() {
return typename Persistent<SturdyRef2, Owner2>::SaveResults::Builder(_builder);
} }
inline bool hasSturdyRef(); inline bool hasSturdyRef();
...@@ -482,8 +486,9 @@ public: ...@@ -482,8 +486,9 @@ public:
} }
#endif // !CAPNP_LITE #endif // !CAPNP_LITE
typename ImportParams::Reader asGeneric() { template <typename InternalRef2 = ::capnp::AnyPointer, typename ExternalRef2 = ::capnp::AnyPointer, typename InternalOwner2 = ::capnp::AnyPointer, typename ExternalOwner2 = ::capnp::AnyPointer>
return typename ImportParams::Reader(_reader); typename RealmGateway<InternalRef2, ExternalRef2, InternalOwner2, ExternalOwner2>::ImportParams::Reader asRealmGatewayGeneric() {
return typename RealmGateway<InternalRef2, ExternalRef2, InternalOwner2, ExternalOwner2>::ImportParams::Reader(_reader);
} }
inline bool hasCap() const; inline bool hasCap() const;
...@@ -523,8 +528,9 @@ public: ...@@ -523,8 +528,9 @@ public:
inline ::kj::StringTree toString() const { return asReader().toString(); } inline ::kj::StringTree toString() const { return asReader().toString(); }
#endif // !CAPNP_LITE #endif // !CAPNP_LITE
typename ImportParams::Builder asGeneric() { template <typename InternalRef2 = ::capnp::AnyPointer, typename ExternalRef2 = ::capnp::AnyPointer, typename InternalOwner2 = ::capnp::AnyPointer, typename ExternalOwner2 = ::capnp::AnyPointer>
return typename ImportParams::Builder(_builder); typename RealmGateway<InternalRef2, ExternalRef2, InternalOwner2, ExternalOwner2>::ImportParams::Builder asRealmGatewayGeneric() {
return typename RealmGateway<InternalRef2, ExternalRef2, InternalOwner2, ExternalOwner2>::ImportParams::Builder(_builder);
} }
inline bool hasCap(); inline bool hasCap();
...@@ -590,8 +596,9 @@ public: ...@@ -590,8 +596,9 @@ public:
} }
#endif // !CAPNP_LITE #endif // !CAPNP_LITE
typename ExportParams::Reader asGeneric() { template <typename InternalRef2 = ::capnp::AnyPointer, typename ExternalRef2 = ::capnp::AnyPointer, typename InternalOwner2 = ::capnp::AnyPointer, typename ExternalOwner2 = ::capnp::AnyPointer>
return typename ExportParams::Reader(_reader); typename RealmGateway<InternalRef2, ExternalRef2, InternalOwner2, ExternalOwner2>::ExportParams::Reader asRealmGatewayGeneric() {
return typename RealmGateway<InternalRef2, ExternalRef2, InternalOwner2, ExternalOwner2>::ExportParams::Reader(_reader);
} }
inline bool hasCap() const; inline bool hasCap() const;
...@@ -631,8 +638,9 @@ public: ...@@ -631,8 +638,9 @@ public:
inline ::kj::StringTree toString() const { return asReader().toString(); } inline ::kj::StringTree toString() const { return asReader().toString(); }
#endif // !CAPNP_LITE #endif // !CAPNP_LITE
typename ExportParams::Builder asGeneric() { template <typename InternalRef2 = ::capnp::AnyPointer, typename ExternalRef2 = ::capnp::AnyPointer, typename InternalOwner2 = ::capnp::AnyPointer, typename ExternalOwner2 = ::capnp::AnyPointer>
return typename ExportParams::Builder(_builder); typename RealmGateway<InternalRef2, ExternalRef2, InternalOwner2, ExternalOwner2>::ExportParams::Builder asRealmGatewayGeneric() {
return typename RealmGateway<InternalRef2, ExternalRef2, InternalOwner2, ExternalOwner2>::ExportParams::Builder(_builder);
} }
inline bool hasCap(); inline bool hasCap();
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment