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>>()),
......
This diff is collapsed.
This diff is collapsed.
...@@ -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