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) {
test::TestGenerics<TestAllTypes>::Interface<>::Client castClient = client.asGeneric<>();
test::TestGenerics<TestAllTypes>::Interface<TestAllTypes>::Client castClient2 =
client.asGeneric<TestAllTypes>();
test::TestGenerics<>::Interface<List<uint32_t>>::Client castClient3 = client.asTestGenericsGeneric<>();
}
TEST(Capability, Generics2) {
......
......@@ -571,8 +571,8 @@ private:
TemplateContext(): parent(nullptr) {}
explicit TemplateContext(schema::Node::Reader node)
: parent(nullptr), node(node) {}
TemplateContext(const TemplateContext& parent, schema::Node::Reader node)
: parent(parent), node(node) {}
TemplateContext(const TemplateContext& parent, kj::StringPtr name, schema::Node::Reader node)
: parent(parent), name(name), node(node) {}
bool hasParams() const {
return node.getParameters().size() > 0;
......@@ -580,6 +580,10 @@ private:
bool isGeneric() const {
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 {
// "template <typename T, typename U>" for this type. Includes default assignments
......@@ -665,6 +669,7 @@ private:
private:
kj::Maybe<const TemplateContext&> parent;
kj::StringPtr name;
schema::Node::Reader node;
};
......@@ -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 {
kj::StringTree outerTypeDecl;
kj::StringTree outerTypeDef;
......@@ -1749,13 +1804,7 @@ private:
" }\n"
"#endif // !CAPNP_LITE\n"
"\n",
templateContext.isGeneric() ? kj::strTree(
" ", 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(),
makeAsGenericDef(AsGenericRole::READER, templateContext, unqualifiedParentType),
isUnion ? kj::strTree(" inline Which which() const;\n") : kj::strTree(),
kj::mv(methodDecls),
"private:\n"
......@@ -1793,13 +1842,7 @@ private:
" inline ::kj::StringTree toString() const { return asReader().toString(); }\n"
"#endif // !CAPNP_LITE\n"
"\n",
templateContext.isGeneric() ? kj::strTree(
" ", 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(),
makeAsGenericDef(AsGenericRole::BUILDER, templateContext, unqualifiedParentType),
isUnion ? kj::strTree(" inline Which which();\n") : kj::strTree(),
kj::mv(methodDecls),
"private:\n"
......@@ -2251,12 +2294,7 @@ private:
" Client& operator=(Client& other);\n"
" Client& operator=(Client&& other);\n"
"\n",
templateContext.isGeneric() ? kj::strTree(
" ", templateContext.decl(true, "2"),
" typename ", name, templateContext.args("2"), "::Client asGeneric() {\n"
" return castAs<", name, templateContext.args("2"), ">();\n"
" }\n"
"\n") : kj::strTree(),
makeAsGenericDef(AsGenericRole::CLIENT, templateContext, name),
KJ_MAP(m, methods) { return kj::mv(m.clientDecls); },
"\n"
"protected:\n"
......@@ -2498,7 +2536,7 @@ private:
}
auto hexId = kj::hex(proto.getId());
TemplateContext templateContext(parentTemplateContext, proto);
TemplateContext templateContext(parentTemplateContext, name, proto);
auto subScope = kj::str(scope, name, templateContext.args(), "::");
......
......@@ -1821,6 +1821,22 @@ TEST(Encoding, Generics) {
initTestMessage(root.initInner().initFoo());
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");
EXPECT_EQ("foo", reader.getInner2().getBaz());
......
......@@ -232,8 +232,9 @@ public:
}
#endif // !CAPNP_LITE
typename SaveParams::Reader asGeneric() {
return typename SaveParams::Reader(_reader);
template <typename SturdyRef2 = ::capnp::AnyPointer, typename Owner2 = ::capnp::AnyPointer>
typename Persistent<SturdyRef2, Owner2>::SaveParams::Reader asPersistentGeneric() {
return typename Persistent<SturdyRef2, Owner2>::SaveParams::Reader(_reader);
}
inline bool hasSealFor() const;
......@@ -268,8 +269,9 @@ public:
inline ::kj::StringTree toString() const { return asReader().toString(); }
#endif // !CAPNP_LITE
typename SaveParams::Builder asGeneric() {
return typename SaveParams::Builder(_builder);
template <typename SturdyRef2 = ::capnp::AnyPointer, typename Owner2 = ::capnp::AnyPointer>
typename Persistent<SturdyRef2, Owner2>::SaveParams::Builder asPersistentGeneric() {
return typename Persistent<SturdyRef2, Owner2>::SaveParams::Builder(_builder);
}
inline bool hasSealFor();
......@@ -326,8 +328,9 @@ public:
}
#endif // !CAPNP_LITE
typename SaveResults::Reader asGeneric() {
return typename SaveResults::Reader(_reader);
template <typename SturdyRef2 = ::capnp::AnyPointer, typename Owner2 = ::capnp::AnyPointer>
typename Persistent<SturdyRef2, Owner2>::SaveResults::Reader asPersistentGeneric() {
return typename Persistent<SturdyRef2, Owner2>::SaveResults::Reader(_reader);
}
inline bool hasSturdyRef() const;
......@@ -362,8 +365,9 @@ public:
inline ::kj::StringTree toString() const { return asReader().toString(); }
#endif // !CAPNP_LITE
typename SaveResults::Builder asGeneric() {
return typename SaveResults::Builder(_builder);
template <typename SturdyRef2 = ::capnp::AnyPointer, typename Owner2 = ::capnp::AnyPointer>
typename Persistent<SturdyRef2, Owner2>::SaveResults::Builder asPersistentGeneric() {
return typename Persistent<SturdyRef2, Owner2>::SaveResults::Builder(_builder);
}
inline bool hasSturdyRef();
......@@ -482,8 +486,9 @@ public:
}
#endif // !CAPNP_LITE
typename ImportParams::Reader asGeneric() {
return typename ImportParams::Reader(_reader);
template <typename InternalRef2 = ::capnp::AnyPointer, typename ExternalRef2 = ::capnp::AnyPointer, typename InternalOwner2 = ::capnp::AnyPointer, typename ExternalOwner2 = ::capnp::AnyPointer>
typename RealmGateway<InternalRef2, ExternalRef2, InternalOwner2, ExternalOwner2>::ImportParams::Reader asRealmGatewayGeneric() {
return typename RealmGateway<InternalRef2, ExternalRef2, InternalOwner2, ExternalOwner2>::ImportParams::Reader(_reader);
}
inline bool hasCap() const;
......@@ -523,8 +528,9 @@ public:
inline ::kj::StringTree toString() const { return asReader().toString(); }
#endif // !CAPNP_LITE
typename ImportParams::Builder asGeneric() {
return typename ImportParams::Builder(_builder);
template <typename InternalRef2 = ::capnp::AnyPointer, typename ExternalRef2 = ::capnp::AnyPointer, typename InternalOwner2 = ::capnp::AnyPointer, typename ExternalOwner2 = ::capnp::AnyPointer>
typename RealmGateway<InternalRef2, ExternalRef2, InternalOwner2, ExternalOwner2>::ImportParams::Builder asRealmGatewayGeneric() {
return typename RealmGateway<InternalRef2, ExternalRef2, InternalOwner2, ExternalOwner2>::ImportParams::Builder(_builder);
}
inline bool hasCap();
......@@ -590,8 +596,9 @@ public:
}
#endif // !CAPNP_LITE
typename ExportParams::Reader asGeneric() {
return typename ExportParams::Reader(_reader);
template <typename InternalRef2 = ::capnp::AnyPointer, typename ExternalRef2 = ::capnp::AnyPointer, typename InternalOwner2 = ::capnp::AnyPointer, typename ExternalOwner2 = ::capnp::AnyPointer>
typename RealmGateway<InternalRef2, ExternalRef2, InternalOwner2, ExternalOwner2>::ExportParams::Reader asRealmGatewayGeneric() {
return typename RealmGateway<InternalRef2, ExternalRef2, InternalOwner2, ExternalOwner2>::ExportParams::Reader(_reader);
}
inline bool hasCap() const;
......@@ -631,8 +638,9 @@ public:
inline ::kj::StringTree toString() const { return asReader().toString(); }
#endif // !CAPNP_LITE
typename ExportParams::Builder asGeneric() {
return typename ExportParams::Builder(_builder);
template <typename InternalRef2 = ::capnp::AnyPointer, typename ExternalRef2 = ::capnp::AnyPointer, typename InternalOwner2 = ::capnp::AnyPointer, typename ExternalOwner2 = ::capnp::AnyPointer>
typename RealmGateway<InternalRef2, ExternalRef2, InternalOwner2, ExternalOwner2>::ExportParams::Builder asRealmGatewayGeneric() {
return typename RealmGateway<InternalRef2, ExternalRef2, InternalOwner2, ExternalOwner2>::ExportParams::Builder(_builder);
}
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