Commit 35adf54b authored by Kenton Varda's avatar Kenton Varda

Implement ability to set() struct and list fields by deep-copying from a…

Implement ability to set() struct and list fields by deep-copying from a corresponding Reader.  This copy requires no schema knowledge.
parent d43aec91
......@@ -509,12 +509,6 @@ Data::Builder DynamicStruct::Builder::initObjectAsData(Text::Reader name, uint s
return initObjectAsText(schema.getMemberByName(name), size);
}
void DynamicStruct::Builder::copyFrom(Reader other) {
// TODO(now): copyFrom on StructBuilder.
// TODO(now): don't forget to check types match.
FAIL_CHECK("Unimplemented: copyFrom()");
}
DynamicValue::Reader DynamicStruct::Reader::getImpl(
internal::StructReader reader, StructSchema::Member member) {
switch (member.getProto().getBody().which()) {
......@@ -821,25 +815,17 @@ void DynamicStruct::Builder::setImpl(
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(builder, member, listValue.size())
.as<DynamicList>().copyFrom(listValue);
builder.setListField(field.getOffset() * POINTERS, value.as<DynamicList>().reader);
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(builder, member).as<DynamicStruct>()
.copyFrom(value.as<DynamicStruct>());
builder.setStructField(field.getOffset() * POINTERS, value.as<DynamicStruct>().reader);
return;
}
case schema::Type::Body::OBJECT_TYPE: {
// TODO(now): Perform schemaless copy.
FAIL_CHECK("TODO");
builder.setObjectField(field.getOffset() * POINTERS, value.as<DynamicObject>().reader);
return;
}
......@@ -1094,17 +1080,15 @@ void DynamicList::Builder::set(uint index, DynamicValue::Reader value) {
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);
builder.setListElement(index * ELEMENTS, value.as<DynamicList>().reader);
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>());
// Not supported for the same reason List<struct> doesn't support it -- the space for the
// element is already allocated, and if it's smaller than the input value the copy would
// have to be lossy.
FAIL_RECOVERABLE_CHECK("DynamicList of structs does not support set().");
break;
case schema::Type::Body::ENUM_TYPE: {
......@@ -1188,12 +1172,6 @@ DynamicValue::Builder DynamicList::Builder::init(uint index, uint size) {
return DynamicValue::Builder();
}
void DynamicList::Builder::copyFrom(Reader other) {
// TODO(now): copyFrom on ListBuilder.
// TODO(now): don't forget to check types match.
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;
......@@ -1401,8 +1379,7 @@ DynamicStruct::Builder PointerHelpers<DynamicStruct, Kind::UNKNOWN>::getDynamic(
}
void PointerHelpers<DynamicStruct, Kind::UNKNOWN>::set(
StructBuilder builder, WirePointerCount index, DynamicStruct::Reader value) {
// TODO(now): schemaless copy
FAIL_CHECK("Unimplemented: copyFrom()");
builder.setStructField(index, value.reader);
}
DynamicStruct::Builder PointerHelpers<DynamicStruct, Kind::UNKNOWN>::init(
StructBuilder builder, WirePointerCount index, StructSchema schema) {
......@@ -1429,8 +1406,7 @@ DynamicList::Builder PointerHelpers<DynamicList, Kind::UNKNOWN>::getDynamic(
}
void PointerHelpers<DynamicList, Kind::UNKNOWN>::set(
StructBuilder builder, WirePointerCount index, DynamicList::Reader value) {
// TODO(now): schemaless copy
FAIL_CHECK("Unimplemented: copyFrom()");
builder.setListField(index, value.reader);
}
DynamicList::Builder PointerHelpers<DynamicList, Kind::UNKNOWN>::init(
StructBuilder builder, WirePointerCount index, ListSchema schema, uint size) {
......
......@@ -333,8 +333,6 @@ public:
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);
Reader asReader();
private:
......@@ -446,7 +444,6 @@ public:
inline iterator begin() { return iterator(this, 0); }
inline iterator end() { return iterator(this, size()); }
void copyFrom(Reader other);
void copyFrom(std::initializer_list<DynamicValue::Reader> value);
Reader asReader();
......
This diff is collapsed.
......@@ -31,6 +31,8 @@
namespace capnproto {
class MessageBuilder; // So that it can be declared a friend.
template <typename T, Kind k = kind<T>()>
struct ToDynamic_; // Defined in dynamic.h, needs to be declared as everyone's friend.
......@@ -50,8 +52,7 @@ struct PointerHelpers<T, Kind::STRUCT> {
}
static inline void set(StructBuilder builder, WirePointerCount index,
typename T::Reader value) {
// TODO(now): schemaless copy
CAPNPROTO_INLINE_PRECOND(false, "Not implemented: set() for struct fields.");
builder.setStructField(index, value._reader);
}
static inline typename T::Builder init(StructBuilder builder, WirePointerCount index) {
return typename T::Builder(builder.initStructField(index, structSize<T>()));
......@@ -70,11 +71,15 @@ struct PointerHelpers<List<T>, Kind::LIST> {
}
static inline void set(StructBuilder builder, WirePointerCount index,
typename List<T>::Reader value) {
init(builder, index, value.size()).copyFrom(value);
builder.setListField(index, value.reader);
}
static inline void set(StructBuilder builder, WirePointerCount index,
std::initializer_list<ReaderFor<T>> value) {
init(builder, index, value.size()).copyFrom(value);
template <typename U>
static void set(StructBuilder builder, WirePointerCount index, std::initializer_list<U> value) {
auto l = init(builder, index, value.size());
uint i = 0;
for (auto& element: value) {
l.set(i++, element);
}
}
static inline typename List<T>::Builder init(
StructBuilder builder, WirePointerCount index, uint size) {
......
......@@ -1070,6 +1070,104 @@ struct WireHelpers {
}
}
static void setStructPointer(SegmentBuilder* segment, WirePointer* ref, StructReader value) {
WordCount dataSize = roundUpToWords(value.dataSize);
WordCount totalSize = dataSize + value.pointerCount * WORDS_PER_POINTER;
word* ptr = allocate(ref, segment, totalSize, WirePointer::STRUCT);
ref->structRef.set(dataSize, value.pointerCount);
if (value.dataSize == 1 * BITS) {
*reinterpret_cast<char*>(ptr) = value.getDataField<bool>(0 * ELEMENTS);
} else {
memcpy(ptr, value.data, value.dataSize / BITS_PER_BYTE / BYTES);
}
WirePointer* pointerSection = reinterpret_cast<WirePointer*>(ptr + dataSize);
for (uint i = 0; i < value.pointerCount / POINTERS; i++) {
setObjectPointer(segment, pointerSection + i, readObjectPointer(
value.segment, value.pointers + i, nullptr, value.nestingLimit));
}
}
static void setListPointer(SegmentBuilder* segment, WirePointer* ref, ListReader value) {
WordCount totalSize = roundUpToWords(value.elementCount * value.step);
if (value.step * ELEMENTS <= BITS_PER_WORD * WORDS) {
// List of non-structs.
word* ptr = allocate(ref, segment, totalSize, WirePointer::LIST);
if (value.structPointerCount == 1 * POINTERS) {
// List of pointers.
ref->listRef.set(FieldSize::POINTER, value.elementCount);
for (uint i = 0; i < value.elementCount / ELEMENTS; i++) {
setObjectPointer(segment, reinterpret_cast<WirePointer*>(ptr) + i, readObjectPointer(
value.segment, reinterpret_cast<const WirePointer*>(value.ptr) + i,
nullptr, value.nestingLimit));
}
} else {
// List of data.
FieldSize elementSize = FieldSize::VOID;
switch (value.step * ELEMENTS / BITS) {
case 0: elementSize = FieldSize::VOID; break;
case 1: elementSize = FieldSize::BIT; break;
case 8: elementSize = FieldSize::BYTE; break;
case 16: elementSize = FieldSize::TWO_BYTES; break;
case 32: elementSize = FieldSize::FOUR_BYTES; break;
case 64: elementSize = FieldSize::EIGHT_BYTES; break;
default:
FAIL_CHECK("invalid list step size", value.step * ELEMENTS / BITS);
break;
}
ref->listRef.set(elementSize, value.elementCount);
memcpy(ptr, value.ptr, totalSize * BYTES_PER_WORD / BYTES);
}
} else {
// List of structs.
word* ptr = allocate(ref, segment, totalSize + POINTER_SIZE_IN_WORDS, WirePointer::LIST);
ref->listRef.setInlineComposite(totalSize);
WordCount dataSize = roundUpToWords(value.structDataSize);
WirePointerCount pointerCount = value.structPointerCount;
WirePointer* tag = reinterpret_cast<WirePointer*>(ptr);
tag->setKindAndInlineCompositeListElementCount(WirePointer::STRUCT, value.elementCount);
tag->structRef.set(dataSize, pointerCount);
ptr += POINTER_SIZE_IN_WORDS;
const word* src = reinterpret_cast<const word*>(value.ptr);
for (uint i = 0; i < value.elementCount / ELEMENTS; i++) {
memcpy(ptr, src, value.structDataSize / BITS_PER_BYTE / BYTES);
ptr += dataSize;
src += dataSize;
for (uint j = 0; j < pointerCount / POINTERS; j++) {
setObjectPointer(segment, reinterpret_cast<WirePointer*>(ptr), readObjectPointer(
value.segment, reinterpret_cast<const WirePointer*>(src), nullptr,
value.nestingLimit));
ptr += POINTER_SIZE_IN_WORDS;
src += POINTER_SIZE_IN_WORDS;
}
}
}
}
static CAPNPROTO_ALWAYS_INLINE(void setObjectPointer(
SegmentBuilder* segment, WirePointer* ref, ObjectReader value)) {
switch (value.kind) {
case ObjectKind::NULL_POINTER:
memset(ref, 0, sizeof(*ref));
break;
case ObjectKind::STRUCT:
setStructPointer(segment, ref, value.structReader);
break;
case ObjectKind::LIST:
setListPointer(segment, ref, value.listReader);
break;
}
}
// -----------------------------------------------------------------
static CAPNPROTO_ALWAYS_INLINE(StructReader readStructPointer(
......@@ -1377,12 +1475,15 @@ struct WireHelpers {
}
}
static CAPNPROTO_ALWAYS_INLINE(ObjectReader readObjectPointer(
static ObjectReader readObjectPointer(
SegmentReader* segment, const WirePointer* ref,
const word* defaultValue, int nestingLimit)) {
const word* defaultValue, int nestingLimit) {
// We can't really reuse readStructPointer() and readListPointer() because they are designed
// for the case where we are expecting a specific type, and they do validation around that,
// whereas this method is for the case where we accept any pointer.
//
// Not always-inline because it is called from several places in the copying code, and anyway
// is relatively rarely used.
const word* ptr;
if (ref == nullptr || ref->isNull()) {
......@@ -1498,6 +1599,10 @@ StructBuilder StructBuilder::initRoot(
reinterpret_cast<WirePointer*>(location), segment, size);
}
void StructBuilder::setRoot(SegmentBuilder* segment, word* location, StructReader value) {
return WireHelpers::setStructPointer(segment, reinterpret_cast<WirePointer*>(location), value);
}
StructBuilder StructBuilder::getRoot(
SegmentBuilder* segment, word* location, StructSize size) {
return WireHelpers::getWritableStructPointer(
......@@ -1575,6 +1680,18 @@ ObjectBuilder StructBuilder::getObjectField(
return WireHelpers::getWritableObjectPointer(segment, pointers + ptrIndex, defaultValue);
}
void StructBuilder::setStructField(WirePointerCount ptrIndex, StructReader value) const {
return WireHelpers::setStructPointer(segment, pointers + ptrIndex, value);
}
void StructBuilder::setListField(WirePointerCount ptrIndex, ListReader value) const {
return WireHelpers::setListPointer(segment, pointers + ptrIndex, value);
}
void StructBuilder::setObjectField(WirePointerCount ptrIndex, ObjectReader value) const {
return WireHelpers::setObjectPointer(segment, pointers + ptrIndex, value);
}
StructReader StructBuilder::asReader() const {
return StructReader(segment, data, pointers,
dataSize, pointerCount, bit0Offset, std::numeric_limits<int>::max());
......@@ -1743,6 +1860,16 @@ ObjectBuilder ListBuilder::getObjectElement(ElementCount index) const {
segment, reinterpret_cast<WirePointer*>(ptr + index * step / BITS_PER_BYTE), nullptr);
}
void ListBuilder::setListElement(ElementCount index, ListReader value) const {
return WireHelpers::setListPointer(
segment, reinterpret_cast<WirePointer*>(ptr + index * step / BITS_PER_BYTE), value);
}
void ListBuilder::setObjectElement(ElementCount index, ObjectReader value) const {
return WireHelpers::setObjectPointer(
segment, reinterpret_cast<WirePointer*>(ptr + index * step / BITS_PER_BYTE), value);
}
ListReader ListBuilder::asReader() const {
return ListReader(segment, ptr, elementCount, step, structDataSize, structPointerCount,
std::numeric_limits<int>::max());
......
......@@ -296,6 +296,7 @@ public:
inline StructBuilder(): segment(nullptr), data(nullptr), pointers(nullptr), bit0Offset(0) {}
static StructBuilder initRoot(SegmentBuilder* segment, word* location, StructSize size);
static void setRoot(SegmentBuilder* segment, word* location, StructReader value);
static StructBuilder getRoot(SegmentBuilder* segment, word* location, StructSize size);
inline BitCount getDataSectionSize() const { return dataSize; }
......@@ -376,6 +377,11 @@ public:
ObjectBuilder getObjectField(WirePointerCount ptrIndex, const word* defaultValue) const;
// Read a pointer of arbitrary type.
void setStructField(WirePointerCount ptrIndex, StructReader value) const;
void setListField(WirePointerCount ptrIndex, ListReader value) const;
void setObjectField(WirePointerCount ptrIndex, ObjectReader value) const;
// Sets a pointer field to a deep copy of the given value.
StructReader asReader() const;
// Gets a StructReader pointing at the same memory.
......@@ -555,6 +561,10 @@ public:
ObjectBuilder getObjectElement(ElementCount index) const;
// Gets a pointer element of arbitrary type.
void setListElement(ElementCount index, ListReader value) const;
void setObjectElement(ElementCount index, ObjectReader value) const;
// Sets a pointer element to a deep copy of the given value.
ListReader asReader() const;
// Get a ListReader pointing at the same memory.
......
......@@ -199,6 +199,10 @@ struct List<T, Kind::PRIMITIVE> {
private:
internal::ListReader reader;
template <typename U, Kind K>
friend struct internal::PointerHelpers;
template <typename U, Kind K>
friend struct List;
};
class Builder {
......@@ -208,6 +212,9 @@ struct List<T, Kind::PRIMITIVE> {
Builder() = default;
inline explicit Builder(internal::ListBuilder builder): builder(builder) {}
inline operator Reader() { return Reader(builder.asReader()); }
inline Reader asReader() { return Reader(builder.asReader()); }
inline uint size() const { return builder.size() / ELEMENTS; }
inline T operator[](uint index) const {
return builder.template getDataElement<T>(index * ELEMENTS);
......@@ -226,25 +233,6 @@ struct List<T, Kind::PRIMITIVE> {
inline iterator begin() const { return iterator(this, 0); }
inline iterator end() const { return iterator(this, size()); }
template <typename Other>
void copyFrom(const Other& other) {
auto i = other.begin();
auto end = other.end();
uint pos = 0;
for (; i != end && pos < size(); ++i) {
set(pos, *i);
}
CAPNPROTO_INLINE_DPRECOND(pos == size() && i == end,
"List::copyFrom() argument had different size.");
}
void copyFrom(std::initializer_list<T> other) {
CAPNPROTO_INLINE_DPRECOND(other.size() == size(),
"List::copyFrom() argument had different size.");
for (uint i = 0; i < other.size(); i++) {
set(i, other.begin()[i]);
}
}
private:
internal::ListBuilder builder;
};
......@@ -308,6 +296,10 @@ struct List<T, Kind::STRUCT> {
private:
internal::ListReader reader;
template <typename U, Kind K>
friend struct internal::PointerHelpers;
template <typename U, Kind K>
friend struct List;
};
class Builder {
......@@ -317,20 +309,23 @@ struct List<T, Kind::STRUCT> {
Builder() = default;
inline explicit Builder(internal::ListBuilder builder): builder(builder) {}
inline operator Reader() { return Reader(builder.asReader()); }
inline Reader asReader() { return Reader(builder.asReader()); }
inline uint size() const { return builder.size() / ELEMENTS; }
inline typename T::Builder operator[](uint index) const {
return typename T::Builder(builder.getStructElement(index * ELEMENTS));
}
// There are no init() or set() methods for lists of structs because the elements of the list
// are inlined and are initialized when the list is initialized. This means that init() would
// be redundant, and set() would risk data loss if the input struct were from a newer version
// of teh protocol.
typedef internal::IndexingIterator<Builder, typename T::Builder> iterator;
inline iterator begin() const { return iterator(this, 0); }
inline iterator end() const { return iterator(this, size()); }
template <typename Other>
void copyFrom(const Other& other);
void copyFrom(std::initializer_list<typename T::Reader> other);
// TODO
private:
internal::ListBuilder builder;
};
......@@ -391,6 +386,10 @@ struct List<List<T>, Kind::LIST> {
private:
internal::ListReader reader;
template <typename U, Kind K>
friend struct internal::PointerHelpers;
template <typename U, Kind K>
friend struct List;
};
class Builder {
......@@ -400,6 +399,9 @@ struct List<List<T>, Kind::LIST> {
Builder() = default;
inline explicit Builder(internal::ListBuilder builder): builder(builder) {}
inline operator Reader() { return Reader(builder.asReader()); }
inline Reader asReader() { return Reader(builder.asReader()); }
inline uint size() const { return builder.size() / ELEMENTS; }
inline typename List<T>::Builder operator[](uint index) const {
return typename List<T>::Builder(List<T>::getAsElementOf(builder, index));
......@@ -407,16 +409,21 @@ struct List<List<T>, Kind::LIST> {
inline typename List<T>::Builder init(uint index, uint size) {
return typename List<T>::Builder(List<T>::initAsElementOf(builder, index, size));
}
inline void set(uint index, typename List<T>::Reader value) {
builder.setListElement(index * ELEMENTS, value.reader);
}
void set(uint index, std::initializer_list<ReaderFor<T>> value) {
auto l = init(index, value.size());
uint i = 0;
for (auto& element: value) {
l.set(i++, element);
}
}
typedef internal::IndexingIterator<Builder, typename List<T>::Builder> iterator;
inline iterator begin() const { return iterator(this, 0); }
inline iterator end() const { return iterator(this, size()); }
template <typename Other>
void copyFrom(const Other& other);
void copyFrom(std::initializer_list<typename List<T>::Reader> other);
// TODO
private:
internal::ListBuilder builder;
};
......@@ -475,6 +482,10 @@ struct List<T, Kind::BLOB> {
private:
internal::ListReader reader;
template <typename U, Kind K>
friend struct internal::PointerHelpers;
template <typename U, Kind K>
friend struct List;
};
class Builder {
......@@ -484,6 +495,9 @@ struct List<T, Kind::BLOB> {
Builder() = default;
inline explicit Builder(internal::ListBuilder builder): builder(builder) {}
inline operator Reader() { return Reader(builder.asReader()); }
inline Reader asReader() { return Reader(builder.asReader()); }
inline uint size() const { return builder.size() / ELEMENTS; }
inline typename T::Builder operator[](uint index) const {
return builder.getBlobElement<T>(index * ELEMENTS);
......@@ -499,25 +513,6 @@ struct List<T, Kind::BLOB> {
inline iterator begin() const { return iterator(this, 0); }
inline iterator end() const { return iterator(this, size()); }
template <typename Other>
void copyFrom(const Other& other) {
auto i = other.begin();
auto end = other.end();
uint pos = 0;
for (; i != end && pos < size(); ++i) {
set(pos, *i);
}
CAPNPROTO_INLINE_DPRECOND(pos == size() && i == end,
"List::copyFrom() argument had different size.");
}
void copyFrom(std::initializer_list<typename T::Reader> other) {
CAPNPROTO_INLINE_DPRECOND(other.size() == size(),
"List::copyFrom() argument had different size.");
for (uint i = 0; i < other.size(); i++) {
set(i, other.begin()[i]);
}
}
private:
internal::ListBuilder builder;
};
......
......@@ -95,6 +95,12 @@ internal::StructBuilder MessageBuilder::initRoot(internal::StructSize size) {
rootSegment, rootSegment->getPtrUnchecked(0 * WORDS), size);
}
void MessageBuilder::setRootInternal(internal::StructReader reader) {
internal::SegmentBuilder* rootSegment = getRootSegment();
internal::StructBuilder::setRoot(
rootSegment, rootSegment->getPtrUnchecked(0 * WORDS), reader);
}
internal::StructBuilder MessageBuilder::getRoot(internal::StructSize size) {
internal::SegmentBuilder* rootSegment = getRootSegment();
return internal::StructBuilder::getRoot(
......
......@@ -27,6 +27,8 @@
#include "type-safety.h"
#include "layout.h"
#include "list.h" // TODO(cleanup): For FromReader. Move elsewhere?
#ifndef CAPNPROTO_MESSAGE_H_
#define CAPNPROTO_MESSAGE_H_
......@@ -133,6 +135,10 @@ public:
typename RootType::Builder initRoot();
// Initialize the root struct of the message as the given struct type.
template <typename Reader>
void setRoot(Reader&& value);
// Set the root struct to a deep copy of the given struct.
template <typename RootType>
typename RootType::Builder getRoot();
// Get the root struct of the message, interpreting it as the given struct type.
......@@ -162,6 +168,7 @@ private:
internal::BuilderArena* arena() { return reinterpret_cast<internal::BuilderArena*>(arenaSpace); }
internal::SegmentBuilder* getRootSegment();
internal::StructBuilder initRoot(internal::StructSize size);
void setRootInternal(internal::StructReader reader);
internal::StructBuilder getRoot(internal::StructSize size);
};
......@@ -301,6 +308,13 @@ inline typename RootType::Builder MessageBuilder::initRoot() {
return typename RootType::Builder(initRoot(internal::structSize<RootType>()));
}
template <typename Reader>
inline void MessageBuilder::setRoot(Reader&& value) {
typedef FromReader<Reader> RootType;
static_assert(kind<RootType>() == Kind::STRUCT, "Root type must be a Cap'n Proto struct type.");
setRootInternal(value._reader);
}
template <typename RootType>
inline typename RootType::Builder MessageBuilder::getRoot() {
static_assert(kind<RootType>() == Kind::STRUCT, "Root type must be a Cap'n Proto struct type.");
......
......@@ -355,16 +355,16 @@ void genericInitListDefaults(Builder builder) {
{
auto l = lists.initInt32ListList(3);
l.init(0, 3).copyFrom({1, 2, 3});
l.init(1, 2).copyFrom({4, 5});
l.init(2, 1).copyFrom({12341234});
l.set(0, {1, 2, 3});
l.set(1, {4, 5});
l.set(2, {12341234});
}
{
auto l = lists.initTextListList(3);
l.init(0, 2).copyFrom({"foo", "bar"});
l.init(1, 1).copyFrom({"baz"});
l.init(2, 2).copyFrom({"qux", "corge"});
l.set(0, {"foo", "bar"});
l.set(1, {"baz"});
l.set(2, {"qux", "corge"});
}
{
......
......@@ -174,6 +174,9 @@ private:
::capnproto::internal::StructReader _reader;
template <typename T, ::capnproto::Kind k>
friend struct ::capnproto::ToDynamic_;
template <typename T, ::capnproto::Kind k>
friend struct ::capnproto::internal::PointerHelpers;
friend struct ::capnproto::MessageBuilder;
};
{{! ------------------------------------------------------------------------------------------- }}
......@@ -207,10 +210,10 @@ public:
{{^fieldIsGenericObject}}
inline {{fieldType}}::Builder get{{fieldTitleCase}}();
inline void set{{fieldTitleCase}}({{fieldType}}::Reader other);
{{#fieldIsList}}
{{#fieldIsNonStructList}}
inline void set{{fieldTitleCase}}(
std::initializer_list<{{fieldElementReaderType}}> other);
{{/fieldIsList}}
{{/fieldIsNonStructList}}
{{#fieldIsListOrBlob}}
inline {{fieldType}}::Builder init{{fieldTitleCase}}(unsigned int size);
{{/fieldIsListOrBlob}}
......@@ -224,6 +227,8 @@ public:
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, typename U> inline void
set{{fieldTitleCase}}(std::initializer_list<U> value);
template <typename T, typename... Params> inline typename T::Builder
init{{fieldTitleCase}}(Params&&... params);
{{/fieldIsGenericObject}}
......@@ -325,7 +330,7 @@ inline void {{typeFullName}}::Builder::set{{fieldTitleCase}}({{fieldType}}::Read
_builder, {{fieldOffset}} * ::capnproto::POINTERS, value);
}
{{#fieldIsList}}
{{#fieldIsNonStructList}}
inline void {{typeFullName}}::Builder::set{{fieldTitleCase}}(
std::initializer_list<{{fieldElementReaderType}}> value) {
{{#fieldUnion}}
......@@ -336,7 +341,7 @@ inline void {{typeFullName}}::Builder::set{{fieldTitleCase}}(
_builder, {{fieldOffset}} * ::capnproto::POINTERS, value);
}
{{/fieldIsList}}
{{/fieldIsNonStructList}}
{{#fieldIsListOrBlob}}
inline {{fieldType}}::Builder {{typeFullName}}::Builder::init{{fieldTitleCase}}(unsigned int size) {
{{#fieldUnion}}
......@@ -413,6 +418,16 @@ inline void {{typeFullName}}::Builder::set{{fieldTitleCase}}(typename T::Reader
_builder, {{fieldOffset}} * ::capnproto::POINTERS, value);
}
template <typename T, typename U>
inline void {{typeFullName}}::Builder::set{{fieldTitleCase}}(std::initializer_list<U> value) {
{{#fieldUnion}}
_builder.setDataField<{{unionTitleCase}}::Which>(
{{unionTagOffset}} * ::capnproto::ELEMENTS, {{unionTitleCase}}::{{fieldUpperCase}});
{{/fieldUnion}}
::capnproto::internal::PointerHelpers<T>::set(
_builder, {{fieldOffset}} * ::capnproto::POINTERS, value);
}
template <typename T, typename... Params>
inline typename T::Builder {{typeFullName}}::Builder::init{{fieldTitleCase}}(Params&&... params) {
{{#fieldUnion}}
......
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