Commit 01ac98df authored by Kenton Varda's avatar Kenton Varda

Implement adopt() and disown() for AnyStruct/AnyList fields.

This eliminates a TODO(soon).
parent 8c1cbc54
...@@ -235,6 +235,15 @@ TEST(Any, AnyStructListCapInSchema) { ...@@ -235,6 +235,15 @@ TEST(Any, AnyStructListCapInSchema) {
AnyStruct::Builder anyStruct = root.getAnyStructField(); AnyStruct::Builder anyStruct = root.getAnyStructField();
checkTestMessage(anyStruct.as<TestAllTypes>()); checkTestMessage(anyStruct.as<TestAllTypes>());
checkTestMessage(anyStruct.asReader().as<TestAllTypes>()); checkTestMessage(anyStruct.asReader().as<TestAllTypes>());
EXPECT_TRUE(root.hasAnyStructField());
auto orphan = root.disownAnyStructField();
checkTestMessage(orphan.getReader().as<TestAllTypes>());
EXPECT_FALSE(root.hasAnyStructField());
root.adoptAnyStructField(kj::mv(orphan));
EXPECT_TRUE(root.hasAnyStructField());
checkTestMessage(root.getAnyStructField().as<TestAllTypes>());
} }
{ {
...@@ -245,9 +254,18 @@ TEST(Any, AnyStructListCapInSchema) { ...@@ -245,9 +254,18 @@ TEST(Any, AnyStructListCapInSchema) {
AnyList::Builder anyList = root.getAnyListField(); AnyList::Builder anyList = root.getAnyListField();
checkList(anyList.as<List<int>>(), {123, 456, 789}); checkList(anyList.as<List<int>>(), {123, 456, 789});
EXPECT_TRUE(root.hasAnyListField());
auto orphan = root.disownAnyListField();
checkList(orphan.getReader().as<List<int>>(), {123, 456, 789});
EXPECT_FALSE(root.hasAnyListField());
root.adoptAnyListField(kj::mv(orphan));
EXPECT_TRUE(root.hasAnyListField());
checkList(root.getAnyListField().as<List<int>>(), {123, 456, 789});
} }
#if !CAPNP_LITE #if !CAPNP_LITE
// This portion of the test relies on a Client, not present in lite-mode. // This portion of the test relies on a Client, not present in lite-mode.
{ {
kj::EventLoop loop; kj::EventLoop loop;
...@@ -261,7 +279,7 @@ TEST(Any, AnyStructListCapInSchema) { ...@@ -261,7 +279,7 @@ TEST(Any, AnyStructListCapInSchema) {
req.send().wait(waitScope); req.send().wait(waitScope);
EXPECT_EQ(1, callCount); EXPECT_EQ(1, callCount);
} }
#endif #endif
} }
KJ_TEST("Builder::isStruct() does not corrupt segment pointer") { KJ_TEST("Builder::isStruct() does not corrupt segment pointer") {
......
...@@ -975,9 +975,12 @@ struct PointerHelpers<AnyStruct, Kind::OTHER> { ...@@ -975,9 +975,12 @@ struct PointerHelpers<AnyStruct, Kind::OTHER> {
bounded(pointerCount) * POINTERS))); bounded(pointerCount) * POINTERS)));
} }
// TODO(soon): implement these static void adopt(PointerBuilder builder, Orphan<AnyStruct>&& value) {
static void adopt(PointerBuilder builder, Orphan<AnyStruct>&& value); builder.adopt(kj::mv(value.builder));
static Orphan<AnyStruct> disown(PointerBuilder builder); }
static Orphan<AnyStruct> disown(PointerBuilder builder) {
return Orphan<AnyStruct>(builder.disown());
}
}; };
template <> template <>
...@@ -1006,9 +1009,12 @@ struct PointerHelpers<AnyList, Kind::OTHER> { ...@@ -1006,9 +1009,12 @@ struct PointerHelpers<AnyList, Kind::OTHER> {
bounded(pointerCount) * POINTERS))); bounded(pointerCount) * POINTERS)));
} }
// TODO(soon): implement these static void adopt(PointerBuilder builder, Orphan<AnyList>&& value) {
static void adopt(PointerBuilder builder, Orphan<AnyList>&& value); builder.adopt(kj::mv(value.builder));
static Orphan<AnyList> disown(PointerBuilder builder); }
static Orphan<AnyList> disown(PointerBuilder builder) {
return Orphan<AnyList>(builder.disown());
}
}; };
template <> template <>
...@@ -1024,6 +1030,19 @@ struct OrphanGetImpl<AnyStruct, Kind::OTHER> { ...@@ -1024,6 +1030,19 @@ struct OrphanGetImpl<AnyStruct, Kind::OTHER> {
} }
}; };
template <>
struct OrphanGetImpl<AnyList, Kind::OTHER> {
static inline AnyList::Builder apply(_::OrphanBuilder& builder) {
return AnyList::Builder(builder.asListAnySize());
}
static inline AnyList::Reader applyReader(const _::OrphanBuilder& builder) {
return AnyList::Reader(builder.asListReaderAnySize());
}
static inline void truncateListOf(_::OrphanBuilder& builder, ElementCount size) {
builder.truncate(size, ElementSize::POINTER);
}
};
} // namespace _ (private) } // namespace _ (private)
#if !CAPNP_LITE #if !CAPNP_LITE
......
...@@ -3422,6 +3422,18 @@ ListBuilder OrphanBuilder::asStructList(StructSize elementSize) { ...@@ -3422,6 +3422,18 @@ ListBuilder OrphanBuilder::asStructList(StructSize elementSize) {
return result; return result;
} }
ListBuilder OrphanBuilder::asListAnySize() {
KJ_DASSERT(tagAsPtr()->isNull() == (location == nullptr));
ListBuilder result = WireHelpers::getWritableListPointerAnySize(
tagAsPtr(), location, segment, capTable, nullptr, segment->getArena());
// Watch out, the pointer could have been updated if the object had to be relocated.
location = result.getLocation();
return result;
}
Text::Builder OrphanBuilder::asText() { Text::Builder OrphanBuilder::asText() {
KJ_DASSERT(tagAsPtr()->isNull() == (location == nullptr)); KJ_DASSERT(tagAsPtr()->isNull() == (location == nullptr));
...@@ -3450,6 +3462,13 @@ ListReader OrphanBuilder::asListReader(ElementSize elementSize) const { ...@@ -3450,6 +3462,13 @@ ListReader OrphanBuilder::asListReader(ElementSize elementSize) const {
segment, capTable, tagAsPtr(), location, nullptr, elementSize, kj::maxValue); segment, capTable, tagAsPtr(), location, nullptr, elementSize, kj::maxValue);
} }
ListReader OrphanBuilder::asListReaderAnySize() const {
KJ_DASSERT(tagAsPtr()->isNull() == (location == nullptr));
return WireHelpers::readListPointer(
segment, capTable, tagAsPtr(), location, nullptr, ElementSize::VOID /* dummy */,
kj::maxValue);
}
#if !CAPNP_LITE #if !CAPNP_LITE
kj::Own<ClientHook> OrphanBuilder::asCapability() const { kj::Own<ClientHook> OrphanBuilder::asCapability() const {
return WireHelpers::readCapabilityPointer(segment, capTable, tagAsPtr(), kj::maxValue); return WireHelpers::readCapabilityPointer(segment, capTable, tagAsPtr(), kj::maxValue);
......
...@@ -897,12 +897,16 @@ public: ...@@ -897,12 +897,16 @@ public:
ListBuilder asStructList(StructSize elementSize); ListBuilder asStructList(StructSize elementSize);
// Interpret as a struct list, or throw an exception if not a list. // Interpret as a struct list, or throw an exception if not a list.
ListBuilder asListAnySize();
// For AnyList.
Text::Builder asText(); Text::Builder asText();
Data::Builder asData(); Data::Builder asData();
// Interpret as a blob, or throw an exception if not a blob. // Interpret as a blob, or throw an exception if not a blob.
StructReader asStructReader(StructSize size) const; StructReader asStructReader(StructSize size) const;
ListReader asListReader(ElementSize elementSize) const; ListReader asListReader(ElementSize elementSize) const;
ListReader asListReaderAnySize() const;
#if !CAPNP_LITE #if !CAPNP_LITE
kj::Own<ClientHook> asCapability() const; kj::Own<ClientHook> asCapability() const;
#endif // !CAPNP_LITE #endif // !CAPNP_LITE
......
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