Commit 4288dd27 authored by Kenton Varda's avatar Kenton Varda

Over the hump, new schema is working and passing most tests. Still lots of cleanup to do.

parent 0c7c610c
......@@ -5,33 +5,34 @@
namespace capnp {
namespace schemas {
static const ::capnp::_::AlignedData<18> b_b9c6f99ebf805f2c = {
{ 0, 0, 0, 0, 3, 0, 4, 0,
static const ::capnp::_::AlignedData<19> b_b9c6f99ebf805f2c = {
{ 0, 0, 0, 0, 5, 0, 5, 0,
44, 95, 128, 191, 158, 249, 198, 185,
0, 0, 0, 0, 5, 0, 1, 0,
129, 78, 48, 184, 123, 125, 248, 189,
5, 0, 0, 0, 0, 0, 0, 0,
13, 0, 0, 0, 210, 0, 0, 0,
25, 0, 0, 0, 7, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0,
20, 0, 0, 0, 1, 0, 1, 0,
0, 0, 0, 0, 0, 0, 0, 0,
17, 0, 0, 0, 210, 0, 0, 0,
29, 0, 0, 0, 7, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0,
24, 0, 0, 0, 2, 0, 1, 0,
0, 0, 0, 0, 0, 0, 0, 0,
99, 97, 112, 110, 112, 47, 99, 43,
43, 46, 99, 97, 112, 110, 112, 58,
110, 97, 109, 101, 115, 112, 97, 99,
101, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 1, 0, 1, 0,
1, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 2, 0, 1, 0,
12, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, }
};
static const ::capnp::_::RawSchema* const d_b9c6f99ebf805f2c[] = {
};
static const ::capnp::_::RawSchema::MemberInfo m_b9c6f99ebf805f2c[] = {
};
static const uint16_t m_b9c6f99ebf805f2c[] = {};
static const uint16_t i_b9c6f99ebf805f2c[] = {};
const ::capnp::_::RawSchema s_b9c6f99ebf805f2c = {
0xb9c6f99ebf805f2c, b_b9c6f99ebf805f2c.words, 18, d_b9c6f99ebf805f2c, m_b9c6f99ebf805f2c,
0, 0, nullptr, nullptr
0xb9c6f99ebf805f2c, b_b9c6f99ebf805f2c.words, 19, d_b9c6f99ebf805f2c, m_b9c6f99ebf805f2c,
0, 0, i_b9c6f99ebf805f2c, nullptr, nullptr
};
} // namespace schemas
namespace _ { // private
......
......@@ -825,10 +825,21 @@ private:
enumerateDeps(proto, deps);
kj::Array<uint> membersByName;
kj::Array<uint> membersByDiscrim;
switch (proto.which()) {
case schema2::Node::STRUCT:
membersByName = makeMembersByName(schema.asStruct().getFields());
case schema2::Node::STRUCT: {
auto structSchema = schema.asStruct();
membersByName = makeMembersByName(structSchema.getFields());
auto builder = kj::heapArrayBuilder<uint>(structSchema.getFields().size());
for (auto field: structSchema.getUnionFields()) {
builder.add(field.getIndex());
}
for (auto field: structSchema.getNonUnionFields()) {
builder.add(field.getIndex());
}
membersByDiscrim = builder.finish();
break;
}
case schema2::Node::ENUM:
membersByName = makeMembersByName(schema.asEnum().getEnumerants());
break;
......@@ -848,12 +859,15 @@ private:
return kj::strTree(" &s_", kj::hex(depId), ",\n");
},
"};\n"
"static const ::capnp::_::RawSchema::MemberInfo m_", hexId, "[] = {\n",
"static const uint16_t m_", hexId, "[] = {",
kj::StringTree(KJ_MAP(membersByName, index) { return kj::strTree(index); }, ", "),
"};\n"
"static const uint16_t i_", hexId, "[] = {",
kj::StringTree(KJ_MAP(membersByDiscrim, index) { return kj::strTree(index); }, ", "),
"};\n"
"const ::capnp::_::RawSchema s_", hexId, " = {\n"
" 0x", hexId, ", b_", hexId, ".words, ", rawSchema.size(), ", d_", hexId, ", m_", hexId, ",\n"
" ", deps.size(), ", ", membersByName.size(), ", nullptr, nullptr\n"
" ", deps.size(), ", ", membersByName.size(), ", i_", hexId, ", nullptr, nullptr\n"
"};\n");
switch (proto.which()) {
......
This source diff could not be displayed because it is too large. You can view the blob instead.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
......@@ -1057,6 +1057,7 @@ private:
if (parent != nullptr) {
uint64_t groupId = generateGroupId(parent->node.getId(), index);
node.setId(groupId);
node.setScopeId(parent->node.getId());
getSchema().setGroup(groupId);
}
}
......@@ -1201,10 +1202,9 @@ private:
.newOrphan<schema2::Node>();
auto node = orphan.get();
// We'll set the ID later.
// We'll set the ID and scope ID later.
node.setDisplayName(kj::str(parent.getDisplayName(), '.', name));
node.setDisplayNamePrefixLength(node.getDisplayName().size() - name.size());
node.setScopeId(parent.getId());
node.initStruct().setIsGroup(true);
// The remaining contents of node.struct will be filled in later.
......@@ -1475,25 +1475,25 @@ private:
static kj::StringPtr getValueUnionFieldNameFor(schema2::Type::Which type) {
switch (type) {
case schema2::Type::VOID: return "voidValue";
case schema2::Type::BOOL: return "boolValue";
case schema2::Type::INT8: return "int8Value";
case schema2::Type::INT16: return "int16Value";
case schema2::Type::INT32: return "int32Value";
case schema2::Type::INT64: return "int64Value";
case schema2::Type::UINT8: return "uint8Value";
case schema2::Type::UINT16: return "uint16Value";
case schema2::Type::UINT32: return "uint32Value";
case schema2::Type::UINT64: return "uint64Value";
case schema2::Type::FLOAT32: return "float32Value";
case schema2::Type::FLOAT64: return "float64Value";
case schema2::Type::TEXT: return "textValue";
case schema2::Type::DATA: return "dataValue";
case schema2::Type::LIST: return "listValue";
case schema2::Type::ENUM: return "enumValue";
case schema2::Type::STRUCT: return "structValue";
case schema2::Type::INTERFACE: return "interfaceValue";
case schema2::Type::OBJECT: return "objectValue";
case schema2::Type::VOID: return "void";
case schema2::Type::BOOL: return "bool";
case schema2::Type::INT8: return "int8";
case schema2::Type::INT16: return "int16";
case schema2::Type::INT32: return "int32";
case schema2::Type::INT64: return "int64";
case schema2::Type::UINT8: return "uint8";
case schema2::Type::UINT16: return "uint16";
case schema2::Type::UINT32: return "uint32";
case schema2::Type::UINT64: return "uint64";
case schema2::Type::FLOAT32: return "float32";
case schema2::Type::FLOAT64: return "float64";
case schema2::Type::TEXT: return "text";
case schema2::Type::DATA: return "data";
case schema2::Type::LIST: return "list";
case schema2::Type::ENUM: return "enum";
case schema2::Type::STRUCT: return "struct";
case schema2::Type::INTERFACE: return "interface";
case schema2::Type::OBJECT: return "object";
}
KJ_FAIL_ASSERT("Unknown type.");
}
......@@ -1533,35 +1533,38 @@ void NodeTranslator::compileValue(ValueExpression::Reader source, schema2::Type:
break;
default:
#if 0
KJ_FAIL_ASSERT("Need to compile value type:", (uint)type.which(),
wipNode.getReader().getDisplayName());
}
#else
break;
}
#if 0
auto valueUnion = toDynamic(target).get("body").as<DynamicUnion>();
auto member = valueUnion.getSchema().getMemberByName(
getValueUnionFieldNameFor(type.getBody().which()));
switch (type.getBody().which()) {
auto valueUnion = toDynamic(target);
auto field = valueUnion.getSchema().getFieldByName(
getValueUnionFieldNameFor(type.which()));
switch (type.which()) {
case schema2::Type::LIST:
KJ_IF_MAYBE(listSchema, makeListSchemaOf(type.getBody().getListType())) {
DynamicSlot slot(valueUnion, member, *listSchema);
KJ_IF_MAYBE(listSchema, makeListSchemaOf(type.getList())) {
DynamicSlot slot(valueUnion, field, *listSchema);
compileValue(source, slot, isBootstrap);
}
break;
case schema2::Type::STRUCT:
KJ_IF_MAYBE(structSchema, resolver.resolveBootstrapSchema(type.getBody().getStructType())) {
DynamicSlot slot(valueUnion, member, structSchema->asStruct());
KJ_IF_MAYBE(structSchema, resolver.resolveBootstrapSchema(type.getStruct())) {
DynamicSlot slot(valueUnion, field, structSchema->asStruct());
compileValue(source, slot, isBootstrap);
}
break;
case schema2::Type::ENUM:
KJ_IF_MAYBE(enumSchema, resolver.resolveBootstrapSchema(type.getBody().getEnumType())) {
DynamicSlot slot(valueUnion, member, enumSchema->asEnum());
KJ_IF_MAYBE(enumSchema, resolver.resolveBootstrapSchema(type.getEnum())) {
DynamicSlot slot(valueUnion, field, enumSchema->asEnum());
compileValue(source, slot, isBootstrap);
}
break;
default:
DynamicSlot slot(valueUnion, member);
DynamicSlot slot(valueUnion, field);
compileValue(source, slot, isBootstrap);
break;
}
......
......@@ -246,24 +246,24 @@ TEST(DynamicApi, UnionsRead) {
{
auto dynamic = toDynamic(root.asReader());
{
auto u = dynamic.get("union0").as<DynamicUnion>();
auto u = dynamic.get("union0").as<DynamicStruct>();
EXPECT_MAYBE_EQ(w, u.which(), "u0f1s32", w->getProto().getName());
EXPECT_EQ(1234567, u.get().as<int32_t>());
EXPECT_EQ(1234567, u.get("u0f1s32").as<int32_t>());
}
{
auto u = dynamic.get("union1").as<DynamicUnion>();
auto u = dynamic.get("union1").as<DynamicStruct>();
EXPECT_MAYBE_EQ(w, u.which(), "u1f1sp", w->getProto().getName());
EXPECT_EQ("foo", u.get().as<Text>());
EXPECT_EQ("foo", u.get("u1f1sp").as<Text>());
}
{
auto u = dynamic.get("union2").as<DynamicUnion>();
auto u = dynamic.get("union2").as<DynamicStruct>();
EXPECT_MAYBE_EQ(w, u.which(), "u2f0s1", w->getProto().getName());
EXPECT_TRUE(u.get().as<bool>());
EXPECT_TRUE(u.get("u2f0s1").as<bool>());
}
{
auto u = dynamic.get("union3").as<DynamicUnion>();
auto u = dynamic.get("union3").as<DynamicStruct>();
EXPECT_MAYBE_EQ(w, u.which(), "u3f0s64", w->getProto().getName());
EXPECT_EQ(1234567890123456789ll, u.get().as<int64_t>());
EXPECT_EQ(1234567890123456789ll, u.get("u3f0s64").as<int64_t>());
}
}
......@@ -271,24 +271,24 @@ TEST(DynamicApi, UnionsRead) {
// Again as a builder.
auto dynamic = toDynamic(root);
{
auto u = dynamic.get("union0").as<DynamicUnion>();
auto u = dynamic.get("union0").as<DynamicStruct>();
EXPECT_MAYBE_EQ(w, u.which(), "u0f1s32", w->getProto().getName());
EXPECT_EQ(1234567, u.get().as<int32_t>());
EXPECT_EQ(1234567, u.get("u0f1s32").as<int32_t>());
}
{
auto u = dynamic.get("union1").as<DynamicUnion>();
auto u = dynamic.get("union1").as<DynamicStruct>();
EXPECT_MAYBE_EQ(w, u.which(), "u1f1sp", w->getProto().getName());
EXPECT_EQ("foo", u.get().as<Text>());
EXPECT_EQ("foo", u.get("u1f1sp").as<Text>());
}
{
auto u = dynamic.get("union2").as<DynamicUnion>();
auto u = dynamic.get("union2").as<DynamicStruct>();
EXPECT_MAYBE_EQ(w, u.which(), "u2f0s1", w->getProto().getName());
EXPECT_TRUE(u.get().as<bool>());
EXPECT_TRUE(u.get("u2f0s1").as<bool>());
}
{
auto u = dynamic.get("union3").as<DynamicUnion>();
auto u = dynamic.get("union3").as<DynamicStruct>();
EXPECT_MAYBE_EQ(w, u.which(), "u3f0s64", w->getProto().getName());
EXPECT_EQ(1234567890123456789ll, u.get().as<int64_t>());
EXPECT_EQ(1234567890123456789ll, u.get("u3f0s64").as<int64_t>());
}
}
}
......@@ -305,10 +305,10 @@ TEST(DynamicApi, UnionsWrite) {
MallocMessageBuilder builder;
auto root = builder.initRoot<DynamicStruct>(Schema::from<TestUnion>());
root.get("union0").as<DynamicUnion>().set("u0f1s32", 1234567);
root.get("union1").as<DynamicUnion>().set("u1f1sp", "foo");
root.get("union2").as<DynamicUnion>().set("u2f0s1", true);
root.get("union3").as<DynamicUnion>().set("u3f0s64", 1234567890123456789ll);
root.get("union0").as<DynamicStruct>().set("u0f1s32", 1234567);
root.get("union1").as<DynamicStruct>().set("u1f1sp", "foo");
root.get("union2").as<DynamicStruct>().set("u2f0s1", true);
root.get("union3").as<DynamicStruct>().set("u3f0s64", 1234567890123456789ll);
auto reader = root.asReader().as<TestUnion>();
ASSERT_EQ(TestUnion::Union0::U0F1S32, reader.getUnion0().which());
......@@ -326,13 +326,6 @@ TEST(DynamicApi, UnionsWrite) {
// Can't access union members by name from the root.
EXPECT_ANY_THROW(root.get("u0f1s32"));
EXPECT_ANY_THROW(root.set("u0f1s32", 1234567));
// But can access them by member pointer.
auto member = root.get("union0").as<DynamicUnion>().getSchema().getMemberByName("u0f1s32");
EXPECT_EQ(1234567, root.get(member).as<int>());
auto member2 = root.get("union0").as<DynamicUnion>().getSchema().getMemberByName("u0f1sp");
root.set(member2, "foo");
EXPECT_EQ("foo", reader.getUnion0().getU0f1sp());
}
TEST(DynamicApi, UnnamedUnion) {
......@@ -340,44 +333,33 @@ TEST(DynamicApi, UnnamedUnion) {
StructSchema schema = Schema::from<test::TestUnnamedUnion>();
auto root = builder.initRoot<DynamicStruct>(schema);
DynamicUnion::Builder unionBuilder =
root.get(KJ_ASSERT_NONNULL(schema.getUnnamedUnion())).as<DynamicUnion>();
EXPECT_EQ(schema.getMemberByName("foo"), KJ_ASSERT_NONNULL(unionBuilder.which()));
EXPECT_EQ(schema.getFieldByName("foo"), KJ_ASSERT_NONNULL(root.which()));
root.set("bar", 321);
EXPECT_EQ(schema.getMemberByName("bar"), KJ_ASSERT_NONNULL(unionBuilder.which()));
EXPECT_EQ(schema.getFieldByName("bar"), KJ_ASSERT_NONNULL(root.which()));
EXPECT_EQ(321u, root.get("bar").as<uint>());
EXPECT_EQ(321u, root.asReader().get("bar").as<uint>());
EXPECT_EQ(321u, unionBuilder.get().as<uint>());
EXPECT_EQ(321u, unionBuilder.asReader().get().as<uint>());
EXPECT_ANY_THROW(root.get("foo"));
EXPECT_ANY_THROW(root.asReader().get("foo"));
root.set("foo", 123);
EXPECT_EQ(schema.getMemberByName("foo"), KJ_ASSERT_NONNULL(unionBuilder.which()));
EXPECT_EQ(schema.getFieldByName("foo"), KJ_ASSERT_NONNULL(root.which()));
EXPECT_EQ(123u, root.get("foo").as<uint>());
EXPECT_EQ(123u, root.asReader().get("foo").as<uint>());
EXPECT_EQ(123u, unionBuilder.get().as<uint>());
EXPECT_EQ(123u, unionBuilder.asReader().get().as<uint>());
EXPECT_ANY_THROW(root.get("bar"));
EXPECT_ANY_THROW(root.asReader().get("bar"));
unionBuilder.set("bar", 321);
EXPECT_EQ(schema.getMemberByName("bar"), KJ_ASSERT_NONNULL(unionBuilder.which()));
root.set("bar", 321);
EXPECT_EQ(schema.getFieldByName("bar"), KJ_ASSERT_NONNULL(root.which()));
EXPECT_EQ(321u, root.get("bar").as<uint>());
EXPECT_EQ(321u, root.asReader().get("bar").as<uint>());
EXPECT_EQ(321u, unionBuilder.get().as<uint>());
EXPECT_EQ(321u, unionBuilder.asReader().get().as<uint>());
EXPECT_ANY_THROW(root.get("foo"));
EXPECT_ANY_THROW(root.asReader().get("foo"));
unionBuilder.set("foo", 123);
EXPECT_EQ(schema.getMemberByName("foo"), KJ_ASSERT_NONNULL(unionBuilder.which()));
root.set("foo", 123);
EXPECT_EQ(schema.getFieldByName("foo"), KJ_ASSERT_NONNULL(root.which()));
EXPECT_EQ(123u, root.get("foo").as<uint>());
EXPECT_EQ(123u, root.asReader().get("foo").as<uint>());
EXPECT_EQ(123u, unionBuilder.get().as<uint>());
EXPECT_EQ(123u, unionBuilder.asReader().get().as<uint>());
EXPECT_ANY_THROW(root.get("bar"));
EXPECT_ANY_THROW(root.asReader().get("bar"));
}
......@@ -403,7 +385,7 @@ TEST(DynamicApi, LateUnion) {
MallocMessageBuilder builder;
auto root = builder.initRoot<DynamicStruct>(Schema::from<test::TestLateUnion>());
root.get("theUnion").as<DynamicUnion>().set("qux", "hello");
root.get("theUnion").as<DynamicStruct>().set("qux", "hello");
EXPECT_EQ("hello", root.as<test::TestLateUnion>().getTheUnion().getQux());
}
......
......@@ -719,7 +719,7 @@ void DynamicStruct::Builder::clear(StructSchema::Field field) {
case schema2::Type::STRUCT:
case schema2::Type::OBJECT:
builder.disown(regularField.getOffset() * POINTERS);
break;
return;
case schema2::Type::INTERFACE:
KJ_FAIL_ASSERT("Interfaces not yet implemented.");
......@@ -737,7 +737,7 @@ void DynamicStruct::Builder::clear(StructSchema::Field field) {
for (auto subField: group.schema.getNonUnionFields()) {
group.clear(subField);
}
break;
return;
}
}
......
......@@ -389,17 +389,11 @@ TEST(Encoding, UnnamedUnion) {
EXPECT_DEBUG_ANY_THROW(root.asReader().getBar());
StructSchema schema = Schema::from<test::TestUnnamedUnion>();
KJ_IF_MAYBE(u, schema.getUnnamedUnion()) {
// The discriminant is allocated just before allocating "bar".
EXPECT_EQ(2, u->getProto().getBody().getUnionMember().getDiscriminantOffset());
EXPECT_EQ(0, u->getMemberByName("foo").getProto().getBody().getFieldMember().getOffset());
EXPECT_EQ(2, u->getMemberByName("bar").getProto().getBody().getFieldMember().getOffset());
// The union receives the ordinal of its first member, since it does not explicitly declare one.
EXPECT_EQ(1, u->getProto().getOrdinal());
} else {
ADD_FAILURE() << "getUnnamedUnion() should have returned non-null.";
}
// The discriminant is allocated just before allocating "bar".
EXPECT_EQ(2, schema.getProto().getStruct().getDiscriminantOffset());
EXPECT_EQ(0, schema.getFieldByName("foo").getProto().getRegular().getOffset());
EXPECT_EQ(2, schema.getFieldByName("bar").getProto().getRegular().getOffset());
}
TEST(Encoding, Groups) {
......
......@@ -163,16 +163,7 @@ struct RawSchema {
//
// TODO(someday): Make this a hashtable.
struct MemberInfo {
uint16_t value;
inline operator uint16_t() const { return value; }
MemberInfo() = default;
constexpr MemberInfo(uint16_t value): value(value) {}
constexpr MemberInfo(uint16_t value, uint16_t dummy): value(value) {}
};
const MemberInfo* membersByName;
const uint16_t* membersByName;
// Indexes of members sorted by name. Used to implement name lookup.
// TODO(someday): Make this a hashtable.
......@@ -229,7 +220,6 @@ template <typename T>
using UnionParentType = typename UnionParentType_<T>::Type;
kj::StringTree structString(StructReader reader, const RawSchema& schema);
kj::StringTree unionString(StructReader reader, const RawSchema& schema, uint memberIndex);
// Declared here so that we can declare inline stringify methods on generated types.
// Defined in stringify.c++, which depends on dynamic.c++, which is allowed not to be linked in.
......@@ -238,12 +228,6 @@ inline kj::StringTree structString(StructReader reader) {
return structString(reader, rawSchema<T>());
}
template <typename T>
inline kj::StringTree unionString(StructReader reader) {
#warning "remove this"
return kj::strTree();
}
} // namespace _ (private)
template <typename T>
......
......@@ -53,7 +53,7 @@ TEST(SchemaLoader, Load) {
EXPECT_TRUE(testListsSchema.getDependency(typeId<test::TestLists::StructP>()) == structPSchema);
auto struct16Schema = testListsSchema.getDependency(typeId<test::TestLists::Struct16>());
EXPECT_EQ(0u, struct16Schema.getProto().getBody().getStructNode().getMembers().size());
EXPECT_EQ(0u, struct16Schema.getProto().getStruct().getFields().size());
}
TEST(SchemaLoader, LoadLateUnion) {
......@@ -61,13 +61,15 @@ TEST(SchemaLoader, LoadLateUnion) {
StructSchema schema =
loader.load(Schema::from<test::TestLateUnion>().getProto()).asStruct();
EXPECT_EQ(6, schema.getMemberByName("theUnion").asUnion()
.getMemberByName("grault").getProto().getOrdinal());
EXPECT_EQ(9, schema.getMemberByName("anotherUnion").asUnion()
.getMemberByName("corge").getProto().getOrdinal());
EXPECT_TRUE(schema.findMemberByName("corge") == nullptr);
EXPECT_TRUE(schema.findMemberByName("grault") == nullptr);
loader.load(Schema::from<test::TestLateUnion::TheUnion>().getProto()).asStruct();
loader.load(Schema::from<test::TestLateUnion::AnotherUnion>().getProto()).asStruct();
EXPECT_EQ(6, schema.getDependency(schema.getFieldByName("theUnion").getProto().getGroup())
.asStruct().getFieldByName("grault").getProto().getOrdinal().getExplicit());
EXPECT_EQ(9, schema.getDependency(schema.getFieldByName("anotherUnion").getProto().getGroup())
.asStruct().getFieldByName("corge").getProto().getOrdinal().getExplicit());
EXPECT_TRUE(schema.findFieldByName("corge") == nullptr);
EXPECT_TRUE(schema.findFieldByName("grault") == nullptr);
}
TEST(SchemaLoader, LoadUnnamedUnion) {
......@@ -76,18 +78,12 @@ TEST(SchemaLoader, LoadUnnamedUnion) {
StructSchema schema =
loader.load(Schema::from<test::TestUnnamedUnion>().getProto()).asStruct();
EXPECT_TRUE(schema.findMemberByName("") == nullptr);
EXPECT_TRUE(schema.findFieldByName("") == nullptr);
KJ_IF_MAYBE(u, schema.getUnnamedUnion()) {
EXPECT_TRUE(schema.getMemberByName("foo") == u->getMemberByName("foo"));
EXPECT_TRUE(schema.getMemberByName("bar") == u->getMemberByName("bar"));
EXPECT_TRUE(u->findMemberByName("before") == nullptr);
EXPECT_TRUE(u->findMemberByName("after") == nullptr);
EXPECT_TRUE(schema.findMemberByName("before") != nullptr);
EXPECT_TRUE(schema.findMemberByName("after") != nullptr);
} else {
ADD_FAILURE() << "getUnnamedUnion() should have returned non-null.";
}
EXPECT_TRUE(schema.findFieldByName("foo") != nullptr);
EXPECT_TRUE(schema.findFieldByName("bar") != nullptr);
EXPECT_TRUE(schema.findFieldByName("before") != nullptr);
EXPECT_TRUE(schema.findFieldByName("after") != nullptr);
}
#if KJ_NO_EXCEPTIONS
......@@ -161,12 +157,14 @@ TEST(SchemaLoader, Use) {
// Finally, let's test some unions.
StructSchema unionSchema = loader.load(Schema::from<TestUnion>().getProto()).asStruct();
loader.load(Schema::from<TestUnion::Union0>().getProto());
loader.load(Schema::from<TestUnion::Union1>().getProto());
{
MallocMessageBuilder builder;
auto root = builder.getRoot<DynamicStruct>(unionSchema);
root.get("union0").as<DynamicUnion>().set("u0f1s16", 123);
root.get("union1").as<DynamicUnion>().set("u1f0sp", "hello");
root.get("union0").as<DynamicStruct>().set("u0f1s16", 123);
root.get("union1").as<DynamicStruct>().set("u1f0sp", "hello");
auto reader = builder.getRoot<TestUnion>().asReader();
EXPECT_EQ(123, reader.getUnion0().getU0f1s16());
......@@ -178,18 +176,18 @@ template <typename T>
Schema loadUnderAlternateTypeId(SchemaLoader& loader, uint64_t id) {
MallocMessageBuilder schemaBuilder;
schemaBuilder.setRoot(Schema::from<T>().getProto());
auto root = schemaBuilder.getRoot<schema::Node>();
auto root = schemaBuilder.getRoot<schema2::Node>();
root.setId(id);
if (root.getBody().which() == schema::Node::Body::STRUCT_NODE) {
if (root.which() == schema2::Node::STRUCT) {
// If the struct contains any self-referential members, change their type IDs as well.
auto members = root.getBody().getStructNode().getMembers();
for (auto member: members) {
if (member.getBody().which() == schema::StructNode::Member::Body::FIELD_MEMBER) {
auto type = member.getBody().getFieldMember().getType().getBody();
if (type.which() == schema::Type::Body::STRUCT_TYPE &&
type.getStructType() == typeId<T>()) {
type.setStructType(id);
auto fields = root.getStruct().getFields();
for (auto field: fields) {
if (field.which() == schema2::Field::REGULAR) {
auto type = field.getRegular().getType();
if (type.which() == schema2::Type::STRUCT &&
type.getStruct() == typeId<T>()) {
type.setStruct(id);
}
}
}
......@@ -284,7 +282,7 @@ TEST(SchemaLoader, EnumerateNoPlaceholders) {
class FakeLoaderCallback: public SchemaLoader::LazyLoadCallback {
public:
FakeLoaderCallback(const schema::Node::Reader node): node(node), loaded(false) {}
FakeLoaderCallback(const schema2::Node::Reader node): node(node), loaded(false) {}
bool isLoaded() { return loaded; }
......@@ -301,7 +299,7 @@ public:
}
private:
const schema::Node::Reader node;
const schema2::Node::Reader node;
mutable bool loaded = false;
};
......
......@@ -170,10 +170,9 @@ public:
return result.begin();
}
const _::RawSchema::MemberInfo* makeMemberInfoArray(uint32_t* count) {
const uint16_t* makeMemberInfoArray(uint32_t* count) {
*count = members.size();
kj::ArrayPtr<_::RawSchema::MemberInfo> result =
loader.arena.allocateArray<_::RawSchema::MemberInfo>(*count);
kj::ArrayPtr<uint16_t> result = loader.arena.allocateArray<uint16_t>(*count);
uint pos = 0;
for (auto& member: members) {
result[pos++] = member.second;
......
......@@ -52,6 +52,12 @@ private:
std::map<kj::StringPtr, kj::StringPtr> files;
};
static uint64_t getFieldTypeFileId(StructSchema::Field field) {
return field.getContainingStruct()
.getDependency(field.getProto().getRegular().getType().getStruct())
.getProto().getScopeId();
}
TEST(SchemaParser, Basic) {
SchemaParser parser;
FakeFileReader reader;
......@@ -90,24 +96,18 @@ TEST(SchemaParser, Basic) {
auto barProto = barSchema.getProto();
EXPECT_EQ(0x8123456789abcdefull, barProto.getId());
EXPECT_EQ("foo2/bar2.capnp", barProto.getDisplayName());
auto barImports = barProto.getBody().getFileNode().getImports();
ASSERT_EQ(4, barImports.size());
EXPECT_EQ("../qux/corge.capnp", barImports[0].getName());
EXPECT_EQ(0x83456789abcdef12ull, barImports[0].getId());
EXPECT_EQ("/garply.capnp", barImports[1].getName());
EXPECT_EQ(0x856789abcdef1234ull, barImports[1].getId());
EXPECT_EQ("/grault.capnp", barImports[2].getName());
EXPECT_EQ(0x8456789abcdef123ull, barImports[2].getId());
EXPECT_EQ("baz.capnp", barImports[3].getName());
EXPECT_EQ(0x823456789abcdef1ull, barImports[3].getId());
auto barStruct = barSchema.getNested("Bar");
auto barMembers = barStruct.asStruct().getMembers();
ASSERT_EQ(4, barMembers.size());
EXPECT_EQ("baz", barMembers[0].getProto().getName());
EXPECT_EQ("corge", barMembers[1].getProto().getName());
EXPECT_EQ("grault", barMembers[2].getProto().getName());
EXPECT_EQ("garply", barMembers[3].getProto().getName());
auto barFields = barStruct.asStruct().getFields();
ASSERT_EQ(4, barFields.size());
EXPECT_EQ("baz", barFields[0].getProto().getName());
EXPECT_EQ(0x823456789abcdef1ull, getFieldTypeFileId(barFields[0]));
EXPECT_EQ("corge", barFields[1].getProto().getName());
EXPECT_EQ(0x83456789abcdef12ull, getFieldTypeFileId(barFields[1]));
EXPECT_EQ("grault", barFields[2].getProto().getName());
EXPECT_EQ(0x8456789abcdef123ull, getFieldTypeFileId(barFields[2]));
EXPECT_EQ("garply", barFields[3].getProto().getName());
EXPECT_EQ(0x856789abcdef1234ull, getFieldTypeFileId(barFields[3]));
auto bazSchema = parser.parseFile(SchemaFile::newDiskFile(
kj::str("not/used/because/already/loaded"),
......
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
......@@ -65,8 +65,21 @@ public:
Schema getDependency(uint64_t id) const;
// Gets the Schema for one of this Schema's dependencies. For example, if this Schema is for a
// struct, you could look up the schema for one of its fields' types. Throws an exception if this
// schema doesn't actually depend on the given id. Note that annotation declarations are not
// considered dependencies for this purpose.
// schema doesn't actually depend on the given id.
//
// Note that not all type IDs found in the schema node are considered "dependencies" -- only the
// ones that are needed to implement the dynamic API are. That includes:
// - Field types.
// - Group types.
// - scopeId for group nodes, but NOT otherwise.
// - Method parameter and return types.
//
// The following are NOT considered dependencies:
// - Nested nodes.
// - scopeId for a non-group node.
// - Annotations.
//
// To obtain schemas for those, you would need a SchemaLoader.
StructSchema asStruct() const;
EnumSchema asEnum() const;
......
This diff is collapsed.
This diff is collapsed.
......@@ -318,21 +318,23 @@ TEST(Stringify, PrettyPrintAdvanced) {
auto s = root.getUn().initAllTypes();
EXPECT_EQ(
"(un = allTypes())",
"(un = (allTypes = ()))",
prettyPrint(root).flatten());
s.setInt32Field(123);
EXPECT_EQ(
"( un = allTypes(int32Field = 123) )",
"( un = (\n"
" allTypes = (int32Field = 123) ) )",
prettyPrint(root).flatten());
s.setTextField("foo");
s.setUInt64Field(0xffffffffffffffffull);
EXPECT_EQ(
"( un = allTypes(\n"
" int32Field = 123,\n"
" uInt64Field = 18446744073709551615,\n"
" textField = \"foo\" ) )",
"( un = (\n"
" allTypes = (\n"
" int32Field = 123,\n"
" uInt64Field = 18446744073709551615,\n"
" textField = \"foo\" ) ) )",
prettyPrint(root).flatten());
}
}
......@@ -347,16 +349,16 @@ TEST(Stringify, Unions) {
root.getUnion3().setU3f0s64(123456789012345678ll);
EXPECT_EQ("("
"union0 = u0f0s16(321), "
"union1 = u1f0sp(\"foo\"), "
"union2 = u2f0s1(true), "
"union3 = u3f0s64(123456789012345678))",
"union0 = (u0f0s16 = 321), "
"union1 = (u1f0sp = \"foo\"), "
"union2 = (u2f0s1 = true), "
"union3 = (u3f0s64 = 123456789012345678))",
kj::str(root));
EXPECT_EQ("u0f0s16(321)", kj::str(root.getUnion0()));
EXPECT_EQ("u1f0sp(\"foo\")", kj::str(root.getUnion1()));
EXPECT_EQ("u2f0s1(true)", kj::str(root.getUnion2()));
EXPECT_EQ("u3f0s64(123456789012345678)", kj::str(root.getUnion3()));
EXPECT_EQ("(u0f0s16 = 321)", kj::str(root.getUnion0()));
EXPECT_EQ("(u1f0sp = \"foo\")", kj::str(root.getUnion1()));
EXPECT_EQ("(u2f0s1 = true)", kj::str(root.getUnion2()));
EXPECT_EQ("(u3f0s64 = 123456789012345678)", kj::str(root.getUnion3()));
}
TEST(Stringify, UnnamedUnions) {
......@@ -365,24 +367,24 @@ TEST(Stringify, UnnamedUnions) {
root.setBar(123);
EXPECT_EQ("(bar(123))", kj::str(root));
EXPECT_EQ("(bar(123))", prettyPrint(root).flatten());
EXPECT_EQ("(bar = 123)", kj::str(root));
EXPECT_EQ("(bar = 123)", prettyPrint(root).flatten());
root.setAfter("foooooooooooooooooooooooooooooooo");
EXPECT_EQ("(bar(123), after = \"foooooooooooooooooooooooooooooooo\")", kj::str(root));
EXPECT_EQ("(bar = 123, after = \"foooooooooooooooooooooooooooooooo\")", kj::str(root));
EXPECT_EQ(
"( bar(123),\n"
"( bar = 123,\n"
" after = \"foooooooooooooooooooooooooooooooo\" )",
prettyPrint(root).flatten());
root.setBefore("before");
EXPECT_EQ("(before = \"before\", bar(123), "
EXPECT_EQ("(before = \"before\", bar = 123, "
"after = \"foooooooooooooooooooooooooooooooo\")", kj::str(root));
EXPECT_EQ(
"( before = \"before\",\n"
" bar(123),\n"
" bar = 123,\n"
" after = \"foooooooooooooooooooooooooooooooo\" )",
prettyPrint(root).flatten());
}
......@@ -395,7 +397,7 @@ TEST(Stringify, StructUnions) {
allTypes.setUInt32Field(12345);
allTypes.setTextField("foo");
EXPECT_EQ("(un = allTypes(uInt32Field = 12345, textField = \"foo\"))", kj::str(root));
EXPECT_EQ("(un = (allTypes = (uInt32Field = 12345, textField = \"foo\")))", kj::str(root));
}
TEST(Stringify, MoreValues) {
......@@ -405,7 +407,7 @@ TEST(Stringify, MoreValues) {
EXPECT_EQ("\"\\a\\b\\n\\t\\\"\"", kj::str(DynamicValue::Reader("\a\b\n\t\"")));
EXPECT_EQ("foo", kj::str(DynamicValue::Reader(TestEnum::FOO)));
EXPECT_EQ("123", kj::str(DynamicValue::Reader(static_cast<TestEnum>(123))));
EXPECT_EQ("(123)", kj::str(DynamicValue::Reader(static_cast<TestEnum>(123))));
}
} // namespace
......
......@@ -195,21 +195,34 @@ static kj::StringTree print(const DynamicValue::Reader& value,
kj::Vector<kj::StringTree> printedFields(nonUnionFields.size() + (unionFields.size() != 0));
KJ_IF_MAYBE(field, structValue.which()) {
if (structValue.has(*field)) {
printedFields.add(kj::strTree(
field->getProto().getName(), " = ",
print(structValue.get(*field), whichFieldType(*field), indent.next(), PREFIXED)));
}
}
// We try to write the union field, if any, in proper order with the rest.
auto which = structValue.which();
for (auto field: nonUnionFields) {
KJ_IF_MAYBE(unionField, which) {
if (unionField->getIndex() < field.getIndex()) {
if (structValue.has(*unionField)) {
printedFields.add(kj::strTree(
unionField->getProto().getName(), " = ",
print(structValue.get(*unionField), whichFieldType(*unionField),
indent.next(), PREFIXED)));
}
which = nullptr;
}
}
if (structValue.has(field)) {
printedFields.add(kj::strTree(
field.getProto().getName(), " = ",
print(structValue.get(field), whichFieldType(field), indent.next(), PREFIXED)));
}
}
KJ_IF_MAYBE(field, which) {
if (structValue.has(*field)) {
printedFields.add(kj::strTree(
field->getProto().getName(), " = ",
print(structValue.get(*field), whichFieldType(*field), indent.next(), PREFIXED)));
}
}
if (mode == PARENTHESIZED) {
return indent.delimit(printedFields.releaseAsArray(), mode);
......
......@@ -291,14 +291,14 @@ struct TestGroups {
struct TestUnionDefaults {
s16s8s64s8Set @0 :TestUnion =
(union0 = u0f0s16(321), union1 = u1f0s8(123), union2 = u2f0s64(12345678901234567),
union3 = u3f0s8(55));
(union0 = (u0f0s16 = 321), union1 = (u1f0s8 = 123), union2 = (u2f0s64 = 12345678901234567),
union3 = (u3f0s8 = 55));
s0sps1s32Set @1 :TestUnion =
(union0 = u0f1s0(void), union1 = u1f0sp("foo"), union2 = u2f0s1(true),
union3 = u3f0s32(12345678));
(union0 = (u0f1s0 = void), union1 = (u1f0sp = "foo"), union2 = (u2f0s1 = true),
union3 = (u3f0s32 = 12345678));
unnamed1 @2 :TestUnnamedUnion = (foo(123));
unnamed2 @3 :TestUnnamedUnion = (bar(321), before = "foo", after = "bar");
unnamed1 @2 :TestUnnamedUnion = (foo = 123);
unnamed2 @3 :TestUnnamedUnion = (bar = 321, before = "foo", after = "bar");
}
struct TestNestedTypes {
......
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