Commit 08d73bef authored by Kenton Varda's avatar Kenton Varda

Refactor dynamic API using new schema API.

parent e7b9e4da
// 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.
// 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.
#define CAPNPROTO_PRIVATE
#include "dynamic.h"
#include "message.h"
#include "logging.h"
#include <gtest/gtest.h>
#include "test-util.h"
namespace capnproto {
namespace internal {
namespace {
void dynamicInitTestmessage(DynamicStruct::Builder builder) {
builder.set("voidField", Void::VOID);
builder.set("boolField", true);
builder.set("int8Field", -123);
builder.set("int16Field", -12345);
builder.set("int32Field", -12345678);
builder.set("int64Field", -123456789012345ll);
builder.set("uInt8Field", 234u);
builder.set("uInt16Field", 45678u);
builder.set("uInt32Field", 3456789012u);
builder.set("uInt64Field", 12345678901234567890ull);
builder.set("float32Field", 1234.5);
builder.set("float64Field", -123e45);
builder.set("textField", Text::Reader("foo"));
builder.set("dataField", Data::Reader("bar"));
{
auto subBuilder = builder.init("structField").as<DynamicStruct>();
subBuilder.set("voidField", Void::VOID);
subBuilder.set("boolField", true);
subBuilder.set("int8Field", -12);
subBuilder.set("int16Field", 3456);
subBuilder.set("int32Field", -78901234);
subBuilder.set("int64Field", 56789012345678ll);
subBuilder.set("uInt8Field", 90u);
subBuilder.set("uInt16Field", 1234u);
subBuilder.set("uInt32Field", 56789012u);
subBuilder.set("uInt64Field", 345678901234567890ull);
subBuilder.set("float32Field", -1.25e-10);
subBuilder.set("float64Field", 345);
subBuilder.set("textField", Text::Reader("baz"));
subBuilder.set("dataField", Data::Reader("qux"));
{
auto subSubBuilder = subBuilder.init("structField").as<DynamicStruct>();
subSubBuilder.set("textField", Text::Reader("nested"));
subSubBuilder.init("structField").as<DynamicStruct>().set("textField", Text::Reader("really nested"));
}
subBuilder.set("enumField", toDynamic(TestEnum::BAZ));
subBuilder.set("voidList", {Void::VOID, Void::VOID, Void::VOID});
subBuilder.set("boolList", {false, true, false, true, true});
subBuilder.set("int8List", {12, -34, -0x80, 0x7f});
subBuilder.set("int16List", {1234, -5678, -0x8000, 0x7fff});
subBuilder.set("int32List", {12345678, -90123456, -0x8000000, 0x7ffffff});
// gcc warns on -0x800...ll and the only work-around I could find was to do -0x7ff...ll-1.
subBuilder.set("int64List", {123456789012345ll, -678901234567890ll, -0x7fffffffffffffffll-1, 0x7fffffffffffffffll});
subBuilder.set("uInt8List", {12u, 34u, 0u, 0xffu});
subBuilder.set("uInt16List", {1234u, 5678u, 0u, 0xffffu});
subBuilder.set("uInt32List", {12345678u, 90123456u, 0u, 0xffffffffu});
subBuilder.set("uInt64List", {123456789012345ull, 678901234567890ull, 0ull, 0xffffffffffffffffull});
subBuilder.set("float32List", {0, 1234567, 1e37, -1e37, 1e-37, -1e-37});
subBuilder.set("float64List", {0, 123456789012345, 1e306, -1e306, 1e-306, -1e-306});
subBuilder.set("textList", {Text::Reader("quux"), Text::Reader("corge"), Text::Reader("grault")});
subBuilder.set("dataList", {Data::Reader("garply"), Data::Reader("waldo"), Data::Reader("fred")});
{
auto listBuilder = subBuilder.init("structList", 3).as<DynamicList>();
listBuilder[0].as<DynamicStruct>().set("textField", Text::Reader("x structlist 1"));
listBuilder[1].as<DynamicStruct>().set("textField", Text::Reader("x structlist 2"));
listBuilder[2].as<DynamicStruct>().set("textField", Text::Reader("x structlist 3"));
}
subBuilder.set("enumList", {toDynamic(TestEnum::QUX),
toDynamic(TestEnum::BAR),
toDynamic(TestEnum::GRAULT)});
}
builder.set("enumField", toDynamic(TestEnum::CORGE));
builder.init("voidList", 6);
builder.set("boolList", {true, false, false, true});
builder.set("int8List", {111, -111});
builder.set("int16List", {11111, -11111});
builder.set("int32List", {111111111, -111111111});
builder.set("int64List", {1111111111111111111ll, -1111111111111111111ll});
builder.set("uInt8List", {111u, 222u});
builder.set("uInt16List", {33333u, 44444u});
builder.set("uInt32List", {3333333333u});
builder.set("uInt64List", {11111111111111111111ull});
builder.set("float32List", {5555.5,
std::numeric_limits<float>::infinity(),
-std::numeric_limits<float>::infinity(),
std::numeric_limits<float>::quiet_NaN()});
builder.set("float64List", {7777.75,
std::numeric_limits<double>::infinity(),
-std::numeric_limits<double>::infinity(),
std::numeric_limits<double>::quiet_NaN()});
builder.set("textList", {Text::Reader("plugh"), Text::Reader("xyzzy"), Text::Reader("thud")});
builder.set("dataList", {Data::Reader("oops"), Data::Reader("exhausted"), Data::Reader("rfc3092")});
{
auto listBuilder = builder.init("structList", 3).as<DynamicList>();
listBuilder[0].as<DynamicStruct>().set("textField", Text::Reader("structlist 1"));
listBuilder[1].as<DynamicStruct>().set("textField", Text::Reader("structlist 2"));
listBuilder[2].as<DynamicStruct>().set("textField", Text::Reader("structlist 3"));
}
builder.set("enumList", {toDynamic(TestEnum::FOO), toDynamic(TestEnum::GARPLY)});
}
TEST(DynamicApi, Struct) {
MallocMessageBuilder builder;
auto root = builder.initRoot<TestAllTypes>();
dynamicInitTestmessage(toDynamic(root));
checkTestMessage(root);
}
} // namespace
} // namespace internal
} // namespace capnproto
......@@ -29,125 +29,6 @@
namespace capnproto {
struct IdTextHash {
size_t operator()(std::pair<uint64_t, Text::Reader> p) const {
// djb2a hash, but seeded with ID.
size_t result = p.first;
int c;
const char* str = p.second.c_str();
while ((c = *str++)) {
result = ((result << 5) + result) ^ c; // (result * 33) ^ c
}
return result;
}
};
struct SchemaPool::Impl {
std::unordered_map<uint64_t, schema::Node::Reader> nodeMap;
std::unordered_map<std::pair<uint64_t, Text::Reader>, schema::StructNode::Member::Reader,
IdTextHash>
memberMap;
std::unordered_map<std::pair<uint64_t, Text::Reader>, schema::EnumNode::Enumerant::Reader,
IdTextHash>
enumerantMap;
std::unordered_set<uint64_t> compiledTypeIds;
};
SchemaPool::SchemaPool(): impl(new Impl) {}
SchemaPool::~SchemaPool() {
delete impl;
}
// TODO(now): Implement this. Need to copy, ick.
void SchemaPool::add(schema::Node::Reader node) {
FAIL_CHECK("Not implemented: copying/validating schemas.");
}
void SchemaPool::add(const internal::RawSchema& rawSchema) {
auto node = readMessageTrusted<schema::Node>(rawSchema.encodedNode);
if (impl->compiledTypeIds.insert(node.getId()).second) {
addNoCopy(node);
for (const internal::RawSchema*const* dep = rawSchema.dependencies;
*dep != nullptr; ++dep) {
add(**dep);
}
}
}
void SchemaPool::addNoCopy(schema::Node::Reader node) {
if (impl == nullptr) {
impl = new Impl;
}
// TODO(soon): Check if node is in base.
// TODO(soon): Check if existing node came from generated code.
uint64_t id = node.getId();
auto entry = std::make_pair(id, node);
auto ins = impl->nodeMap.insert(entry);
if (!ins.second) {
// TODO(soon): Check for compatibility.
FAIL_CHECK("TODO: Check schema compatibility when adding.");
}
switch (node.getBody().which()) {
case schema::Node::Body::STRUCT_NODE:
for (auto member: node.getBody().getStructNode().getMembers()) {
impl->memberMap[std::pair<uint64_t, Text::Reader>(id, member.getName())] = member;
}
break;
case schema::Node::Body::ENUM_NODE:
for (auto enumerant: node.getBody().getEnumNode().getEnumerants()) {
impl->enumerantMap[std::pair<uint64_t, Text::Reader>(id, enumerant.getName())] = enumerant;
}
break;
default:
break;
}
}
Maybe<schema::Node::Reader> SchemaPool::tryGetNode(uint64_t id) const {
auto iter = impl->nodeMap.find(id);
if (iter == impl->nodeMap.end()) {
return nullptr;
} else {
return iter->second;
}
}
schema::Node::Reader SchemaPool::getNode(uint64_t id) const {
auto maybeNode = tryGetNode(id);
PRECOND(maybeNode != nullptr, "Requested node ID not found in SchemaPool", hex(id));
return *maybeNode;
}
schema::Node::Reader SchemaPool::getStruct(uint64_t id) const {
auto node = getNode(id);
PRECOND(node.getBody().which() == schema::Node::Body::STRUCT_NODE,
"Looking for a struct node, but this node ID refers to something else.",
node.getBody().which());
return node;
}
schema::Node::Reader SchemaPool::getEnum(uint64_t id) const {
auto node = getNode(id);
PRECOND(node.getBody().which() == schema::Node::Body::ENUM_NODE,
"Looking for a enum node, but this node ID refers to something else.",
node.getBody().which());
return node;
}
schema::Node::Reader SchemaPool::getInterface(uint64_t id) const {
auto node = getNode(id);
PRECOND(node.getBody().which() == schema::Node::Body::INTERFACE_NODE,
"Looking for a interface node, but this node ID refers to something else.",
node.getBody().which());
return node;
}
// =======================================================================================
namespace {
template <typename T, typename U>
......@@ -210,52 +91,20 @@ internal::FieldSize elementSizeFor(schema::Type::Body::Which elementType) {
return internal::FieldSize::VOID;
}
inline internal::StructSize structSizeFromSchema(schema::StructNode::Reader schema) {
inline internal::StructSize structSizeFromSchema(StructSchema schema) {
auto node = schema.getProto().getBody().getStructNode();
return internal::StructSize(
schema.getDataSectionWordSize() * WORDS,
schema.getPointerSectionSize() * REFERENCES,
static_cast<internal::FieldSize>(schema.getPreferredListEncoding()));
node.getDataSectionWordSize() * WORDS,
node.getPointerSectionSize() * REFERENCES,
static_cast<internal::FieldSize>(node.getPreferredListEncoding()));
}
} // namespace
namespace internal {
ListSchema::ListSchema(schema::Type::Reader elementType): nestingDepth(0) {
auto etypeBody = elementType.getBody();
while (etypeBody.which() == schema::Type::Body::LIST_TYPE) {
++nestingDepth;
etypeBody = etypeBody.getListType().getBody();
}
this->elementType = etypeBody.which();
switch (etypeBody.which()) {
case schema::Type::Body::STRUCT_TYPE:
this->elementTypeId = etypeBody.getStructType();
break;
case schema::Type::Body::ENUM_TYPE:
this->elementTypeId = etypeBody.getEnumType();
break;
case schema::Type::Body::INTERFACE_TYPE:
this->elementTypeId = etypeBody.getInterfaceType();
break;
default:
this->elementTypeId = 0;
break;
}
}
} // namespace internal
// =======================================================================================
schema::EnumNode::Reader DynamicEnum::getSchema() {
return schema.getBody().getEnumNode();
}
Maybe<schema::EnumNode::Enumerant::Reader> DynamicEnum::getEnumerant() {
auto enumerants = getSchema().getEnumerants();
Maybe<EnumSchema::Enumerant> DynamicEnum::getEnumerant() {
auto enumerants = schema.getEnumerants();
if (value < enumerants.size()) {
return enumerants[value];
} else {
......@@ -263,17 +112,9 @@ Maybe<schema::EnumNode::Enumerant::Reader> DynamicEnum::getEnumerant() {
}
}
Maybe<schema::EnumNode::Enumerant::Reader> DynamicEnum::findEnumerantByName(Text::Reader name) {
auto iter = pool->impl->enumerantMap.find(std::make_pair(schema.getId(), name));
if (iter == pool->impl->enumerantMap.end()) {
return nullptr;
} else {
return iter->second;
}
}
uint16_t DynamicEnum::asImpl(uint64_t requestedTypeId) {
VALIDATE_INPUT(requestedTypeId == schema.getId(), "Type mismatch in DynamicEnum.as().") {
VALIDATE_INPUT(requestedTypeId == schema.getProto().getId(),
"Type mismatch in DynamicEnum.as().") {
// Go on with value.
}
return value;
......@@ -281,75 +122,50 @@ uint16_t DynamicEnum::asImpl(uint64_t requestedTypeId) {
// =======================================================================================
DynamicStruct::Reader DynamicObject::Reader::asStruct(schema::Node::Reader schema) {
PRECOND(schema.getBody().which() == schema::Node::Body::STRUCT_NODE,
"asStruct() passed a non-struct schema.");
DynamicStruct::Reader DynamicObject::Reader::as(StructSchema schema) {
if (reader.kind == internal::ObjectKind::NULL_POINTER) {
return DynamicStruct::Reader(pool, schema, internal::StructReader());
return DynamicStruct::Reader(schema, internal::StructReader());
}
VALIDATE_INPUT(reader.kind == internal::ObjectKind::STRUCT, "Object is not a struct.") {
return DynamicStruct::Reader(pool, schema, internal::StructReader());
return DynamicStruct::Reader(schema, internal::StructReader());
}
return DynamicStruct::Reader(pool, schema, reader.structReader);
return DynamicStruct::Reader(schema, reader.structReader);
}
DynamicStruct::Builder DynamicObject::Builder::asStruct(schema::Node::Reader schema) {
PRECOND(schema.getBody().which() == schema::Node::Body::STRUCT_NODE,
"asStruct() passed a non-struct schema.");
DynamicStruct::Builder DynamicObject::Builder::as(StructSchema schema) {
if (builder.kind == internal::ObjectKind::NULL_POINTER) {
return DynamicStruct::Builder(pool, schema, internal::StructBuilder());
return DynamicStruct::Builder(schema, internal::StructBuilder());
}
VALIDATE_INPUT(builder.kind == internal::ObjectKind::STRUCT, "Object is not a struct.") {
return DynamicStruct::Builder(pool, schema, internal::StructBuilder());
return DynamicStruct::Builder(schema, internal::StructBuilder());
}
return DynamicStruct::Builder(pool, schema, builder.structBuilder);
}
DynamicStruct::Reader DynamicObject::Reader::asStruct(uint64_t typeId) {
return asStruct(pool->getStruct(typeId));
}
DynamicStruct::Builder DynamicObject::Builder::asStruct(uint64_t typeId) {
return asStruct(pool->getStruct(typeId));
return DynamicStruct::Builder(schema, builder.structBuilder);
}
DynamicList::Reader DynamicObject::Reader::asList(schema::Type::Reader elementType) {
return asList(internal::ListSchema(elementType));
}
DynamicList::Builder DynamicObject::Builder::asList(schema::Type::Reader elementType) {
return asList(internal::ListSchema(elementType));
}
DynamicList::Reader DynamicObject::Reader::asList(internal::ListSchema schema) {
DynamicList::Reader DynamicObject::Reader::as(ListSchema schema) {
if (reader.kind == internal::ObjectKind::NULL_POINTER) {
return DynamicList::Reader(pool, schema, internal::ListReader());
return DynamicList::Reader(schema, internal::ListReader());
}
VALIDATE_INPUT(reader.kind == internal::ObjectKind::LIST, "Object is not a list.") {
return DynamicList::Reader(pool, schema, internal::ListReader());
return DynamicList::Reader(schema, internal::ListReader());
}
return DynamicList::Reader(pool, schema, reader.listReader);
return DynamicList::Reader(schema, reader.listReader);
}
DynamicList::Builder DynamicObject::Builder::asList(internal::ListSchema schema) {
DynamicList::Builder DynamicObject::Builder::as(ListSchema schema) {
if (builder.kind == internal::ObjectKind::NULL_POINTER) {
return DynamicList::Builder(pool, schema, internal::ListBuilder());
return DynamicList::Builder(schema, internal::ListBuilder());
}
VALIDATE_INPUT(builder.kind == internal::ObjectKind::LIST, "Object is not a list.") {
return DynamicList::Builder(pool, schema, internal::ListBuilder());
return DynamicList::Builder(schema, internal::ListBuilder());
}
return DynamicList::Builder(pool, schema, builder.listBuilder);
return DynamicList::Builder(schema, builder.listBuilder);
}
// =======================================================================================
schema::StructNode::Union::Reader DynamicUnion::Reader::getSchema() {
return schema.getBody().getUnionMember();
}
schema::StructNode::Union::Reader DynamicUnion::Builder::getSchema() {
return schema.getBody().getUnionMember();
}
Maybe<schema::StructNode::Member::Reader> DynamicUnion::Reader::which() {
auto uschema = getSchema();
auto members = uschema.getMembers();
uint16_t discrim = reader.getDataField<uint32_t>(uschema.getDiscriminantOffset() * ELEMENTS);
Maybe<StructSchema::Member> DynamicUnion::Reader::which() {
auto members = schema.getMembers();
uint16_t discrim = reader.getDataField<uint32_t>(
schema.getProto().getBody().getUnionMember().getDiscriminantOffset() * ELEMENTS);
if (discrim < members.size()) {
return members[discrim];
......@@ -357,10 +173,10 @@ Maybe<schema::StructNode::Member::Reader> DynamicUnion::Reader::which() {
return nullptr;
}
}
Maybe<schema::StructNode::Member::Reader> DynamicUnion::Builder::which() {
auto uschema = getSchema();
auto members = uschema.getMembers();
uint16_t discrim = builder.getDataField<uint32_t>(uschema.getDiscriminantOffset() * ELEMENTS);
Maybe<StructSchema::Member> DynamicUnion::Builder::which() {
auto members = schema.getMembers();
uint16_t discrim = builder.getDataField<uint32_t>(
schema.getProto().getBody().getUnionMember().getDiscriminantOffset() * ELEMENTS);
if (discrim < members.size()) {
return members[discrim];
......@@ -374,9 +190,9 @@ DynamicValue::Reader DynamicUnion::Reader::get() {
RECOVERABLE_PRECOND(w != nullptr, "Can't get() unknown union value.") {
return DynamicValue::Reader();
}
CHECK(w->getBody().which() == schema::StructNode::Member::Body::FIELD_MEMBER,
CHECK(w->getProto().getBody().which() == schema::StructNode::Member::Body::FIELD_MEMBER,
"Unsupported union member type.");
return DynamicValue::Reader(DynamicStruct::Reader::getImpl(pool, reader, *w));
return DynamicValue::Reader(DynamicStruct::Reader::getImpl(reader, *w));
}
DynamicValue::Builder DynamicUnion::Builder::get() {
......@@ -384,169 +200,222 @@ DynamicValue::Builder DynamicUnion::Builder::get() {
RECOVERABLE_PRECOND(w != nullptr, "Can't get() unknown union value.") {
return DynamicValue::Builder();
}
CHECK(w->getBody().which() == schema::StructNode::Member::Body::FIELD_MEMBER,
CHECK(w->getProto().getBody().which() == schema::StructNode::Member::Body::FIELD_MEMBER,
"Unsupported union member type.");
return DynamicValue::Builder(DynamicStruct::Builder::getImpl(pool, builder, *w));
return DynamicValue::Builder(DynamicStruct::Builder::getImpl(builder, *w));
}
void DynamicUnion::Builder::set(
schema::StructNode::Member::Reader member, DynamicValue::Reader value) {
builder.setDataField<uint16_t>(getSchema().getDiscriminantOffset() * ELEMENTS, member.getIndex());
DynamicStruct::Builder::setImpl(pool, builder, member, value);
void DynamicUnion::Builder::set(StructSchema::Member member, DynamicValue::Reader value) {
auto containingUnion = member.getContainingUnion();
RECOVERABLE_PRECOND(containingUnion != nullptr && *containingUnion == schema,
"`member` is not a member of this union.") {
return;
}
builder.setDataField<uint16_t>(
schema.getProto().getBody().getUnionMember().getDiscriminantOffset() * ELEMENTS,
member.getIndex());
DynamicStruct::Builder::setImpl(builder, member, value);
}
DynamicValue::Builder DynamicUnion::Builder::init(schema::StructNode::Member::Reader member) {
builder.setDataField<uint16_t>(getSchema().getDiscriminantOffset() * ELEMENTS, member.getIndex());
return DynamicStruct::Builder::initImpl(pool, builder, member);
DynamicValue::Builder DynamicUnion::Builder::init(StructSchema::Member member) {
builder.setDataField<uint16_t>(
schema.getProto().getBody().getUnionMember().getDiscriminantOffset() * ELEMENTS,
member.getIndex());
return DynamicStruct::Builder::initImpl(builder, member);
}
DynamicValue::Builder DynamicUnion::Builder::init(schema::StructNode::Member::Reader member,
uint size) {
builder.setDataField<uint16_t>(getSchema().getDiscriminantOffset() * ELEMENTS, member.getIndex());
return DynamicStruct::Builder::initImpl(pool, builder, member, size);
DynamicValue::Builder DynamicUnion::Builder::init(StructSchema::Member member, uint size) {
builder.setDataField<uint16_t>(
schema.getProto().getBody().getUnionMember().getDiscriminantOffset() * ELEMENTS,
member.getIndex());
return DynamicStruct::Builder::initImpl(builder, member, size);
}
// =======================================================================================
void DynamicStruct::Reader::verifyTypeId(uint64_t id) {
VALIDATE_INPUT(id == schema.getId(),
VALIDATE_INPUT(id == schema.getProto().getId(),
"Type mismatch when using DynamicStruct::Reader::as().") {
// Go on with bad type ID.
}
}
void DynamicStruct::Builder::verifyTypeId(uint64_t id) {
VALIDATE_INPUT(id == schema.getId(),
VALIDATE_INPUT(id == schema.getProto().getId(),
"Type mismatch when using DynamicStruct::Builder::as().") {
// Go on with bad type ID.
}
}
schema::StructNode::Reader DynamicStruct::Reader::getSchema() {
return schema.getBody().getStructNode();
DynamicValue::Reader DynamicStruct::Reader::get(StructSchema::Member member) {
PRECOND(member.getContainingStruct() == schema, "`member` is not a member of this struct.");
return getImpl(reader, member);
}
schema::StructNode::Reader DynamicStruct::Builder::getSchema() {
return schema.getBody().getStructNode();
DynamicValue::Builder DynamicStruct::Builder::get(StructSchema::Member member) {
PRECOND(member.getContainingStruct() == schema, "`member` is not a member of this struct.");
return getImpl(builder, member);
}
void DynamicStruct::Builder::set(StructSchema::Member member, DynamicValue::Reader value) {
PRECOND(member.getContainingStruct() == schema, "`member` is not a member of this struct.");
return setImpl(builder, member, value);
}
DynamicValue::Builder DynamicStruct::Builder::init(StructSchema::Member member) {
PRECOND(member.getContainingStruct() == schema, "`member` is not a member of this struct.");
return initImpl(builder, member);
}
DynamicValue::Builder DynamicStruct::Builder::init(StructSchema::Member member, uint size) {
PRECOND(member.getContainingStruct() == schema,
"`member` is not a member of this struct.");
return initImpl(builder, member, size);
}
DynamicStruct::Builder DynamicStruct::Builder::initObject(
StructSchema::Member member, StructSchema type) {
PRECOND(member.getContainingStruct() == schema, "`member` is not a member of this struct.");
switch (member.getProto().getBody().which()) {
case schema::StructNode::Member::Body::UNION_MEMBER:
FAIL_PRECOND("Can't init() a union. get() it first and then init() one of its members.");
return DynamicStruct::Builder();
Maybe<schema::StructNode::Member::Reader> DynamicStruct::Reader::findMemberByName(
Text::Reader name) {
auto iter = pool->impl->memberMap.find(std::make_pair(schema.getId(), name));
if (iter == pool->impl->memberMap.end()) {
return nullptr;
} else {
return iter->second;
case schema::StructNode::Member::Body::FIELD_MEMBER: {
auto field = member.getProto().getBody().getFieldMember();
PRECOND(field.getType().getBody().which() == schema::Type::Body::OBJECT_TYPE,
"Expected an Object. (To dynamically initialize a non-Object field, do not "
"pass an element type to initObjectField().)");
return initFieldImpl(builder, member, type);
}
}
FAIL_CHECK("switch() missing case.", member.getProto().getBody().which());
return DynamicStruct::Builder();
}
Maybe<schema::StructNode::Member::Reader> DynamicStruct::Builder::findMemberByName(
Text::Reader name) {
auto iter = pool->impl->memberMap.find(std::make_pair(schema.getId(), name));
if (iter == pool->impl->memberMap.end()) {
return nullptr;
} else {
return iter->second;
DynamicList::Builder DynamicStruct::Builder::initObject(
StructSchema::Member member, ListSchema type, uint size) {
PRECOND(member.getContainingStruct() == schema, "`member` is not a member of this struct.");
switch (member.getProto().getBody().which()) {
case schema::StructNode::Member::Body::UNION_MEMBER:
FAIL_PRECOND("Can't init() a union. get() it first and then init() one of its members.");
return DynamicList::Builder();
case schema::StructNode::Member::Body::FIELD_MEMBER: {
auto field = member.getProto().getBody().getFieldMember();
PRECOND(field.getType().getBody().which() == schema::Type::Body::OBJECT_TYPE,
"Expected an Object. (To dynamically initialize a non-Object field, do not "
"pass a struct schema to initObjectField().)");
return initFieldImpl(builder, member, type, size);
}
}
}
DynamicValue::Builder DynamicStruct::Builder::initObject(
schema::StructNode::Member::Reader member, schema::Type::Reader type) {
switch (member.getBody().which()) {
FAIL_CHECK("switch() missing case.", member.getProto().getBody().which());
return DynamicList::Builder();
}
Text::Builder DynamicStruct::Builder::initObjectAsText(StructSchema::Member member, uint size) {
PRECOND(member.getContainingStruct() == schema, "`member` is not a member of this struct.");
switch (member.getProto().getBody().which()) {
case schema::StructNode::Member::Body::UNION_MEMBER:
FAIL_VALIDATE_INPUT(
"Can't init() a union. get() it first and then init() one of its members.");
return getImpl(pool, builder, member);
FAIL_PRECOND("Can't init() a union. get() it first and then init() one of its members.");
return Text::Builder();
case schema::StructNode::Member::Body::FIELD_MEMBER: {
auto field = member.getBody().getFieldMember();
VALIDATE_INPUT(field.getType().getBody().which() == schema::Type::Body::OBJECT_TYPE,
"Expected an Object. (To dynamically initialize a non-Object field, do not "
"pass an element type to initObjectField().)") {
return initImpl(pool, builder, member);
}
return initFieldImpl(pool, builder, field, type);
auto field = member.getProto().getBody().getFieldMember();
PRECOND(field.getType().getBody().which() == schema::Type::Body::OBJECT_TYPE,
"Expected an Object. (To dynamically initialize a non-Object field, do not "
"pass a struct schema to initObjectField().)");
return initFieldAsDataImpl(builder, member, size);
}
}
FAIL_CHECK("switch() missing case.", member.getBody().which());
return getImpl(pool, builder, member);
FAIL_CHECK("switch() missing case.", member.getProto().getBody().which());
return Text::Builder();
}
DynamicValue::Builder DynamicStruct::Builder::initObject(
schema::StructNode::Member::Reader member, schema::Type::Reader type, uint size) {
switch (member.getBody().which()) {
Data::Builder DynamicStruct::Builder::initObjectAsData(StructSchema::Member member, uint size) {
PRECOND(member.getContainingStruct() == schema, "`member` is not a member of this struct.");
switch (member.getProto().getBody().which()) {
case schema::StructNode::Member::Body::UNION_MEMBER:
FAIL_VALIDATE_INPUT(
"Can't init() a union. get() it first and then init() one of its members.");
return getImpl(pool, builder, member);
FAIL_PRECOND("Can't init() a union. get() it first and then init() one of its members.");
return Data::Builder();
case schema::StructNode::Member::Body::FIELD_MEMBER: {
auto field = member.getBody().getFieldMember();
VALIDATE_INPUT(field.getType().getBody().which() == schema::Type::Body::OBJECT_TYPE,
"Expected an Object. (To dynamically initialize a non-Object field, do not "
"pass a struct schema to initObjectField().)") {
return initImpl(pool, builder, member, size);
}
return initFieldImpl(pool, builder, field, type, size);
auto field = member.getProto().getBody().getFieldMember();
PRECOND(field.getType().getBody().which() == schema::Type::Body::OBJECT_TYPE,
"Expected an Object. (To dynamically initialize a non-Object field, do not "
"pass a struct schema to initObjectField().)");
return initFieldAsDataImpl(builder, member, size);
}
}
FAIL_CHECK("switch() missing case.", member.getBody().which());
return getImpl(pool, builder, member);
FAIL_CHECK("switch() missing case.", member.getProto().getBody().which());
return Data::Builder();
}
DynamicValue::Reader DynamicStruct::Reader::get(Text::Reader name) {
auto member = findMemberByName(name);
auto member = schema.findMemberByName(name);
RECOVERABLE_PRECOND(member != nullptr, "struct has no such member", name) {
return DynamicValue::Reader();
}
return get(*member);
return getImpl(reader, *member);
}
DynamicValue::Builder DynamicStruct::Builder::get(Text::Reader name) {
auto member = findMemberByName(name);
auto member = schema.findMemberByName(name);
RECOVERABLE_PRECOND(member != nullptr, "struct has no such member", name) {
return DynamicValue::Builder();
}
return get(*member);
return getImpl(builder, *member);
}
void DynamicStruct::Builder::set(Text::Reader name, DynamicValue::Reader value) {
auto member = findMemberByName(name);
auto member = schema.findMemberByName(name);
RECOVERABLE_PRECOND(member != nullptr, "struct has no such member", name) {
return;
}
return set(*member, value);
return setImpl(builder, *member, value);
}
void DynamicStruct::Builder::set(Text::Reader name,
std::initializer_list<DynamicValue::Reader> value) {
init(name, value.size()).as<DynamicList>().copyFrom(value);
}
DynamicValue::Builder DynamicStruct::Builder::init(Text::Reader name) {
auto member = findMemberByName(name);
auto member = schema.findMemberByName(name);
RECOVERABLE_PRECOND(member != nullptr, "struct has no such member", name) {
return DynamicValue::Builder();
}
return init(*member);
return initImpl(builder, *member);
}
DynamicValue::Builder DynamicStruct::Builder::init(Text::Reader name, uint size) {
auto member = findMemberByName(name);
auto member = schema.findMemberByName(name);
RECOVERABLE_PRECOND(member != nullptr, "struct has no such member", name) {
return DynamicValue::Builder();
}
return init(*member, size);
return initImpl(builder, *member, size);
}
DynamicValue::Builder DynamicStruct::Builder::initObject(
Text::Reader name, schema::Type::Reader type) {
auto member = findMemberByName(name);
DynamicStruct::Builder DynamicStruct::Builder::initObject(
Text::Reader name, StructSchema type) {
auto member = schema.findMemberByName(name);
RECOVERABLE_PRECOND(member != nullptr, "struct has no such member", name) {
return DynamicValue::Builder();
return DynamicStruct::Builder();
}
return initObject(*member, type);
}
DynamicValue::Builder DynamicStruct::Builder::initObject(
Text::Reader name, schema::Type::Reader type, uint size) {
auto member = findMemberByName(name);
DynamicList::Builder DynamicStruct::Builder::initObject(
Text::Reader name, ListSchema type, uint size) {
auto member = schema.findMemberByName(name);
RECOVERABLE_PRECOND(member != nullptr, "struct has no such member", name) {
return DynamicValue::Builder();
return DynamicList::Builder();
}
return initObject(*member, type, size);
}
Text::Builder DynamicStruct::Builder::initObjectAsText(Text::Reader name, uint size) {
auto member = schema.findMemberByName(name);
RECOVERABLE_PRECOND(member != nullptr, "struct has no such member", name) {
return Text::Builder();
}
return initObjectAsText(*member, size);
}
Data::Builder DynamicStruct::Builder::initObjectAsData(Text::Reader name, uint size) {
auto member = schema.findMemberByName(name);
RECOVERABLE_PRECOND(member != nullptr, "struct has no such member", name) {
return Data::Builder();
}
return initObjectAsText(*member, size);
}
void DynamicStruct::Builder::copyFrom(Reader other) {
// TODO(now): copyFrom on StructBuilder.
......@@ -555,14 +424,13 @@ void DynamicStruct::Builder::copyFrom(Reader other) {
}
DynamicValue::Reader DynamicStruct::Reader::getImpl(
const SchemaPool* pool, internal::StructReader reader,
schema::StructNode::Member::Reader member) {
switch (member.getBody().which()) {
internal::StructReader reader, StructSchema::Member member) {
switch (member.getProto().getBody().which()) {
case schema::StructNode::Member::Body::UNION_MEMBER:
return DynamicUnion::Reader(pool, member, reader);
return DynamicUnion::Reader(member.asUnion(), reader);
case schema::StructNode::Member::Body::FIELD_MEMBER: {
auto field = member.getBody().getFieldMember();
auto field = member.getProto().getBody().getFieldMember();
auto type = field.getType().getBody();
auto dval = field.getDefaultValue().getBody();
......@@ -594,7 +462,7 @@ DynamicValue::Reader DynamicStruct::Reader::getImpl(
uint16_t typedDval;
typedDval = dval.getEnumValue();
return DynamicValue::Reader(DynamicEnum(
pool, pool->getEnum(type.getEnumType()),
member.getContainingStruct().getDependency(type.getEnumType()).asEnum(),
reader.getDataField<uint16_t>(field.getOffset() * ELEMENTS, typedDval)));
}
......@@ -615,7 +483,7 @@ DynamicValue::Reader DynamicStruct::Reader::getImpl(
case schema::Type::Body::LIST_TYPE: {
auto elementType = type.getListType();
return DynamicValue::Reader(DynamicList::Reader(
pool, elementType,
ListSchema::of(elementType, member.getContainingStruct()),
reader.getListField(field.getOffset() * REFERENCES,
elementSizeFor(elementType.getBody().which()),
dval.getListValue<internal::TrustedMessage>())));
......@@ -623,15 +491,15 @@ DynamicValue::Reader DynamicStruct::Reader::getImpl(
case schema::Type::Body::STRUCT_TYPE: {
return DynamicValue::Reader(DynamicStruct::Reader(
pool, pool->getStruct(type.getStructType()),
member.getContainingStruct().getDependency(type.getStructType()).asStruct(),
reader.getStructField(field.getOffset() * REFERENCES,
dval.getStructValue<internal::TrustedMessage>())));
}
case schema::Type::Body::OBJECT_TYPE: {
return DynamicValue::Reader(DynamicObject::Reader(
pool, reader.getObjectField(field.getOffset() * REFERENCES,
dval.getObjectValue<internal::TrustedMessage>())));
reader.getObjectField(field.getOffset() * REFERENCES,
dval.getObjectValue<internal::TrustedMessage>())));
}
case schema::Type::Body::INTERFACE_TYPE:
......@@ -644,19 +512,18 @@ DynamicValue::Reader DynamicStruct::Reader::getImpl(
}
}
FAIL_CHECK("switch() missing case.", member.getBody().which());
FAIL_CHECK("switch() missing case.", member.getProto().getBody().which());
return DynamicValue::Reader();
}
DynamicValue::Builder DynamicStruct::Builder::getImpl(
const SchemaPool* pool, internal::StructBuilder builder,
schema::StructNode::Member::Reader member) {
switch (member.getBody().which()) {
internal::StructBuilder builder, StructSchema::Member member) {
switch (member.getProto().getBody().which()) {
case schema::StructNode::Member::Body::UNION_MEMBER:
return DynamicUnion::Builder(pool, member, builder);
return DynamicUnion::Builder(member.asUnion(), builder);
case schema::StructNode::Member::Body::FIELD_MEMBER: {
auto field = member.getBody().getFieldMember();
auto field = member.getProto().getBody().getFieldMember();
auto type = field.getType().getBody();
auto dval = field.getDefaultValue().getBody();
......@@ -688,7 +555,7 @@ DynamicValue::Builder DynamicStruct::Builder::getImpl(
uint16_t typedDval;
typedDval = dval.getEnumValue();
return DynamicValue::Builder(DynamicEnum(
pool, pool->getEnum(type.getEnumType()),
member.getContainingStruct().getDependency(type.getEnumType()).asEnum(),
builder.getDataField<uint16_t>(field.getOffset() * ELEMENTS, typedDval)));
}
......@@ -709,29 +576,26 @@ DynamicValue::Builder DynamicStruct::Builder::getImpl(
case schema::Type::Body::LIST_TYPE: {
auto elementType = type.getListType();
return DynamicValue::Builder(DynamicList::Builder(
pool, elementType,
ListSchema::of(elementType, member.getContainingStruct()),
builder.getListField(field.getOffset() * REFERENCES,
dval.getListValue<internal::TrustedMessage>())));
}
case schema::Type::Body::STRUCT_TYPE: {
auto structNode = pool->getStruct(type.getStructType());
auto structSchema = structNode.getBody().getStructNode();
auto structSchema =
member.getContainingStruct().getDependency(type.getStructType()).asStruct();
return DynamicValue::Builder(DynamicStruct::Builder(
pool, structNode,
structSchema,
builder.getStructField(
field.getOffset() * REFERENCES,
internal::StructSize(
structSchema.getDataSectionWordSize() * WORDS,
structSchema.getPointerSectionSize() * REFERENCES,
static_cast<internal::FieldSize>(structSchema.getPreferredListEncoding())),
structSizeFromSchema(structSchema),
dval.getStructValue<internal::TrustedMessage>())));
}
case schema::Type::Body::OBJECT_TYPE: {
return DynamicValue::Builder(DynamicObject::Builder(
pool, builder.getObjectField(field.getOffset() * REFERENCES,
dval.getObjectValue<internal::TrustedMessage>())));
builder.getObjectField(field.getOffset() * REFERENCES,
dval.getObjectValue<internal::TrustedMessage>())));
}
case schema::Type::Body::INTERFACE_TYPE:
......@@ -744,14 +608,13 @@ DynamicValue::Builder DynamicStruct::Builder::getImpl(
}
}
FAIL_CHECK("switch() missing case.", member.getBody().which());
FAIL_CHECK("switch() missing case.", member.getProto().getBody().which());
return DynamicValue::Builder();
}
void DynamicStruct::Builder::setImpl(
const SchemaPool* pool, internal::StructBuilder builder,
schema::StructNode::Member::Reader member, DynamicValue::Reader value) {
switch (member.getBody().which()) {
internal::StructBuilder builder, StructSchema::Member member, DynamicValue::Reader value) {
switch (member.getProto().getBody().which()) {
case schema::StructNode::Member::Body::UNION_MEMBER: {
auto src = value.as<DynamicUnion>();
auto which = src.which();
......@@ -760,12 +623,13 @@ void DynamicStruct::Builder::setImpl(
"was probably constructed using a newer version of the schema.") {
return;
}
setImpl(pool, builder, *which, src.get());
getImpl(builder, member).as<DynamicUnion>().set(member, src.get());
return;
}
case schema::StructNode::Member::Body::FIELD_MEMBER: {
auto field = member.getBody().getFieldMember();
auto field = member.getProto().getBody().getFieldMember();
auto type = field.getType().getBody();
auto dval = field.getDefaultValue().getBody();
......@@ -813,7 +677,7 @@ void DynamicStruct::Builder::setImpl(
// TODO(now): We need to do a schemaless copy to avoid losing information if the values
// are larger than what the schema defines.
auto listValue = value.as<DynamicList>();
initImpl(pool, builder, member, listValue.size())
initImpl(builder, member, listValue.size())
.as<DynamicList>().copyFrom(listValue);
return;
}
......@@ -821,7 +685,7 @@ void DynamicStruct::Builder::setImpl(
case schema::Type::Body::STRUCT_TYPE: {
// TODO(now): We need to do a schemaless copy to avoid losing information if the values
// are larger than what the schema defines.
initImpl(pool, builder, member).as<DynamicStruct>()
initImpl(builder, member).as<DynamicStruct>()
.copyFrom(value.as<DynamicStruct>());
return;
}
......@@ -842,149 +706,94 @@ void DynamicStruct::Builder::setImpl(
}
}
FAIL_CHECK("switch() missing case.", member.getBody().which());
FAIL_CHECK("switch() missing case.", member.getProto().getBody().which());
}
DynamicValue::Builder DynamicStruct::Builder::initImpl(
const SchemaPool* pool, internal::StructBuilder builder,
schema::StructNode::Member::Reader member, uint size) {
switch (member.getBody().which()) {
internal::StructBuilder builder, StructSchema::Member member, uint size) {
switch (member.getProto().getBody().which()) {
case schema::StructNode::Member::Body::UNION_MEMBER:
FAIL_VALIDATE_INPUT(
"Can't init() a union. get() it first and then init() one of its members.");
return getImpl(pool, builder, member);
break;
case schema::StructNode::Member::Body::FIELD_MEMBER: {
auto field = member.getBody().getFieldMember();
return initFieldImpl(pool, builder, field, field.getType(), size);
auto type = member.getProto().getBody().getFieldMember().getType().getBody();
switch (type.which()) {
case schema::Type::Body::LIST_TYPE:
return initFieldImpl(builder, member, ListSchema::of(
type.getListType(), member.getContainingStruct()), size);
case schema::Type::Body::TEXT_TYPE:
return initFieldAsTextImpl(builder, member, size);
case schema::Type::Body::DATA_TYPE:
return initFieldAsDataImpl(builder, member, size);
default:
FAIL_VALIDATE_INPUT(
"init() with size is only valid for list, text, or data fields.", type.which());
break;
}
break;
}
}
FAIL_CHECK("switch() missing case.", member.getBody().which());
return getImpl(pool, builder, member);
// Failed.
return getImpl(builder, member);
}
DynamicValue::Builder DynamicStruct::Builder::initImpl(
const SchemaPool* pool, internal::StructBuilder builder,
schema::StructNode::Member::Reader member) {
switch (member.getBody().which()) {
internal::StructBuilder builder, StructSchema::Member member) {
switch (member.getProto().getBody().which()) {
case schema::StructNode::Member::Body::UNION_MEMBER:
FAIL_VALIDATE_INPUT(
"Can't init() a union. get() it first and then init() one of its members.");
return getImpl(pool, builder, member);
break;
case schema::StructNode::Member::Body::FIELD_MEMBER: {
auto field = member.getBody().getFieldMember();
return initFieldImpl(pool, builder, field, field.getType());
}
}
FAIL_CHECK("switch() missing case.", member.getBody().which());
return getImpl(pool, builder, member);
}
DynamicValue::Builder DynamicStruct::Builder::initFieldImpl(
const SchemaPool* pool, internal::StructBuilder builder,
schema::StructNode::Field::Reader field,
schema::Type::Reader type, uint size) {
switch (type.getBody().which()) {
case schema::Type::Body::VOID_TYPE:
case schema::Type::Body::BOOL_TYPE:
case schema::Type::Body::INT8_TYPE:
case schema::Type::Body::INT16_TYPE:
case schema::Type::Body::INT32_TYPE:
case schema::Type::Body::INT64_TYPE:
case schema::Type::Body::UINT8_TYPE:
case schema::Type::Body::UINT16_TYPE:
case schema::Type::Body::UINT32_TYPE:
case schema::Type::Body::UINT64_TYPE:
case schema::Type::Body::FLOAT32_TYPE:
case schema::Type::Body::FLOAT64_TYPE:
case schema::Type::Body::ENUM_TYPE:
case schema::Type::Body::STRUCT_TYPE:
case schema::Type::Body::INTERFACE_TYPE:
FAIL_VALIDATE_INPUT("Expected a list or blob.");
return DynamicValue::Builder();
case schema::Type::Body::TEXT_TYPE:
return DynamicValue::Builder(
builder.initBlobField<Text>(field.getOffset() * REFERENCES, size * BYTES));
case schema::Type::Body::DATA_TYPE:
return DynamicValue::Builder(
builder.initBlobField<Data>(field.getOffset() * REFERENCES, size * BYTES));
case schema::Type::Body::LIST_TYPE: {
auto elementType = type.getBody().getListType();
if (elementType.getBody().which() == schema::Type::Body::STRUCT_TYPE) {
auto structType = pool->getStruct(elementType.getBody().getStructType());
return DynamicValue::Builder(DynamicList::Builder(
pool, schema::Type::Body::STRUCT_TYPE, 0, structType, builder.initStructListField(
field.getOffset() * REFERENCES, size * ELEMENTS,
structSizeFromSchema(structType.getBody().getStructNode()))));
} else {
return DynamicValue::Builder(DynamicList::Builder(
pool, elementType, builder.initListField(
field.getOffset() * REFERENCES,
elementSizeFor(elementType.getBody().which()),
size * ELEMENTS)));
auto type = member.getProto().getBody().getFieldMember().getType().getBody();
VALIDATE_INPUT(type.which() == schema::Type::Body::STRUCT_TYPE,
"init() without a size is only valid for struct fields.") {
break;
}
}
case schema::Type::Body::OBJECT_TYPE: {
FAIL_VALIDATE_INPUT(
"Expected a list or blob, but found Object. (To dynamically initialize an object "
"field, you must pass an element type to initField().)");
return DynamicValue::Builder();
return initFieldImpl(builder, member,
member.getContainingStruct().getDependency(type.getStructType()).asStruct());
}
}
FAIL_CHECK("switch() missing case.", type.getBody().which());
return DynamicValue::Builder();
}
DynamicValue::Builder DynamicStruct::Builder::initFieldImpl(
const SchemaPool* pool, internal::StructBuilder builder,
schema::StructNode::Field::Reader field,
schema::Type::Reader type) {
switch (type.getBody().which()) {
case schema::Type::Body::VOID_TYPE:
case schema::Type::Body::BOOL_TYPE:
case schema::Type::Body::INT8_TYPE:
case schema::Type::Body::INT16_TYPE:
case schema::Type::Body::INT32_TYPE:
case schema::Type::Body::INT64_TYPE:
case schema::Type::Body::UINT8_TYPE:
case schema::Type::Body::UINT16_TYPE:
case schema::Type::Body::UINT32_TYPE:
case schema::Type::Body::UINT64_TYPE:
case schema::Type::Body::FLOAT32_TYPE:
case schema::Type::Body::FLOAT64_TYPE:
case schema::Type::Body::ENUM_TYPE:
case schema::Type::Body::TEXT_TYPE:
case schema::Type::Body::DATA_TYPE:
case schema::Type::Body::LIST_TYPE:
case schema::Type::Body::INTERFACE_TYPE:
FAIL_VALIDATE_INPUT("Expected a list or blob.");
return DynamicValue::Builder();
case schema::Type::Body::STRUCT_TYPE: {
auto structType = pool->getStruct(type.getBody().getStructType());
return DynamicValue::Builder(DynamicStruct::Builder(
pool, structType, builder.initStructField(
field.getOffset() * REFERENCES,
structSizeFromSchema(structType.getBody().getStructNode()))));
}
case schema::Type::Body::OBJECT_TYPE: {
FAIL_VALIDATE_INPUT(
"Expected a struct, but found Object. (To dynamically initialize an object "
"field, you must pass an element type to initField().)");
return DynamicValue::Builder();
}
// Failed.
return getImpl(builder, member);
}
DynamicStruct::Builder DynamicStruct::Builder::initFieldImpl(
internal::StructBuilder builder, StructSchema::Member field, StructSchema type) {
return DynamicStruct::Builder(
type, builder.initStructField(
field.getProto().getBody().getFieldMember().getOffset() * REFERENCES,
structSizeFromSchema(type)));
}
DynamicList::Builder DynamicStruct::Builder::initFieldImpl(
internal::StructBuilder builder, StructSchema::Member field,
ListSchema type, uint size) {
if (type.whichElementType() == schema::Type::Body::STRUCT_TYPE) {
return DynamicList::Builder(
type, builder.initStructListField(
field.getProto().getBody().getFieldMember().getOffset() * REFERENCES, size * ELEMENTS,
structSizeFromSchema(type.getStructElementType())));
} else {
return DynamicList::Builder(
type, builder.initListField(
field.getProto().getBody().getFieldMember().getOffset() * REFERENCES,
elementSizeFor(type.whichElementType()),
size * ELEMENTS));
}
FAIL_CHECK("switch() missing case.", type.getBody().which());
return DynamicValue::Builder();
}
Text::Builder DynamicStruct::Builder::initFieldAsTextImpl(
internal::StructBuilder builder, StructSchema::Member field, uint size) {
return builder.initBlobField<Text>(
field.getProto().getBody().getFieldMember().getOffset() * REFERENCES, size * BYTES);
}
Data::Builder DynamicStruct::Builder::initFieldAsDataImpl(
internal::StructBuilder builder, StructSchema::Member field, uint size) {
return builder.initBlobField<Data>(
field.getProto().getBody().getFieldMember().getOffset() * REFERENCES, size * BYTES);
}
// =======================================================================================
......@@ -992,244 +801,224 @@ DynamicValue::Builder DynamicStruct::Builder::initFieldImpl(
DynamicValue::Reader DynamicList::Reader::operator[](uint index) {
PRECOND(index < size(), "List index out-of-bounds.");
if (depth == 0) {
switch (elementType) {
switch (schema.whichElementType()) {
#define HANDLE_TYPE(name, discrim, typeName) \
case schema::Type::Body::discrim##_TYPE: \
return DynamicValue::Reader(reader.getDataElement<typeName>(index * ELEMENTS));
HANDLE_TYPE(void, VOID, Void)
HANDLE_TYPE(bool, BOOL, bool)
HANDLE_TYPE(int8, INT8, int8_t)
HANDLE_TYPE(int16, INT16, int16_t)
HANDLE_TYPE(int32, INT32, int32_t)
HANDLE_TYPE(int64, INT64, int64_t)
HANDLE_TYPE(uint8, UINT8, uint8_t)
HANDLE_TYPE(uint16, UINT16, uint16_t)
HANDLE_TYPE(uint32, UINT32, uint32_t)
HANDLE_TYPE(uint64, UINT64, uint64_t)
HANDLE_TYPE(float32, FLOAT32, float)
HANDLE_TYPE(float64, FLOAT64, double)
case schema::Type::Body::discrim##_TYPE: \
return DynamicValue::Reader(reader.getDataElement<typeName>(index * ELEMENTS));
HANDLE_TYPE(void, VOID, Void)
HANDLE_TYPE(bool, BOOL, bool)
HANDLE_TYPE(int8, INT8, int8_t)
HANDLE_TYPE(int16, INT16, int16_t)
HANDLE_TYPE(int32, INT32, int32_t)
HANDLE_TYPE(int64, INT64, int64_t)
HANDLE_TYPE(uint8, UINT8, uint8_t)
HANDLE_TYPE(uint16, UINT16, uint16_t)
HANDLE_TYPE(uint32, UINT32, uint32_t)
HANDLE_TYPE(uint64, UINT64, uint64_t)
HANDLE_TYPE(float32, FLOAT32, float)
HANDLE_TYPE(float64, FLOAT64, double)
#undef HANDLE_TYPE
case schema::Type::Body::TEXT_TYPE:
return DynamicValue::Reader(reader.getBlobElement<Text>(index * ELEMENTS));
case schema::Type::Body::DATA_TYPE:
return DynamicValue::Reader(reader.getBlobElement<Data>(index * ELEMENTS));
case schema::Type::Body::LIST_TYPE:
FAIL_CHECK("elementType should not be LIST_TYPE when depth == 0.");
return DynamicValue::Reader();
case schema::Type::Body::TEXT_TYPE:
return DynamicValue::Reader(reader.getBlobElement<Text>(index * ELEMENTS));
case schema::Type::Body::DATA_TYPE:
return DynamicValue::Reader(reader.getBlobElement<Data>(index * ELEMENTS));
case schema::Type::Body::STRUCT_TYPE:
return DynamicValue::Reader(DynamicStruct::Reader(
pool, elementSchema, reader.getStructElement(index * ELEMENTS)));
case schema::Type::Body::LIST_TYPE: {
auto elementType = schema.getListElementType();
return DynamicValue::Reader(DynamicList::Reader(
elementType, reader.getListElement(
index * ELEMENTS, elementSizeFor(elementType.whichElementType()))));
}
case schema::Type::Body::ENUM_TYPE:
return DynamicValue::Reader(DynamicEnum(
pool, elementSchema, reader.getDataElement<uint16_t>(index * ELEMENTS)));
case schema::Type::Body::STRUCT_TYPE:
return DynamicValue::Reader(DynamicStruct::Reader(
schema.getStructElementType(), reader.getStructElement(index * ELEMENTS)));
case schema::Type::Body::OBJECT_TYPE:
return DynamicValue::Reader(DynamicObject::Reader(
pool, reader.getObjectElement(index * ELEMENTS)));
case schema::Type::Body::ENUM_TYPE:
return DynamicValue::Reader(DynamicEnum(
schema.getEnumElementType(), reader.getDataElement<uint16_t>(index * ELEMENTS)));
case schema::Type::Body::INTERFACE_TYPE:
FAIL_RECOVERABLE_CHECK("Interfaces not implemented.") {}
return DynamicValue::Reader();
}
case schema::Type::Body::OBJECT_TYPE:
return DynamicValue::Reader(DynamicObject::Reader(
reader.getObjectElement(index * ELEMENTS)));
FAIL_CHECK("switch() missing case.", elementType);
return DynamicValue::Reader();
} else {
// List of lists.
return DynamicValue::Reader(DynamicList::Reader(
pool, elementType, depth - 1, elementSchema,
reader.getListElement(index * ELEMENTS,
depth == 1 ? elementSizeFor(elementType) : internal::FieldSize::REFERENCE)));
case schema::Type::Body::INTERFACE_TYPE:
FAIL_RECOVERABLE_CHECK("Interfaces not implemented.") {}
return DynamicValue::Reader();
}
FAIL_CHECK("switch() missing case.", schema.whichElementType());
return DynamicValue::Reader();
}
DynamicValue::Builder DynamicList::Builder::operator[](uint index) {
PRECOND(index < size(), "List index out-of-bounds.");
if (depth == 0) {
switch (elementType) {
switch (schema.whichElementType()) {
#define HANDLE_TYPE(name, discrim, typeName) \
case schema::Type::Body::discrim##_TYPE: \
return DynamicValue::Builder(builder.getDataElement<typeName>(index * ELEMENTS));
HANDLE_TYPE(void, VOID, Void)
HANDLE_TYPE(bool, BOOL, bool)
HANDLE_TYPE(int8, INT8, int8_t)
HANDLE_TYPE(int16, INT16, int16_t)
HANDLE_TYPE(int32, INT32, int32_t)
HANDLE_TYPE(int64, INT64, int64_t)
HANDLE_TYPE(uint8, UINT8, uint8_t)
HANDLE_TYPE(uint16, UINT16, uint16_t)
HANDLE_TYPE(uint32, UINT32, uint32_t)
HANDLE_TYPE(uint64, UINT64, uint64_t)
HANDLE_TYPE(float32, FLOAT32, float)
HANDLE_TYPE(float64, FLOAT64, double)
case schema::Type::Body::discrim##_TYPE: \
return DynamicValue::Builder(builder.getDataElement<typeName>(index * ELEMENTS));
HANDLE_TYPE(void, VOID, Void)
HANDLE_TYPE(bool, BOOL, bool)
HANDLE_TYPE(int8, INT8, int8_t)
HANDLE_TYPE(int16, INT16, int16_t)
HANDLE_TYPE(int32, INT32, int32_t)
HANDLE_TYPE(int64, INT64, int64_t)
HANDLE_TYPE(uint8, UINT8, uint8_t)
HANDLE_TYPE(uint16, UINT16, uint16_t)
HANDLE_TYPE(uint32, UINT32, uint32_t)
HANDLE_TYPE(uint64, UINT64, uint64_t)
HANDLE_TYPE(float32, FLOAT32, float)
HANDLE_TYPE(float64, FLOAT64, double)
#undef HANDLE_TYPE
case schema::Type::Body::TEXT_TYPE:
return DynamicValue::Builder(builder.getBlobElement<Text>(index * ELEMENTS));
case schema::Type::Body::DATA_TYPE:
return DynamicValue::Builder(builder.getBlobElement<Data>(index * ELEMENTS));
case schema::Type::Body::LIST_TYPE:
FAIL_CHECK("elementType should not be LIST_TYPE when depth == 0.");
return DynamicValue::Builder();
case schema::Type::Body::TEXT_TYPE:
return DynamicValue::Builder(builder.getBlobElement<Text>(index * ELEMENTS));
case schema::Type::Body::DATA_TYPE:
return DynamicValue::Builder(builder.getBlobElement<Data>(index * ELEMENTS));
case schema::Type::Body::STRUCT_TYPE:
return DynamicValue::Builder(DynamicStruct::Builder(
pool, elementSchema, builder.getStructElement(index * ELEMENTS)));
case schema::Type::Body::LIST_TYPE:
return DynamicValue::Builder(DynamicList::Builder(
schema.getListElementType(), builder.getListElement(index * ELEMENTS)));
case schema::Type::Body::ENUM_TYPE:
return DynamicValue::Builder(DynamicEnum(
pool, elementSchema, builder.getDataElement<uint16_t>(index * ELEMENTS)));
case schema::Type::Body::STRUCT_TYPE:
return DynamicValue::Builder(DynamicStruct::Builder(
schema.getStructElementType(), builder.getStructElement(index * ELEMENTS)));
case schema::Type::Body::OBJECT_TYPE:
FAIL_CHECK("List(Object) not supported.");
break;
case schema::Type::Body::ENUM_TYPE:
return DynamicValue::Builder(DynamicEnum(
schema.getEnumElementType(), builder.getDataElement<uint16_t>(index * ELEMENTS)));
case schema::Type::Body::INTERFACE_TYPE:
FAIL_RECOVERABLE_CHECK("Interfaces not implemented.") {}
return DynamicValue::Builder();
}
case schema::Type::Body::OBJECT_TYPE:
FAIL_CHECK("List(Object) not supported.");
break;
FAIL_CHECK("switch() missing case.", elementType);
return DynamicValue::Builder();
} else {
// List of lists.
return DynamicValue::Builder(DynamicList::Builder(
pool, elementType, depth - 1, elementSchema,
builder.getListElement(index * ELEMENTS)));
case schema::Type::Body::INTERFACE_TYPE:
FAIL_RECOVERABLE_CHECK("Interfaces not implemented.") {}
return DynamicValue::Builder();
}
FAIL_CHECK("switch() missing case.", schema.whichElementType());
return DynamicValue::Builder();
}
void DynamicList::Builder::set(uint index, DynamicValue::Reader value) {
PRECOND(index < size(), "List index out-of-bounds.");
if (depth == 0) {
switch (elementType) {
switch (schema.whichElementType()) {
#define HANDLE_TYPE(name, discrim, typeName) \
case schema::Type::Body::discrim##_TYPE: \
builder.setDataElement<typeName>(index * ELEMENTS, value.as<typeName>()); \
break;
case schema::Type::Body::discrim##_TYPE: \
builder.setDataElement<typeName>(index * ELEMENTS, value.as<typeName>()); \
break;
HANDLE_TYPE(void, VOID, Void)
HANDLE_TYPE(bool, BOOL, bool)
HANDLE_TYPE(int8, INT8, int8_t)
HANDLE_TYPE(int16, INT16, int16_t)
HANDLE_TYPE(int32, INT32, int32_t)
HANDLE_TYPE(int64, INT64, int64_t)
HANDLE_TYPE(uint8, UINT8, uint8_t)
HANDLE_TYPE(uint16, UINT16, uint16_t)
HANDLE_TYPE(uint32, UINT32, uint32_t)
HANDLE_TYPE(uint64, UINT64, uint64_t)
HANDLE_TYPE(float32, FLOAT32, float)
HANDLE_TYPE(float64, FLOAT64, double)
HANDLE_TYPE(void, VOID, Void)
HANDLE_TYPE(bool, BOOL, bool)
HANDLE_TYPE(int8, INT8, int8_t)
HANDLE_TYPE(int16, INT16, int16_t)
HANDLE_TYPE(int32, INT32, int32_t)
HANDLE_TYPE(int64, INT64, int64_t)
HANDLE_TYPE(uint8, UINT8, uint8_t)
HANDLE_TYPE(uint16, UINT16, uint16_t)
HANDLE_TYPE(uint32, UINT32, uint32_t)
HANDLE_TYPE(uint64, UINT64, uint64_t)
HANDLE_TYPE(float32, FLOAT32, float)
HANDLE_TYPE(float64, FLOAT64, double)
#undef HANDLE_TYPE
case schema::Type::Body::TEXT_TYPE:
builder.setBlobElement<Text>(index * ELEMENTS, value.as<Text>());
break;
case schema::Type::Body::DATA_TYPE:
builder.setBlobElement<Data>(index * ELEMENTS, value.as<Data>());
break;
case schema::Type::Body::TEXT_TYPE:
builder.setBlobElement<Text>(index * ELEMENTS, value.as<Text>());
break;
case schema::Type::Body::DATA_TYPE:
builder.setBlobElement<Data>(index * ELEMENTS, value.as<Data>());
break;
case schema::Type::Body::LIST_TYPE:
FAIL_CHECK("elementType should not be LIST_TYPE when depth == 0.");
break;
case schema::Type::Body::LIST_TYPE: {
// TODO(now): Perform schemaless copy.
auto listValue = value.as<DynamicList>();
init(index, listValue.size()).as<DynamicList>().copyFrom(listValue);
break;
}
case schema::Type::Body::STRUCT_TYPE:
// Note we can't do a schemaless copy here because the space is already allocated.
DynamicStruct::Builder(pool, elementSchema, builder.getStructElement(index * ELEMENTS))
.copyFrom(value.as<DynamicStruct>());
break;
case schema::Type::Body::STRUCT_TYPE:
// Note we can't do a schemaless copy here because the space is already allocated.
DynamicStruct::Builder(
schema.getStructElementType(), builder.getStructElement(index * ELEMENTS))
.copyFrom(value.as<DynamicStruct>());
break;
case schema::Type::Body::ENUM_TYPE: {
auto enumValue = value.as<DynamicEnum>();
VALIDATE_INPUT(elementSchema.getId() == enumValue.getSchemaNode().getId(),
"Type mismatch when using DynamicList::Builder::set().");
builder.setDataElement<uint16_t>(index * ELEMENTS, value.as<DynamicEnum>().getRaw());
break;
}
case schema::Type::Body::ENUM_TYPE: {
auto enumValue = value.as<DynamicEnum>();
VALIDATE_INPUT(schema.getEnumElementType() == enumValue.getSchema(),
"Type mismatch when using DynamicList::Builder::set().");
builder.setDataElement<uint16_t>(index * ELEMENTS, value.as<DynamicEnum>().getRaw());
break;
}
case schema::Type::Body::OBJECT_TYPE:
FAIL_CHECK("List(Object) not supported.");
break;
case schema::Type::Body::OBJECT_TYPE:
FAIL_CHECK("List(Object) not supported.");
break;
case schema::Type::Body::INTERFACE_TYPE:
FAIL_RECOVERABLE_CHECK("Interfaces not implemented.") {}
break;
}
} else {
// List of lists.
// TODO(now): Perform schemaless copy.
auto listValue = value.as<DynamicList>();
init(index, listValue.size()).as<DynamicList>().copyFrom(listValue);
case schema::Type::Body::INTERFACE_TYPE:
FAIL_RECOVERABLE_CHECK("Interfaces not implemented.") {}
break;
}
}
DynamicValue::Builder DynamicList::Builder::init(uint index, uint size) {
PRECOND(index < this->size(), "List index out-of-bounds.");
if (depth == 0) {
switch (elementType) {
case schema::Type::Body::VOID_TYPE:
case schema::Type::Body::BOOL_TYPE:
case schema::Type::Body::INT8_TYPE:
case schema::Type::Body::INT16_TYPE:
case schema::Type::Body::INT32_TYPE:
case schema::Type::Body::INT64_TYPE:
case schema::Type::Body::UINT8_TYPE:
case schema::Type::Body::UINT16_TYPE:
case schema::Type::Body::UINT32_TYPE:
case schema::Type::Body::UINT64_TYPE:
case schema::Type::Body::FLOAT32_TYPE:
case schema::Type::Body::FLOAT64_TYPE:
case schema::Type::Body::ENUM_TYPE:
case schema::Type::Body::STRUCT_TYPE:
case schema::Type::Body::INTERFACE_TYPE:
FAIL_VALIDATE_INPUT("Expected a list or blob.");
return DynamicValue::Builder();
case schema::Type::Body::TEXT_TYPE:
return DynamicValue::Builder(builder.initBlobElement<Text>(index * ELEMENTS, size * BYTES));
case schema::Type::Body::DATA_TYPE:
return DynamicValue::Builder(builder.initBlobElement<Data>(index * ELEMENTS, size * BYTES));
case schema::Type::Body::LIST_TYPE:
FAIL_CHECK("elementType should not be LIST_TYPE when depth == 0.");
return DynamicValue::Builder();
case schema::Type::Body::OBJECT_TYPE: {
FAIL_CHECK("List(Object) not supported.");
return DynamicValue::Builder();
switch (schema.whichElementType()) {
case schema::Type::Body::VOID_TYPE:
case schema::Type::Body::BOOL_TYPE:
case schema::Type::Body::INT8_TYPE:
case schema::Type::Body::INT16_TYPE:
case schema::Type::Body::INT32_TYPE:
case schema::Type::Body::INT64_TYPE:
case schema::Type::Body::UINT8_TYPE:
case schema::Type::Body::UINT16_TYPE:
case schema::Type::Body::UINT32_TYPE:
case schema::Type::Body::UINT64_TYPE:
case schema::Type::Body::FLOAT32_TYPE:
case schema::Type::Body::FLOAT64_TYPE:
case schema::Type::Body::ENUM_TYPE:
case schema::Type::Body::STRUCT_TYPE:
case schema::Type::Body::INTERFACE_TYPE:
FAIL_VALIDATE_INPUT("Expected a list or blob.");
return DynamicValue::Builder();
case schema::Type::Body::TEXT_TYPE:
return DynamicValue::Builder(builder.initBlobElement<Text>(index * ELEMENTS, size * BYTES));
case schema::Type::Body::DATA_TYPE:
return DynamicValue::Builder(builder.initBlobElement<Data>(index * ELEMENTS, size * BYTES));
case schema::Type::Body::LIST_TYPE: {
auto elementType = schema.getListElementType();
if (elementType.whichElementType() == schema::Type::Body::STRUCT_TYPE) {
return DynamicValue::Builder(DynamicList::Builder(
elementType, builder.initStructListElement(
index * ELEMENTS, size * ELEMENTS,
structSizeFromSchema(elementType.getStructElementType()))));
} else {
return DynamicValue::Builder(DynamicList::Builder(
elementType, builder.initListElement(
index * ELEMENTS, elementSizeFor(elementType.whichElementType()),
size * ELEMENTS)));
}
}
FAIL_CHECK("switch() missing case.", elementType);
return DynamicValue::Builder();
} else {
// List of lists.
internal::FieldSize elementSize = depth == 1 ?
elementSizeFor(elementType) : internal::FieldSize::REFERENCE;
if (elementSize == internal::FieldSize::INLINE_COMPOSITE) {
return DynamicValue::Builder(DynamicList::Builder(
pool, elementType, depth - 1, elementSchema, builder.initStructListElement(
index * ELEMENTS, size * ELEMENTS,
structSizeFromSchema(elementSchema.getBody().getStructNode()))));
} else {
return DynamicValue::Builder(DynamicList::Builder(
pool, elementType, depth - 1, elementSchema, builder.initListElement(
index * ELEMENTS, elementSizeFor(elementType), size * ELEMENTS)));
case schema::Type::Body::OBJECT_TYPE: {
FAIL_CHECK("List(Object) not supported.");
return DynamicValue::Builder();
}
}
FAIL_CHECK("switch() missing case.", schema.whichElementType());
return DynamicValue::Builder();
}
void DynamicList::Builder::copyFrom(Reader other) {
......@@ -1247,63 +1036,15 @@ void DynamicList::Builder::copyFrom(std::initializer_list<DynamicValue::Reader>
}
DynamicList::Reader DynamicList::Builder::asReader() {
return DynamicList::Reader(pool, elementType, depth, elementSchema, builder.asReader());
}
DynamicList::Reader::Reader(const SchemaPool* pool, schema::Type::Reader elementType,
internal::ListReader reader)
: Reader(pool, internal::ListSchema(elementType), reader) {}
DynamicList::Reader::Reader(const SchemaPool* pool, internal::ListSchema schema,
internal::ListReader reader)
: pool(pool), elementType(schema.elementType), depth(schema.nestingDepth), reader(reader) {
switch (elementType) {
case schema::Type::Body::ENUM_TYPE:
elementSchema = pool->getEnum(schema.elementTypeId);
break;
case schema::Type::Body::STRUCT_TYPE:
elementSchema = pool->getStruct(schema.elementTypeId);
break;
case schema::Type::Body::INTERFACE_TYPE:
elementSchema = pool->getInterface(schema.elementTypeId);
break;
default:
// Leave schema default-initialized.
break;
}
}
DynamicList::Builder::Builder(const SchemaPool* pool, schema::Type::Reader elementType,
internal::ListBuilder builder)
: Builder(pool, internal::ListSchema(elementType), builder) {}
DynamicList::Builder::Builder(const SchemaPool* pool, internal::ListSchema schema,
internal::ListBuilder builder)
: pool(pool), elementType(schema.elementType), depth(schema.nestingDepth), builder(builder) {
switch (elementType) {
case schema::Type::Body::ENUM_TYPE:
elementSchema = pool->getEnum(schema.elementTypeId);
break;
case schema::Type::Body::STRUCT_TYPE:
elementSchema = pool->getStruct(schema.elementTypeId);
break;
case schema::Type::Body::INTERFACE_TYPE:
elementSchema = pool->getInterface(schema.elementTypeId);
break;
default:
// Leave schema default-initialized.
break;
}
return DynamicList::Reader(schema, builder.asReader());
}
void DynamicList::Reader::verifySchema(internal::ListSchema schema) {
VALIDATE_INPUT(schema.elementType == elementType &&
schema.nestingDepth == depth &&
schema.elementTypeId == elementSchema.getId(),
void DynamicList::Reader::verifySchema(ListSchema expectedSchema) {
VALIDATE_INPUT(schema == expectedSchema,
"Type mismatch when using DynamicList::Reader::as().");
}
void DynamicList::Builder::verifySchema(internal::ListSchema schema) {
VALIDATE_INPUT(schema.elementType == elementType &&
schema.nestingDepth == depth &&
schema.elementTypeId == elementSchema.getId(),
void DynamicList::Builder::verifySchema(ListSchema expectedSchema) {
VALIDATE_INPUT(schema == expectedSchema,
"Type mismatch when using DynamicList::Reader::as().");
}
......@@ -1445,39 +1186,30 @@ Void DynamicValue::Builder::AsImpl<Void>::apply(Builder builder) {
// =======================================================================================
template <>
DynamicStruct::Reader MessageReader::getRoot<DynamicStruct>(
const SchemaPool& pool, uint64_t typeId) {
return DynamicStruct::Reader(&pool, pool.getStruct(typeId), getRootInternal());
DynamicStruct::Reader MessageReader::getRoot<DynamicStruct>(StructSchema schema) {
return DynamicStruct::Reader(schema, getRootInternal());
}
template <>
DynamicStruct::Builder MessageBuilder::initRoot<DynamicStruct>(
const SchemaPool& pool, uint64_t typeId) {
auto schema = pool.getStruct(typeId);
return DynamicStruct::Builder(&pool, schema,
initRoot(structSizeFromSchema(schema.getBody().getStructNode())));
DynamicStruct::Builder MessageBuilder::initRoot<DynamicStruct>(StructSchema schema) {
return DynamicStruct::Builder(schema, initRoot(structSizeFromSchema(schema)));
}
template <>
DynamicStruct::Builder MessageBuilder::getRoot<DynamicStruct>(
const SchemaPool& pool, uint64_t typeId) {
auto schema = pool.getStruct(typeId);
return DynamicStruct::Builder(&pool, schema,
getRoot(structSizeFromSchema(schema.getBody().getStructNode())));
DynamicStruct::Builder MessageBuilder::getRoot<DynamicStruct>(StructSchema schema) {
return DynamicStruct::Builder(schema, getRoot(structSizeFromSchema(schema)));
}
namespace internal {
DynamicStruct::Reader PointerHelpers<DynamicStruct, Kind::UNKNOWN>::get(
StructReader reader, WireReferenceCount index, const SchemaPool& pool, uint64_t typeId) {
return DynamicStruct::Reader(&pool, pool.getStruct(typeId),
reader.getStructField(index, nullptr));
DynamicStruct::Reader PointerHelpers<DynamicStruct, Kind::UNKNOWN>::getDynamic(
StructReader reader, WireReferenceCount index, StructSchema schema) {
return DynamicStruct::Reader(schema, reader.getStructField(index, nullptr));
}
DynamicStruct::Builder PointerHelpers<DynamicStruct, Kind::UNKNOWN>::get(
StructBuilder builder, WireReferenceCount index, const SchemaPool& pool, uint64_t typeId) {
auto schema = pool.getStruct(typeId);
return DynamicStruct::Builder(&pool, schema, builder.getStructField(
index, structSizeFromSchema(schema.getBody().getStructNode()), nullptr));
DynamicStruct::Builder PointerHelpers<DynamicStruct, Kind::UNKNOWN>::getDynamic(
StructBuilder builder, WireReferenceCount index, StructSchema schema) {
return DynamicStruct::Builder(schema, builder.getStructField(
index, structSizeFromSchema(schema), nullptr));
}
void PointerHelpers<DynamicStruct, Kind::UNKNOWN>::set(
StructBuilder builder, WireReferenceCount index, DynamicStruct::Reader value) {
......@@ -1485,22 +1217,19 @@ void PointerHelpers<DynamicStruct, Kind::UNKNOWN>::set(
FAIL_CHECK("Unimplemented: copyFrom()");
}
DynamicStruct::Builder PointerHelpers<DynamicStruct, Kind::UNKNOWN>::init(
StructBuilder builder, WireReferenceCount index, const SchemaPool& pool, uint64_t typeId) {
auto schema = pool.getStruct(typeId);
return DynamicStruct::Builder(&pool, schema, builder.initStructField(
index, structSizeFromSchema(schema.getBody().getStructNode())));
StructBuilder builder, WireReferenceCount index, StructSchema schema) {
return DynamicStruct::Builder(schema,
builder.initStructField(index, structSizeFromSchema(schema)));
}
DynamicList::Reader PointerHelpers<DynamicList, Kind::UNKNOWN>::get(
StructReader reader, WireReferenceCount index, const SchemaPool& pool,
schema::Type::Reader elementType) {
return DynamicList::Reader(&pool, elementType,
reader.getListField(index, elementSizeFor(elementType.getBody().which()), nullptr));
DynamicList::Reader PointerHelpers<DynamicList, Kind::UNKNOWN>::getDynamic(
StructReader reader, WireReferenceCount index, ListSchema schema) {
return DynamicList::Reader(schema,
reader.getListField(index, elementSizeFor(schema.whichElementType()), nullptr));
}
DynamicList::Builder PointerHelpers<DynamicList, Kind::UNKNOWN>::get(
StructBuilder builder, WireReferenceCount index, const SchemaPool& pool,
schema::Type::Reader elementType) {
return DynamicList::Builder(&pool, elementType, builder.getListField(index, nullptr));
DynamicList::Builder PointerHelpers<DynamicList, Kind::UNKNOWN>::getDynamic(
StructBuilder builder, WireReferenceCount index, ListSchema schema) {
return DynamicList::Builder(schema, builder.getListField(index, nullptr));
}
void PointerHelpers<DynamicList, Kind::UNKNOWN>::set(
StructBuilder builder, WireReferenceCount index, DynamicList::Reader value) {
......@@ -1508,17 +1237,14 @@ void PointerHelpers<DynamicList, Kind::UNKNOWN>::set(
FAIL_CHECK("Unimplemented: copyFrom()");
}
DynamicList::Builder PointerHelpers<DynamicList, Kind::UNKNOWN>::init(
StructBuilder builder, WireReferenceCount index,
const SchemaPool& pool, schema::Type::Reader elementType, uint size) {
auto elementSize = elementSizeFor(elementType.getBody().which());
if (elementSize == FieldSize::INLINE_COMPOSITE) {
auto elementSchema = pool.getStruct(elementType.getBody().getStructType());
return DynamicList::Builder(&pool, schema::Type::Body::STRUCT_TYPE, 0, elementSchema,
StructBuilder builder, WireReferenceCount index, ListSchema schema, uint size) {
if (schema.whichElementType() == schema::Type::Body::STRUCT_TYPE) {
return DynamicList::Builder(schema,
builder.initStructListField(index, size * ELEMENTS,
structSizeFromSchema(elementSchema.getBody().getStructNode())));
structSizeFromSchema(schema.getStructElementType())));
} else {
return DynamicList::Builder(&pool, elementType,
builder.initListField(index, elementSize, size * ELEMENTS));
return DynamicList::Builder(schema,
builder.initListField(index, elementSizeFor(schema.whichElementType()), size * ELEMENTS));
}
}
......
......@@ -35,7 +35,7 @@
#ifndef CAPNPROTO_DYNAMIC_H_
#define CAPNPROTO_DYNAMIC_H_
#include "schema.capnp.h"
#include "schema.h"
#include "layout.h"
#include "message.h"
......@@ -90,152 +90,12 @@ template <> struct DynamicTypeFor_<Kind::LIST> { typedef DynamicList Type; };
template <typename T>
using DynamicTypeFor = typename DynamicTypeFor_<kind<T>()>::Type;
class SchemaPool {
// Class representing a pool of schema data which is indexed for convenient traversal.
//
// TODO(someday): Allow registration of a callback to look up missing nodes. The callback
// should not return a value, but instead should receive a pointer to the pool to populate.
// This will make it easier to deal with ownership and to batch-add related nodes.
public:
SchemaPool();
~SchemaPool();
CAPNPROTO_DISALLOW_COPY(SchemaPool);
void add(schema::Node::Reader node);
// Add a schema node. It will be copied and validated, throwing an exception if invalid. If
// another node with the same ID already exists, the nodes will be compared for compatibility
// and the definition determined to be "newer" will be kept. If the nodes are not compatible,
// an exception will be thrown.
template <typename T>
inline void add() { add(internal::rawSchema<T>()); }
// Add schema for the given compiled-in type and all of its transitive dependencies, including
// nested nodes, but NOT necessarily including annotation definitions (because those are not
// always compiled in) or parent scopes (because adding parent scopes would necessarily mean
// adding all types in the file and in all transitive imports, which may be much more than you
// want).
Maybe<schema::Node::Reader> tryGetNode(uint64_t id) const;
// Try to look up the node, but return nullptr if it's unknown.
schema::Node::Reader getNode(uint64_t id) const;
// Look up the node with the given ID, throwing an exception if not found.
schema::Node::Reader getStruct(uint64_t id) const;
schema::Node::Reader getEnum(uint64_t id) const;
schema::Node::Reader getInterface(uint64_t id) const;
// Like getNode() but also throws if the kind is not as requested.
template <typename T>
ReaderFor<DynamicTypeFor<FromReader<T>>> toDynamic(T&& value) const;
template <typename T>
BuilderFor<DynamicTypeFor<FromBuilder<T>>> toDynamic(T&& value) const;
template <typename T>
DynamicTypeFor<TypeIfEnum<T>> toDynamic(T&& value) const;
// Convert an arbitrary struct or list reader or builder type, or an enum type, into the
// equivalent dynamic type.
// Example:
// // myStruct has a field named foo that has struct type.
// DynamicStruct::Reader foo = pool.toDynamic(myStruct.getFoo());
private:
struct Impl;
Impl* impl;
void add(const internal::RawSchema& rawSchema);
void addNoCopy(schema::Node::Reader node);
template <typename T, Kind k = kind<T>()>
struct ToDynamicImpl;
friend class DynamicEnum;
friend struct DynamicStruct;
friend struct DynamicList;
friend struct DynamicObject;
};
// -------------------------------------------------------------------
namespace internal {
struct ListSchema {
// Hack for determining/specifying the schema for a List without having to construct a Cap'n Proto
// message.
schema::Type::Body::Which elementType;
uint8_t nestingDepth; // 0 for T, 1 for List(T), 2 for List(List(T)), ...
uint64_t elementTypeId;
constexpr ListSchema(schema::Type::Body::Which elementType)
: elementType(elementType), nestingDepth(0), elementTypeId(0) {}
constexpr ListSchema(schema::Type::Body::Which elementType, uint64_t elementTypeId)
: elementType(elementType), nestingDepth(0), elementTypeId(elementTypeId) {}
constexpr ListSchema(schema::Type::Body::Which elementType, uint8_t nestingDepth,
uint64_t elementTypeId)
: elementType(elementType), nestingDepth(nestingDepth), elementTypeId(elementTypeId) {}
ListSchema(schema::Type::Reader elementType);
// Construct from an actual schema.
constexpr ListSchema deeper() {
return ListSchema(elementType, nestingDepth + 1, elementTypeId);
}
};
template <typename ElementType, Kind kind = kind<ElementType>()>
struct ListSchemaForElement;
#define CAPNPROTO_DECLARE_TYPE(discrim, typeName) \
template <> \
struct ListSchemaForElement<List<typeName>> { \
static constexpr ListSchema type = ListSchema(schema::Type::Body::discrim##_TYPE); \
};
CAPNPROTO_DECLARE_TYPE(VOID, Void)
CAPNPROTO_DECLARE_TYPE(BOOL, bool)
CAPNPROTO_DECLARE_TYPE(INT8, int8_t)
CAPNPROTO_DECLARE_TYPE(INT16, int16_t)
CAPNPROTO_DECLARE_TYPE(INT32, int32_t)
CAPNPROTO_DECLARE_TYPE(INT64, int64_t)
CAPNPROTO_DECLARE_TYPE(UINT8, uint8_t)
CAPNPROTO_DECLARE_TYPE(UINT16, uint16_t)
CAPNPROTO_DECLARE_TYPE(UINT32, uint32_t)
CAPNPROTO_DECLARE_TYPE(UINT64, uint64_t)
CAPNPROTO_DECLARE_TYPE(FLOAT32, float)
CAPNPROTO_DECLARE_TYPE(FLOAT64, double)
CAPNPROTO_DECLARE_TYPE(TEXT, Text)
CAPNPROTO_DECLARE_TYPE(DATA, Data)
CAPNPROTO_DECLARE_TYPE(LIST, DynamicList)
#undef CAPNPROTO_DECLARE_TYPE
template <typename T>
struct ListSchemaForElement<T, Kind::ENUM> {
static constexpr ListSchema type = ListSchema(schema::Type::Body::ENUM_TYPE, typeId<T>());
};
template <typename T>
struct ListSchemaForElement<T, Kind::STRUCT> {
static constexpr ListSchema type = ListSchema(schema::Type::Body::STRUCT_TYPE, typeId<T>());
};
ReaderFor<DynamicTypeFor<FromReader<T>>> toDynamic(T&& value);
template <typename T>
struct ListSchemaForElement<T, Kind::INTERFACE> {
static constexpr ListSchema type = ListSchema(schema::Type::Body::INTERFACE_TYPE, typeId<T>());
};
BuilderFor<DynamicTypeFor<FromBuilder<T>>> toDynamic(T&& value);
template <typename T>
struct ListSchemaForElement<List<T>, Kind::LIST> {
static constexpr ListSchema type = ListSchemaForElement<T>::schema.deeper();
};
template <typename T>
struct ListSchemaFor;
template <typename T>
struct ListSchemaFor<List<T>>: public ListSchemaForElement<T> {};
} // namespace internal
DynamicTypeFor<TypeIfEnum<T>> toDynamic(T&& value);
// -------------------------------------------------------------------
......@@ -247,33 +107,29 @@ public:
inline T as() { return static_cast<T>(asImpl(typeId<T>())); }
// Cast to a native enum type.
schema::Node::Reader getSchemaNode() { return schema; }
schema::EnumNode::Reader getSchema();
inline EnumSchema getSchema() { return schema; }
Maybe<schema::EnumNode::Enumerant::Reader> getEnumerant();
Maybe<EnumSchema::Enumerant> getEnumerant();
// Get which enumerant this enum value represents. Returns nullptr if the numeric value does not
// correspond to any enumerant in the schema -- this can happen if the data was built using a
// newer schema that has more values defined.
Maybe<schema::EnumNode::Enumerant::Reader> findEnumerantByName(Text::Reader name);
// Search this enum's type for an enumerant with the given name.
inline uint16_t getRaw() { return value; }
// Returns the raw underlying enum value.
private:
const SchemaPool* pool;
schema::Node::Reader schema;
EnumSchema schema;
uint16_t value;
inline DynamicEnum(const SchemaPool* pool, schema::Node::Reader schema, uint16_t value)
: pool(pool), schema(schema), value(value) {}
inline DynamicEnum(EnumSchema schema, uint16_t value)
: schema(schema), value(value) {}
uint16_t asImpl(uint64_t requestedTypeId);
friend struct DynamicStruct;
friend struct DynamicList;
friend class SchemaPool;
template <typename T>
friend DynamicTypeFor<TypeIfEnum<T>> toDynamic(T&& value);
};
// -------------------------------------------------------------------
......@@ -286,23 +142,18 @@ public:
inline typename T::Reader as() { return AsImpl<T>::apply(*this); }
// Convert the object to the given struct, list, or blob type.
DynamicStruct::Reader asStruct(schema::Node::Reader schema);
DynamicList::Reader asList(schema::Type::Reader elementType);
DynamicStruct::Reader as(StructSchema schema);
DynamicList::Reader as(ListSchema schema);
private:
const SchemaPool* pool;
internal::ObjectReader reader;
inline Reader(const SchemaPool* pool, internal::ObjectReader reader)
: pool(pool), reader(reader) {}
inline Reader(internal::ObjectReader reader): reader(reader) {}
template <typename T, Kind kind = kind<T>()> struct AsImpl;
// Implementation backing the as() method. Needs to be a struct to allow partial
// specialization. Has a method apply() which does the work.
DynamicStruct::Reader asStruct(uint64_t typeId);
DynamicList::Reader asList(internal::ListSchema schema);
friend struct DynamicStruct;
friend struct DynamicList;
};
......@@ -315,23 +166,18 @@ public:
inline typename T::Builder as() { return AsImpl<T>::apply(*this); }
// Convert the object to the given struct, list, or blob type.
DynamicStruct::Builder asStruct(schema::Node::Reader schema);
DynamicList::Builder asList(schema::Type::Reader elementType);
DynamicStruct::Builder as(StructSchema schema);
DynamicList::Builder as(ListSchema schema);
private:
const SchemaPool* pool;
internal::ObjectBuilder builder;
inline Builder(const SchemaPool* pool, internal::ObjectBuilder builder)
: pool(pool), builder(builder) {}
inline Builder(internal::ObjectBuilder builder): builder(builder) {}
template <typename T, Kind kind = kind<T>()> struct AsImpl;
// Implementation backing the as() method. Needs to be a struct to allow partial
// specialization. Has a method apply() which does the work.
DynamicStruct::Builder asStruct(uint64_t typeId);
DynamicList::Builder asList(internal::ListSchema schema);
friend struct DynamicStruct;
friend struct DynamicList;
};
......@@ -342,24 +188,22 @@ class DynamicUnion::Reader {
public:
Reader() = default;
schema::StructNode::Member::Reader getMemberSchema() { return schema; }
schema::StructNode::Union::Reader getSchema();
inline StructSchema::Union getSchema() { return schema; }
Maybe<schema::StructNode::Member::Reader> which();
Maybe<StructSchema::Member> which();
// Returns which field is set, or nullptr if an unknown field is set (i.e. the schema is old, and
// the underlying data has the union set to a member we don't know about).
DynamicValue::Reader get();
// Get the value of whichever field of the union is set.
// Get the value of whichever field of the union is set. Throws an exception if which() returns
// nullptr.
private:
const SchemaPool* pool;
schema::StructNode::Member::Reader schema;
StructSchema::Union schema;
internal::StructReader reader;
inline Reader(const SchemaPool* pool, schema::StructNode::Member::Reader schema,
internal::StructReader reader)
: pool(pool), schema(schema), reader(reader) {}
inline Reader(StructSchema::Union schema, internal::StructReader reader)
: schema(schema), reader(reader) {}
friend struct DynamicStruct;
};
......@@ -368,26 +212,23 @@ class DynamicUnion::Builder {
public:
Builder() = default;
schema::StructNode::Member::Reader getMemberSchema() { return schema; }
schema::StructNode::Union::Reader getSchema();
inline StructSchema::Union getSchema() { return schema; }
Maybe<schema::StructNode::Member::Reader> which();
Maybe<StructSchema::Member> which();
// Returns which field is set, or nullptr if an unknown field is set (i.e. the schema is old, and
// the underlying data has the union set to a member we don't know about).
DynamicValue::Builder get();
void set(schema::StructNode::Member::Reader member, DynamicValue::Reader value);
DynamicValue::Builder init(schema::StructNode::Member::Reader member);
DynamicValue::Builder init(schema::StructNode::Member::Reader member, uint size);
void set(StructSchema::Member member, DynamicValue::Reader value);
DynamicValue::Builder init(StructSchema::Member member);
DynamicValue::Builder init(StructSchema::Member member, uint size);
private:
const SchemaPool* pool;
schema::StructNode::Member::Reader schema;
StructSchema::Union schema;
internal::StructBuilder builder;
inline Builder(const SchemaPool* pool, schema::StructNode::Member::Reader schema,
internal::StructBuilder builder)
: pool(pool), schema(schema), builder(builder) {}
inline Builder(StructSchema::Union schema, internal::StructBuilder builder)
: schema(schema), builder(builder) {}
friend struct DynamicStruct;
};
......@@ -402,31 +243,24 @@ public:
typename T::Reader as();
// Convert the dynamic struct to its compiled-in type.
schema::Node::Reader getSchemaNode() { return schema; }
schema::StructNode::Reader getSchema();
inline StructSchema getSchema() { return schema; }
Maybe<schema::StructNode::Member::Reader> findMemberByName(Text::Reader name);
// Looks up the member with the given name, or returns nullptr if no such member exists.
DynamicValue::Reader get(schema::StructNode::Member::Reader member);
DynamicValue::Reader get(StructSchema::Member member);
// Read the given member value.
DynamicValue::Reader get(Text::Reader name);
// Shortcut to read a member by name. Throws an exception if no such member exists.
private:
const SchemaPool* pool;
schema::Node::Reader schema;
StructSchema schema;
internal::StructReader reader;
inline Reader(const SchemaPool* pool, schema::Node::Reader schema, internal::StructReader reader)
: pool(pool), schema(schema), reader(reader) {}
inline Reader(StructSchema schema, internal::StructReader reader)
: schema(schema), reader(reader) {}
void verifyTypeId(uint64_t id);
static DynamicValue::Reader getImpl(
const SchemaPool* pool, internal::StructReader reader,
schema::StructNode::Member::Reader member);
static DynamicValue::Reader getImpl(internal::StructReader reader, StructSchema::Member member);
template <typename T>
friend struct internal::PointerHelpers;
......@@ -436,7 +270,8 @@ private:
friend struct DynamicList;
friend class MessageReader;
friend class MessageBuilder;
friend class SchemaPool;
template <typename T, ::capnproto::Kind k>
friend struct ::capnproto::ToDynamic_;
};
class DynamicStruct::Builder {
......@@ -447,37 +282,33 @@ public:
typename T::Builder as();
// Cast to a particular struct type.
schema::Node::Reader getSchemaNode() { return schema; }
schema::StructNode::Reader getSchema();
Maybe<schema::StructNode::Member::Reader> findMemberByName(Text::Reader name);
// Looks up the member with the given name, or returns nullptr if no such member exists.
inline StructSchema getSchema() { return schema; }
DynamicValue::Builder get(schema::StructNode::Member::Reader member);
DynamicValue::Builder get(StructSchema::Member member);
// Read the given member value.
void set(schema::StructNode::Member::Reader member, DynamicValue::Reader value);
void set(StructSchema::Member member, DynamicValue::Reader value);
// Set the given member value.
DynamicValue::Builder init(schema::StructNode::Member::Reader member);
DynamicValue::Builder init(schema::StructNode::Member::Reader member, uint size);
DynamicValue::Builder init(StructSchema::Member member);
DynamicValue::Builder init(StructSchema::Member member, uint size);
// Init a struct, list, or blob field.
DynamicValue::Builder initObject(schema::StructNode::Member::Reader member,
schema::Type::Reader type);
DynamicValue::Builder initObject(schema::StructNode::Member::Reader member,
schema::Type::Reader type, uint size);
// Init an object field. You must specify the type. The provided Type::Reader can point to a
// temporary message; it will not be accessed again after the method returns. Of course, if it
// refers to any other types by ID, those types must be present in the SchemaPool.
DynamicStruct::Builder initObject(StructSchema::Member member, StructSchema type);
DynamicList::Builder initObject(StructSchema::Member member, ListSchema type, uint size);
Text::Builder initObjectAsText(StructSchema::Member member, uint size);
Data::Builder initObjectAsData(StructSchema::Member member, uint size);
// Init an object field. You must specify the type.
DynamicValue::Builder get(Text::Reader name);
void set(Text::Reader name, DynamicValue::Reader value);
void set(Text::Reader name, std::initializer_list<DynamicValue::Reader> value);
DynamicValue::Builder init(Text::Reader name);
DynamicValue::Builder init(Text::Reader name, uint size);
DynamicValue::Builder initObject(Text::Reader name, schema::Type::Reader type);
DynamicValue::Builder initObject(Text::Reader name, schema::Type::Reader type, uint size);
DynamicStruct::Builder initObject(Text::Reader name, StructSchema type);
DynamicList::Builder initObject(Text::Reader name, ListSchema type, uint size);
Text::Builder initObjectAsText(Text::Reader name, uint size);
Data::Builder initObjectAsData(Text::Reader name, uint size);
// Shortcuts to access members by name. These throw exceptions if no such field exists.
void copyFrom(Reader other);
......@@ -485,36 +316,30 @@ public:
Reader asReader();
private:
const SchemaPool* pool;
schema::Node::Reader schema;
StructSchema schema;
internal::StructBuilder builder;
inline Builder(const SchemaPool* pool, schema::Node::Reader schema,
internal::StructBuilder builder)
: pool(pool), schema(schema), builder(builder) {}
inline Builder(StructSchema schema, internal::StructBuilder builder)
: schema(schema), builder(builder) {}
void verifyTypeId(uint64_t id);
static DynamicValue::Builder getImpl(
const SchemaPool* pool, internal::StructBuilder builder,
schema::StructNode::Member::Reader member);
internal::StructBuilder builder, StructSchema::Member member);
static void setImpl(
const SchemaPool* pool, internal::StructBuilder builder,
schema::StructNode::Member::Reader member, DynamicValue::Reader value);
internal::StructBuilder builder, StructSchema::Member member, DynamicValue::Reader value);
static DynamicValue::Builder initImpl(
const SchemaPool* pool, internal::StructBuilder builder,
schema::StructNode::Member::Reader member, uint size);
internal::StructBuilder builder, StructSchema::Member member, uint size);
static DynamicValue::Builder initImpl(
const SchemaPool* pool, internal::StructBuilder builder,
schema::StructNode::Member::Reader member);
static DynamicValue::Builder initFieldImpl(
const SchemaPool* pool, internal::StructBuilder builder,
schema::StructNode::Field::Reader field,
schema::Type::Reader type, uint size);
static DynamicValue::Builder initFieldImpl(
const SchemaPool* pool, internal::StructBuilder builder,
schema::StructNode::Field::Reader field,
schema::Type::Reader type);
internal::StructBuilder builder, StructSchema::Member member);
static DynamicStruct::Builder initFieldImpl(
internal::StructBuilder builder, StructSchema::Member field, StructSchema type);
static DynamicList::Builder initFieldImpl(
internal::StructBuilder builder, StructSchema::Member field, ListSchema type, uint size);
static Text::Builder initFieldAsTextImpl(
internal::StructBuilder builder, StructSchema::Member field, uint size);
static Data::Builder initFieldAsDataImpl(
internal::StructBuilder builder, StructSchema::Member field, uint size);
template <typename T>
friend struct internal::PointerHelpers;
......@@ -523,7 +348,8 @@ private:
friend struct DynamicList;
friend class MessageReader;
friend class MessageBuilder;
friend class SchemaPool;
template <typename T, ::capnproto::Kind k>
friend struct ::capnproto::ToDynamic_;
};
// -------------------------------------------------------------------
......@@ -531,13 +357,14 @@ private:
class DynamicList::Reader {
public:
Reader() = default;
inline explicit Reader(internal::ListReader reader): reader(reader) {}
template <typename T>
typename T::Reader as();
// Try to convert to any List<T>, Data, or Text. Throws an exception if the underlying data
// can't possibly represent the requested type.
inline ListSchema getSchema() { return schema; }
inline uint size() { return reader.size() / ELEMENTS; }
DynamicValue::Reader operator[](uint index);
......@@ -546,48 +373,33 @@ public:
inline iterator end() { return iterator(this, size()); }
private:
const SchemaPool* pool;
// We don't encode the element type as schema::Type::Reader because we want to be able to
// construct DynamicList from List<T> without knowing of any particular field that has type
// List<T>, and we don't want to construct a fresh schema object every time this happens.
schema::Type::Body::Which elementType; // cannot be list
uint depth;
// Number of types elementType must be wrapped in List() to get the actual element type, e.g.
// List(List(List(Bool))) has depth = 2.
schema::Node::Reader elementSchema; // if elementType is struct/enum/interface
ListSchema schema;
internal::ListReader reader;
Reader(const SchemaPool* pool, schema::Type::Reader elementType, internal::ListReader reader);
Reader(const SchemaPool* pool, internal::ListSchema schema, internal::ListReader reader);
Reader(const SchemaPool* pool, schema::Type::Body::Which elementType, uint depth,
schema::Node::Reader elementSchema, internal::ListReader reader)
: pool(pool), elementType(elementType), depth(depth), elementSchema(elementSchema),
reader(reader) {}
Reader(ListSchema schema, internal::ListReader reader): schema(schema), reader(reader) {}
void verifySchema(internal::ListSchema schema);
void verifySchema(ListSchema expectedSchema);
template <typename T>
friend struct internal::PointerHelpers;
friend struct DynamicStruct;
friend struct DynamicObject;
friend class DynamicList::Builder;
friend class SchemaPool;
template <typename T, ::capnproto::Kind k>
friend struct ::capnproto::ToDynamic_;
};
class DynamicList::Builder {
public:
Builder() = default;
inline explicit Builder(internal::ListBuilder builder): builder(builder) {}
template <typename T>
typename T::Builder as();
// Try to convert to any List<T>, Data, or Text. Throws an exception if the underlying data
// can't possibly represent the requested type.
inline ListSchema getSchema() { return schema; }
inline uint size() { return builder.size() / ELEMENTS; }
DynamicValue::Builder operator[](uint index);
void set(uint index, DynamicValue::Reader value);
......@@ -603,26 +415,19 @@ public:
Reader asReader();
private:
const SchemaPool* pool;
schema::Type::Body::Which elementType;
uint depth;
schema::Node::Reader elementSchema;
ListSchema schema;
internal::ListBuilder builder;
Builder(const SchemaPool* pool, schema::Type::Reader elementType, internal::ListBuilder builder);
Builder(const SchemaPool* pool, internal::ListSchema schema, internal::ListBuilder builder);
Builder(const SchemaPool* pool, schema::Type::Body::Which elementType, uint depth,
schema::Node::Reader elementSchema, internal::ListBuilder builder)
: pool(pool), elementType(elementType), depth(depth), elementSchema(elementSchema),
builder(builder) {}
Builder(ListSchema schema, internal::ListBuilder builder): schema(schema), builder(builder) {}
void verifySchema(internal::ListSchema schema);
void verifySchema(ListSchema expectedSchema);
template <typename T>
friend struct internal::PointerHelpers;
friend struct DynamicStruct;
friend struct DynamicObject;
friend class SchemaPool;
template <typename T, ::capnproto::Kind k>
friend struct ::capnproto::ToDynamic_;
};
// -------------------------------------------------------------------
......@@ -791,38 +596,42 @@ private:
// generated Object accessors.
template <>
DynamicStruct::Reader MessageReader::getRoot<DynamicStruct>(
const SchemaPool& pool, uint64_t typeId);
DynamicStruct::Reader MessageReader::getRoot<DynamicStruct>(StructSchema schema);
template <>
DynamicStruct::Builder MessageBuilder::initRoot<DynamicStruct>(
const SchemaPool& pool, uint64_t typeId);
DynamicStruct::Builder MessageBuilder::initRoot<DynamicStruct>(StructSchema schema);
template <>
DynamicStruct::Builder MessageBuilder::getRoot<DynamicStruct>(
const SchemaPool& pool, uint64_t typeId);
DynamicStruct::Builder MessageBuilder::getRoot<DynamicStruct>(StructSchema schema);
namespace internal {
template <>
struct PointerHelpers<DynamicStruct, Kind::UNKNOWN> {
static DynamicStruct::Reader get(StructReader reader, WireReferenceCount index,
const SchemaPool& pool, uint64_t typeId);
static DynamicStruct::Builder get(StructBuilder builder, WireReferenceCount index,
const SchemaPool& pool, uint64_t typeId);
static void set(StructBuilder builder, WireReferenceCount index, DynamicStruct::Reader value);
static DynamicStruct::Builder init(StructBuilder builder, WireReferenceCount index,
const SchemaPool& pool, uint64_t typeId);
// getDynamic() is used when an Object's get() accessor is passed arguments, because for
// non-dynamic types PointerHelpers::get() takes a default value as the third argument, and we
// don't want people to accidentally be able to provide their own default value.
static DynamicStruct::Reader getDynamic(
StructReader reader, WireReferenceCount index, StructSchema schema);
static DynamicStruct::Builder getDynamic(
StructBuilder builder, WireReferenceCount index, StructSchema schema);
static void set(
StructBuilder builder, WireReferenceCount index, DynamicStruct::Reader value);
static DynamicStruct::Builder init(
StructBuilder builder, WireReferenceCount index, StructSchema schema);
};
template <>
struct PointerHelpers<DynamicList, Kind::UNKNOWN> {
static DynamicList::Reader get(StructReader reader, WireReferenceCount index,
const SchemaPool& pool, schema::Type::Reader elementType);
static DynamicList::Builder get(StructBuilder builder, WireReferenceCount index,
const SchemaPool& pool, schema::Type::Reader elementType);
static void set(StructBuilder builder, WireReferenceCount index, DynamicList::Reader value);
static DynamicList::Builder init(StructBuilder builder, WireReferenceCount index,
const SchemaPool& pool, schema::Type::Reader elementType,
uint size);
// getDynamic() is used when an Object's get() accessor is passed arguments, because for
// non-dynamic types PointerHelpers::get() takes a default value as the third argument, and we
// don't want people to accidentally be able to provide their own default value.
static DynamicList::Reader getDynamic(
StructReader reader, WireReferenceCount index, ListSchema schema);
static DynamicList::Builder getDynamic(
StructBuilder builder, WireReferenceCount index, ListSchema schema);
static void set(
StructBuilder builder, WireReferenceCount index, DynamicList::Reader value);
static DynamicList::Builder init(
StructBuilder builder, WireReferenceCount index, ListSchema schema, uint size);
};
} // namespace internal
......@@ -831,36 +640,36 @@ struct PointerHelpers<DynamicList, Kind::UNKNOWN> {
// Inline implementation details.
template <typename T>
struct SchemaPool::ToDynamicImpl<T, Kind::STRUCT> {
static inline DynamicStruct::Reader apply(const SchemaPool* pool, typename T::Reader value) {
return DynamicStruct::Reader(pool, pool->getStruct(typeId<T>()), value._reader);
struct ToDynamic_<T, Kind::STRUCT> {
static inline DynamicStruct::Reader apply(typename T::Reader value) {
return DynamicStruct::Reader(Schema::from<T>(), value._reader);
}
static inline DynamicStruct::Builder apply(const SchemaPool* pool, typename T::Builder value) {
return DynamicStruct::Builder(pool, pool->getStruct(typeId<T>()), value._builder);
static inline DynamicStruct::Builder apply(typename T::Builder value) {
return DynamicStruct::Builder(Schema::from<T>(), value._builder);
}
};
template <typename T>
struct SchemaPool::ToDynamicImpl<T, Kind::LIST> {
static inline DynamicList::Reader apply(const SchemaPool* pool, typename T::Reader value) {
return DynamicList::Reader(pool, internal::ListSchemaFor<T>::schema, value.reader);
struct ToDynamic_<T, Kind::LIST> {
static inline DynamicList::Reader apply(typename T::Reader value) {
return DynamicList::Reader(Schema::from<T>(), value.reader);
}
static inline DynamicList::Builder apply(const SchemaPool* pool, typename T::Builder value) {
return DynamicList::Builder(pool, internal::ListSchemaFor<T>::schema, value.builder);
static inline DynamicList::Builder apply(typename T::Builder value) {
return DynamicList::Builder(Schema::from<T>(), value.builder);
}
};
template <typename T>
ReaderFor<DynamicTypeFor<FromReader<T>>> SchemaPool::toDynamic(T&& value) const {
return ToDynamicImpl<FromReader<T>>::apply(this, value);
ReaderFor<DynamicTypeFor<FromReader<T>>> toDynamic(T&& value) {
return ToDynamic_<FromReader<T>>::apply(value);
}
template <typename T>
BuilderFor<DynamicTypeFor<FromBuilder<T>>> SchemaPool::toDynamic(T&& value) const {
return ToDynamicImpl<FromBuilder<T>>::apply(this, value);
BuilderFor<DynamicTypeFor<FromBuilder<T>>> toDynamic(T&& value) {
return ToDynamic_<FromBuilder<T>>::apply(value);
}
template <typename T>
DynamicTypeFor<TypeIfEnum<T>> SchemaPool::toDynamic(T&& value) const {
return DynamicEnum(this, getEnum(typeId<T>()), static_cast<uint16_t>(value));
DynamicTypeFor<TypeIfEnum<T>> toDynamic(T&& value) {
return DynamicEnum(Schema::from<T>(), static_cast<uint16_t>(value));
}
#define CAPNPROTO_DECLARE_DYNAMIC_VALUE_CONSTRUCTOR(cppType, typeTag, fieldName) \
......@@ -989,26 +798,26 @@ struct DynamicValue::Builder::AsImpl<T, Kind::LIST> {
template <typename T>
struct DynamicObject::Reader::AsImpl<T, Kind::STRUCT> {
static T apply(Reader reader) {
return reader.asStruct(typeId<T>()).as<T>();
return reader.as(Schema::from<T>()).as<T>();
}
};
template <typename T>
struct DynamicObject::Builder::AsImpl<T, Kind::STRUCT> {
static T apply(Builder builder) {
return builder.asStruct(typeId<T>()).as<T>();
return builder.as(Schema::from<T>()).as<T>();
}
};
template <typename T>
struct DynamicObject::Reader::AsImpl<List<T>, Kind::LIST> {
struct DynamicObject::Reader::AsImpl<T, Kind::LIST> {
static T apply(Reader reader) {
return reader.asList(internal::ListSchemaForElement<T>::schema).as<T>();
return reader.as(Schema::from<T>()).as<T>();
}
};
template <typename T>
struct DynamicObject::Builder::AsImpl<List<T>, Kind::LIST> {
struct DynamicObject::Builder::AsImpl<T, Kind::LIST> {
static T apply(Builder builder) {
return builder.asList(internal::ListSchemaForElement<T>::schema).as<T>();
return builder.as(Schema::from<T>()).as<T>();
}
};
......@@ -1029,29 +838,8 @@ typename T::Builder DynamicStruct::Builder::as() {
return typename T::Builder(builder);
}
inline DynamicValue::Reader DynamicStruct::Reader::get(
schema::StructNode::Member::Reader member) {
return getImpl(pool, reader, member);
}
inline DynamicValue::Builder DynamicStruct::Builder::get(
schema::StructNode::Member::Reader member) {
return getImpl(pool, builder, member);
}
inline void DynamicStruct::Builder::set(
schema::StructNode::Member::Reader member, DynamicValue::Reader value) {
return setImpl(pool, builder, member, value);
}
inline DynamicValue::Builder DynamicStruct::Builder::init(
schema::StructNode::Member::Reader member) {
return initImpl(pool, builder, member);
}
inline DynamicValue::Builder DynamicStruct::Builder::init(
schema::StructNode::Member::Reader member, uint size) {
return initImpl(pool, builder, member, size);
}
inline DynamicStruct::Reader DynamicStruct::Builder::asReader() {
return DynamicStruct::Reader(pool, schema, builder.asReader());
return DynamicStruct::Reader(schema, builder.asReader());
}
// -------------------------------------------------------------------
......@@ -1060,14 +848,14 @@ template <typename T>
typename T::Reader DynamicList::Reader::as() {
static_assert(kind<T>() == Kind::LIST,
"DynamicStruct::Reader::as<T>() can only convert to list types.");
verifySchema(internal::ListSchemaFor<T>::schema);
verifySchema(Schema::from<T>());
return typename T::Reader(reader);
}
template <typename T>
typename T::Builder DynamicList::Builder::as() {
static_assert(kind<T>() == Kind::LIST,
"DynamicStruct::Builder::as<T>() can only convert to list types.");
verifySchema(internal::ListSchemaFor<T>::schema);
verifySchema(Schema::from<T>());
return typename T::Builder(builder);
}
......
......@@ -31,7 +31,8 @@
namespace capnproto {
class SchemaPool; // Needs to be declared for dynamic Object accessors.
template <typename T, Kind k = kind<T>()>
struct ToDynamic_; // Defined in dynamic.h, needs to be declared as everyone's friend.
class DynamicStruct; // So that it can be declared a friend.
......
......@@ -37,7 +37,7 @@ namespace internal {
class BuilderArena;
}
class SchemaPool;
class StructSchema;
// =======================================================================================
......@@ -99,8 +99,8 @@ public:
// Get the root struct of the message, interpreting it as the given struct type.
template <typename RootType>
typename RootType::Reader getRoot(const SchemaPool& pool, uint64_t typeId);
// Dynamically interpret the root struct of the message using the type with the given ID.
typename RootType::Reader getRoot(StructSchema schema);
// Dynamically interpret the root struct of the message using the given schema.
// RootType in this case must be DynamicStruct, and you must #include <capnproto/dynamic.h> to
// use this.
......@@ -138,14 +138,14 @@ public:
// Get the root struct of the message, interpreting it as the given struct type.
template <typename RootType>
typename RootType::Builder getRoot(const SchemaPool& pool, uint64_t typeId);
// Dynamically interpret the root struct of the message using the type with the given ID.
typename RootType::Builder getRoot(StructSchema schema);
// Dynamically interpret the root struct of the message using the given schema.
// RootType in this case must be DynamicStruct, and you must #include <capnproto/dynamic.h> to
// use this.
template <typename RootType>
typename RootType::Builder initRoot(const SchemaPool& pool, uint64_t typeId);
// Dynamically init the root struct of the message using the type with the given ID.
typename RootType::Builder initRoot(StructSchema schema);
// Dynamically init the root struct of the message using the given schema.
// RootType in this case must be DynamicStruct, and you must #include <capnproto/dynamic.h> to
// use this.
......
......@@ -67,9 +67,9 @@ TEST(Schema, Structs) {
EXPECT_ANY_THROW(schema.asEnum());
EXPECT_ANY_THROW(schema.asInterface());
ASSERT_EQ(schema.members().size(),
ASSERT_EQ(schema.getMembers().size(),
schema.getProto().getBody().getStructNode().getMembers().size());
StructSchema::Member member = schema.members()[0];
StructSchema::Member member = schema.getMembers()[0];
EXPECT_EQ("voidField", member.getProto().getName());
EXPECT_TRUE(member.getContainingStruct() == schema);
EXPECT_TRUE(member.getContainingUnion() == nullptr);
......@@ -79,7 +79,7 @@ TEST(Schema, Structs) {
Maybe<StructSchema::Member> lookup = schema.findMemberByName("voidField");
ASSERT_TRUE(lookup != nullptr);
EXPECT_TRUE(*lookup == member);
EXPECT_TRUE(*lookup != schema.members()[1]);
EXPECT_TRUE(*lookup != schema.getMembers()[1]);
EXPECT_TRUE(schema.findMemberByName("noSuchField") == nullptr);
......@@ -95,15 +95,15 @@ TEST(Schema, FieldLookupOutOfOrder) {
// file.
auto schema = Schema::from<test::TestOutOfOrder>().asStruct();
EXPECT_EQ("qux", schema.members()[0].getProto().getName());
EXPECT_EQ("grault", schema.members()[1].getProto().getName());
EXPECT_EQ("bar", schema.members()[2].getProto().getName());
EXPECT_EQ("foo", schema.members()[3].getProto().getName());
EXPECT_EQ("corge", schema.members()[4].getProto().getName());
EXPECT_EQ("waldo", schema.members()[5].getProto().getName());
EXPECT_EQ("quux", schema.members()[6].getProto().getName());
EXPECT_EQ("garply", schema.members()[7].getProto().getName());
EXPECT_EQ("baz", schema.members()[8].getProto().getName());
EXPECT_EQ("qux", schema.getMembers()[0].getProto().getName());
EXPECT_EQ("grault", schema.getMembers()[1].getProto().getName());
EXPECT_EQ("bar", schema.getMembers()[2].getProto().getName());
EXPECT_EQ("foo", schema.getMembers()[3].getProto().getName());
EXPECT_EQ("corge", schema.getMembers()[4].getProto().getName());
EXPECT_EQ("waldo", schema.getMembers()[5].getProto().getName());
EXPECT_EQ("quux", schema.getMembers()[6].getProto().getName());
EXPECT_EQ("garply", schema.getMembers()[7].getProto().getName());
EXPECT_EQ("baz", schema.getMembers()[8].getProto().getName());
EXPECT_EQ(3, schema.findMemberByName("foo")->getProto().getOrdinal());
EXPECT_EQ(2, schema.findMemberByName("bar")->getProto().getOrdinal());
......@@ -160,16 +160,16 @@ TEST(Schema, Enums) {
EXPECT_ANY_THROW(schema.asInterface());
EXPECT_TRUE(schema.asEnum() == schema);
ASSERT_EQ(schema.enumerants().size(),
ASSERT_EQ(schema.getEnumerants().size(),
schema.getProto().getBody().getEnumNode().getEnumerants().size());
EnumSchema::Enumerant enumerant = schema.enumerants()[0];
EnumSchema::Enumerant enumerant = schema.getEnumerants()[0];
EXPECT_EQ("foo", enumerant.getProto().getName());
EXPECT_TRUE(enumerant.getContainingEnum() == schema);
Maybe<EnumSchema::Enumerant> lookup = schema.findEnumerantByName("foo");
ASSERT_TRUE(lookup != nullptr);
EXPECT_TRUE(*lookup == enumerant);
EXPECT_TRUE(*lookup != schema.enumerants()[1]);
EXPECT_TRUE(*lookup != schema.getEnumerants()[1]);
EXPECT_TRUE(schema.findEnumerantByName("noSuchEnumerant") == nullptr);
......
......@@ -114,17 +114,17 @@ auto findSchemaMemberByName(const internal::RawSchema* raw, Text::Reader name,
} // namespace
StructSchema::MemberList StructSchema::members() const {
StructSchema::MemberList StructSchema::getMembers() const {
return MemberList(*this, 0, getProto().getBody().getStructNode().getMembers());
}
Maybe<StructSchema::Member> StructSchema::findMemberByName(Text::Reader name) const {
return findSchemaMemberByName(raw, name, 0, members());
return findSchemaMemberByName(raw, name, 0, getMembers());
}
Maybe<StructSchema::Union> StructSchema::Member::getContainingUnion() const {
if (unionIndex == 0) return nullptr;
return parent.members()[unionIndex - 1].asUnion();
return parent.getMembers()[unionIndex - 1].asUnion();
}
StructSchema::Union StructSchema::Member::asUnion() const {
......@@ -134,32 +134,32 @@ StructSchema::Union StructSchema::Member::asUnion() const {
return Union(*this);
}
StructSchema::MemberList StructSchema::Union::members() const {
StructSchema::MemberList StructSchema::Union::getMembers() const {
return MemberList(parent, index + 1, proto.getBody().getUnionMember().getMembers());
}
Maybe<StructSchema::Member> StructSchema::Union::findMemberByName(Text::Reader name) const {
return findSchemaMemberByName(parent.raw, name, index + 1, members());
return findSchemaMemberByName(parent.raw, name, index + 1, getMembers());
}
// -------------------------------------------------------------------
EnumSchema::EnumerantList EnumSchema::enumerants() const {
EnumSchema::EnumerantList EnumSchema::getEnumerants() const {
return EnumerantList(*this, getProto().getBody().getEnumNode().getEnumerants());
}
Maybe<EnumSchema::Enumerant> EnumSchema::findEnumerantByName(Text::Reader name) const {
return findSchemaMemberByName(raw, name, 0, enumerants());
return findSchemaMemberByName(raw, name, 0, getEnumerants());
}
// -------------------------------------------------------------------
InterfaceSchema::MethodList InterfaceSchema::methods() const {
InterfaceSchema::MethodList InterfaceSchema::getMethods() const {
return MethodList(*this, getProto().getBody().getInterfaceNode().getMethods());
}
Maybe<InterfaceSchema::Method> InterfaceSchema::findMethodByName(Text::Reader name) const {
return findSchemaMemberByName(raw, name, 0, methods());
return findSchemaMemberByName(raw, name, 0, getMethods());
}
// =======================================================================================
......
......@@ -99,7 +99,7 @@ public:
class Union;
class MemberList;
MemberList members() const;
MemberList getMembers() const;
Maybe<Member> findMemberByName(Text::Reader name) const;
private:
......@@ -147,7 +147,7 @@ class StructSchema::Union: public Member {
public:
Union() = default;
MemberList members() const;
MemberList getMembers() const;
Maybe<Member> findMemberByName(Text::Reader name) const;
private:
......@@ -181,10 +181,12 @@ private:
class EnumSchema: public Schema {
public:
EnumSchema() = default;
class Enumerant;
class EnumerantList;
EnumerantList enumerants() const;
EnumerantList getEnumerants() const;
Maybe<Enumerant> findEnumerantByName(Text::Reader name) const;
private:
......@@ -242,10 +244,12 @@ private:
class InterfaceSchema: public Schema {
public:
InterfaceSchema() = default;
class Method;
class MethodList;
MethodList methods() const;
MethodList getMethods() const;
Maybe<Method> findMethodByName(Text::Reader name) const;
private:
......@@ -332,6 +336,9 @@ public:
// Get the schema for complex element types. Each of these throws an exception if the element
// type is not of the requested kind.
inline bool operator==(const ListSchema& other) const;
inline bool operator!=(const ListSchema& other) const { return !(*this == other); }
private:
schema::Type::Body::Which elementType;
uint8_t nestingDepth; // 0 for T, 1 for List(T), 2 for List(List(T)), ...
......@@ -400,6 +407,11 @@ inline schema::Type::Body::Which ListSchema::whichElementType() const {
return nestingDepth == 0 ? elementType : schema::Type::Body::LIST_TYPE;
}
inline bool ListSchema::operator==(const ListSchema& other) const {
return elementType == other.elementType && nestingDepth == other.nestingDepth &&
elementSchema == other.elementSchema;
}
template <typename T>
struct ListSchema::FromImpl<List<T>> {
static inline ListSchema get() { return of(Schema::from<T>()); }
......
......@@ -166,13 +166,14 @@ public:
{{/fieldIsPrimitive}}
{{#fieldIsGenericObject}}
template <typename T> inline typename T::Reader get{{fieldTitleCase}}();
template <typename T, typename... Params> inline typename T::Reader get{{fieldTitleCase}}(
const ::capnproto::SchemaPool& pool, Params&&... params);
template <typename T, typename Param> inline typename T::Reader
get{{fieldTitleCase}}(Param&& param);
{{/fieldIsGenericObject}}
{{/typeFields}}
private:
::capnproto::internal::StructReader _reader;
friend class ::capnproto::SchemaPool;
template <typename T, ::capnproto::Kind k>
friend struct ::capnproto::ToDynamic_;
};
{{! ------------------------------------------------------------------------------------------- }}
......@@ -220,19 +221,17 @@ public:
{{/fieldIsPrimitive}}
{{#fieldIsGenericObject}}
template <typename T> inline typename T::Builder get{{fieldTitleCase}}();
template <typename T, typename Param> inline typename T::Builder
get{{fieldTitleCase}}(Param&& param);
template <typename T> inline void set{{fieldTitleCase}}(typename T::Reader value);
template <typename T> inline typename T::Builder init{{fieldTitleCase}}();
template <typename T> inline typename T::Builder init{{fieldTitleCase}}(unsigned int size);
template <typename T, typename... Params> inline typename T::Builder get{{fieldTitleCase}}(
const ::capnproto::SchemaPool& pool, Params&&... params);
template <typename T, typename... Params> inline typename T::Builder init{{fieldTitleCase}}(
const ::capnproto::SchemaPool& pool, Params&&... params);
template <typename T, typename... Params> inline typename T::Builder
init{{fieldTitleCase}}(Params&&... params);
{{/fieldIsGenericObject}}
{{/typeFields}}
private:
::capnproto::internal::StructBuilder _builder;
friend class ::capnproto::SchemaPool;
template <typename T, ::capnproto::Kind k>
friend struct ::capnproto::ToDynamic_;
};
{{/typeStructOrUnion}}
{{/fileTypes}}
......@@ -384,70 +383,44 @@ inline typename T::Builder {{typeFullName}}::Builder::get{{fieldTitleCase}}() {
_builder, {{fieldOffset}} * ::capnproto::REFERENCES);
}
template <typename T>
inline void {{typeFullName}}::Builder::set{{fieldTitleCase}}(typename T::Reader value) {
template <typename T, typename Param>
inline typename T::Reader {{typeFullName}}::Reader::get{{fieldTitleCase}}(Param&& param) {
{{#fieldUnion}}
_builder.setDataField<{{unionTitleCase}}::Which>(
{{unionTagOffset}} * ::capnproto::ELEMENTS, {{unionTitleCase}}::{{fieldUpperCase}});
CAPNPROTO_INLINE_DPRECOND(which() == {{unionTitleCase}}::{{fieldUpperCase}},
"Must check which() before get()ing a union member.");
{{/fieldUnion}}
::capnproto::internal::PointerHelpers<T>::set(
_builder, {{fieldOffset}} * ::capnproto::REFERENCES, value);
return ::capnproto::internal::PointerHelpers<T>::getDynamic(
_reader, {{fieldOffset}} * ::capnproto::REFERENCES, ::capnproto::forward<Param>(param));
}
template <typename T>
inline typename T::Builder {{typeFullName}}::Builder::init{{fieldTitleCase}}() {
template <typename T, typename Param>
inline typename T::Builder {{typeFullName}}::Builder::get{{fieldTitleCase}}(Param&& param) {
{{#fieldUnion}}
_builder.setDataField<{{unionTitleCase}}::Which>(
{{unionTagOffset}} * ::capnproto::ELEMENTS, {{unionTitleCase}}::{{fieldUpperCase}});
CAPNPROTO_INLINE_DPRECOND(which() == {{unionTitleCase}}::{{fieldUpperCase}},
"Must check which() before get()ing a union member.");
{{/fieldUnion}}
return ::capnproto::internal::PointerHelpers<T>::init(
_builder, {{fieldOffset}} * ::capnproto::REFERENCES);
return ::capnproto::internal::PointerHelpers<T>::getDynamic(
_builder, {{fieldOffset}} * ::capnproto::REFERENCES, ::capnproto::forward<Param>(param));
}
template <typename T>
inline typename T::Builder {{typeFullName}}::Builder::init{{fieldTitleCase}}(unsigned int size) {
inline void {{typeFullName}}::Builder::set{{fieldTitleCase}}(typename T::Reader value) {
{{#fieldUnion}}
_builder.setDataField<{{unionTitleCase}}::Which>(
{{unionTagOffset}} * ::capnproto::ELEMENTS, {{unionTitleCase}}::{{fieldUpperCase}});
{{/fieldUnion}}
return ::capnproto::internal::PointerHelpers<T>::init(
_builder, {{fieldOffset}} * ::capnproto::REFERENCES, size);
}
template <typename T, typename... Params>
inline typename T::Reader {{typeFullName}}::Reader::get{{fieldTitleCase}}(
const ::capnproto::SchemaPool& pool, Params&&... params) {
{{#fieldUnion}}
CAPNPROTO_INLINE_DPRECOND(which() == {{unionTitleCase}}::{{fieldUpperCase}},
"Must check which() before get()ing a union member.");
{{/fieldUnion}}
return ::capnproto::internal::PointerHelpers<T>::get(
_reader, {{fieldOffset}} * ::capnproto::REFERENCES,
pool, ::capnproto::forward<Params>(params)...);
}
template <typename T, typename... Params>
inline typename T::Builder {{typeFullName}}::Builder::get{{fieldTitleCase}}(
const ::capnproto::SchemaPool& pool, Params&&... params) {
{{#fieldUnion}}
CAPNPROTO_INLINE_DPRECOND(which() == {{unionTitleCase}}::{{fieldUpperCase}},
"Must check which() before get()ing a union member.");
{{/fieldUnion}}
return ::capnproto::internal::PointerHelpers<T>::get(
_builder, {{fieldOffset}} * ::capnproto::REFERENCES,
pool, ::capnproto::forward<Params>(params)...);
::capnproto::internal::PointerHelpers<T>::set(
_builder, {{fieldOffset}} * ::capnproto::REFERENCES, value);
}
template <typename T, typename... Params>
inline typename T::Builder {{typeFullName}}::Builder::init{{fieldTitleCase}}(
const ::capnproto::SchemaPool& pool, Params&&... params) {
inline typename T::Builder {{typeFullName}}::Builder::init{{fieldTitleCase}}(Params&&... params) {
{{#fieldUnion}}
_builder.setDataField<{{unionTitleCase}}::Which>(
{{unionTagOffset}} * ::capnproto::ELEMENTS, {{unionTitleCase}}::{{fieldUpperCase}});
{{/fieldUnion}}
return ::capnproto::internal::PointerHelpers<T>::init(
_builder, {{fieldOffset}} * ::capnproto::REFERENCES,
pool, ::capnproto::forward<Params>(params)...);
_builder, {{fieldOffset}} * ::capnproto::REFERENCES, ::capnproto::forward<Params>(params)...);
}
{{/fieldIsGenericObject}}
......
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