Commit d99c0b4c authored by Kenton Varda's avatar Kenton Varda

Remove DynamicObject. DynamicValue can now contain an ObjectPointer to represent object fields.

parent 2b643930
...@@ -1811,13 +1811,13 @@ kj::Maybe<DynamicValue::Reader> NodeTranslator::readConstant( ...@@ -1811,13 +1811,13 @@ kj::Maybe<DynamicValue::Reader> NodeTranslator::readConstant(
if (constValue.getType() == DynamicValue::OBJECT) { if (constValue.getType() == DynamicValue::OBJECT) {
// We need to assign an appropriate schema to this object. // We need to assign an appropriate schema to this object.
DynamicObject::Reader objValue = constValue.as<DynamicObject>(); ObjectPointer::Reader objValue = constValue.as<ObjectPointer>();
auto constType = constReader.getType(); auto constType = constReader.getType();
switch (constType.which()) { switch (constType.which()) {
case schema::Type::STRUCT: case schema::Type::STRUCT:
KJ_IF_MAYBE(structSchema, resolver.resolveBootstrapSchema( KJ_IF_MAYBE(structSchema, resolver.resolveBootstrapSchema(
constType.getStruct().getTypeId())) { constType.getStruct().getTypeId())) {
constValue = objValue.as(structSchema->asStruct()); constValue = objValue.getAs<DynamicStruct>(structSchema->asStruct());
} else { } else {
// The struct's schema is broken for reasons already reported. // The struct's schema is broken for reasons already reported.
return nullptr; return nullptr;
...@@ -1825,7 +1825,7 @@ kj::Maybe<DynamicValue::Reader> NodeTranslator::readConstant( ...@@ -1825,7 +1825,7 @@ kj::Maybe<DynamicValue::Reader> NodeTranslator::readConstant(
break; break;
case schema::Type::LIST: case schema::Type::LIST:
KJ_IF_MAYBE(listSchema, makeListSchemaOf(constType.getList().getElementType())) { KJ_IF_MAYBE(listSchema, makeListSchemaOf(constType.getList().getElementType())) {
constValue = objValue.as(*listSchema); constValue = objValue.getAs<DynamicList>(*listSchema);
} else { } else {
// The list's schema is broken for reasons already reported. // The list's schema is broken for reasons already reported.
return nullptr; return nullptr;
......
...@@ -191,11 +191,14 @@ TEST(DynamicApi, DynamicGenericObjects) { ...@@ -191,11 +191,14 @@ TEST(DynamicApi, DynamicGenericObjects) {
checkTestMessage(root.asReader().as<test::TestObject>().getObjectField().getAs<TestAllTypes>()); checkTestMessage(root.asReader().as<test::TestObject>().getObjectField().getAs<TestAllTypes>());
checkDynamicTestMessage( checkDynamicTestMessage(
root.asReader().get("objectField").as<DynamicObject>().as(Schema::from<TestAllTypes>())); root.asReader().get("objectField").as<ObjectPointer>()
.getAs<DynamicStruct>(Schema::from<TestAllTypes>()));
checkDynamicTestMessage( checkDynamicTestMessage(
root.asReader().get("objectField").as<DynamicObject>().as(Schema::from<TestAllTypes>())); root.asReader().get("objectField").as<ObjectPointer>()
.getAs<DynamicStruct>(Schema::from<TestAllTypes>()));
checkDynamicTestMessage( checkDynamicTestMessage(
root.get("objectField").as<DynamicObject>().asReader().as(Schema::from<TestAllTypes>())); root.get("objectField").as<ObjectPointer>().asReader()
.getAs<DynamicStruct>(Schema::from<TestAllTypes>()));
checkDynamicTestMessage( checkDynamicTestMessage(
root.getObject("objectField", Schema::from<TestAllTypes>())); root.getObject("objectField", Schema::from<TestAllTypes>()));
...@@ -218,13 +221,16 @@ TEST(DynamicApi, DynamicGenericObjects) { ...@@ -218,13 +221,16 @@ TEST(DynamicApi, DynamicGenericObjects) {
} }
checkList<uint32_t>( checkList<uint32_t>(
root.asReader().get("objectField").as<DynamicObject>().as(Schema::from<List<uint32_t>>()), root.asReader().get("objectField").as<ObjectPointer>()
.getAs<DynamicList>(Schema::from<List<uint32_t>>()),
{123u, 456u, 789u, 123456789u}); {123u, 456u, 789u, 123456789u});
checkList<uint32_t>( checkList<uint32_t>(
root.asReader().get("objectField").as<DynamicObject>().as(Schema::from<List<uint32_t>>()), root.asReader().get("objectField").as<ObjectPointer>()
.getAs<DynamicList>(Schema::from<List<uint32_t>>()),
{123u, 456u, 789u, 123456789u}); {123u, 456u, 789u, 123456789u});
checkList<uint32_t>( checkList<uint32_t>(
root.get("objectField").as<DynamicObject>().asReader().as(Schema::from<List<uint32_t>>()), root.get("objectField").as<ObjectPointer>().asReader()
.getAs<DynamicList>(Schema::from<List<uint32_t>>()),
{123u, 456u, 789u, 123456789u}); {123u, 456u, 789u, 123456789u});
checkList<uint32_t>( checkList<uint32_t>(
root.getObject("objectField", Schema::from<List<uint32_t>>()), root.getObject("objectField", Schema::from<List<uint32_t>>()),
......
...@@ -125,30 +125,6 @@ uint16_t DynamicEnum::asImpl(uint64_t requestedTypeId) const { ...@@ -125,30 +125,6 @@ uint16_t DynamicEnum::asImpl(uint64_t requestedTypeId) const {
// ======================================================================================= // =======================================================================================
DynamicStruct::Reader DynamicObject::Reader::as(StructSchema schema) const {
if (reader.kind == _::ObjectKind::NULL_POINTER) {
return DynamicStruct::Reader(schema, _::StructReader());
}
KJ_REQUIRE(reader.kind == _::ObjectKind::STRUCT, "Object is not a struct.") {
// Return default struct.
return DynamicStruct::Reader(schema, _::StructReader());
}
return DynamicStruct::Reader(schema, reader.structReader);
}
DynamicList::Reader DynamicObject::Reader::as(ListSchema schema) const {
if (reader.kind == _::ObjectKind::NULL_POINTER) {
return DynamicList::Reader(schema, _::ListReader());
}
KJ_REQUIRE(reader.kind == _::ObjectKind::LIST, "Object is not a list.") {
// Return empty list.
return DynamicList::Reader(schema, _::ListReader());
}
return DynamicList::Reader(schema, reader.listReader);
}
// =======================================================================================
bool DynamicStruct::Reader::isSetInUnion(StructSchema::Field field) const { bool DynamicStruct::Reader::isSetInUnion(StructSchema::Field field) const {
auto proto = field.getProto(); auto proto = field.getProto();
if (proto.hasDiscriminantValue()) { if (proto.hasDiscriminantValue()) {
...@@ -257,18 +233,14 @@ DynamicValue::Reader DynamicStruct::Reader::get(StructSchema::Field field) const ...@@ -257,18 +233,14 @@ DynamicValue::Reader DynamicStruct::Reader::get(StructSchema::Field field) const
dval.getList().getAs<_::UncheckedMessage>())); dval.getList().getAs<_::UncheckedMessage>()));
} }
case schema::Type::STRUCT: { case schema::Type::STRUCT:
return DynamicStruct::Reader( return DynamicStruct::Reader(
field.getContainingStruct().getDependency(type.getStruct().getTypeId()).asStruct(), field.getContainingStruct().getDependency(type.getStruct().getTypeId()).asStruct(),
reader.getPointerField(slot.getOffset() * POINTERS) reader.getPointerField(slot.getOffset() * POINTERS)
.getStruct(dval.getStruct().getAs<_::UncheckedMessage>())); .getStruct(dval.getStruct().getAs<_::UncheckedMessage>()));
}
case schema::Type::OBJECT: { case schema::Type::OBJECT:
return DynamicObject::Reader( return ObjectPointer::Reader(reader.getPointerField(slot.getOffset() * POINTERS));
reader.getPointerField(slot.getOffset() * POINTERS)
.getObject(dval.getObject().getAs<_::UncheckedMessage>()));
}
case schema::Type::INTERFACE: case schema::Type::INTERFACE:
KJ_FAIL_ASSERT("Interfaces not yet implemented."); KJ_FAIL_ASSERT("Interfaces not yet implemented.");
...@@ -366,11 +338,8 @@ DynamicValue::Builder DynamicStruct::Builder::get(StructSchema::Field field) { ...@@ -366,11 +338,8 @@ DynamicValue::Builder DynamicStruct::Builder::get(StructSchema::Field field) {
dval.getStruct().getAs<_::UncheckedMessage>())); dval.getStruct().getAs<_::UncheckedMessage>()));
} }
case schema::Type::OBJECT: { case schema::Type::OBJECT:
return DynamicObject::Builder( return ObjectPointer::Builder(builder.getPointerField(slot.getOffset() * POINTERS));
builder.getPointerField(slot.getOffset() * POINTERS)
.getObject(dval.getObject().getAs<_::UncheckedMessage>()));
}
case schema::Type::INTERFACE: case schema::Type::INTERFACE:
KJ_FAIL_ASSERT("Interfaces not yet implemented."); KJ_FAIL_ASSERT("Interfaces not yet implemented.");
...@@ -579,8 +548,8 @@ void DynamicStruct::Builder::set(StructSchema::Field field, const DynamicValue:: ...@@ -579,8 +548,8 @@ void DynamicStruct::Builder::set(StructSchema::Field field, const DynamicValue::
} }
case schema::Type::OBJECT: case schema::Type::OBJECT:
builder.getPointerField(slot.getOffset() * POINTERS) ObjectPointer::Builder(builder.getPointerField(slot.getOffset() * POINTERS))
.setObject(value.as<DynamicObject>().reader); .set(value.as<ObjectPointer>());
return; return;
case schema::Type::INTERFACE: case schema::Type::INTERFACE:
...@@ -1115,7 +1084,7 @@ DynamicValue::Reader DynamicList::Reader::operator[](uint index) const { ...@@ -1115,7 +1084,7 @@ DynamicValue::Reader DynamicList::Reader::operator[](uint index) const {
reader.getDataElement<uint16_t>(index * ELEMENTS)); reader.getDataElement<uint16_t>(index * ELEMENTS));
case schema::Type::OBJECT: case schema::Type::OBJECT:
return DynamicObject::Reader(reader.getPointerElement(index * ELEMENTS).getObject(nullptr)); return ObjectPointer::Reader(reader.getPointerElement(index * ELEMENTS));
case schema::Type::INTERFACE: case schema::Type::INTERFACE:
KJ_FAIL_ASSERT("Interfaces not implemented.") { KJ_FAIL_ASSERT("Interfaces not implemented.") {
...@@ -1480,7 +1449,7 @@ DynamicValue::Reader::Reader(ConstSchema constant) { ...@@ -1480,7 +1449,7 @@ DynamicValue::Reader::Reader(ConstSchema constant) {
break; break;
case schema::Type::OBJECT: case schema::Type::OBJECT:
*this = value.getObject().getAs<DynamicObject>(); *this = value.getObject();
break; break;
case schema::Type::INTERFACE: case schema::Type::INTERFACE:
...@@ -1620,7 +1589,7 @@ HANDLE_TYPE(text, TEXT, Text) ...@@ -1620,7 +1589,7 @@ HANDLE_TYPE(text, TEXT, Text)
HANDLE_TYPE(list, LIST, DynamicList) HANDLE_TYPE(list, LIST, DynamicList)
HANDLE_TYPE(struct, STRUCT, DynamicStruct) HANDLE_TYPE(struct, STRUCT, DynamicStruct)
HANDLE_TYPE(enum, ENUM, DynamicEnum) HANDLE_TYPE(enum, ENUM, DynamicEnum)
HANDLE_TYPE(object, OBJECT, DynamicObject) HANDLE_TYPE(object, OBJECT, ObjectPointer)
#undef HANDLE_TYPE #undef HANDLE_TYPE
...@@ -1759,17 +1728,6 @@ DynamicList::Builder PointerHelpers<DynamicList, Kind::UNKNOWN>::init( ...@@ -1759,17 +1728,6 @@ DynamicList::Builder PointerHelpers<DynamicList, Kind::UNKNOWN>::init(
} }
} }
DynamicObject::Reader PointerHelpers<DynamicObject, Kind::UNKNOWN>::get(PointerReader reader) {
return DynamicObject::Reader(reader.getObject(nullptr));
}
DynamicObject::Builder PointerHelpers<DynamicObject, Kind::UNKNOWN>::get(PointerBuilder builder) {
return DynamicObject::Builder(builder.getObject(nullptr));
}
void PointerHelpers<DynamicObject, Kind::UNKNOWN>::set(
PointerBuilder builder, const DynamicObject::Reader& value) {
builder.setObject(value.reader);
}
} // namespace _ (private) } // namespace _ (private)
template <> template <>
...@@ -1795,6 +1753,38 @@ void ObjectPointer::Builder::adopt<DynamicValue>(Orphan<DynamicValue>&& orphan) ...@@ -1795,6 +1753,38 @@ void ObjectPointer::Builder::adopt<DynamicValue>(Orphan<DynamicValue>&& orphan)
} }
} }
template <>
DynamicStruct::Builder Orphan<ObjectPointer>::getAs<DynamicStruct>(StructSchema schema) {
return DynamicStruct::Builder(schema, builder.asStruct(structSizeFromSchema(schema)));
}
template <>
DynamicStruct::Reader Orphan<ObjectPointer>::getAsReader<DynamicStruct>(StructSchema schema) const {
return DynamicStruct::Reader(schema, builder.asStructReader(structSizeFromSchema(schema)));
}
template <>
Orphan<DynamicStruct> Orphan<ObjectPointer>::releaseAs<DynamicStruct>(StructSchema schema) {
return Orphan<DynamicStruct>(schema, kj::mv(builder));
}
template <>
DynamicList::Builder Orphan<ObjectPointer>::getAs<DynamicList>(ListSchema schema) {
if (schema.whichElementType() == schema::Type::STRUCT) {
return DynamicList::Builder(schema, builder.asStructList(
structSizeFromSchema(schema.getStructElementType())));
} else {
return DynamicList::Builder(schema, builder.asList(elementSizeFor(schema.whichElementType())));
}
}
template <>
DynamicList::Reader Orphan<ObjectPointer>::getAsReader<DynamicList>(ListSchema schema) const {
return DynamicList::Reader(schema, builder.asListReader(
elementSizeFor(schema.whichElementType())));
}
template <>
Orphan<DynamicList> Orphan<ObjectPointer>::releaseAs<DynamicList>(ListSchema schema) {
return Orphan<DynamicList>(schema, kj::mv(builder));
}
// ------------------------------------------------------------------- // -------------------------------------------------------------------
Orphan<DynamicStruct> Orphanage::newOrphan(StructSchema schema) const { Orphan<DynamicStruct> Orphanage::newOrphan(StructSchema schema) const {
...@@ -1835,53 +1825,6 @@ DynamicList::Reader Orphan<DynamicList>::getReader() const { ...@@ -1835,53 +1825,6 @@ DynamicList::Reader Orphan<DynamicList>::getReader() const {
schema, builder.asListReader(elementSizeFor(schema.whichElementType()))); schema, builder.asListReader(elementSizeFor(schema.whichElementType())));
} }
DynamicObject::Builder Orphan<DynamicObject>::get() {
return DynamicObject::Builder(builder.asObject());
}
DynamicObject::Reader Orphan<DynamicObject>::getReader() const {
return DynamicObject::Reader(builder.asObjectReader());
}
DynamicStruct::Builder Orphan<DynamicObject>::getAs(StructSchema schema) {
return DynamicStruct::Builder(schema, builder.asStruct(structSizeFromSchema(schema)));
}
DynamicList::Builder Orphan<DynamicObject>::getAs(ListSchema schema) {
if (schema.whichElementType() == schema::Type::STRUCT) {
return DynamicList::Builder(schema,
builder.asStructList(structSizeFromSchema(schema.getStructElementType())));
} else {
return DynamicList::Builder(schema,
builder.asList(elementSizeFor(schema.whichElementType())));
}
}
template <>
Text::Builder Orphan<DynamicObject>::getAs<Text>() {
return builder.asText();
}
template <>
Data::Builder Orphan<DynamicObject>::getAs<Data>() {
return builder.asData();
}
Orphan<DynamicStruct> Orphan<DynamicObject>::releaseAs(StructSchema schema) {
getAs(schema); // type check
return Orphan<DynamicStruct>(schema, kj::mv(builder));
}
Orphan<DynamicList> Orphan<DynamicObject>::releaseAs(ListSchema schema) {
getAs(schema); // type check
return Orphan<DynamicList>(schema, kj::mv(builder));
}
template <>
Orphan<Text> Orphan<DynamicObject>::releaseAs<Text>() {
getAs<Text>(); // type check
return Orphan<Text>(kj::mv(builder));
}
template <>
Orphan<Data> Orphan<DynamicObject>::releaseAs<Data>() {
getAs<Data>(); // type check
return Orphan<Data>(kj::mv(builder));
}
Orphan<DynamicValue>::Orphan(DynamicValue::Builder value, _::OrphanBuilder&& builder) Orphan<DynamicValue>::Orphan(DynamicValue::Builder value, _::OrphanBuilder&& builder)
: type(value.getType()), builder(kj::mv(builder)) { : type(value.getType()), builder(kj::mv(builder)) {
switch (type) { switch (type) {
...@@ -1928,7 +1871,8 @@ DynamicValue::Builder Orphan<DynamicValue>::get() { ...@@ -1928,7 +1871,8 @@ DynamicValue::Builder Orphan<DynamicValue>::get() {
case DynamicValue::INTERFACE: case DynamicValue::INTERFACE:
KJ_FAIL_ASSERT("Interfaces not implemented."); KJ_FAIL_ASSERT("Interfaces not implemented.");
case DynamicValue::OBJECT: case DynamicValue::OBJECT:
return DynamicObject::Builder(builder.asObject()); KJ_FAIL_REQUIRE("Can't get() an untyped Object orphan; there is no underlying pointer to "
"wrap in an ObjectPointer::Builder.");
} }
KJ_UNREACHABLE; KJ_UNREACHABLE;
} }
...@@ -1953,11 +1897,18 @@ DynamicValue::Reader Orphan<DynamicValue>::getReader() const { ...@@ -1953,11 +1897,18 @@ DynamicValue::Reader Orphan<DynamicValue>::getReader() const {
case DynamicValue::INTERFACE: case DynamicValue::INTERFACE:
KJ_FAIL_ASSERT("Interfaces not implemented."); KJ_FAIL_ASSERT("Interfaces not implemented.");
case DynamicValue::OBJECT: case DynamicValue::OBJECT:
return DynamicObject::Reader(builder.asObjectReader()); KJ_FAIL_ASSERT("Can't get() an untyped Object orphan; there is no underlying pointer to "
"wrap in an ObjectPointer::Builder.");
} }
KJ_UNREACHABLE; KJ_UNREACHABLE;
} }
template <>
Orphan<ObjectPointer> Orphan<DynamicValue>::releaseAs<ObjectPointer>() {
KJ_REQUIRE(type == DynamicValue::OBJECT, "Value type mismatch.");
type = DynamicValue::UNKNOWN;
return Orphan<ObjectPointer>(kj::mv(builder));
}
template <> template <>
Orphan<DynamicStruct> Orphan<DynamicValue>::releaseAs<DynamicStruct>() { Orphan<DynamicStruct> Orphan<DynamicValue>::releaseAs<DynamicStruct>() {
KJ_REQUIRE(type == DynamicValue::STRUCT, "Value type mismatch."); KJ_REQUIRE(type == DynamicValue::STRUCT, "Value type mismatch.");
...@@ -1971,20 +1922,6 @@ Orphan<DynamicList> Orphan<DynamicValue>::releaseAs<DynamicList>() { ...@@ -1971,20 +1922,6 @@ Orphan<DynamicList> Orphan<DynamicValue>::releaseAs<DynamicList>() {
return Orphan<DynamicList>(listSchema, kj::mv(builder)); return Orphan<DynamicList>(listSchema, kj::mv(builder));
} }
template <>
Orphan<DynamicObject> Orphanage::newOrphanCopy<DynamicObject::Reader>(
const DynamicObject::Reader& copyFrom) const {
switch (copyFrom.reader.kind) {
case _::ObjectKind::NULL_POINTER:
return Orphan<DynamicObject>();
case _::ObjectKind::STRUCT:
return Orphan<DynamicObject>(_::OrphanBuilder::copy(arena, copyFrom.reader.structReader));
case _::ObjectKind::LIST:
return Orphan<DynamicObject>(_::OrphanBuilder::copy(arena, copyFrom.reader.listReader));
}
KJ_UNREACHABLE;
}
template <> template <>
Orphan<DynamicValue> Orphanage::newOrphanCopy<DynamicValue::Reader>( Orphan<DynamicValue> Orphanage::newOrphanCopy<DynamicValue::Reader>(
const DynamicValue::Reader& copyFrom) const { const DynamicValue::Reader& copyFrom) const {
......
...@@ -72,11 +72,6 @@ struct DynamicValue { ...@@ -72,11 +72,6 @@ struct DynamicValue {
class Builder; class Builder;
}; };
class DynamicEnum; class DynamicEnum;
struct DynamicObject {
DynamicObject() = delete;
class Reader;
class Builder;
};
struct DynamicStruct { struct DynamicStruct {
DynamicStruct() = delete; DynamicStruct() = delete;
class Reader; class Reader;
...@@ -147,68 +142,6 @@ private: ...@@ -147,68 +142,6 @@ private:
// ------------------------------------------------------------------- // -------------------------------------------------------------------
class DynamicObject::Reader {
// Represents an "Object" field of unknown type.
public:
typedef DynamicObject Reads;
Reader() = default;
template <typename T>
typename T::Reader as() const;
// Convert the object to the given struct, list, or blob type.
DynamicStruct::Reader as(StructSchema schema) const;
DynamicList::Reader as(ListSchema schema) const;
private:
_::ObjectReader reader;
inline Reader(_::ObjectReader reader): reader(reader) {}
friend struct DynamicStruct;
friend struct DynamicList;
template <typename T, Kind K>
friend struct _::PointerHelpers;
friend class DynamicObject::Builder;
friend class Orphan<DynamicObject>;
friend class Orphan<DynamicValue>;
friend class Orphanage;
};
class DynamicObject::Builder: public kj::DisallowConstCopy {
// Represents an "Object" field of unknown type.
//
// You can't actually do anything with a DynamicObject::Builder except read it. It can't be
// converted to a Builder for any specific type because that could require initializing or
// updating the pointer that points *to* this object. Therefore, you must call
// DynamicStruct::Builder::{get,set,init}Object() and pass a type schema to build object fields.
public:
typedef DynamicObject Builds;
Builder() = default;
inline Builder(decltype(nullptr)) {}
Builder(Builder&) = default;
Builder(Builder&&) = default;
Reader asReader() const { return Reader(builder.asReader()); }
private:
_::ObjectBuilder builder;
inline Builder(_::ObjectBuilder builder): builder(builder) {}
friend struct DynamicStruct;
friend struct DynamicList;
template <typename T, Kind K>
friend struct _::PointerHelpers;
friend class Orphan<DynamicObject>;
friend class Orphan<DynamicValue>;
};
// -------------------------------------------------------------------
class DynamicStruct::Reader { class DynamicStruct::Reader {
public: public:
typedef DynamicStruct Reads; typedef DynamicStruct Reads;
...@@ -260,7 +193,6 @@ private: ...@@ -260,7 +193,6 @@ private:
template <typename T, Kind K> template <typename T, Kind K>
friend struct _::PointerHelpers; friend struct _::PointerHelpers;
friend struct DynamicObject;
friend class DynamicStruct::Builder; friend class DynamicStruct::Builder;
friend struct DynamicList; friend struct DynamicList;
friend class MessageReader; friend class MessageReader;
...@@ -272,6 +204,7 @@ private: ...@@ -272,6 +204,7 @@ private:
friend class Orphanage; friend class Orphanage;
friend class Orphan<DynamicStruct>; friend class Orphan<DynamicStruct>;
friend class Orphan<DynamicValue>; friend class Orphan<DynamicValue>;
friend class Orphan<ObjectPointer>;
}; };
class DynamicStruct::Builder { class DynamicStruct::Builder {
...@@ -380,8 +313,8 @@ private: ...@@ -380,8 +313,8 @@ private:
friend struct ::capnp::ToDynamic_; friend struct ::capnp::ToDynamic_;
friend class Orphanage; friend class Orphanage;
friend class Orphan<DynamicStruct>; friend class Orphan<DynamicStruct>;
friend class Orphan<DynamicObject>;
friend class Orphan<DynamicValue>; friend class Orphan<DynamicValue>;
friend class Orphan<ObjectPointer>;
}; };
// ------------------------------------------------------------------- // -------------------------------------------------------------------
...@@ -418,13 +351,13 @@ private: ...@@ -418,13 +351,13 @@ private:
template <typename T, Kind k> template <typename T, Kind k>
friend struct _::PointerHelpers; friend struct _::PointerHelpers;
friend struct DynamicStruct; friend struct DynamicStruct;
friend struct DynamicObject;
friend class DynamicList::Builder; friend class DynamicList::Builder;
template <typename T, ::capnp::Kind k> template <typename T, ::capnp::Kind k>
friend struct ::capnp::ToDynamic_; friend struct ::capnp::ToDynamic_;
friend class Orphanage; friend class Orphanage;
friend class Orphan<DynamicList>; friend class Orphan<DynamicList>;
friend class Orphan<DynamicValue>; friend class Orphan<DynamicValue>;
friend class Orphan<ObjectPointer>;
}; };
class DynamicList::Builder { class DynamicList::Builder {
...@@ -474,19 +407,17 @@ private: ...@@ -474,19 +407,17 @@ private:
template <typename T, Kind k> template <typename T, Kind k>
friend struct _::OrphanGetImpl; friend struct _::OrphanGetImpl;
friend class Orphan<DynamicList>; friend class Orphan<DynamicList>;
friend class Orphan<DynamicObject>;
friend class Orphan<DynamicValue>; friend class Orphan<DynamicValue>;
friend class Orphan<ObjectPointer>;
}; };
// ------------------------------------------------------------------- // -------------------------------------------------------------------
// Make sure ReaderFor<T> and BuilderFor<T> work for DynamicEnum, DynamicObject, DynamicStruct, and // Make sure ReaderFor<T> and BuilderFor<T> work for DynamicEnum, DynamicStruct, and
// DynamicList, so that we can define DynamicValue::as(). // DynamicList, so that we can define DynamicValue::as().
template <> struct ReaderFor_ <DynamicEnum, Kind::UNKNOWN> { typedef DynamicEnum Type; }; template <> struct ReaderFor_ <DynamicEnum, Kind::UNKNOWN> { typedef DynamicEnum Type; };
template <> struct BuilderFor_<DynamicEnum, Kind::UNKNOWN> { typedef DynamicEnum Type; }; template <> struct BuilderFor_<DynamicEnum, Kind::UNKNOWN> { typedef DynamicEnum Type; };
template <> struct ReaderFor_ <DynamicObject, Kind::UNKNOWN> { typedef DynamicObject::Reader Type; };
template <> struct BuilderFor_<DynamicObject, Kind::UNKNOWN> { typedef DynamicObject::Builder Type; };
template <> struct ReaderFor_ <DynamicStruct, Kind::UNKNOWN> { typedef DynamicStruct::Reader Type; }; template <> struct ReaderFor_ <DynamicStruct, Kind::UNKNOWN> { typedef DynamicStruct::Reader Type; };
template <> struct BuilderFor_<DynamicStruct, Kind::UNKNOWN> { typedef DynamicStruct::Builder Type; }; template <> struct BuilderFor_<DynamicStruct, Kind::UNKNOWN> { typedef DynamicStruct::Builder Type; };
template <> struct ReaderFor_ <DynamicList, Kind::UNKNOWN> { typedef DynamicList::Reader Type; }; template <> struct ReaderFor_ <DynamicList, Kind::UNKNOWN> { typedef DynamicList::Reader Type; };
...@@ -518,7 +449,7 @@ public: ...@@ -518,7 +449,7 @@ public:
inline Reader(const DynamicList::Reader& value); inline Reader(const DynamicList::Reader& value);
inline Reader(DynamicEnum value); inline Reader(DynamicEnum value);
inline Reader(const DynamicStruct::Reader& value); inline Reader(const DynamicStruct::Reader& value);
inline Reader(const DynamicObject::Reader& value); inline Reader(const ObjectPointer::Reader& value);
Reader(ConstSchema constant); Reader(ConstSchema constant);
template <typename T, typename = decltype(toDynamic(kj::instance<T>()))> template <typename T, typename = decltype(toDynamic(kj::instance<T>()))>
...@@ -528,9 +459,9 @@ public: ...@@ -528,9 +459,9 @@ public:
inline ReaderFor<T> as() const { return AsImpl<T>::apply(*this); } inline ReaderFor<T> as() const { return AsImpl<T>::apply(*this); }
// Use to interpret the value as some Cap'n Proto type. Allowed types are: // Use to interpret the value as some Cap'n Proto type. Allowed types are:
// - Void, bool, [u]int{8,16,32,64}_t, float, double, any enum: Returns the raw value. // - Void, bool, [u]int{8,16,32,64}_t, float, double, any enum: Returns the raw value.
// - Text, Data, any struct type: Returns the corresponding Reader. // - Text, Data, ObjectPointer, any struct type: Returns the corresponding Reader.
// - List<T> for any T listed above: Returns List<T>::Reader. // - List<T> for any T listed above: Returns List<T>::Reader.
// - DynamicEnum, DynamicObject: Returns the corresponding type. // - DynamicEnum: Returns the corresponding type.
// - DynamicStruct, DynamicList: Returns the corresponding Reader. // - DynamicStruct, DynamicList: Returns the corresponding Reader.
// //
// DynamicValue allows various implicit conversions, mostly just to make the interface friendlier. // DynamicValue allows various implicit conversions, mostly just to make the interface friendlier.
...@@ -563,7 +494,7 @@ private: ...@@ -563,7 +494,7 @@ private:
DynamicList::Reader listValue; DynamicList::Reader listValue;
DynamicEnum enumValue; DynamicEnum enumValue;
DynamicStruct::Reader structValue; DynamicStruct::Reader structValue;
DynamicObject::Reader objectValue; ObjectPointer::Reader objectValue;
}; };
template <typename T, Kind kind = kind<T>()> struct AsImpl; template <typename T, Kind kind = kind<T>()> struct AsImpl;
...@@ -598,7 +529,7 @@ public: ...@@ -598,7 +529,7 @@ public:
inline Builder(DynamicList::Builder value); inline Builder(DynamicList::Builder value);
inline Builder(DynamicEnum value); inline Builder(DynamicEnum value);
inline Builder(DynamicStruct::Builder value); inline Builder(DynamicStruct::Builder value);
inline Builder(DynamicObject::Builder value); inline Builder(ObjectPointer::Builder value);
template <typename T, typename = decltype(toDynamic(kj::instance<T>()))> template <typename T, typename = decltype(toDynamic(kj::instance<T>()))>
inline Builder(T value): Builder(toDynamic(value)) {} inline Builder(T value): Builder(toDynamic(value)) {}
...@@ -635,7 +566,7 @@ private: ...@@ -635,7 +566,7 @@ private:
DynamicList::Builder listValue; DynamicList::Builder listValue;
DynamicEnum enumValue; DynamicEnum enumValue;
DynamicStruct::Builder structValue; DynamicStruct::Builder structValue;
DynamicObject::Builder objectValue; ObjectPointer::Builder objectValue;
}; };
template <typename T, Kind kind = kind<T>()> struct AsImpl; template <typename T, Kind kind = kind<T>()> struct AsImpl;
...@@ -648,8 +579,6 @@ private: ...@@ -648,8 +579,6 @@ private:
kj::StringTree KJ_STRINGIFY(const DynamicValue::Reader& value); kj::StringTree KJ_STRINGIFY(const DynamicValue::Reader& value);
kj::StringTree KJ_STRINGIFY(const DynamicValue::Builder& value); kj::StringTree KJ_STRINGIFY(const DynamicValue::Builder& value);
kj::StringTree KJ_STRINGIFY(DynamicEnum value); kj::StringTree KJ_STRINGIFY(DynamicEnum value);
kj::StringTree KJ_STRINGIFY(const DynamicObject::Reader& value);
kj::StringTree KJ_STRINGIFY(const DynamicObject::Builder& value);
kj::StringTree KJ_STRINGIFY(const DynamicStruct::Reader& value); kj::StringTree KJ_STRINGIFY(const DynamicStruct::Reader& value);
kj::StringTree KJ_STRINGIFY(const DynamicStruct::Builder& value); kj::StringTree KJ_STRINGIFY(const DynamicStruct::Builder& value);
kj::StringTree KJ_STRINGIFY(const DynamicList::Reader& value); kj::StringTree KJ_STRINGIFY(const DynamicList::Reader& value);
...@@ -689,8 +618,8 @@ private: ...@@ -689,8 +618,8 @@ private:
friend struct _::PointerHelpers; friend struct _::PointerHelpers;
friend struct DynamicList; friend struct DynamicList;
friend class Orphanage; friend class Orphanage;
friend class Orphan<DynamicObject>;
friend class Orphan<DynamicValue>; friend class Orphan<DynamicValue>;
friend class Orphan<ObjectPointer>;
friend class MessageBuilder; friend class MessageBuilder;
}; };
...@@ -725,56 +654,8 @@ private: ...@@ -725,56 +654,8 @@ private:
friend struct _::PointerHelpers; friend struct _::PointerHelpers;
friend struct DynamicList; friend struct DynamicList;
friend class Orphanage; friend class Orphanage;
friend class Orphan<DynamicObject>;
friend class Orphan<DynamicValue>;
};
template <>
class Orphan<DynamicObject> {
public:
Orphan() = default;
KJ_DISALLOW_COPY(Orphan);
Orphan(Orphan&&) = default;
Orphan& operator=(Orphan&&) = default;
DynamicObject::Builder get();
DynamicObject::Reader getReader() const;
template <typename T>
BuilderFor<T> getAs();
// Coerce the object to the given type and return a builder for that type. This may relocate
// the object if it was originally created with a previous version of the schema and the sizes
// don't match.
//
// Notice that DynamicObject::Builder does not have an "as<T>()" method, which is why this is
// needed.
template <typename T>
Orphan<T> releaseAs();
// Like DynamicValue::Builder::as(), but coerces the Orphan type. Since Orphans are move-only,
// the original Orphan<DynamicStruct> is no longer valid after this call; ownership is
// transferred to the returned Orphan<T>.
DynamicStruct::Builder getAs(StructSchema schema);
DynamicList::Builder getAs(ListSchema schema);
// Dynamic versions of 'getAs()'.
Orphan<DynamicStruct> releaseAs(StructSchema schema);
Orphan<DynamicList> releaseAs(ListSchema schema);
// Dynamic versions of 'releaseAs()'.
inline bool operator==(decltype(nullptr)) const { return builder == nullptr; }
inline bool operator!=(decltype(nullptr)) const { return builder != nullptr; }
private:
_::OrphanBuilder builder;
explicit Orphan(_::OrphanBuilder&& builder): builder(kj::mv(builder)) {}
template <typename, Kind>
friend struct _::PointerHelpers;
friend class Orphan<DynamicValue>; friend class Orphan<DynamicValue>;
friend class Orphanage; friend class Orphan<ObjectPointer>;
}; };
template <> template <>
...@@ -800,6 +681,7 @@ public: ...@@ -800,6 +681,7 @@ public:
Orphan(Orphan&&) = default; Orphan(Orphan&&) = default;
template <typename T> template <typename T>
Orphan(Orphan<T>&&); Orphan(Orphan<T>&&);
Orphan(Orphan<ObjectPointer>&&);
KJ_DISALLOW_COPY(Orphan); KJ_DISALLOW_COPY(Orphan);
Orphan& operator=(Orphan&&) = default; Orphan& operator=(Orphan&&) = default;
...@@ -848,27 +730,12 @@ private: ...@@ -848,27 +730,12 @@ private:
}; };
template <typename T> template <typename T>
BuilderFor<T> Orphan<DynamicObject>::getAs() { inline Orphan<DynamicValue>::Orphan(Orphan<T>&& other)
return getAs(Schema::from<T>()).template as<T>();
}
template <>
Text::Builder Orphan<DynamicObject>::getAs<Text>();
template <>
Data::Builder Orphan<DynamicObject>::getAs<Data>();
template <typename T>
Orphan<T> Orphan<DynamicObject>::releaseAs() {
return releaseAs(Schema::from<T>()).template releaseAs<T>();
}
template <>
Orphan<Text> Orphan<DynamicObject>::releaseAs<Text>();
template <>
Orphan<Data> Orphan<DynamicObject>::releaseAs<Data>();
template <typename T>
Orphan<DynamicValue>::Orphan(Orphan<T>&& other)
: Orphan(other.get(), kj::mv(other.builder)) {} : Orphan(other.get(), kj::mv(other.builder)) {}
inline Orphan<DynamicValue>::Orphan(Orphan<ObjectPointer>&& other)
: type(DynamicValue::OBJECT), builder(kj::mv(other.builder)) {}
template <typename T> template <typename T>
Orphan<T> Orphan<DynamicStruct>::releaseAs() { Orphan<T> Orphan<DynamicStruct>::releaseAs() {
get().as<T>(); // type check get().as<T>(); // type check
...@@ -888,6 +755,8 @@ Orphan<T> Orphan<DynamicValue>::releaseAs() { ...@@ -888,6 +755,8 @@ Orphan<T> Orphan<DynamicValue>::releaseAs() {
return Orphan<T>(kj::mv(builder)); return Orphan<T>(kj::mv(builder));
} }
template <>
Orphan<ObjectPointer> Orphan<DynamicValue>::releaseAs<ObjectPointer>();
template <> template <>
Orphan<DynamicStruct> Orphan<DynamicValue>::releaseAs<DynamicStruct>(); Orphan<DynamicStruct> Orphan<DynamicValue>::releaseAs<DynamicStruct>();
template <> template <>
...@@ -920,10 +789,6 @@ inline Orphan<DynamicList> Orphanage::newOrphanCopy<DynamicList::Reader>( ...@@ -920,10 +789,6 @@ inline Orphan<DynamicList> Orphanage::newOrphanCopy<DynamicList::Reader>(
return Orphan<DynamicList>(copyFrom.getSchema(), _::OrphanBuilder::copy(arena, copyFrom.reader)); return Orphan<DynamicList>(copyFrom.getSchema(), _::OrphanBuilder::copy(arena, copyFrom.reader));
} }
template <>
Orphan<DynamicObject> Orphanage::newOrphanCopy<DynamicObject::Reader>(
const DynamicObject::Reader& copyFrom) const;
template <> template <>
Orphan<DynamicValue> Orphanage::newOrphanCopy<DynamicValue::Reader>( Orphan<DynamicValue> Orphanage::newOrphanCopy<DynamicValue::Reader>(
const DynamicValue::Reader& copyFrom) const; const DynamicValue::Reader& copyFrom) const;
...@@ -985,19 +850,6 @@ struct PointerHelpers<DynamicList, Kind::UNKNOWN> { ...@@ -985,19 +850,6 @@ struct PointerHelpers<DynamicList, Kind::UNKNOWN> {
} }
}; };
template <>
struct PointerHelpers<DynamicObject, Kind::UNKNOWN> {
static DynamicObject::Reader get(PointerReader reader);
static DynamicObject::Builder get(PointerBuilder builder);
static void set(PointerBuilder builder, const DynamicObject::Reader& value);
static inline void adopt(PointerBuilder builder, Orphan<DynamicObject>&& value) {
builder.adopt(kj::mv(value.builder));
}
static inline Orphan<DynamicObject> disown(PointerBuilder builder) {
return Orphan<DynamicObject>(builder.disown());
}
};
} // namespace _ (private) } // namespace _ (private)
template <typename T> template <typename T>
...@@ -1043,6 +895,19 @@ inline Orphan<T> ObjectPointer::Builder::disownAs(ListSchema schema) { ...@@ -1043,6 +895,19 @@ inline Orphan<T> ObjectPointer::Builder::disownAs(ListSchema schema) {
return _::PointerHelpers<T>::disown(builder, schema); return _::PointerHelpers<T>::disown(builder, schema);
} }
template <>
DynamicStruct::Builder Orphan<ObjectPointer>::getAs<DynamicStruct>(StructSchema schema);
template <>
DynamicList::Builder Orphan<ObjectPointer>::getAs<DynamicList>(ListSchema schema);
template <>
DynamicStruct::Reader Orphan<ObjectPointer>::getAsReader<DynamicStruct>(StructSchema schema) const;
template <>
DynamicList::Reader Orphan<ObjectPointer>::getAsReader<DynamicList>(ListSchema schema) const;
template <>
Orphan<DynamicStruct> Orphan<ObjectPointer>::releaseAs<DynamicStruct>(StructSchema schema);
template <>
Orphan<DynamicList> Orphan<ObjectPointer>::releaseAs<DynamicList>(ListSchema schema);
// ======================================================================================= // =======================================================================================
// Inline implementation details. // Inline implementation details.
...@@ -1118,7 +983,7 @@ CAPNP_DECLARE_DYNAMIC_VALUE_CONSTRUCTOR(Text, TEXT, text); ...@@ -1118,7 +983,7 @@ CAPNP_DECLARE_DYNAMIC_VALUE_CONSTRUCTOR(Text, TEXT, text);
CAPNP_DECLARE_DYNAMIC_VALUE_CONSTRUCTOR(Data, DATA, data); CAPNP_DECLARE_DYNAMIC_VALUE_CONSTRUCTOR(Data, DATA, data);
CAPNP_DECLARE_DYNAMIC_VALUE_CONSTRUCTOR(DynamicList, LIST, list); CAPNP_DECLARE_DYNAMIC_VALUE_CONSTRUCTOR(DynamicList, LIST, list);
CAPNP_DECLARE_DYNAMIC_VALUE_CONSTRUCTOR(DynamicStruct, STRUCT, struct); CAPNP_DECLARE_DYNAMIC_VALUE_CONSTRUCTOR(DynamicStruct, STRUCT, struct);
CAPNP_DECLARE_DYNAMIC_VALUE_CONSTRUCTOR(DynamicObject, OBJECT, object); CAPNP_DECLARE_DYNAMIC_VALUE_CONSTRUCTOR(ObjectPointer, OBJECT, object);
#undef CAPNP_DECLARE_DYNAMIC_VALUE_CONSTRUCTOR #undef CAPNP_DECLARE_DYNAMIC_VALUE_CONSTRUCTOR
...@@ -1152,7 +1017,7 @@ CAPNP_DECLARE_TYPE(data, DATA, Data) ...@@ -1152,7 +1017,7 @@ CAPNP_DECLARE_TYPE(data, DATA, Data)
CAPNP_DECLARE_TYPE(list, LIST, DynamicList) CAPNP_DECLARE_TYPE(list, LIST, DynamicList)
CAPNP_DECLARE_TYPE(struct, STRUCT, DynamicStruct) CAPNP_DECLARE_TYPE(struct, STRUCT, DynamicStruct)
CAPNP_DECLARE_TYPE(enum, ENUM, DynamicEnum) CAPNP_DECLARE_TYPE(enum, ENUM, DynamicEnum)
CAPNP_DECLARE_TYPE(object, OBJECT, DynamicObject) CAPNP_DECLARE_TYPE(object, OBJECT, ObjectPointer)
#undef CAPNP_DECLARE_TYPE #undef CAPNP_DECLARE_TYPE
// CAPNP_DECLARE_TYPE(Void) causes gcc 4.7 to segfault. If I do it manually and remove the // CAPNP_DECLARE_TYPE(Void) causes gcc 4.7 to segfault. If I do it manually and remove the
...@@ -1207,13 +1072,6 @@ struct DynamicValue::Builder::AsImpl<T, Kind::LIST> { ...@@ -1207,13 +1072,6 @@ struct DynamicValue::Builder::AsImpl<T, Kind::LIST> {
// ------------------------------------------------------------------- // -------------------------------------------------------------------
template <typename T>
inline typename T::Reader DynamicObject::Reader::as() const {
return as(Schema::from<T>()).template as<T>();
}
// -------------------------------------------------------------------
template <typename T> template <typename T>
typename T::Reader DynamicStruct::Reader::as() const { typename T::Reader DynamicStruct::Reader::as() const {
static_assert(kind<T>() == Kind::STRUCT, static_assert(kind<T>() == Kind::STRUCT,
......
...@@ -1617,19 +1617,19 @@ struct WireHelpers { ...@@ -1617,19 +1617,19 @@ struct WireHelpers {
} }
} }
static KJ_ALWAYS_INLINE(void setObjectPointer( static KJ_ALWAYS_INLINE(SegmentAnd<word*> setObjectPointer(
SegmentBuilder* segment, WirePointer* ref, ObjectReader value)) { SegmentBuilder* segment, WirePointer* ref, ObjectReader value,
BuilderArena* orphanArena = nullptr)) {
switch (value.kind) { switch (value.kind) {
case ObjectKind::NULL_POINTER: case ObjectKind::NULL_POINTER:
memset(ref, 0, sizeof(*ref)); memset(ref, 0, sizeof(*ref));
break; return { segment, nullptr };
case ObjectKind::STRUCT: case ObjectKind::STRUCT:
setStructPointer(segment, ref, value.structReader); return setStructPointer(segment, ref, value.structReader, orphanArena);
break;
case ObjectKind::LIST: case ObjectKind::LIST:
setListPointer(segment, ref, value.listReader); return setListPointer(segment, ref, value.listReader, orphanArena);
break;
} }
KJ_UNREACHABLE;
} }
static void adopt(SegmentBuilder* segment, WirePointer* ref, OrphanBuilder&& value) { static void adopt(SegmentBuilder* segment, WirePointer* ref, OrphanBuilder&& value) {
...@@ -2139,7 +2139,7 @@ void PointerBuilder::setList(const ListReader& value) { ...@@ -2139,7 +2139,7 @@ void PointerBuilder::setList(const ListReader& value) {
} }
void PointerBuilder::setObject(const ObjectReader& value) { void PointerBuilder::setObject(const ObjectReader& value) {
return WireHelpers::setObjectPointer(segment, pointer, value); WireHelpers::setObjectPointer(segment, pointer, value);
} }
void PointerBuilder::adopt(OrphanBuilder&& value) { void PointerBuilder::adopt(OrphanBuilder&& value) {
...@@ -2159,6 +2159,18 @@ bool PointerBuilder::isNull() { ...@@ -2159,6 +2159,18 @@ bool PointerBuilder::isNull() {
return pointer->isNull(); return pointer->isNull();
} }
void PointerBuilder::transferFrom(PointerBuilder other) {
WireHelpers::transferPointer(segment, pointer, other.segment, other.pointer);
}
void PointerBuilder::copyFrom(PointerReader other) {
WireHelpers::setObjectPointer(segment, pointer, other.getObject(nullptr));
}
PointerReader PointerBuilder::asReader() const {
return PointerReader(segment, pointer, std::numeric_limits<int>::max());
}
// ======================================================================================= // =======================================================================================
// PointerReader // PointerReader
...@@ -2541,6 +2553,15 @@ OrphanBuilder OrphanBuilder::copy(BuilderArena* arena, ListReader copyFrom) { ...@@ -2541,6 +2553,15 @@ OrphanBuilder OrphanBuilder::copy(BuilderArena* arena, ListReader copyFrom) {
return result; return result;
} }
OrphanBuilder OrphanBuilder::copy(BuilderArena* arena, PointerReader copyFrom) {
OrphanBuilder result;
auto allocation = WireHelpers::setObjectPointer(
nullptr, result.tagAsPtr(), copyFrom.getObject(nullptr), arena);
result.segment = allocation.segment;
result.location = reinterpret_cast<word*>(allocation.value);
return result;
}
OrphanBuilder OrphanBuilder::copy(BuilderArena* arena, Text::Reader copyFrom) { OrphanBuilder OrphanBuilder::copy(BuilderArena* arena, Text::Reader copyFrom) {
OrphanBuilder result; OrphanBuilder result;
auto allocation = WireHelpers::setTextPointer( auto allocation = WireHelpers::setTextPointer(
......
...@@ -316,6 +316,8 @@ public: ...@@ -316,6 +316,8 @@ public:
void copyFrom(PointerReader other); void copyFrom(PointerReader other);
// Equivalent to `set(other.get())`. // Equivalent to `set(other.get())`.
PointerReader asReader() const;
private: private:
SegmentBuilder* segment; // Memory segment in which the pointer resides. SegmentBuilder* segment; // Memory segment in which the pointer resides.
WirePointer* pointer; // Pointer to the pointer. WirePointer* pointer; // Pointer to the pointer.
...@@ -360,6 +362,7 @@ private: ...@@ -360,6 +362,7 @@ private:
friend class StructReader; friend class StructReader;
friend class ListReader; friend class ListReader;
friend class PointerBuilder;
}; };
// ------------------------------------------------------------------- // -------------------------------------------------------------------
...@@ -739,6 +742,7 @@ public: ...@@ -739,6 +742,7 @@ public:
static OrphanBuilder copy(BuilderArena* arena, StructReader copyFrom); static OrphanBuilder copy(BuilderArena* arena, StructReader copyFrom);
static OrphanBuilder copy(BuilderArena* arena, ListReader copyFrom); static OrphanBuilder copy(BuilderArena* arena, ListReader copyFrom);
static OrphanBuilder copy(BuilderArena* arena, PointerReader copyFrom);
static OrphanBuilder copy(BuilderArena* arena, Text::Reader copyFrom); static OrphanBuilder copy(BuilderArena* arena, Text::Reader copyFrom);
static OrphanBuilder copy(BuilderArena* arena, Data::Reader copyFrom); static OrphanBuilder copy(BuilderArena* arena, Data::Reader copyFrom);
......
...@@ -26,11 +26,13 @@ ...@@ -26,11 +26,13 @@
#include "layout.h" #include "layout.h"
#include "pointer-helpers.h" #include "pointer-helpers.h"
#include "orphan.h"
namespace capnp { namespace capnp {
class StructSchema; class StructSchema;
class ListSchema; class ListSchema;
class Orphanage;
struct ObjectPointer { struct ObjectPointer {
// Reader/Builder for the `Object` field type, i.e. a pointer that can point to an arbitrary // Reader/Builder for the `Object` field type, i.e. a pointer that can point to an arbitrary
...@@ -38,6 +40,8 @@ struct ObjectPointer { ...@@ -38,6 +40,8 @@ struct ObjectPointer {
class Reader { class Reader {
public: public:
typedef ObjectPointer Reads;
Reader() = default; Reader() = default;
inline Reader(_::PointerReader reader): reader(reader) {} inline Reader(_::PointerReader reader): reader(reader) {}
...@@ -57,10 +61,14 @@ struct ObjectPointer { ...@@ -57,10 +61,14 @@ struct ObjectPointer {
private: private:
_::PointerReader reader; _::PointerReader reader;
friend struct ObjectPointer;
friend class Orphanage;
}; };
class Builder { class Builder {
public: public:
typedef ObjectPointer Builds;
Builder() = delete; Builder() = delete;
inline Builder(decltype(nullptr)) {} inline Builder(decltype(nullptr)) {}
inline Builder(_::PointerBuilder builder): builder(builder) {} inline Builder(_::PointerBuilder builder): builder(builder) {}
...@@ -107,6 +115,9 @@ struct ObjectPointer { ...@@ -107,6 +115,9 @@ struct ObjectPointer {
inline void setAs(std::initializer_list<ReaderFor<ListElementType<T>>> list); inline void setAs(std::initializer_list<ReaderFor<ListElementType<T>>> list);
// Valid for T = List<?>. // Valid for T = List<?>.
inline void set(Reader value) { builder.copyFrom(value.reader); }
// Set to a copy of another ObjectPointer.
template <typename T> template <typename T>
inline void adopt(Orphan<T>&& orphan); inline void adopt(Orphan<T>&& orphan);
// Valid for T = any generated struct type, List<U>, Text, Data, DynamicList, DynamicStruct, // Valid for T = any generated struct type, List<U>, Text, Data, DynamicList, DynamicStruct,
...@@ -124,11 +135,69 @@ struct ObjectPointer { ...@@ -124,11 +135,69 @@ struct ObjectPointer {
inline Orphan<T> disownAs(ListSchema schema); inline Orphan<T> disownAs(ListSchema schema);
// Only valid for T = DynamicList. Requires `#include <capnp/dynamic.h>`. // Only valid for T = DynamicList. Requires `#include <capnp/dynamic.h>`.
inline Orphan<ObjectPointer> disown();
// Disown without a type.
inline Reader asReader() const { return Reader(builder.asReader()); }
inline operator Reader() const { return Reader(builder.asReader()); }
private: private:
_::PointerBuilder builder; _::PointerBuilder builder;
}; };
}; };
template <>
class Orphan<ObjectPointer> {
// An orphaned object of unknown type.
public:
Orphan() = default;
KJ_DISALLOW_COPY(Orphan);
Orphan(Orphan&&) = default;
Orphan& operator=(Orphan&&) = default;
// It's not possible to get an ObjectPointer::{Reader,Builder} directly since there is no
// underlying pointer (the pointer would normally live in the parent, but this object is
// orphaned). It is possible, however, to request readers/builders.
template <typename T>
inline typename T::Builder getAs();
template <typename T>
inline typename T::Builder getAs(StructSchema schema);
template <typename T>
inline typename T::Builder getAs(ListSchema schema);
template <typename T>
inline typename T::Reader getAsReader() const;
template <typename T>
inline typename T::Reader getAsReader(StructSchema schema) const;
template <typename T>
inline typename T::Reader getAsReader(ListSchema schema) const;
template <typename T>
inline Orphan<T> releaseAs();
template <typename T>
inline Orphan<T> releaseAs(StructSchema schema);
template <typename T>
inline Orphan<T> releaseAs(ListSchema schema);
// Down-cast the orphan to a specific type.
inline bool operator==(decltype(nullptr)) const { return builder == nullptr; }
inline bool operator!=(decltype(nullptr)) const { return builder != nullptr; }
private:
_::OrphanBuilder builder;
inline Orphan(_::OrphanBuilder&& builder)
: builder(kj::mv(builder)) {}
template <typename, Kind>
friend struct _::PointerHelpers;
friend class Orphanage;
template <typename U>
friend class Orphan;
friend class ObjectPointer::Builder;
};
// ======================================================================================= // =======================================================================================
// Inline implementation details // Inline implementation details
...@@ -185,6 +254,33 @@ inline Orphan<T> ObjectPointer::Builder::disownAs() { ...@@ -185,6 +254,33 @@ inline Orphan<T> ObjectPointer::Builder::disownAs() {
return _::PointerHelpers<T>::disown(builder); return _::PointerHelpers<T>::disown(builder);
} }
inline Orphan<ObjectPointer> ObjectPointer::Builder::disown() {
return Orphan<ObjectPointer>(builder.disown());
}
template <> struct ReaderFor_ <ObjectPointer, Kind::UNKNOWN> { typedef ObjectPointer::Reader Type; };
template <> struct BuilderFor_<ObjectPointer, Kind::UNKNOWN> { typedef ObjectPointer::Builder Type; };
template <>
struct Orphanage::GetInnerReader<ObjectPointer, Kind::UNKNOWN> {
static inline _::PointerReader apply(const ObjectPointer::Reader& t) {
return t.reader;
}
};
template <typename T>
inline typename T::Builder Orphan<ObjectPointer>::getAs() {
return _::OrphanGetImpl<T>::apply(builder);
}
template <typename T>
inline typename T::Reader Orphan<ObjectPointer>::getAsReader() const {
return _::OrphanGetImpl<T>::applyReader(builder);
}
template <typename T>
inline Orphan<T> Orphan<ObjectPointer>::releaseAs() {
return Orphan<T>(kj::mv(builder));
}
} // namespace capnp } // namespace capnp
#endif // CAPNP_OBJECT_H_ #endif // CAPNP_OBJECT_H_
...@@ -529,14 +529,12 @@ TEST(Orphans, DynamicObject) { ...@@ -529,14 +529,12 @@ TEST(Orphans, DynamicObject) {
initTestMessage(root.getObjectField().initAs<TestAllTypes>()); initTestMessage(root.getObjectField().initAs<TestAllTypes>());
EXPECT_TRUE(root.hasObjectField()); EXPECT_TRUE(root.hasObjectField());
Orphan<DynamicValue> orphan = root.getObjectField().disownAs<DynamicObject>(); Orphan<DynamicValue> orphan = root.getObjectField().disown();
EXPECT_EQ(DynamicValue::OBJECT, orphan.getType()); EXPECT_EQ(DynamicValue::OBJECT, orphan.getType());
checkTestMessage(orphan.getReader().as<DynamicObject>().as<TestAllTypes>()); Orphan<ObjectPointer> objectOrphan = orphan.releaseAs<ObjectPointer>();
Orphan<DynamicObject> objectOrphan = orphan.releaseAs<DynamicObject>();
checkTestMessage(objectOrphan.getAs<TestAllTypes>()); checkTestMessage(objectOrphan.getAs<TestAllTypes>());
checkDynamicTestMessage(objectOrphan.getAs(Schema::from<TestAllTypes>())); checkDynamicTestMessage(objectOrphan.getAs<DynamicStruct>(Schema::from<TestAllTypes>()));
} }
TEST(Orphans, DynamicDisown) { TEST(Orphans, DynamicDisown) {
......
...@@ -267,8 +267,6 @@ kj::StringTree prettyPrint(DynamicList::Builder value) { return prettyPrint(valu ...@@ -267,8 +267,6 @@ kj::StringTree prettyPrint(DynamicList::Builder value) { return prettyPrint(valu
kj::StringTree KJ_STRINGIFY(const DynamicValue::Reader& value) { return stringify(value); } kj::StringTree KJ_STRINGIFY(const DynamicValue::Reader& value) { return stringify(value); }
kj::StringTree KJ_STRINGIFY(const DynamicValue::Builder& value) { return stringify(value.asReader()); } kj::StringTree KJ_STRINGIFY(const DynamicValue::Builder& value) { return stringify(value.asReader()); }
kj::StringTree KJ_STRINGIFY(DynamicEnum value) { return stringify(value); } kj::StringTree KJ_STRINGIFY(DynamicEnum value) { return stringify(value); }
kj::StringTree KJ_STRINGIFY(const DynamicObject::Reader& value) { return stringify(value); }
kj::StringTree KJ_STRINGIFY(const DynamicObject::Builder& value) { return stringify(value.asReader()); }
kj::StringTree KJ_STRINGIFY(const DynamicStruct::Reader& value) { return stringify(value); } kj::StringTree KJ_STRINGIFY(const DynamicStruct::Reader& value) { return stringify(value); }
kj::StringTree KJ_STRINGIFY(const DynamicStruct::Builder& value) { return stringify(value.asReader()); } kj::StringTree KJ_STRINGIFY(const DynamicStruct::Builder& value) { return stringify(value.asReader()); }
kj::StringTree KJ_STRINGIFY(const DynamicList::Reader& value) { return stringify(value); } kj::StringTree KJ_STRINGIFY(const DynamicList::Reader& value) { return stringify(value); }
......
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