Commit 2b643930 authored by Kenton Varda's avatar Kenton Varda

Revamp generated interface to Object fields. Now there is an…

Revamp generated interface to Object fields.  Now there is an ObjectPointer::{Reader,Builder}.  This will simplify the dynamic API (next change) and also makes it easier to delegate decisions about the object type to a function that doesn't know about the context where the object lives (i.e. by passing an ObjectPointer::Builder).
parent 58d8f75c
......@@ -151,6 +151,8 @@ includecapnp_HEADERS = \
src/capnp/pretty-print.h \
src/capnp/serialize.h \
src/capnp/serialize-packed.h \
src/capnp/pointer-helpers.h \
src/capnp/object.h \
src/capnp/generated-header-support.h
lib_LTLIBRARIES = libkj.la libcapnp.la libcapnpc.la
......@@ -313,6 +315,7 @@ capnp_test_SOURCES = \
src/capnp/stringify-test.c++ \
src/capnp/encoding-test.c++ \
src/capnp/orphan-test.c++ \
src/capnp/object-test.c++ \
src/capnp/serialize-test.c++ \
src/capnp/serialize-packed-test.c++ \
src/capnp/test-util.c++ \
......
......@@ -99,6 +99,10 @@ inline constexpr Kind kind() {
template <typename T, Kind k = kind<T>()>
struct List;
template <typename T> struct ListElementType_;
template <typename T> struct ListElementType_<List<T>> { typedef T Type; };
template <typename T> using ListElementType = typename ListElementType_<T>::Type;
namespace _ { // private
template <typename T, Kind k> struct Kind_<List<T, k>> { static constexpr Kind kind = Kind::LIST; };
} // namespace _ (private)
......
......@@ -809,29 +809,14 @@ private:
kj::strTree(
kj::mv(unionDiscrim.readerIsDecl),
" inline bool has", titleCase, "() const;\n"
" template <typename T>\n"
" inline typename T::Reader get", titleCase, "() const;\n"
" template <typename T, typename Param>\n"
" inline typename T::Reader get", titleCase, "(Param&& param) const;\n"
" inline ::capnp::ObjectPointer::Reader get", titleCase, "() const;\n"
"\n"),
kj::strTree(
kj::mv(unionDiscrim.builderIsDecl),
" inline bool has", titleCase, "();\n"
" template <typename T>\n"
" inline typename T::Builder get", titleCase, "();\n"
" template <typename T, typename Param>\n"
" inline typename T::Builder get", titleCase, "(Param&& param);\n"
" template <typename T>\n"
" inline void set", titleCase, "(typename T::Reader value);\n"
" template <typename T, typename U>"
" inline void set", titleCase, "(std::initializer_list<U> value);\n"
" template <typename T, typename... Params>\n"
" inline typename T::Builder init", titleCase, "(Params&&... params);\n"
" template <typename T>\n"
" inline void adopt", titleCase, "(::capnp::Orphan<T>&& value);\n"
" template <typename T, typename... Params>\n"
" inline ::capnp::Orphan<T> disown", titleCase, "(Params&&... params);\n"
" inline ::capnp::ObjectPointer::Builder get", titleCase, "();\n"
" inline ::capnp::ObjectPointer::Builder init", titleCase, "();\n"
"\n"),
kj::strTree(
......@@ -844,63 +829,22 @@ private:
unionDiscrim.has,
" return !_builder.getPointerField(", offset, " * ::capnp::POINTERS).isNull();\n"
"}\n"
"template <typename T>\n"
"inline typename T::Reader ", scope, "Reader::get", titleCase, "() const {\n",
"inline ::capnp::ObjectPointer::Reader ", scope, "Reader::get", titleCase, "() const {\n",
unionDiscrim.check,
" return ::capnp::_::PointerHelpers<T>::get(\n"
" return ::capnp::ObjectPointer::Reader(\n"
" _reader.getPointerField(", offset, " * ::capnp::POINTERS));\n"
"}\n"
"template <typename T>\n"
"inline typename T::Builder ", scope, "Builder::get", titleCase, "() {\n",
"inline ::capnp::ObjectPointer::Builder ", scope, "Builder::get", titleCase, "() {\n",
unionDiscrim.check,
" return ::capnp::_::PointerHelpers<T>::get(\n"
" return ::capnp::ObjectPointer::Builder(\n"
" _builder.getPointerField(", offset, " * ::capnp::POINTERS));\n"
"}\n"
"template <typename T, typename Param>\n"
"inline typename T::Reader ", scope, "Reader::get", titleCase, "(Param&& param) const {\n",
unionDiscrim.check,
" return ::capnp::_::PointerHelpers<T>::getDynamic(\n"
" _reader.getPointerField(", offset, " * ::capnp::POINTERS),\n"
" ::kj::fwd<Param>(param));\n"
"}\n"
"template <typename T, typename Param>\n"
"inline typename T::Builder ", scope, "Builder::get", titleCase, "(Param&& param) {\n",
unionDiscrim.check,
" return ::capnp::_::PointerHelpers<T>::getDynamic(\n"
" _builder.getPointerField(", offset, " * ::capnp::POINTERS),\n"
" ::kj::fwd<Param>(param));\n"
"}\n"
"template <typename T>\n"
"inline void ", scope, "Builder::set", titleCase, "(typename T::Reader value) {\n",
unionDiscrim.set,
" ::capnp::_::PointerHelpers<T>::set(\n"
" _builder.getPointerField(", offset, " * ::capnp::POINTERS), value);\n"
"}\n"
"template <typename T, typename U>"
"inline void ", scope, "Builder::set", titleCase, "(std::initializer_list<U> value) {\n",
unionDiscrim.set,
" ::capnp::_::PointerHelpers<T>::set(\n"
" _builder.getPointerField(", offset, " * ::capnp::POINTERS), value);\n"
"}\n"
"template <typename T, typename... Params>\n"
"inline typename T::Builder ", scope, "Builder::init", titleCase, "(Params&&... params) {\n",
unionDiscrim.set,
" return ::capnp::_::PointerHelpers<T>::init(\n"
" _builder.getPointerField(", offset, " * ::capnp::POINTERS),\n"
" ::kj::fwd<Params>(params)...);\n"
"}\n"
"template <typename T>\n"
"inline void ", scope, "Builder::adopt", titleCase, "(::capnp::Orphan<T>&& value) {\n",
"inline ::capnp::ObjectPointer::Builder ", scope, "Builder::init", titleCase, "() {\n",
unionDiscrim.set,
" ::capnp::_::PointerHelpers<T>::adopt(\n"
" _builder.getPointerField(", offset, " * ::capnp::POINTERS), kj::mv(value));\n"
"}\n"
"template <typename T, typename... Params>\n"
"inline ::capnp::Orphan<T> ", scope, "Builder::disown", titleCase, "(Params&&... params) {\n",
unionDiscrim.check,
" return ::capnp::_::PointerHelpers<T>::disown(\n"
" _builder.getPointerField(", offset, " * ::capnp::POINTERS),\n"
" ::kj::fwd<Params>(params)...);\n"
" auto result = ::capnp::ObjectPointer::Builder(\n"
" _builder.getPointerField(", offset, " * ::capnp::POINTERS));\n"
" result.clear();\n"
" return result;\n"
"}\n"
"\n")
};
......
......@@ -256,7 +256,7 @@ private:
return kj::strTree(DynamicValue::Reader(value.getData()));
case schema::Value::LIST: {
KJ_REQUIRE(type.isList(), "type/value mismatch");
auto listValue = value.getList<DynamicList>(
auto listValue = value.getList().getAs<DynamicList>(
ListSchema::of(type.getList().getElementType(), scope));
return kj::strTree(listValue);
}
......@@ -270,7 +270,7 @@ private:
}
case schema::Value::STRUCT: {
KJ_REQUIRE(type.isStruct(), "type/value mismatch");
auto structValue = value.getStruct<DynamicStruct>(
auto structValue = value.getStruct().getAs<DynamicStruct>(
scope.getDependency(type.getStruct().getTypeId()).asStruct());
return kj::strTree(structValue);
}
......
......@@ -1392,13 +1392,13 @@ void NodeTranslator::compileDefaultDefaultValue(
case schema::Type::ENUM: target.setEnum(0); break;
case schema::Type::INTERFACE: target.setInterface(); break;
// Bit of a hack: For "Object" types, we adopt a null orphan, which sets the field to null.
// Bit of a hack: For Text/Data, we adopt a null orphan, which sets the field to null.
// TODO(cleanup): Create a cleaner way to do this.
case schema::Type::TEXT: target.adoptText(Orphan<Text>()); break;
case schema::Type::DATA: target.adoptData(Orphan<Data>()); break;
case schema::Type::STRUCT: target.adoptStruct(Orphan<Data>()); break;
case schema::Type::LIST: target.adoptList(Orphan<Data>()); break;
case schema::Type::OBJECT: target.adoptObject(Orphan<Data>()); break;
case schema::Type::STRUCT: target.initStruct(); break;
case schema::Type::LIST: target.initList(); break;
case schema::Type::OBJECT: target.initObject(); break;
}
}
......
......@@ -151,16 +151,16 @@ TEST(DynamicApi, GenericObjects) {
MallocMessageBuilder builder;
auto root = builder.getRoot<test::TestObject>();
initDynamicTestMessage(root.initObjectField<DynamicStruct>(Schema::from<TestAllTypes>()));
checkTestMessage(root.asReader().getObjectField<TestAllTypes>());
initDynamicTestMessage(root.getObjectField().initAs<DynamicStruct>(Schema::from<TestAllTypes>()));
checkTestMessage(root.asReader().getObjectField().getAs<TestAllTypes>());
checkDynamicTestMessage(
root.asReader().getObjectField<DynamicStruct>(Schema::from<TestAllTypes>()));
checkDynamicTestMessage(root.getObjectField<DynamicStruct>(Schema::from<TestAllTypes>()));
root.asReader().getObjectField().getAs<DynamicStruct>(Schema::from<TestAllTypes>()));
checkDynamicTestMessage(root.getObjectField().getAs<DynamicStruct>(Schema::from<TestAllTypes>()));
{
{
auto list = root.initObjectField<DynamicList>(Schema::from<List<uint32_t>>(), 4);
auto list = root.getObjectField().initAs<DynamicList>(Schema::from<List<uint32_t>>(), 4);
list.set(0, 123);
list.set(1, 456);
list.set(2, 789);
......@@ -168,7 +168,7 @@ TEST(DynamicApi, GenericObjects) {
}
{
auto list = root.asReader().getObjectField<List<uint32_t>>();
auto list = root.asReader().getObjectField().getAs<List<uint32_t>>();
ASSERT_EQ(4u, list.size());
EXPECT_EQ(123u, list[0]);
EXPECT_EQ(456u, list[1]);
......@@ -176,10 +176,10 @@ TEST(DynamicApi, GenericObjects) {
EXPECT_EQ(123456789u, list[3]);
}
checkList<uint32_t>(root.asReader().getObjectField<DynamicList>(Schema::from<List<uint32_t>>()),
{123u, 456u, 789u, 123456789u});
checkList<uint32_t>(root.getObjectField<DynamicList>(Schema::from<List<uint32_t>>()),
{123u, 456u, 789u, 123456789u});
checkList<uint32_t>(root.asReader().getObjectField().getAs<DynamicList>(
Schema::from<List<uint32_t>>()), {123u, 456u, 789u, 123456789u});
checkList<uint32_t>(root.getObjectField().getAs<DynamicList>(
Schema::from<List<uint32_t>>()), {123u, 456u, 789u, 123456789u});
}
}
......@@ -188,7 +188,7 @@ TEST(DynamicApi, DynamicGenericObjects) {
auto root = builder.getRoot<DynamicStruct>(Schema::from<test::TestObject>());
initDynamicTestMessage(root.initObject("objectField", Schema::from<TestAllTypes>()));
checkTestMessage(root.asReader().as<test::TestObject>().getObjectField<TestAllTypes>());
checkTestMessage(root.asReader().as<test::TestObject>().getObjectField().getAs<TestAllTypes>());
checkDynamicTestMessage(
root.asReader().get("objectField").as<DynamicObject>().as(Schema::from<TestAllTypes>()));
......@@ -209,7 +209,7 @@ TEST(DynamicApi, DynamicGenericObjects) {
}
{
auto list = root.asReader().as<test::TestObject>().getObjectField<List<uint32_t>>();
auto list = root.asReader().as<test::TestObject>().getObjectField().getAs<List<uint32_t>>();
ASSERT_EQ(4u, list.size());
EXPECT_EQ(123u, list[0]);
EXPECT_EQ(456u, list[1]);
......
......@@ -254,20 +254,20 @@ DynamicValue::Reader DynamicStruct::Reader::get(StructSchema::Field field) const
ListSchema::of(elementType, field.getContainingStruct()),
reader.getPointerField(slot.getOffset() * POINTERS)
.getList(elementSizeFor(elementType.which()),
dval.getList<_::UncheckedMessage>()));
dval.getList().getAs<_::UncheckedMessage>()));
}
case schema::Type::STRUCT: {
return DynamicStruct::Reader(
field.getContainingStruct().getDependency(type.getStruct().getTypeId()).asStruct(),
reader.getPointerField(slot.getOffset() * POINTERS)
.getStruct(dval.getStruct<_::UncheckedMessage>()));
.getStruct(dval.getStruct().getAs<_::UncheckedMessage>()));
}
case schema::Type::OBJECT: {
return DynamicObject::Reader(
reader.getPointerField(slot.getOffset() * POINTERS)
.getObject(dval.getObject<_::UncheckedMessage>()));
.getObject(dval.getObject().getAs<_::UncheckedMessage>()));
}
case schema::Type::INTERFACE:
......@@ -348,12 +348,12 @@ DynamicValue::Builder DynamicStruct::Builder::get(StructSchema::Field field) {
return DynamicList::Builder(listType,
builder.getPointerField(slot.getOffset() * POINTERS)
.getStructList(structSizeFromSchema(listType.getStructElementType()),
dval.getList<_::UncheckedMessage>()));
dval.getList().getAs<_::UncheckedMessage>()));
} else {
return DynamicList::Builder(listType,
builder.getPointerField(slot.getOffset() * POINTERS)
.getList(elementSizeFor(listType.whichElementType()),
dval.getList<_::UncheckedMessage>()));
dval.getList().getAs<_::UncheckedMessage>()));
}
}
......@@ -363,13 +363,13 @@ DynamicValue::Builder DynamicStruct::Builder::get(StructSchema::Field field) {
return DynamicStruct::Builder(structSchema,
builder.getPointerField(slot.getOffset() * POINTERS)
.getStruct(structSizeFromSchema(structSchema),
dval.getStruct<_::UncheckedMessage>()));
dval.getStruct().getAs<_::UncheckedMessage>()));
}
case schema::Type::OBJECT: {
return DynamicObject::Builder(
builder.getPointerField(slot.getOffset() * POINTERS)
.getObject(dval.getObject<_::UncheckedMessage>()));
.getObject(dval.getObject().getAs<_::UncheckedMessage>()));
}
case schema::Type::INTERFACE:
......@@ -1470,17 +1470,17 @@ DynamicValue::Reader::Reader(ConstSchema constant) {
break;
case schema::Type::STRUCT:
*this = value.getStruct<DynamicStruct>(
*this = value.getStruct().getAs<DynamicStruct>(
constant.getDependency(typeSchema.getStruct().getTypeId()).asStruct());
break;
case schema::Type::LIST:
*this = value.getList<DynamicList>(
*this = value.getList().getAs<DynamicList>(
ListSchema::of(typeSchema.getList().getElementType(), constant));
break;
case schema::Type::OBJECT:
*this = value.getObject<DynamicObject>();
*this = value.getObject().getAs<DynamicObject>();
break;
case schema::Type::INTERFACE:
......@@ -1772,6 +1772,29 @@ void PointerHelpers<DynamicObject, Kind::UNKNOWN>::set(
} // namespace _ (private)
template <>
void ObjectPointer::Builder::adopt<DynamicValue>(Orphan<DynamicValue>&& orphan) {
switch (orphan.getType()) {
case DynamicValue::UNKNOWN:
case DynamicValue::VOID:
case DynamicValue::BOOL:
case DynamicValue::INT:
case DynamicValue::UINT:
case DynamicValue::FLOAT:
case DynamicValue::ENUM:
KJ_FAIL_REQUIRE("ObjectPointer cannot adopt primitive (non-object) value.");
case DynamicValue::STRUCT:
case DynamicValue::LIST:
case DynamicValue::TEXT:
case DynamicValue::DATA:
case DynamicValue::INTERFACE:
case DynamicValue::OBJECT:
builder.adopt(kj::mv(orphan.builder));
break;
}
}
// -------------------------------------------------------------------
Orphan<DynamicStruct> Orphanage::newOrphan(StructSchema schema) const {
......
......@@ -38,6 +38,7 @@
#include "schema.h"
#include "layout.h"
#include "message.h"
#include "object.h"
namespace capnp {
......@@ -842,6 +843,7 @@ private:
friend struct _::PointerHelpers;
friend struct DynamicStruct;
friend struct DynamicList;
friend struct ObjectPointer;
friend class Orphanage;
};
......@@ -998,6 +1000,49 @@ struct PointerHelpers<DynamicObject, Kind::UNKNOWN> {
} // namespace _ (private)
template <typename T>
inline typename T::Reader ObjectPointer::Reader::getAs(StructSchema schema) {
return _::PointerHelpers<T>::getDynamic(reader, schema);
}
template <typename T>
inline typename T::Reader ObjectPointer::Reader::getAs(ListSchema schema) {
return _::PointerHelpers<T>::getDynamic(reader, schema);
}
template <typename T>
inline typename T::Builder ObjectPointer::Builder::getAs(StructSchema schema) {
return _::PointerHelpers<T>::getDynamic(builder, schema);
}
template <typename T>
inline typename T::Builder ObjectPointer::Builder::getAs(ListSchema schema) {
return _::PointerHelpers<T>::getDynamic(builder, schema);
}
template <typename T>
inline typename T::Builder ObjectPointer::Builder::initAs(StructSchema schema) {
return _::PointerHelpers<T>::init(builder, schema);
}
template <typename T>
inline typename T::Builder ObjectPointer::Builder::initAs(ListSchema schema, uint elementCount) {
return _::PointerHelpers<T>::init(builder, schema, elementCount);
}
template <>
inline void ObjectPointer::Builder::setAs<DynamicStruct>(DynamicStruct::Reader value) {
return _::PointerHelpers<DynamicStruct>::set(builder, value);
}
template <>
inline void ObjectPointer::Builder::setAs<DynamicList>(DynamicList::Reader value) {
return _::PointerHelpers<DynamicList>::set(builder, value);
}
template <>
void ObjectPointer::Builder::adopt<DynamicValue>(Orphan<DynamicValue>&& orphan);
template <typename T>
inline Orphan<T> ObjectPointer::Builder::disownAs(StructSchema schema) {
return _::PointerHelpers<T>::disown(builder, schema);
}
template <typename T>
inline Orphan<T> ObjectPointer::Builder::disownAs(ListSchema schema) {
return _::PointerHelpers<T>::disown(builder, schema);
}
// =======================================================================================
// Inline implementation details.
......
This diff is collapsed.
......@@ -30,6 +30,7 @@
#include "list.h"
#include "orphan.h"
#include "pointer-helpers.h"
#include "object.h"
#include <kj/string.h>
#include <kj/string-tree.h>
......
// Copyright (c) 2013, Kenton Varda <temporal@gmail.com>
// All rights reserved.
//
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions are met:
//
// 1. Redistributions of source code must retain the above copyright notice, this
// list of conditions and the following disclaimer.
// 2. Redistributions in binary form must reproduce the above copyright notice,
// this list of conditions and the following disclaimer in the documentation
// and/or other materials provided with the distribution.
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
// ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
// WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
// DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
// ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
// (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
// LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
// ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
// SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#include "object.h"
#include "message.h"
#include <gtest/gtest.h>
#include "test-util.h"
namespace capnp {
namespace _ { // private
namespace {
TEST(Object, Basic) {
MallocMessageBuilder builder;
auto root = builder.getRoot<test::TestObject>();
initTestMessage(root.getObjectField().initAs<TestAllTypes>());
checkTestMessage(root.getObjectField().getAs<TestAllTypes>());
checkTestMessage(root.asReader().getObjectField().getAs<TestAllTypes>());
root.getObjectField().setAs<Text>("foo");
EXPECT_EQ("foo", root.getObjectField().getAs<Text>());
EXPECT_EQ("foo", root.asReader().getObjectField().getAs<Text>());
root.getObjectField().setAs<Data>(data("foo"));
EXPECT_EQ(data("foo"), root.getObjectField().getAs<Data>());
EXPECT_EQ(data("foo"), root.asReader().getObjectField().getAs<Data>());
{
root.getObjectField().setAs<List<uint32_t>>({123, 456, 789});
{
List<uint32_t>::Builder list = root.getObjectField().getAs<List<uint32_t>>();
ASSERT_EQ(3u, list.size());
EXPECT_EQ(123u, list[0]);
EXPECT_EQ(456u, list[1]);
EXPECT_EQ(789u, list[2]);
}
{
List<uint32_t>::Reader list = root.asReader().getObjectField().getAs<List<uint32_t>>();
ASSERT_EQ(3u, list.size());
EXPECT_EQ(123u, list[0]);
EXPECT_EQ(456u, list[1]);
EXPECT_EQ(789u, list[2]);
}
}
{
root.getObjectField().setAs<List<Text>>({"foo", "bar"});
{
List<Text>::Builder list = root.getObjectField().getAs<List<Text>>();
ASSERT_EQ(2u, list.size());
EXPECT_EQ("foo", list[0]);
EXPECT_EQ("bar", list[1]);
}
{
List<Text>::Reader list = root.asReader().getObjectField().getAs<List<Text>>();
ASSERT_EQ(2u, list.size());
EXPECT_EQ("foo", list[0]);
EXPECT_EQ("bar", list[1]);
}
}
{
{
List<TestAllTypes>::Builder list = root.getObjectField().initAs<List<TestAllTypes>>(2);
ASSERT_EQ(2u, list.size());
initTestMessage(list[0]);
}
{
List<TestAllTypes>::Builder list = root.getObjectField().getAs<List<TestAllTypes>>();
ASSERT_EQ(2u, list.size());
checkTestMessage(list[0]);
checkTestMessageAllZero(list[1]);
}
{
List<TestAllTypes>::Reader list = root.asReader().getObjectField().getAs<List<TestAllTypes>>();
ASSERT_EQ(2u, list.size());
checkTestMessage(list[0]);
checkTestMessageAllZero(list[1]);
}
}
}
} // namespace
} // namespace _ (private)
} // namespace capnp
// Copyright (c) 2013, Kenton Varda <temporal@gmail.com>
// All rights reserved.
//
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions are met:
//
// 1. Redistributions of source code must retain the above copyright notice, this
// list of conditions and the following disclaimer.
// 2. Redistributions in binary form must reproduce the above copyright notice,
// this list of conditions and the following disclaimer in the documentation
// and/or other materials provided with the distribution.
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
// ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
// WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
// DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
// ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
// (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
// LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
// ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
// SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#ifndef CAPNP_OBJECT_H_
#define CAPNP_OBJECT_H_
#include "layout.h"
#include "pointer-helpers.h"
namespace capnp {
class StructSchema;
class ListSchema;
struct ObjectPointer {
// Reader/Builder for the `Object` field type, i.e. a pointer that can point to an arbitrary
// object.
class Reader {
public:
Reader() = default;
inline Reader(_::PointerReader reader): reader(reader) {}
inline bool isNull();
template <typename T>
inline typename T::Reader getAs();
// Valid for T = any generated struct type, List<U>, Text, or Data.
template <typename T>
inline typename T::Reader getAs(StructSchema schema);
// Only valid for T = DynamicStruct. Requires `#include <capnp/dynamic.h>`.
template <typename T>
inline typename T::Reader getAs(ListSchema schema);
// Only valid for T = DynamicList. Requires `#include <capnp/dynamic.h>`.
private:
_::PointerReader reader;
};
class Builder {
public:
Builder() = delete;
inline Builder(decltype(nullptr)) {}
inline Builder(_::PointerBuilder builder): builder(builder) {}
inline bool isNull();
inline void clear();
// Set to null.
template <typename T>
inline typename T::Builder getAs();
// Valid for T = any generated struct type, List<U>, Text, or Data.
template <typename T>
inline typename T::Builder getAs(StructSchema schema);
// Only valid for T = DynamicStruct. Requires `#include <capnp/dynamic.h>`.
template <typename T>
inline typename T::Builder getAs(ListSchema schema);
// Only valid for T = DynamicList. Requires `#include <capnp/dynamic.h>`.
template <typename T>
inline typename T::Builder initAs();
// Valid for T = any generated struct type.
template <typename T>
inline typename T::Builder initAs(uint elementCount);
// Valid for T = List<U>, Text, or Data.
template <typename T>
inline typename T::Builder initAs(StructSchema schema);
// Only valid for T = DynamicStruct. Requires `#include <capnp/dynamic.h>`.
template <typename T>
inline typename T::Builder initAs(ListSchema schema, uint elementCount);
// Only valid for T = DynamicList. Requires `#include <capnp/dynamic.h>`.
template <typename T>
inline void setAs(typename T::Reader value);
// Valid for ReaderType = T::Reader for T = any generated struct type, List<U>, Text, Data,
// DynamicStruct, or DynamicList (the dynamic types require `#include <capnp/dynamic.h>`).
template <typename T>
inline void setAs(std::initializer_list<ReaderFor<ListElementType<T>>> list);
// Valid for T = List<?>.
template <typename T>
inline void adopt(Orphan<T>&& orphan);
// Valid for T = any generated struct type, List<U>, Text, Data, DynamicList, DynamicStruct,
// or DynamicValue (the dynamic types require `#include <capnp/dynamic.h>`).
template <typename T>
inline Orphan<T> disownAs();
// Valid for T = any generated struct type, List<U>, Text, Data.
template <typename T>
inline Orphan<T> disownAs(StructSchema schema);
// Only valid for T = DynamicStruct. Requires `#include <capnp/dynamic.h>`.
template <typename T>
inline Orphan<T> disownAs(ListSchema schema);
// Only valid for T = DynamicList. Requires `#include <capnp/dynamic.h>`.
private:
_::PointerBuilder builder;
};
};
// =======================================================================================
// Inline implementation details
inline bool ObjectPointer::Reader::isNull() {
return reader.isNull();
}
template <typename T>
inline typename T::Reader ObjectPointer::Reader::getAs() {
return _::PointerHelpers<T>::get(reader);
}
inline bool ObjectPointer::Builder::isNull() {
return builder.isNull();
}
inline void ObjectPointer::Builder::clear() {
return builder.clear();
}
template <typename T>
inline typename T::Builder ObjectPointer::Builder::getAs() {
return _::PointerHelpers<T>::get(builder);
}
template <typename T>
inline typename T::Builder ObjectPointer::Builder::initAs() {
return _::PointerHelpers<T>::init(builder);
}
template <typename T>
inline typename T::Builder ObjectPointer::Builder::initAs(uint elementCount) {
return _::PointerHelpers<T>::init(builder, elementCount);
}
template <typename T>
inline void ObjectPointer::Builder::setAs(typename T::Reader value) {
return _::PointerHelpers<T>::set(builder, value);
}
template <typename T>
inline void ObjectPointer::Builder::setAs(
std::initializer_list<ReaderFor<ListElementType<T>>> list) {
return _::PointerHelpers<T>::set(builder, list);
}
template <typename T>
inline void ObjectPointer::Builder::adopt(Orphan<T>&& orphan) {
_::PointerHelpers<T>::adopt(builder, kj::mv(orphan));
}
template <typename T>
inline Orphan<T> ObjectPointer::Builder::disownAs() {
return _::PointerHelpers<T>::disown(builder);
}
} // namespace capnp
#endif // CAPNP_OBJECT_H_
This diff is collapsed.
......@@ -1017,10 +1017,10 @@ private:
case schema::Type::ENUM: value.setEnum(0); break;
case schema::Type::TEXT: value.adoptText(Orphan<Text>()); break;
case schema::Type::DATA: value.adoptData(Orphan<Data>()); break;
case schema::Type::LIST: value.adoptList(Orphan<Data>()); break;
case schema::Type::STRUCT: value.adoptStruct(Orphan<Data>()); break;
case schema::Type::LIST: value.initList(); break;
case schema::Type::STRUCT: value.initStruct(); break;
case schema::Type::INTERFACE: value.setInterface(); break;
case schema::Type::OBJECT: value.adoptObject(Orphan<Data>()); break;
case schema::Type::OBJECT: value.initObject(); break;
}
}
......
......@@ -105,13 +105,13 @@ uint32_t Schema::getSchemaOffset(const schema::Value::Reader& value) const {
ptr = reinterpret_cast<const word*>(value.getData().begin());
break;
case schema::Value::STRUCT:
ptr = value.getStruct<_::UncheckedMessage>();
ptr = value.getStruct().getAs<_::UncheckedMessage>();
break;
case schema::Value::LIST:
ptr = value.getList<_::UncheckedMessage>();
ptr = value.getList().getAs<_::UncheckedMessage>();
break;
case schema::Value::OBJECT:
ptr = value.getObject<_::UncheckedMessage>();
ptr = value.getObject().getAs<_::UncheckedMessage>();
break;
default:
KJ_FAIL_ASSERT("getDefaultValueSchemaOffset() can only be called on struct, list, "
......
This diff is collapsed.
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