Commit 80722b03 authored by Kenton Varda's avatar Kenton Varda

Revamp dynamic struct getters/setters to not distinguish unions. Add…

Revamp dynamic struct getters/setters to not distinguish unions.  Add converience versions that take string names.
parent 449f4b23
...@@ -39,7 +39,7 @@ TEST(Blob, Text) { ...@@ -39,7 +39,7 @@ TEST(Blob, Text) {
EXPECT_STREQ("foo", text.data()); EXPECT_STREQ("foo", text.data());
EXPECT_EQ(3u, text.size()); EXPECT_EQ(3u, text.size());
std::string str2 = text; std::string str2 = text.as<std::string>();
EXPECT_EQ("foo", str2); EXPECT_EQ("foo", str2);
Text::Reader text2 = "bar"; Text::Reader text2 = "bar";
...@@ -62,7 +62,7 @@ TEST(Blob, Data) { ...@@ -62,7 +62,7 @@ TEST(Blob, Data) {
EXPECT_EQ("foo", data); EXPECT_EQ("foo", data);
EXPECT_EQ(3u, data.size()); EXPECT_EQ(3u, data.size());
std::string str2 = data; std::string str2 = data.as<std::string>();
EXPECT_EQ("foo", str2); EXPECT_EQ("foo", str2);
Data::Reader data2 = "bar"; Data::Reader data2 = "bar";
......
...@@ -66,10 +66,6 @@ public: ...@@ -66,10 +66,6 @@ public:
inline Reader(const T& other): bytes(other.data()), size_(other.size()) {} inline Reader(const T& other): bytes(other.data()), size_(other.size()) {}
// Primarily intended for converting from std::string. // Primarily intended for converting from std::string.
template <typename T>
inline operator T() const { return T(bytes, size_); }
// Primarily intended for converting to std::string.
template <typename T> template <typename T>
inline T as() const { return T(bytes, size_); } inline T as() const { return T(bytes, size_); }
// Explicitly converts to the desired type, which must have a (const char*, size) constructor. // Explicitly converts to the desired type, which must have a (const char*, size) constructor.
......
...@@ -339,9 +339,17 @@ DynamicList::Builder DynamicObject::Builder::asList(internal::ListSchema schema) ...@@ -339,9 +339,17 @@ DynamicList::Builder DynamicObject::Builder::asList(internal::ListSchema schema)
// ======================================================================================= // =======================================================================================
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() { Maybe<schema::StructNode::Member::Reader> DynamicUnion::Reader::which() {
auto members = schema.getMembers(); auto uschema = getSchema();
uint16_t discrim = reader.getDataField<uint32_t>(schema.getDiscriminantOffset() * ELEMENTS); auto members = uschema.getMembers();
uint16_t discrim = reader.getDataField<uint32_t>(uschema.getDiscriminantOffset() * ELEMENTS);
if (discrim < members.size()) { if (discrim < members.size()) {
return members[discrim]; return members[discrim];
...@@ -350,8 +358,9 @@ Maybe<schema::StructNode::Member::Reader> DynamicUnion::Reader::which() { ...@@ -350,8 +358,9 @@ Maybe<schema::StructNode::Member::Reader> DynamicUnion::Reader::which() {
} }
} }
Maybe<schema::StructNode::Member::Reader> DynamicUnion::Builder::which() { Maybe<schema::StructNode::Member::Reader> DynamicUnion::Builder::which() {
auto members = schema.getMembers(); auto uschema = getSchema();
uint16_t discrim = builder.getDataField<uint32_t>(schema.getDiscriminantOffset() * ELEMENTS); auto members = uschema.getMembers();
uint16_t discrim = builder.getDataField<uint32_t>(uschema.getDiscriminantOffset() * ELEMENTS);
if (discrim < members.size()) { if (discrim < members.size()) {
return members[discrim]; return members[discrim];
...@@ -365,11 +374,9 @@ DynamicValue::Reader DynamicUnion::Reader::get() { ...@@ -365,11 +374,9 @@ DynamicValue::Reader DynamicUnion::Reader::get() {
RECOVERABLE_PRECOND(w != nullptr, "Can't get() unknown union value.") { RECOVERABLE_PRECOND(w != nullptr, "Can't get() unknown union value.") {
return DynamicValue::Reader(); return DynamicValue::Reader();
} }
auto body = w->getBody(); CHECK(w->getBody().which() == schema::StructNode::Member::Body::FIELD_MEMBER,
CHECK(body.which() == schema::StructNode::Member::Body::FIELD_MEMBER,
"Unsupported union member type."); "Unsupported union member type.");
return DynamicValue::Reader(DynamicStruct::Reader::getFieldImpl( return DynamicValue::Reader(DynamicStruct::Reader::getImpl(pool, reader, *w));
pool, reader, body.getFieldMember()));
} }
DynamicValue::Builder DynamicUnion::Builder::get() { DynamicValue::Builder DynamicUnion::Builder::get() {
...@@ -377,28 +384,26 @@ DynamicValue::Builder DynamicUnion::Builder::get() { ...@@ -377,28 +384,26 @@ DynamicValue::Builder DynamicUnion::Builder::get() {
RECOVERABLE_PRECOND(w != nullptr, "Can't get() unknown union value.") { RECOVERABLE_PRECOND(w != nullptr, "Can't get() unknown union value.") {
return DynamicValue::Builder(); return DynamicValue::Builder();
} }
auto body = w->getBody(); CHECK(w->getBody().which() == schema::StructNode::Member::Body::FIELD_MEMBER,
CHECK(body.which() == schema::StructNode::Member::Body::FIELD_MEMBER,
"Unsupported union member type."); "Unsupported union member type.");
return DynamicValue::Builder(DynamicStruct::Builder::getFieldImpl( return DynamicValue::Builder(DynamicStruct::Builder::getImpl(pool, builder, *w));
pool, builder, body.getFieldMember()));
} }
void DynamicUnion::Builder::set( void DynamicUnion::Builder::set(
schema::StructNode::Field::Reader field, DynamicValue::Reader value) { schema::StructNode::Member::Reader member, DynamicValue::Reader value) {
builder.setDataField<uint16_t>(schema.getDiscriminantOffset() * ELEMENTS, field.getIndex()); builder.setDataField<uint16_t>(getSchema().getDiscriminantOffset() * ELEMENTS, member.getIndex());
DynamicStruct::Builder::setFieldImpl(pool, builder, field, value); DynamicStruct::Builder::setImpl(pool, builder, member, value);
} }
DynamicValue::Builder DynamicUnion::Builder::init(schema::StructNode::Field::Reader field) { DynamicValue::Builder DynamicUnion::Builder::init(schema::StructNode::Member::Reader member) {
builder.setDataField<uint16_t>(schema.getDiscriminantOffset() * ELEMENTS, field.getIndex()); builder.setDataField<uint16_t>(getSchema().getDiscriminantOffset() * ELEMENTS, member.getIndex());
return DynamicStruct::Builder::initFieldImpl(pool, builder, field); return DynamicStruct::Builder::initImpl(pool, builder, member);
} }
DynamicValue::Builder DynamicUnion::Builder::init(schema::StructNode::Field::Reader field, DynamicValue::Builder DynamicUnion::Builder::init(schema::StructNode::Member::Reader member,
uint size) { uint size) {
builder.setDataField<uint16_t>(schema.getDiscriminantOffset() * ELEMENTS, field.getIndex()); builder.setDataField<uint16_t>(getSchema().getDiscriminantOffset() * ELEMENTS, member.getIndex());
return DynamicStruct::Builder::initFieldImpl(pool, builder, field, size); return DynamicStruct::Builder::initImpl(pool, builder, member, size);
} }
// ======================================================================================= // =======================================================================================
...@@ -442,30 +447,105 @@ Maybe<schema::StructNode::Member::Reader> DynamicStruct::Builder::findMemberByNa ...@@ -442,30 +447,105 @@ Maybe<schema::StructNode::Member::Reader> DynamicStruct::Builder::findMemberByNa
} }
} }
DynamicValue::Builder DynamicStruct::Builder::initObjectField( DynamicValue::Builder DynamicStruct::Builder::initObject(
schema::StructNode::Field::Reader field, schema::Type::Reader type) { schema::StructNode::Member::Reader member, schema::Type::Reader type) {
VALIDATE_INPUT(field.getType().getBody().which() == schema::Type::Body::OBJECT_TYPE, switch (member.getBody().which()) {
"Expected an Object. (To dynamically initialize a non-Object field, do not " case schema::StructNode::Member::Body::UNION_MEMBER:
"pass an element type to initObjectField().)") { FAIL_VALIDATE_INPUT(
return initFieldImpl(pool, builder, field); "Can't init() a union. get() it first and then init() one of its members.");
return getImpl(pool, builder, member);
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);
}
} }
return initFieldImpl(pool, builder, field, type);
} FAIL_CHECK("switch() missing case.", member.getBody().which());
DynamicValue::Builder DynamicStruct::Builder::initObjectField( return getImpl(pool, builder, member);
schema::StructNode::Field::Reader field, schema::Type::Reader type, uint size) { }
VALIDATE_INPUT(field.getType().getBody().which() == schema::Type::Body::OBJECT_TYPE, DynamicValue::Builder DynamicStruct::Builder::initObject(
"Expected an Object. (To dynamically initialize a non-Object field, do not " schema::StructNode::Member::Reader member, schema::Type::Reader type, uint size) {
"pass a struct schema to initObjectField().)") { switch (member.getBody().which()) {
return initFieldImpl(pool, builder, field, size); 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);
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);
}
} }
return initFieldImpl(pool, builder, field, type, size);
FAIL_CHECK("switch() missing case.", member.getBody().which());
return getImpl(pool, builder, member);
} }
DynamicUnion::Reader DynamicStruct::Reader::getUnion(schema::StructNode::Union::Reader un) { DynamicValue::Reader DynamicStruct::Reader::get(Text::Reader name) {
return DynamicUnion::Reader(pool, un, reader); auto member = findMemberByName(name);
RECOVERABLE_PRECOND(member != nullptr, "struct has no such member", name) {
return DynamicValue::Reader();
}
return get(*member);
}
DynamicValue::Builder DynamicStruct::Builder::get(Text::Reader name) {
auto member = findMemberByName(name);
RECOVERABLE_PRECOND(member != nullptr, "struct has no such member", name) {
return DynamicValue::Builder();
}
return get(*member);
}
void DynamicStruct::Builder::set(Text::Reader name, DynamicValue::Reader value) {
auto member = findMemberByName(name);
RECOVERABLE_PRECOND(member != nullptr, "struct has no such member", name) {
return;
}
return set(*member, value);
} }
DynamicUnion::Builder DynamicStruct::Builder::getUnion(schema::StructNode::Union::Reader un) { void DynamicStruct::Builder::set(Text::Reader name,
return DynamicUnion::Builder(pool, un, builder); 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);
RECOVERABLE_PRECOND(member != nullptr, "struct has no such member", name) {
return DynamicValue::Builder();
}
return init(*member);
}
DynamicValue::Builder DynamicStruct::Builder::init(Text::Reader name, uint size) {
auto member = findMemberByName(name);
RECOVERABLE_PRECOND(member != nullptr, "struct has no such member", name) {
return DynamicValue::Builder();
}
return init(*member, size);
}
DynamicValue::Builder DynamicStruct::Builder::initObject(
Text::Reader name, schema::Type::Reader type) {
auto member = findMemberByName(name);
RECOVERABLE_PRECOND(member != nullptr, "struct has no such member", name) {
return DynamicValue::Builder();
}
return initObject(*member, type);
}
DynamicValue::Builder DynamicStruct::Builder::initObject(
Text::Reader name, schema::Type::Reader type, uint size) {
auto member = findMemberByName(name);
RECOVERABLE_PRECOND(member != nullptr, "struct has no such member", name) {
return DynamicValue::Builder();
}
return initObject(*member, type, size);
} }
void DynamicStruct::Builder::copyFrom(Reader other) { void DynamicStruct::Builder::copyFrom(Reader other) {
...@@ -474,261 +554,333 @@ void DynamicStruct::Builder::copyFrom(Reader other) { ...@@ -474,261 +554,333 @@ void DynamicStruct::Builder::copyFrom(Reader other) {
FAIL_CHECK("Unimplemented: copyFrom()"); FAIL_CHECK("Unimplemented: copyFrom()");
} }
DynamicValue::Reader DynamicStruct::Reader::getFieldImpl( DynamicValue::Reader DynamicStruct::Reader::getImpl(
const SchemaPool* pool, internal::StructReader reader, const SchemaPool* pool, internal::StructReader reader,
schema::StructNode::Field::Reader field) { schema::StructNode::Member::Reader member) {
auto type = field.getType().getBody(); switch (member.getBody().which()) {
auto dval = field.getDefaultValue().getBody(); case schema::StructNode::Member::Body::UNION_MEMBER:
return DynamicUnion::Reader(pool, member, reader);
switch (type.which()) { case schema::StructNode::Member::Body::FIELD_MEMBER: {
case schema::Type::Body::VOID_TYPE: auto field = member.getBody().getFieldMember();
return DynamicValue::Reader(reader.getDataField<Void>(field.getOffset() * ELEMENTS)); auto type = field.getType().getBody();
auto dval = field.getDefaultValue().getBody();
switch (type.which()) {
case schema::Type::Body::VOID_TYPE:
return DynamicValue::Reader(reader.getDataField<Void>(field.getOffset() * ELEMENTS));
#define HANDLE_TYPE(discrim, titleCase, type) \ #define HANDLE_TYPE(discrim, titleCase, type) \
case schema::Type::Body::discrim##_TYPE: \ case schema::Type::Body::discrim##_TYPE: \
return DynamicValue::Reader(reader.getDataField<type>( \ return DynamicValue::Reader(reader.getDataField<type>( \
field.getOffset() * ELEMENTS, \ field.getOffset() * ELEMENTS, \
bitCast<typename internal::MaskType<type>::Type>(dval.get##titleCase##Value()))); bitCast<typename internal::MaskType<type>::Type>(dval.get##titleCase##Value())));
HANDLE_TYPE(BOOL, Bool, bool) HANDLE_TYPE(BOOL, Bool, bool)
HANDLE_TYPE(INT8, Int8, int8_t) HANDLE_TYPE(INT8, Int8, int8_t)
HANDLE_TYPE(INT16, Int16, int16_t) HANDLE_TYPE(INT16, Int16, int16_t)
HANDLE_TYPE(INT32, Int32, int32_t) HANDLE_TYPE(INT32, Int32, int32_t)
HANDLE_TYPE(INT64, Int64, int64_t) HANDLE_TYPE(INT64, Int64, int64_t)
HANDLE_TYPE(UINT8, Uint8, uint8_t) HANDLE_TYPE(UINT8, Uint8, uint8_t)
HANDLE_TYPE(UINT16, Uint16, uint16_t) HANDLE_TYPE(UINT16, Uint16, uint16_t)
HANDLE_TYPE(UINT32, Uint32, uint32_t) HANDLE_TYPE(UINT32, Uint32, uint32_t)
HANDLE_TYPE(UINT64, Uint64, uint64_t) HANDLE_TYPE(UINT64, Uint64, uint64_t)
HANDLE_TYPE(FLOAT32, Float32, float) HANDLE_TYPE(FLOAT32, Float32, float)
HANDLE_TYPE(FLOAT64, Float64, double) HANDLE_TYPE(FLOAT64, Float64, double)
#undef HANDLE_TYPE #undef HANDLE_TYPE
case schema::Type::Body::ENUM_TYPE: { case schema::Type::Body::ENUM_TYPE: {
uint16_t typedDval; uint16_t typedDval;
typedDval = dval.getEnumValue(); typedDval = dval.getEnumValue();
return DynamicValue::Reader(DynamicEnum( return DynamicValue::Reader(DynamicEnum(
pool, pool->getEnum(type.getEnumType()), pool, pool->getEnum(type.getEnumType()),
reader.getDataField<uint16_t>(field.getOffset() * ELEMENTS, typedDval))); reader.getDataField<uint16_t>(field.getOffset() * ELEMENTS, typedDval)));
} }
case schema::Type::Body::TEXT_TYPE: { case schema::Type::Body::TEXT_TYPE: {
Text::Reader typedDval = dval.getTextValue(); Text::Reader typedDval = dval.getTextValue();
return DynamicValue::Reader( return DynamicValue::Reader(
reader.getBlobField<Text>(field.getOffset() * REFERENCES, reader.getBlobField<Text>(field.getOffset() * REFERENCES,
typedDval.data(), typedDval.size() * BYTES)); typedDval.data(), typedDval.size() * BYTES));
} }
case schema::Type::Body::DATA_TYPE: { case schema::Type::Body::DATA_TYPE: {
Data::Reader typedDval = dval.getDataValue(); Data::Reader typedDval = dval.getDataValue();
return DynamicValue::Reader( return DynamicValue::Reader(
reader.getBlobField<Data>(field.getOffset() * REFERENCES, reader.getBlobField<Data>(field.getOffset() * REFERENCES,
typedDval.data(), typedDval.size() * BYTES)); typedDval.data(), typedDval.size() * BYTES));
} }
case schema::Type::Body::LIST_TYPE: {
auto elementType = type.getListType();
return DynamicValue::Reader(DynamicList::Reader(
pool, elementType,
reader.getListField(field.getOffset() * REFERENCES,
elementSizeFor(elementType.getBody().which()),
dval.getListValue<internal::TrustedMessage>())));
}
case schema::Type::Body::STRUCT_TYPE: {
return DynamicValue::Reader(DynamicStruct::Reader(
pool, pool->getStruct(type.getStructType()),
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>())));
}
case schema::Type::Body::INTERFACE_TYPE:
FAIL_CHECK("Interfaces not yet implemented.");
break;
}
case schema::Type::Body::LIST_TYPE: { FAIL_CHECK("switch() missing case.", type.which());
auto elementType = type.getListType(); return DynamicValue::Reader();
return DynamicValue::Reader(DynamicList::Reader(
pool, elementType,
reader.getListField(field.getOffset() * REFERENCES,
elementSizeFor(elementType.getBody().which()),
dval.getListValue<internal::TrustedMessage>())));
} }
case schema::Type::Body::STRUCT_TYPE: {
return DynamicValue::Reader(DynamicStruct::Reader(
pool, pool->getStruct(type.getStructType()),
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>())));
}
case schema::Type::Body::INTERFACE_TYPE:
FAIL_CHECK("Interfaces not yet implemented.");
break;
} }
FAIL_CHECK("switch() missing case.", type.which()); FAIL_CHECK("switch() missing case.", member.getBody().which());
return DynamicValue::Reader(); return DynamicValue::Reader();
} }
DynamicValue::Builder DynamicStruct::Builder::getFieldImpl( DynamicValue::Builder DynamicStruct::Builder::getImpl(
const SchemaPool* pool, internal::StructBuilder builder, const SchemaPool* pool, internal::StructBuilder builder,
schema::StructNode::Field::Reader field) { schema::StructNode::Member::Reader member) {
auto type = field.getType().getBody(); switch (member.getBody().which()) {
auto dval = field.getDefaultValue().getBody(); case schema::StructNode::Member::Body::UNION_MEMBER:
return DynamicUnion::Builder(pool, member, builder);
switch (type.which()) { case schema::StructNode::Member::Body::FIELD_MEMBER: {
case schema::Type::Body::VOID_TYPE: auto field = member.getBody().getFieldMember();
return DynamicValue::Builder(builder.getDataField<Void>(field.getOffset() * ELEMENTS)); auto type = field.getType().getBody();
auto dval = field.getDefaultValue().getBody();
switch (type.which()) {
case schema::Type::Body::VOID_TYPE:
return DynamicValue::Builder(builder.getDataField<Void>(field.getOffset() * ELEMENTS));
#define HANDLE_TYPE(discrim, titleCase, type) \ #define HANDLE_TYPE(discrim, titleCase, type) \
case schema::Type::Body::discrim##_TYPE: \ case schema::Type::Body::discrim##_TYPE: \
return DynamicValue::Builder(builder.getDataField<type>( \ return DynamicValue::Builder(builder.getDataField<type>( \
field.getOffset() * ELEMENTS, \ field.getOffset() * ELEMENTS, \
bitCast<typename internal::MaskType<type>::Type>(dval.get##titleCase##Value()))); bitCast<typename internal::MaskType<type>::Type>(dval.get##titleCase##Value())));
HANDLE_TYPE(BOOL, Bool, bool) HANDLE_TYPE(BOOL, Bool, bool)
HANDLE_TYPE(INT8, Int8, int8_t) HANDLE_TYPE(INT8, Int8, int8_t)
HANDLE_TYPE(INT16, Int16, int16_t) HANDLE_TYPE(INT16, Int16, int16_t)
HANDLE_TYPE(INT32, Int32, int32_t) HANDLE_TYPE(INT32, Int32, int32_t)
HANDLE_TYPE(INT64, Int64, int64_t) HANDLE_TYPE(INT64, Int64, int64_t)
HANDLE_TYPE(UINT8, Uint8, uint8_t) HANDLE_TYPE(UINT8, Uint8, uint8_t)
HANDLE_TYPE(UINT16, Uint16, uint16_t) HANDLE_TYPE(UINT16, Uint16, uint16_t)
HANDLE_TYPE(UINT32, Uint32, uint32_t) HANDLE_TYPE(UINT32, Uint32, uint32_t)
HANDLE_TYPE(UINT64, Uint64, uint64_t) HANDLE_TYPE(UINT64, Uint64, uint64_t)
HANDLE_TYPE(FLOAT32, Float32, float) HANDLE_TYPE(FLOAT32, Float32, float)
HANDLE_TYPE(FLOAT64, Float64, double) HANDLE_TYPE(FLOAT64, Float64, double)
#undef HANDLE_TYPE #undef HANDLE_TYPE
case schema::Type::Body::ENUM_TYPE: { case schema::Type::Body::ENUM_TYPE: {
uint16_t typedDval; uint16_t typedDval;
typedDval = dval.getEnumValue(); typedDval = dval.getEnumValue();
return DynamicValue::Builder(DynamicEnum( return DynamicValue::Builder(DynamicEnum(
pool, pool->getEnum(type.getEnumType()), pool, pool->getEnum(type.getEnumType()),
builder.getDataField<uint16_t>(field.getOffset() * ELEMENTS, typedDval))); builder.getDataField<uint16_t>(field.getOffset() * ELEMENTS, typedDval)));
} }
case schema::Type::Body::TEXT_TYPE: { case schema::Type::Body::TEXT_TYPE: {
Text::Reader typedDval = dval.getTextValue(); Text::Reader typedDval = dval.getTextValue();
return DynamicValue::Builder( return DynamicValue::Builder(
builder.getBlobField<Text>(field.getOffset() * REFERENCES, builder.getBlobField<Text>(field.getOffset() * REFERENCES,
typedDval.data(), typedDval.size() * BYTES)); typedDval.data(), typedDval.size() * BYTES));
} }
case schema::Type::Body::DATA_TYPE: { case schema::Type::Body::DATA_TYPE: {
Data::Reader typedDval = dval.getDataValue(); Data::Reader typedDval = dval.getDataValue();
return DynamicValue::Builder( return DynamicValue::Builder(
builder.getBlobField<Data>(field.getOffset() * REFERENCES, builder.getBlobField<Data>(field.getOffset() * REFERENCES,
typedDval.data(), typedDval.size() * BYTES)); typedDval.data(), typedDval.size() * BYTES));
} }
case schema::Type::Body::LIST_TYPE: { case schema::Type::Body::LIST_TYPE: {
auto elementType = type.getListType(); auto elementType = type.getListType();
return DynamicValue::Builder(DynamicList::Builder( return DynamicValue::Builder(DynamicList::Builder(
pool, elementType, pool, elementType,
builder.getListField(field.getOffset() * REFERENCES, builder.getListField(field.getOffset() * REFERENCES,
dval.getListValue<internal::TrustedMessage>()))); dval.getListValue<internal::TrustedMessage>())));
} }
case schema::Type::Body::STRUCT_TYPE: { case schema::Type::Body::STRUCT_TYPE: {
auto structNode = pool->getStruct(type.getStructType()); auto structNode = pool->getStruct(type.getStructType());
auto structSchema = structNode.getBody().getStructNode(); auto structSchema = structNode.getBody().getStructNode();
return DynamicValue::Builder(DynamicStruct::Builder( return DynamicValue::Builder(DynamicStruct::Builder(
pool, structNode, pool, structNode,
builder.getStructField( builder.getStructField(
field.getOffset() * REFERENCES, field.getOffset() * REFERENCES,
internal::StructSize( internal::StructSize(
structSchema.getDataSectionWordSize() * WORDS, structSchema.getDataSectionWordSize() * WORDS,
structSchema.getPointerSectionSize() * REFERENCES, structSchema.getPointerSectionSize() * REFERENCES,
static_cast<internal::FieldSize>(structSchema.getPreferredListEncoding())), static_cast<internal::FieldSize>(structSchema.getPreferredListEncoding())),
dval.getStructValue<internal::TrustedMessage>()))); 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>())));
}
case schema::Type::Body::INTERFACE_TYPE:
FAIL_CHECK("Interfaces not yet implemented.");
break;
}
case schema::Type::Body::OBJECT_TYPE: { FAIL_CHECK("switch() missing case.", type.which());
return DynamicValue::Builder(DynamicObject::Builder( return DynamicValue::Builder();
pool, builder.getObjectField(field.getOffset() * REFERENCES,
dval.getObjectValue<internal::TrustedMessage>())));
} }
case schema::Type::Body::INTERFACE_TYPE:
FAIL_CHECK("Interfaces not yet implemented.");
break;
} }
FAIL_CHECK("switch() missing case.", type.which()); FAIL_CHECK("switch() missing case.", member.getBody().which());
return DynamicValue::Builder(); return DynamicValue::Builder();
} }
void DynamicStruct::Builder::setFieldImpl( void DynamicStruct::Builder::setImpl(
const SchemaPool* pool, internal::StructBuilder builder, const SchemaPool* pool, internal::StructBuilder builder,
schema::StructNode::Field::Reader field, DynamicValue::Reader value) { schema::StructNode::Member::Reader member, DynamicValue::Reader value) {
auto type = field.getType().getBody(); switch (member.getBody().which()) {
auto dval = field.getDefaultValue().getBody(); case schema::StructNode::Member::Body::UNION_MEMBER: {
auto src = value.as<DynamicUnion>();
auto which = src.which();
VALIDATE_INPUT(which != nullptr,
"Trying to copy a union value, but the union's discriminant is not recognized. It "
"was probably constructed using a newer version of the schema.") {
return;
}
setImpl(pool, builder, *which, src.get());
return;
}
switch (type.which()) { case schema::StructNode::Member::Body::FIELD_MEMBER: {
case schema::Type::Body::VOID_TYPE: auto field = member.getBody().getFieldMember();
builder.setDataField<Void>(field.getOffset() * ELEMENTS, value.as<Void>()); auto type = field.getType().getBody();
break; auto dval = field.getDefaultValue().getBody();
#define HANDLE_TYPE(discrim, titleCase, type) \ switch (type.which()) {
case schema::Type::Body::discrim##_TYPE: \ case schema::Type::Body::VOID_TYPE:
builder.setDataField<type>( \ builder.setDataField<Void>(field.getOffset() * ELEMENTS, value.as<Void>());
field.getOffset() * ELEMENTS, value.as<type>(), \ return;
bitCast<internal::Mask<type> >(dval.get##titleCase##Value())); \
break;
HANDLE_TYPE(BOOL, Bool, bool) #define HANDLE_TYPE(discrim, titleCase, type) \
HANDLE_TYPE(INT8, Int8, int8_t) case schema::Type::Body::discrim##_TYPE: \
HANDLE_TYPE(INT16, Int16, int16_t) builder.setDataField<type>( \
HANDLE_TYPE(INT32, Int32, int32_t) field.getOffset() * ELEMENTS, value.as<type>(), \
HANDLE_TYPE(INT64, Int64, int64_t) bitCast<internal::Mask<type> >(dval.get##titleCase##Value())); \
HANDLE_TYPE(UINT8, Uint8, uint8_t) return;
HANDLE_TYPE(UINT16, Uint16, uint16_t)
HANDLE_TYPE(UINT32, Uint32, uint32_t) HANDLE_TYPE(BOOL, Bool, bool)
HANDLE_TYPE(UINT64, Uint64, uint64_t) HANDLE_TYPE(INT8, Int8, int8_t)
HANDLE_TYPE(FLOAT32, Float32, float) HANDLE_TYPE(INT16, Int16, int16_t)
HANDLE_TYPE(FLOAT64, Float64, double) 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 #undef HANDLE_TYPE
case schema::Type::Body::ENUM_TYPE: case schema::Type::Body::ENUM_TYPE:
builder.setDataField<uint16_t>( builder.setDataField<uint16_t>(
field.getOffset() * ELEMENTS, value.as<DynamicEnum>().getRaw(), field.getOffset() * ELEMENTS, value.as<DynamicEnum>().getRaw(),
dval.getEnumValue()); dval.getEnumValue());
break; return;
case schema::Type::Body::TEXT_TYPE: case schema::Type::Body::TEXT_TYPE:
builder.setBlobField<Text>(field.getOffset() * REFERENCES, value.as<Text>()); builder.setBlobField<Text>(field.getOffset() * REFERENCES, value.as<Text>());
break; return;
case schema::Type::Body::DATA_TYPE: case schema::Type::Body::DATA_TYPE:
builder.setBlobField<Data>(field.getOffset() * REFERENCES, value.as<Data>()); builder.setBlobField<Data>(field.getOffset() * REFERENCES, value.as<Data>());
break; return;
case schema::Type::Body::LIST_TYPE: {
// 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())
.as<DynamicList>().copyFrom(listValue);
return;
}
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>()
.copyFrom(value.as<DynamicStruct>());
return;
}
case schema::Type::Body::OBJECT_TYPE: {
// TODO(now): Perform schemaless copy.
FAIL_CHECK("TODO");
return;
}
case schema::Type::Body::INTERFACE_TYPE:
FAIL_CHECK("Interfaces not yet implemented.");
return;
}
case schema::Type::Body::LIST_TYPE: { FAIL_CHECK("switch() missing case.", type.which());
// TODO(now): We need to do a schemaless copy to avoid losing information if the values are return;
// larger than what the schema defines.
auto listValue = value.as<DynamicList>();
initFieldImpl(pool, builder, field, listValue.size()).as<DynamicList>().copyFrom(listValue);
break;
} }
}
case schema::Type::Body::STRUCT_TYPE: { FAIL_CHECK("switch() missing case.", member.getBody().which());
// TODO(now): We need to do a schemaless copy to avoid losing information if the values are }
// larger than what the schema defines.
initFieldImpl(pool, builder, field).as<DynamicStruct>().copyFrom(value.as<DynamicStruct>());
break;
}
case schema::Type::Body::OBJECT_TYPE: { DynamicValue::Builder DynamicStruct::Builder::initImpl(
// TODO(now): Perform schemaless copy. const SchemaPool* pool, internal::StructBuilder builder,
FAIL_CHECK("TODO"); schema::StructNode::Member::Reader member, uint size) {
break; switch (member.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);
case schema::Type::Body::INTERFACE_TYPE: case schema::StructNode::Member::Body::FIELD_MEMBER: {
FAIL_CHECK("Interfaces not yet implemented."); auto field = member.getBody().getFieldMember();
break; return initFieldImpl(pool, builder, field, field.getType(), size);
}
} }
}
DynamicValue::Builder DynamicStruct::Builder::initFieldImpl( FAIL_CHECK("switch() missing case.", member.getBody().which());
const SchemaPool* pool, internal::StructBuilder builder, return getImpl(pool, builder, member);
schema::StructNode::Field::Reader field, uint size) {
return initFieldImpl(pool, builder, field, field.getType(), size);
} }
DynamicValue::Builder DynamicStruct::Builder::initFieldImpl( DynamicValue::Builder DynamicStruct::Builder::initImpl(
const SchemaPool* pool, internal::StructBuilder builder, const SchemaPool* pool, internal::StructBuilder builder,
schema::StructNode::Field::Reader field) { schema::StructNode::Member::Reader member) {
return initFieldImpl(pool, builder, field, field.getType()); switch (member.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);
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( DynamicValue::Builder DynamicStruct::Builder::initFieldImpl(
...@@ -752,7 +904,7 @@ DynamicValue::Builder DynamicStruct::Builder::initFieldImpl( ...@@ -752,7 +904,7 @@ DynamicValue::Builder DynamicStruct::Builder::initFieldImpl(
case schema::Type::Body::STRUCT_TYPE: case schema::Type::Body::STRUCT_TYPE:
case schema::Type::Body::INTERFACE_TYPE: case schema::Type::Body::INTERFACE_TYPE:
FAIL_VALIDATE_INPUT("Expected a list or blob."); FAIL_VALIDATE_INPUT("Expected a list or blob.");
return getFieldImpl(pool, builder, field); return DynamicValue::Builder();
case schema::Type::Body::TEXT_TYPE: case schema::Type::Body::TEXT_TYPE:
return DynamicValue::Builder( return DynamicValue::Builder(
...@@ -813,7 +965,7 @@ DynamicValue::Builder DynamicStruct::Builder::initFieldImpl( ...@@ -813,7 +965,7 @@ DynamicValue::Builder DynamicStruct::Builder::initFieldImpl(
case schema::Type::Body::LIST_TYPE: case schema::Type::Body::LIST_TYPE:
case schema::Type::Body::INTERFACE_TYPE: case schema::Type::Body::INTERFACE_TYPE:
FAIL_VALIDATE_INPUT("Expected a list or blob."); FAIL_VALIDATE_INPUT("Expected a list or blob.");
return getFieldImpl(pool, builder, field); return DynamicValue::Builder();
case schema::Type::Body::STRUCT_TYPE: { case schema::Type::Body::STRUCT_TYPE: {
auto structType = pool->getStruct(type.getBody().getStructType()); auto structType = pool->getStruct(type.getBody().getStructType());
...@@ -1086,6 +1238,14 @@ void DynamicList::Builder::copyFrom(Reader other) { ...@@ -1086,6 +1238,14 @@ void DynamicList::Builder::copyFrom(Reader other) {
FAIL_CHECK("Unimplemented: copyFrom()"); FAIL_CHECK("Unimplemented: copyFrom()");
} }
void DynamicList::Builder::copyFrom(std::initializer_list<DynamicValue::Reader> value) {
PRECOND(value.size() == size(), "DynamicList::copyFrom() argument had different size.");
uint i = 0;
for (auto element: value) {
set(i++, element);
}
}
DynamicList::Reader DynamicList::Builder::asReader() { DynamicList::Reader DynamicList::Builder::asReader() {
return DynamicList::Reader(pool, elementType, depth, elementSchema, builder.asReader()); return DynamicList::Reader(pool, elementType, depth, elementSchema, builder.asReader());
} }
......
...@@ -131,16 +131,13 @@ public: ...@@ -131,16 +131,13 @@ public:
ReaderFor<DynamicTypeFor<FromReader<T>>> toDynamic(T&& value) const; ReaderFor<DynamicTypeFor<FromReader<T>>> toDynamic(T&& value) const;
template <typename T> template <typename T>
BuilderFor<DynamicTypeFor<FromBuilder<T>>> toDynamic(T&& value) const; BuilderFor<DynamicTypeFor<FromBuilder<T>>> toDynamic(T&& value) const;
// Convert an arbitrary struct or list reader or builder type into the equivalent dynamic type. 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: // Example:
// DynamicStruct::Reader foo = pool.toDynamic(myType.getFoo()); // // myStruct has a field named foo that has struct type.
// DynamicStruct::Reader foo = pool.toDynamic(myStruct.getFoo());
template <typename T> DynamicEnum fromEnum(T&& value) const;
template <typename T> DynamicStruct::Reader fromStructReader(T&& reader) const;
template <typename T> DynamicStruct::Builder fromStructBuilder(T&& builder) const;
template <typename T> DynamicList::Reader fromListReader(T&& reader) const;
template <typename T> DynamicList::Builder fromListBuilder(T&& builder) const;
// Convert native types to dynamic types.
private: private:
struct Impl; struct Impl;
...@@ -276,6 +273,7 @@ private: ...@@ -276,6 +273,7 @@ private:
friend struct DynamicStruct; friend struct DynamicStruct;
friend struct DynamicList; friend struct DynamicList;
friend class SchemaPool;
}; };
// ------------------------------------------------------------------- // -------------------------------------------------------------------
...@@ -344,7 +342,8 @@ class DynamicUnion::Reader { ...@@ -344,7 +342,8 @@ class DynamicUnion::Reader {
public: public:
Reader() = default; Reader() = default;
schema::StructNode::Union::Reader getSchema() { return schema; } schema::StructNode::Member::Reader getMemberSchema() { return schema; }
schema::StructNode::Union::Reader getSchema();
Maybe<schema::StructNode::Member::Reader> which(); Maybe<schema::StructNode::Member::Reader> which();
// Returns which field is set, or nullptr if an unknown field is set (i.e. the schema is old, and // Returns which field is set, or nullptr if an unknown field is set (i.e. the schema is old, and
...@@ -355,10 +354,10 @@ public: ...@@ -355,10 +354,10 @@ public:
private: private:
const SchemaPool* pool; const SchemaPool* pool;
schema::StructNode::Union::Reader schema; schema::StructNode::Member::Reader schema;
internal::StructReader reader; internal::StructReader reader;
inline Reader(const SchemaPool* pool, schema::StructNode::Union::Reader schema, inline Reader(const SchemaPool* pool, schema::StructNode::Member::Reader schema,
internal::StructReader reader) internal::StructReader reader)
: pool(pool), schema(schema), reader(reader) {} : pool(pool), schema(schema), reader(reader) {}
...@@ -369,23 +368,24 @@ class DynamicUnion::Builder { ...@@ -369,23 +368,24 @@ class DynamicUnion::Builder {
public: public:
Builder() = default; Builder() = default;
schema::StructNode::Union::Reader getSchema() { return schema; } schema::StructNode::Member::Reader getMemberSchema() { return schema; }
schema::StructNode::Union::Reader getSchema();
Maybe<schema::StructNode::Member::Reader> which(); Maybe<schema::StructNode::Member::Reader> which();
// Returns which field is set, or nullptr if an unknown field is set (i.e. the schema is old, and // 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). // the underlying data has the union set to a member we don't know about).
DynamicValue::Builder get(); DynamicValue::Builder get();
void set(schema::StructNode::Field::Reader field, DynamicValue::Reader value); void set(schema::StructNode::Member::Reader member, DynamicValue::Reader value);
DynamicValue::Builder init(schema::StructNode::Field::Reader field); DynamicValue::Builder init(schema::StructNode::Member::Reader member);
DynamicValue::Builder init(schema::StructNode::Field::Reader field, uint size); DynamicValue::Builder init(schema::StructNode::Member::Reader member, uint size);
private: private:
const SchemaPool* pool; const SchemaPool* pool;
schema::StructNode::Union::Reader schema; schema::StructNode::Member::Reader schema;
internal::StructBuilder builder; internal::StructBuilder builder;
inline Builder(const SchemaPool* pool, schema::StructNode::Union::Reader schema, inline Builder(const SchemaPool* pool, schema::StructNode::Member::Reader schema,
internal::StructBuilder builder) internal::StructBuilder builder)
: pool(pool), schema(schema), builder(builder) {} : pool(pool), schema(schema), builder(builder) {}
...@@ -408,11 +408,11 @@ public: ...@@ -408,11 +408,11 @@ public:
Maybe<schema::StructNode::Member::Reader> findMemberByName(Text::Reader name); 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. // Looks up the member with the given name, or returns nullptr if no such member exists.
DynamicValue::Reader getField(schema::StructNode::Field::Reader field); DynamicValue::Reader get(schema::StructNode::Member::Reader member);
// Returns the value of the given field. // Read the given member value.
DynamicUnion::Reader getUnion(schema::StructNode::Union::Reader un); DynamicValue::Reader get(Text::Reader name);
// Returns the value of the given union. // Shortcut to read a member by name. Throws an exception if no such member exists.
private: private:
const SchemaPool* pool; const SchemaPool* pool;
...@@ -424,9 +424,9 @@ private: ...@@ -424,9 +424,9 @@ private:
void verifyTypeId(uint64_t id); void verifyTypeId(uint64_t id);
static DynamicValue::Reader getFieldImpl( static DynamicValue::Reader getImpl(
const SchemaPool* pool, internal::StructReader reader, const SchemaPool* pool, internal::StructReader reader,
schema::StructNode::Field::Reader field); schema::StructNode::Member::Reader member);
template <typename T> template <typename T>
friend struct internal::PointerHelpers; friend struct internal::PointerHelpers;
...@@ -453,24 +453,32 @@ public: ...@@ -453,24 +453,32 @@ public:
Maybe<schema::StructNode::Member::Reader> findMemberByName(Text::Reader name); 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. // Looks up the member with the given name, or returns nullptr if no such member exists.
DynamicValue::Builder getField(schema::StructNode::Field::Reader field); DynamicValue::Builder get(schema::StructNode::Member::Reader member);
// Returns the value of the given field. // Read the given member value.
void setField(schema::StructNode::Field::Reader field, DynamicValue::Reader value); void set(schema::StructNode::Member::Reader member, DynamicValue::Reader value);
// Sets the value of the given field. // Set the given member value.
DynamicValue::Builder initField(schema::StructNode::Field::Reader field); DynamicValue::Builder init(schema::StructNode::Member::Reader member);
DynamicValue::Builder initField(schema::StructNode::Field::Reader field, uint size); DynamicValue::Builder init(schema::StructNode::Member::Reader member, uint size);
// Initialize a struct or list field by field schema. // Init a struct, list, or blob field.
DynamicValue::Builder initObjectField(schema::StructNode::Field::Reader field, DynamicValue::Builder initObject(schema::StructNode::Member::Reader member,
schema::Type::Reader type); schema::Type::Reader type);
DynamicValue::Builder initObjectField(schema::StructNode::Field::Reader field, DynamicValue::Builder initObject(schema::StructNode::Member::Reader member,
schema::Type::Reader type, uint size); schema::Type::Reader type, uint size);
// Initialize an Object-typed field. You must specify the type to initialize as. // 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
DynamicUnion::Builder getUnion(schema::StructNode::Union::Reader un); // refers to any other types by ID, those types must be present in the SchemaPool.
// Returns the value of the given union.
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);
// Shortcuts to access members by name. These throw exceptions if no such field exists.
void copyFrom(Reader other); void copyFrom(Reader other);
...@@ -487,18 +495,18 @@ private: ...@@ -487,18 +495,18 @@ private:
void verifyTypeId(uint64_t id); void verifyTypeId(uint64_t id);
static DynamicValue::Builder getFieldImpl( static DynamicValue::Builder getImpl(
const SchemaPool* pool, internal::StructBuilder builder, const SchemaPool* pool, internal::StructBuilder builder,
schema::StructNode::Field::Reader field); schema::StructNode::Member::Reader member);
static void setFieldImpl( static void setImpl(
const SchemaPool* pool, internal::StructBuilder builder, const SchemaPool* pool, internal::StructBuilder builder,
schema::StructNode::Field::Reader field, DynamicValue::Reader value); schema::StructNode::Member::Reader member, DynamicValue::Reader value);
static DynamicValue::Builder initFieldImpl( static DynamicValue::Builder initImpl(
const SchemaPool* pool, internal::StructBuilder builder, const SchemaPool* pool, internal::StructBuilder builder,
schema::StructNode::Field::Reader field, uint size); schema::StructNode::Member::Reader member, uint size);
static DynamicValue::Builder initFieldImpl( static DynamicValue::Builder initImpl(
const SchemaPool* pool, internal::StructBuilder builder, const SchemaPool* pool, internal::StructBuilder builder,
schema::StructNode::Field::Reader field); schema::StructNode::Member::Reader member);
static DynamicValue::Builder initFieldImpl( static DynamicValue::Builder initFieldImpl(
const SchemaPool* pool, internal::StructBuilder builder, const SchemaPool* pool, internal::StructBuilder builder,
schema::StructNode::Field::Reader field, schema::StructNode::Field::Reader field,
...@@ -590,6 +598,7 @@ public: ...@@ -590,6 +598,7 @@ public:
inline iterator end() { return iterator(this, size()); } inline iterator end() { return iterator(this, size()); }
void copyFrom(Reader other); void copyFrom(Reader other);
void copyFrom(std::initializer_list<DynamicValue::Reader> value);
Reader asReader(); Reader asReader();
...@@ -849,6 +858,10 @@ template <typename T> ...@@ -849,6 +858,10 @@ template <typename T>
BuilderFor<DynamicTypeFor<FromBuilder<T>>> SchemaPool::toDynamic(T&& value) const { BuilderFor<DynamicTypeFor<FromBuilder<T>>> SchemaPool::toDynamic(T&& value) const {
return ToDynamicImpl<FromBuilder<T>>::apply(this, value); return ToDynamicImpl<FromBuilder<T>>::apply(this, value);
} }
template <typename T>
DynamicTypeFor<TypeIfEnum<T>> SchemaPool::toDynamic(T&& value) const {
return DynamicEnum(this, getEnum(typeId<T>()), static_cast<uint16_t>(value));
}
#define CAPNPROTO_DECLARE_DYNAMIC_VALUE_CONSTRUCTOR(cppType, typeTag, fieldName) \ #define CAPNPROTO_DECLARE_DYNAMIC_VALUE_CONSTRUCTOR(cppType, typeTag, fieldName) \
inline DynamicValue::Reader::Reader(cppType value) \ inline DynamicValue::Reader::Reader(cppType value) \
...@@ -1016,25 +1029,25 @@ typename T::Builder DynamicStruct::Builder::as() { ...@@ -1016,25 +1029,25 @@ typename T::Builder DynamicStruct::Builder::as() {
return typename T::Builder(builder); return typename T::Builder(builder);
} }
inline DynamicValue::Reader DynamicStruct::Reader::getField( inline DynamicValue::Reader DynamicStruct::Reader::get(
schema::StructNode::Field::Reader field) { schema::StructNode::Member::Reader member) {
return getFieldImpl(pool, reader, field); return getImpl(pool, reader, member);
} }
inline DynamicValue::Builder DynamicStruct::Builder::getField( inline DynamicValue::Builder DynamicStruct::Builder::get(
schema::StructNode::Field::Reader field) { schema::StructNode::Member::Reader member) {
return getFieldImpl(pool, builder, field); return getImpl(pool, builder, member);
} }
inline void DynamicStruct::Builder::setField( inline void DynamicStruct::Builder::set(
schema::StructNode::Field::Reader field, DynamicValue::Reader value) { schema::StructNode::Member::Reader member, DynamicValue::Reader value) {
return setFieldImpl(pool, builder, field, value); return setImpl(pool, builder, member, value);
} }
inline DynamicValue::Builder DynamicStruct::Builder::initField( inline DynamicValue::Builder DynamicStruct::Builder::init(
schema::StructNode::Field::Reader field) { schema::StructNode::Member::Reader member) {
return initFieldImpl(pool, builder, field); return initImpl(pool, builder, member);
} }
inline DynamicValue::Builder DynamicStruct::Builder::initField( inline DynamicValue::Builder DynamicStruct::Builder::init(
schema::StructNode::Field::Reader field, uint size) { schema::StructNode::Member::Reader member, uint size) {
return initFieldImpl(pool, builder, field, size); return initImpl(pool, builder, member, size);
} }
inline DynamicStruct::Reader DynamicStruct::Builder::asReader() { inline DynamicStruct::Reader DynamicStruct::Builder::asReader() {
......
...@@ -70,6 +70,12 @@ template <typename T> ...@@ -70,6 +70,12 @@ template <typename T>
using FromBuilder = typename RemoveReference<T>::Builds; using FromBuilder = typename RemoveReference<T>::Builds;
// FromBuilder<MyType::Builder> = MyType (for any Cap'n Proto type). // FromBuilder<MyType::Builder> = MyType (for any Cap'n Proto type).
template <typename T, Kind k = kind<T>()> struct TypeIfEnum_;
template <typename T> struct TypeIfEnum_<T, Kind::ENUM> { typedef T Type; };
template <typename T>
using TypeIfEnum = typename TypeIfEnum_<RemoveReference<T>>::Type;
namespace internal { namespace internal {
template <typename T, Kind k> struct KindOf<List<T, k>> { static constexpr Kind kind = Kind::LIST; }; template <typename T, Kind k> struct KindOf<List<T, k>> { static constexpr Kind kind = Kind::LIST; };
...@@ -229,11 +235,11 @@ struct List<T, Kind::PRIMITIVE> { ...@@ -229,11 +235,11 @@ struct List<T, Kind::PRIMITIVE> {
set(pos, *i); set(pos, *i);
} }
CAPNPROTO_INLINE_DPRECOND(pos == size() && i == end, CAPNPROTO_INLINE_DPRECOND(pos == size() && i == end,
"List::copyFrom() argument had different size."); "List::copyFrom() argument had different size.");
} }
void copyFrom(std::initializer_list<T> other) { void copyFrom(std::initializer_list<T> other) {
CAPNPROTO_INLINE_DPRECOND(other.size() == size(), CAPNPROTO_INLINE_DPRECOND(other.size() == size(),
"List::copyFrom() argument had different size."); "List::copyFrom() argument had different size.");
for (uint i = 0; i < other.size(); i++) { for (uint i = 0; i < other.size(); i++) {
set(i, other.begin()[i]); set(i, other.begin()[i]);
} }
......
...@@ -198,6 +198,11 @@ struct StructNode { ...@@ -198,6 +198,11 @@ struct StructNode {
ordinal @1 :UInt16; ordinal @1 :UInt16;
index @7 :UInt16;
# The index of this member within the containing struct or union's member list. This is
# redundant information, but it can be useful for the dynamic API which has methods that take
# a Member pointer to specify on which member to act.
codeOrder @2 :UInt16; codeOrder @2 :UInt16;
# Indicates where this member appeared in the code, relative to other members. # Indicates where this member appeared in the code, relative to other members.
# Code ordering may have semantic relevance -- programmers tend to place related fields # Code ordering may have semantic relevance -- programmers tend to place related fields
...@@ -219,11 +224,6 @@ struct StructNode { ...@@ -219,11 +224,6 @@ struct StructNode {
} }
struct Field { struct Field {
index @3 :UInt16;
# The index of this field within the containing struct or union's member list. This is
# redundant information, but it can be useful for the dynamic API which uses Field pointers as
# identifiers.
offset @0 :UInt32; offset @0 :UInt32;
# Offset, in units of the field's size, from the beginning of the section in which the field # Offset, in units of the field's size, from the beginning of the section in which the field
# resides. E.g. for a UInt32 field, multiply this by 4 to get the byte offset from the # resides. E.g. for a UInt32 field, multiply this by 4 to get the byte offset from the
......
...@@ -617,15 +617,15 @@ encodeSchema requestedFiles allFiles = (encRoot, nodesForEmbedding) where ...@@ -617,15 +617,15 @@ encodeSchema requestedFiles allFiles = (encRoot, nodesForEmbedding) where
dataValues2 = [ (0, encUInt16 $ fieldNumber field) dataValues2 = [ (0, encUInt16 $ fieldNumber field)
, (16, encUInt16 codeOrder) , (16, encUInt16 codeOrder)
, (32, encUInt16 (0::Word16)) -- discriminant , (32, encUInt16 (0::Word16)) -- discriminant
, (48, encUInt16 index)
] ]
ptrValues2 = [ (0, encText $ fieldName field) ptrValues2 = [ (0, encText $ fieldName field)
, (1, encAnnotationList $ fieldAnnotations field) , (1, encAnnotationList $ fieldAnnotations field)
, (2, encStruct (DataSectionWords 1, 2) (dataValues3, ptrValues3)) , (2, encStruct (DataSection32, 2) (dataValues3, ptrValues3))
] ]
-- StructNode.Field -- StructNode.Field
dataValues3 = [ (0, encUInt32 $ offsetToInt $ fieldOffset field) dataValues3 = [ (0, encUInt32 $ offsetToInt $ fieldOffset field) ]
, (32, encUInt16 index) ]
ptrValues3 = [ (0, encStruct typeSize $ encType $ fieldType field) ptrValues3 = [ (0, encStruct typeSize $ encType $ fieldType field)
, (1, encStruct valueSize $ encValue (fieldType field) $ , (1, encStruct valueSize $ encValue (fieldType field) $
fieldDefaultValue field) fieldDefaultValue field)
...@@ -637,10 +637,11 @@ encodeSchema requestedFiles allFiles = (encRoot, nodesForEmbedding) where ...@@ -637,10 +637,11 @@ encodeSchema requestedFiles allFiles = (encRoot, nodesForEmbedding) where
offsetToInt (InlineCompositeOffset {}) = offsetToInt (InlineCompositeOffset {}) =
error "Inline types not currently supported by codegen plugins." error "Inline types not currently supported by codegen plugins."
encMember _ (codeOrder, (_, DescUnion union)) = (dataValues2, ptrValues2) where encMember index (codeOrder, (_, DescUnion union)) = (dataValues2, ptrValues2) where
dataValues2 = [ (0, encUInt16 $ unionNumber union) dataValues2 = [ (0, encUInt16 $ unionNumber union)
, (16, encUInt16 codeOrder) , (16, encUInt16 codeOrder)
, (32, encUInt16 (1::Word16)) -- discriminant , (32, encUInt16 (1::Word16)) -- discriminant
, (48, encUInt16 index)
] ]
ptrValues2 = [ (0, encText $ unionName union) ptrValues2 = [ (0, encText $ unionName union)
, (1, encAnnotationList $ unionAnnotations union) , (1, encAnnotationList $ unionAnnotations union)
......
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