Commit 45c23897 authored by Kenton Varda's avatar Kenton Varda

Fix bug with dynamic unions.

parent 6e335427
......@@ -733,6 +733,14 @@ TEST(DynamicApi, ConversionFailures) {
EXPECT_ANY_THROW(root.set("boolField", 1));
}
TEST(DynamicApi, LateUnion) {
MallocMessageBuilder builder;
auto root = builder.initRoot<DynamicStruct>(Schema::from<test::TestLateUnion>());
root.get("theUnion").as<DynamicUnion>().set("qux", "hello");
EXPECT_EQ("hello", root.as<test::TestLateUnion>().getTheUnion().getQux());
}
} // namespace
} // namespace internal
} // namespace capnproto
......@@ -150,7 +150,7 @@ Maybe<StructSchema::Member> StructSchema::Union::findMemberByName(Text::Reader n
StructSchema::Member StructSchema::Union::getMemberByName(Text::Reader name) const {
Maybe<StructSchema::Member> member = findMemberByName(name);
PRECOND(member != nullptr, "struct has no such member", name);
PRECOND(member != nullptr, "union has no such member", name);
return *member;
}
......
......@@ -339,3 +339,18 @@ struct TestListDefaults {
textListList = [["foo", "bar"], ["baz"], ["qux", "corge"]],
structListList = [[(int32Field = 123), (int32Field = 456)], [(int32Field = 789)]]);
}
struct TestLateUnion {
# Test what happens if the unions are the first ordinals in the struct. At one point this was
# broken for the dynamic API.
foo @0 :Int32;
bar @1 :Text;
baz @2 :Int16;
theUnion @3 union {
qux @4 :Text;
corge @5 :List(Int32);
grault @6 :Float32;
}
}
......@@ -287,8 +287,8 @@ memberTable (DescStruct desc) = let
$ List.sortBy (compare `on` ordinal) $ structMembers desc
-- Fields of each union.
innerMembers = zipWith indexedUnionMembers [1..]
$ List.sortBy (compare `on` unionNumber) $ structUnions desc
innerMembers = catMaybes $ zipWith indexedUnionMembers [1..]
$ List.sortBy (compare `on` ordinal) $ structMembers desc
ordinal (DescField f) = fieldNumber f
ordinal (DescUnion u) = unionNumber u
......@@ -298,8 +298,10 @@ memberTable (DescStruct desc) = let
memberName (DescUnion u) = Just $ unionName u
memberName _ = Nothing
indexedUnionMembers i u = zip (memberIndexes i) $ mapMaybe memberName
$ List.sortBy (compare `on` ordinal) $ unionMembers u
indexedUnionMembers i (DescUnion u) =
Just $ zip (memberIndexes i) $ mapMaybe memberName $
List.sortBy (compare `on` ordinal) $ unionMembers u
indexedUnionMembers _ _ = Nothing
in concat $ topMembers : innerMembers
......
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