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

Merge pull request #134 from joshuawarner32/any-struct-list

Add initial implementation of AnyStruct and AnyList
parents 9c1c6a87 0a7bc6e5
...@@ -106,6 +106,80 @@ TEST(Any, AnyPointer) { ...@@ -106,6 +106,80 @@ TEST(Any, AnyPointer) {
} }
} }
TEST(Any, AnyStruct) {
MallocMessageBuilder builder;
auto root = builder.getRoot<test::TestAnyPointer>();
initTestMessage(root.getAnyPointerField().initAs<TestAllTypes>());
checkTestMessage(root.getAnyPointerField().getAs<TestAllTypes>());
checkTestMessage(root.asReader().getAnyPointerField().getAs<TestAllTypes>());
EXPECT_EQ(48, root.getAnyPointerField().getAs<AnyStruct>().getDataSection().size());
EXPECT_EQ(20, root.getAnyPointerField().getAs<AnyStruct>().getPointerSection().size());
EXPECT_EQ(48, root.getAnyPointerField().asReader().getAs<AnyStruct>().getDataSection().size());
EXPECT_EQ(20, root.getAnyPointerField().asReader().getAs<AnyStruct>().getPointerSection().size());
auto b = toAny(root.getAnyPointerField().getAs<TestAllTypes>());
EXPECT_EQ(48, b.getDataSection().size());
EXPECT_EQ(20, b.getPointerSection().size());
auto r = toAny(root.getAnyPointerField().getAs<TestAllTypes>().asReader());
EXPECT_EQ(48, r.getDataSection().size());
EXPECT_EQ(20, r.getPointerSection().size());
r = toAny(root.getAnyPointerField().getAs<TestAllTypes>()).asReader();
EXPECT_EQ(48, r.getDataSection().size());
EXPECT_EQ(20, r.getPointerSection().size());
{
MallocMessageBuilder b2;
auto root2 = b2.getRoot<test::TestAnyPointer>();
auto sb = root2.getAnyPointerField().initAsAnyStruct(r.getDataSection().size() / 8, r.getPointerSection().size());
EXPECT_EQ(48, sb.getDataSection().size());
EXPECT_EQ(20, sb.getPointerSection().size());
// TODO: is there a higher-level API for this?
memcpy(sb.getDataSection().begin(), r.getDataSection().begin(), r.getDataSection().size());
}
}
TEST(Any, AnyList) {
MallocMessageBuilder builder;
auto root = builder.getRoot<test::TestAnyPointer>();
List<TestAllTypes>::Builder b = root.getAnyPointerField().initAs<List<TestAllTypes>>(2);
initTestMessage(b[0]);
auto ptr = root.getAnyPointerField().getAs<AnyList>();
EXPECT_EQ(2, ptr.size());
EXPECT_EQ(48, ptr.as<List<AnyStruct>>()[0].getDataSection().size());
EXPECT_EQ(20, ptr.as<List<AnyStruct>>()[0].getPointerSection().size());
auto readPtr = root.getAnyPointerField().asReader().getAs<AnyList>();
EXPECT_EQ(2, readPtr.size());
EXPECT_EQ(48, readPtr.as<List<AnyStruct>>()[0].getDataSection().size());
EXPECT_EQ(20, readPtr.as<List<AnyStruct>>()[0].getPointerSection().size());
auto alb = toAny(root.getAnyPointerField().getAs<List<TestAllTypes>>());
EXPECT_EQ(2, alb.size());
EXPECT_EQ(48, alb.as<List<AnyStruct>>()[0].getDataSection().size());
EXPECT_EQ(20, alb.as<List<AnyStruct>>()[0].getPointerSection().size());
auto alr = toAny(root.getAnyPointerField().getAs<List<TestAllTypes>>().asReader());
EXPECT_EQ(2, alr.size());
EXPECT_EQ(48, alr.as<List<AnyStruct>>()[0].getDataSection().size());
EXPECT_EQ(20, alr.as<List<AnyStruct>>()[0].getPointerSection().size());
alr = toAny(root.getAnyPointerField().getAs<List<TestAllTypes>>()).asReader();
EXPECT_EQ(2, alr.size());
EXPECT_EQ(48, alr.as<List<AnyStruct>>()[0].getDataSection().size());
EXPECT_EQ(20, alr.as<List<AnyStruct>>()[0].getPointerSection().size());
}
} // namespace } // namespace
} // namespace _ (private) } // namespace _ (private)
} // namespace capnp } // namespace capnp
...@@ -25,6 +25,7 @@ ...@@ -25,6 +25,7 @@
#include "layout.h" #include "layout.h"
#include "pointer-helpers.h" #include "pointer-helpers.h"
#include "orphan.h" #include "orphan.h"
#include "list.h"
namespace capnp { namespace capnp {
...@@ -35,6 +36,36 @@ class Orphanage; ...@@ -35,6 +36,36 @@ class Orphanage;
class ClientHook; class ClientHook;
class PipelineHook; class PipelineHook;
struct PipelineOp; struct PipelineOp;
struct AnyPointer;
struct AnyList {
AnyList() = delete;
class Reader;
class Builder;
};
struct AnyStruct {
AnyStruct() = delete;
class Reader;
class Builder;
class Pipeline;
};
template<>
struct List<AnyStruct, Kind::OTHER> {
List() = delete;
class Reader;
class Builder;
};
namespace _ { // private
template <> struct Kind_<AnyPointer> { static constexpr Kind kind = Kind::OTHER; };
template <> struct Kind_<AnyStruct> { static constexpr Kind kind = Kind::OTHER; };
template <> struct Kind_<AnyList> { static constexpr Kind kind = Kind::OTHER; };
} // namespace _ (private)
// ======================================================================================= // =======================================================================================
// AnyPointer! // AnyPointer!
...@@ -43,6 +74,8 @@ struct AnyPointer { ...@@ -43,6 +74,8 @@ struct AnyPointer {
// Reader/Builder for the `AnyPointer` field type, i.e. a pointer that can point to an arbitrary // Reader/Builder for the `AnyPointer` field type, i.e. a pointer that can point to an arbitrary
// object. // object.
AnyPointer() = delete;
class Reader { class Reader {
public: public:
typedef AnyPointer Reads; typedef AnyPointer Reads;
...@@ -54,6 +87,12 @@ struct AnyPointer { ...@@ -54,6 +87,12 @@ struct AnyPointer {
// Get the total size of the target object and all its children. // Get the total size of the target object and all its children.
inline bool isNull() const; inline bool isNull() const;
inline bool isStruct() {
return reader.isStruct();
}
inline bool isList() {
return reader.isList();
}
template <typename T> template <typename T>
inline ReaderFor<T> getAs() const; inline ReaderFor<T> getAs() const;
...@@ -96,6 +135,12 @@ struct AnyPointer { ...@@ -96,6 +135,12 @@ struct AnyPointer {
// Get the total size of the target object and all its children. // Get the total size of the target object and all its children.
inline bool isNull(); inline bool isNull();
inline bool isStruct() {
return builder.isStruct();
}
inline bool isList() {
return builder.isList();
}
inline void clear(); inline void clear();
// Set to null. // Set to null.
...@@ -132,6 +177,13 @@ struct AnyPointer { ...@@ -132,6 +177,13 @@ struct AnyPointer {
inline BuilderFor<T> initAs(ListSchema schema, uint elementCount); inline BuilderFor<T> initAs(ListSchema schema, uint elementCount);
// Only valid for T = DynamicList. Requires `#include <capnp/dynamic.h>`. // Only valid for T = DynamicList. Requires `#include <capnp/dynamic.h>`.
inline AnyList::Builder initAsAnyList(_::FieldSize elementSize, uint elementCount);
// Note: Does not accept INLINE_COMPOSITE for elementSize.
inline List<AnyStruct>::Builder initAsListOfAnyStruct(uint dataWordCount, uint pointerCount, uint elementCount);
inline AnyStruct::Builder initAsAnyStruct(uint dataWordCount, uint pointerCount);
template <typename T> template <typename T>
inline void setAs(ReaderFor<T> value); inline void setAs(ReaderFor<T> value);
// Valid for ReaderType = T::Reader for T = any generated struct type, List<U>, Text, Data, // Valid for ReaderType = T::Reader for T = any generated struct type, List<U>, Text, Data,
...@@ -193,11 +245,9 @@ struct AnyPointer { ...@@ -193,11 +245,9 @@ struct AnyPointer {
// Just make a copy. // Just make a copy.
Pipeline getPointerField(uint16_t pointerIndex); Pipeline getPointerField(uint16_t pointerIndex);
// Return a new Promise representing a sub-object of the result. `pointerIndex` is the index // Deprecated. In the future, we should use .asAnyStruct.getPointerField.
// of the sub-object within the pointer section of the result (the result must be a struct).
// inline AnyStruct::Pipeline asAnyStruct();
// TODO(kenton): On GCC 4.8 / Clang 3.3, use rvalue qualifiers to avoid the need for copies.
// Also make `ops` into a Vector to optimize this.
kj::Own<ClientHook> asCap(); kj::Own<ClientHook> asCap();
// Expect that the result is a capability and construct a pipelined version of it now. // Expect that the result is a capability and construct a pipelined version of it now.
...@@ -282,6 +332,282 @@ private: ...@@ -282,6 +332,282 @@ private:
friend class AnyPointer::Builder; friend class AnyPointer::Builder;
}; };
struct AnyList;
struct AnyStruct;
template <Kind k> struct AnyTypeFor_;
template <> struct AnyTypeFor_<Kind::STRUCT> { typedef AnyStruct Type; };
template <> struct AnyTypeFor_<Kind::LIST> { typedef AnyList Type; };
template <typename T>
using AnyTypeFor = typename AnyTypeFor_<kind<T>()>::Type;
template <typename T>
inline ReaderFor<AnyTypeFor<FromReader<T>>> toAny(T&& value) {
return ReaderFor<AnyTypeFor<FromReader<T> > >(
_::PointerHelpers<FromReader<T>>::getInternalReader(value));
}
template <typename T>
inline BuilderFor<AnyTypeFor<FromBuilder<T>>> toAny(T&& value) {
return BuilderFor<AnyTypeFor<FromBuilder<T> > >(
_::PointerHelpers<FromBuilder<T>>::getInternalBuilder(kj::mv(value)));
}
template <>
struct List<AnyPointer, Kind::OTHER> {
List() = delete;
class Reader {
public:
typedef List<AnyPointer> Reads;
Reader() = default;
inline explicit Reader(_::ListReader reader): reader(reader) {}
inline uint size() const { return reader.size() / ELEMENTS; }
inline typename AnyPointer::Reader operator[](uint index) const {
KJ_IREQUIRE(index < size());
return typename AnyPointer::Reader(reader.getPointerElement(index * ELEMENTS));
}
typedef _::IndexingIterator<const Reader, typename AnyPointer::Reader> Iterator;
inline Iterator begin() const { return Iterator(this, 0); }
inline Iterator end() const { return Iterator(this, size()); }
private:
_::ListReader reader;
template <typename U, Kind K>
friend struct _::PointerHelpers;
template <typename U, Kind K>
friend struct List;
friend class Orphanage;
template <typename U, Kind K>
friend struct ToDynamic_;
};
class Builder {
public:
typedef List<AnyPointer> Builds;
Builder() = delete;
inline Builder(decltype(nullptr)) {}
inline explicit Builder(_::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 AnyPointer::Builder operator[](uint index) {
KJ_IREQUIRE(index < size());
return typename AnyPointer::Builder(builder.getPointerElement(index * ELEMENTS));
}
typedef _::IndexingIterator<Builder, typename AnyPointer::Builder> Iterator;
inline Iterator begin() { return Iterator(this, 0); }
inline Iterator end() { return Iterator(this, size()); }
private:
_::ListBuilder builder;
template <typename U, Kind K>
friend struct _::PointerHelpers;
friend class Orphanage;
template <typename U, Kind K>
friend struct ToDynamic_;
};
};
class AnyStruct::Reader {
public:
Reader() = default;
inline Reader(_::StructReader reader): _reader(reader) {}
Data::Reader getDataSection() {
return _reader.getDataSectionAsBlob();
}
List<AnyPointer>::Reader getPointerSection() {
return List<AnyPointer>::Reader(_reader.getPointerSectionAsList());
}
template <typename T>
ReaderFor<T> as();
// T must be a struct type.
private:
_::StructReader _reader;
};
class AnyStruct::Builder {
public:
inline Builder(decltype(nullptr)) {}
inline Builder(_::PointerBuilder builder, _::StructSize size, const word* defaultValue = nullptr): _builder(builder.getStruct(size, defaultValue)) {}
inline Builder(_::StructBuilder builder): _builder(builder) {}
inline Data::Builder getDataSection() {
return _builder.getDataSectionAsBlob();
}
List<AnyPointer>::Builder getPointerSection() {
return List<AnyPointer>::Builder(_builder.getPointerSectionAsList());
}
inline operator Reader() const { return Reader(_builder.asReader()); }
inline Reader asReader() const { return Reader(_builder.asReader()); }
private:
_::StructBuilder _builder;
friend class Orphanage;
friend class CapBuilderContext;
};
class AnyStruct::Pipeline {
public:
Pipeline getPointerField(uint16_t pointerIndex);
// Return a new Promise representing a sub-object of the result. `pointerIndex` is the index
// of the sub-object within the pointer section of the result (the result must be a struct).
//
// TODO(kenton): On GCC 4.8 / Clang 3.3, use rvalue qualifiers to avoid the need for copies.
// Also make `ops` into a Vector to optimize this.
private:
kj::Own<PipelineHook> hook;
kj::Array<PipelineOp> ops;
inline Pipeline(kj::Own<PipelineHook>&& hook, kj::Array<PipelineOp>&& ops)
: hook(kj::mv(hook)), ops(kj::mv(ops)) {}
};
class List<AnyStruct, Kind::OTHER>::Reader {
public:
typedef List<AnyStruct> Reads;
Reader() = default;
inline explicit Reader(_::ListReader reader): reader(reader) {}
inline uint size() const { return reader.size() / ELEMENTS; }
inline typename AnyStruct::Reader operator[](uint index) const {
KJ_IREQUIRE(index < size());
return typename AnyStruct::Reader(reader.getStructElement(index * ELEMENTS));
}
typedef _::IndexingIterator<const Reader, typename AnyStruct::Reader> Iterator;
inline Iterator begin() const { return Iterator(this, 0); }
inline Iterator end() const { return Iterator(this, size()); }
private:
_::ListReader reader;
template <typename U, Kind K>
friend struct _::PointerHelpers;
template <typename U, Kind K>
friend struct List;
friend class Orphanage;
template <typename U, Kind K>
friend struct ToDynamic_;
};
class List<AnyStruct, Kind::OTHER>::Builder {
public:
typedef List<AnyStruct> Builds;
Builder() = delete;
inline Builder(decltype(nullptr)) {}
inline explicit Builder(_::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 AnyStruct::Builder operator[](uint index) {
KJ_IREQUIRE(index < size());
return typename AnyStruct::Builder(builder.getStructElement(index * ELEMENTS));
}
typedef _::IndexingIterator<Builder, typename AnyStruct::Builder> Iterator;
inline Iterator begin() { return Iterator(this, 0); }
inline Iterator end() { return Iterator(this, size()); }
private:
_::ListBuilder builder;
template <typename U, Kind K>
friend struct _::PointerHelpers;
friend class Orphanage;
template <typename U, Kind K>
friend struct ToDynamic_;
};
class AnyList::Reader {
public:
Reader() = default;
inline Reader(_::ListReader reader): _reader(reader) {}
_::FieldSize getElementSize();
ElementCount size() {
return _reader.size();
}
template <typename T> ReaderFor<T> as() {
// T must be List<U>.
return ReaderFor<T>(_reader);
}
private:
_::ListReader _reader;
};
class AnyList::Builder {
public:
inline Builder(decltype(nullptr)) {}
inline Builder(_::PointerBuilder builder, _::FieldSize size, const word* defaultValue = nullptr): _builder(builder.getList(size, defaultValue)) {}
inline Builder(_::ListBuilder builder): _builder(builder) {}
_::FieldSize getElementSize();
ElementCount size() {
return _builder.size();
}
template <typename T> BuilderFor<T> as() {
// T must be List<U>.
return BuilderFor<T>(_builder);
}
inline operator Reader() const { return Reader(_builder.asReader()); }
inline Reader asReader() const { return Reader(_builder.asReader()); }
private:
_::ListBuilder _builder;
};
namespace _ { // (private)
template <>
struct PointerHelpers<AnyStruct, Kind::OTHER> {
static inline typename AnyStruct::Reader get(PointerReader reader, const word* defaultValue = nullptr) {
return typename AnyStruct::Reader(reader.getStruct(defaultValue));
}
static inline typename AnyStruct::Builder get(PointerBuilder builder,
const word* defaultValue = nullptr) {
return typename AnyStruct::Builder(builder, /* TODO: allow specifying the size! */ _::StructSize(0, 0), defaultValue);
}
static inline typename AnyStruct::Builder init(PointerBuilder builder, uint dataWordCount, uint pointerCount) {
return typename AnyStruct::Builder(builder.initStruct(StructSize(dataWordCount, pointerCount)));
}
};
template <>
struct PointerHelpers<AnyList, Kind::OTHER> {
static inline typename AnyList::Reader get(PointerReader reader, const word* defaultValue = nullptr) {
return typename AnyList::Reader(reader.getList(/* TODO: allow specifying the size! */ FieldSize::VOID, defaultValue));
}
static inline typename AnyList::Builder get(PointerBuilder builder,
const word* defaultValue = nullptr) {
return typename AnyList::Builder(builder, /* TODO: allow specifying the size! */ FieldSize::VOID, defaultValue);
}
static inline typename AnyList::Builder init(PointerBuilder builder, FieldSize elementSize, uint elementCount) {
return typename AnyList::Builder(builder.initList(elementSize, elementCount));
}
static inline typename AnyList::Builder init(PointerBuilder builder, uint dataWordCount, uint pointerCount, uint elementCount) {
return typename AnyList::Builder(builder.initStructList(
elementCount,
StructSize(dataWordCount, pointerCount)));
}
};
} // end namespace _ (private)
// ======================================================================================= // =======================================================================================
// Pipeline helpers // Pipeline helpers
// //
...@@ -331,10 +657,6 @@ public: ...@@ -331,10 +657,6 @@ public:
// ======================================================================================= // =======================================================================================
// Inline implementation details // Inline implementation details
namespace _ { // private
template <> struct Kind_<AnyPointer> { static constexpr Kind kind = Kind::OTHER; };
} // namespace _ (private)
inline MessageSize AnyPointer::Reader::targetSize() const { inline MessageSize AnyPointer::Reader::targetSize() const {
return reader.targetSize().asPublic(); return reader.targetSize().asPublic();
} }
...@@ -375,6 +697,16 @@ inline BuilderFor<T> AnyPointer::Builder::initAs(uint elementCount) { ...@@ -375,6 +697,16 @@ inline BuilderFor<T> AnyPointer::Builder::initAs(uint elementCount) {
return _::PointerHelpers<T>::init(builder, elementCount); return _::PointerHelpers<T>::init(builder, elementCount);
} }
inline AnyList::Builder AnyPointer::Builder::initAsAnyList(_::FieldSize elementSize, uint elementCount) {
return _::PointerHelpers<AnyList>::init(builder, elementSize, elementCount);
}
// inline List<AnyStruct>::Builder AnyPointer::Builder::initAsListOfAnyStruct(uint dataWordCount, uint pointerCount, uint elementCount);
inline AnyStruct::Builder AnyPointer::Builder::initAsAnyStruct(uint dataWordCount, uint pointerCount) {
return _::PointerHelpers<AnyStruct>::init(builder, dataWordCount, pointerCount);
}
template <typename T> template <typename T>
inline void AnyPointer::Builder::setAs(ReaderFor<T> value) { inline void AnyPointer::Builder::setAs(ReaderFor<T> value) {
return _::PointerHelpers<T>::set(builder, value); return _::PointerHelpers<T>::set(builder, value);
...@@ -402,6 +734,8 @@ inline Orphan<AnyPointer> AnyPointer::Builder::disown() { ...@@ -402,6 +734,8 @@ inline Orphan<AnyPointer> AnyPointer::Builder::disown() {
template <> struct ReaderFor_ <AnyPointer, Kind::OTHER> { typedef AnyPointer::Reader Type; }; template <> struct ReaderFor_ <AnyPointer, Kind::OTHER> { typedef AnyPointer::Reader Type; };
template <> struct BuilderFor_<AnyPointer, Kind::OTHER> { typedef AnyPointer::Builder Type; }; template <> struct BuilderFor_<AnyPointer, Kind::OTHER> { typedef AnyPointer::Builder Type; };
template <> struct ReaderFor_ <AnyStruct, Kind::OTHER> { typedef AnyStruct::Reader Type; };
template <> struct BuilderFor_<AnyStruct, Kind::OTHER> { typedef AnyStruct::Builder Type; };
template <> template <>
struct Orphanage::GetInnerReader<AnyPointer, Kind::OTHER> { struct Orphanage::GetInnerReader<AnyPointer, Kind::OTHER> {
......
...@@ -1700,6 +1700,8 @@ private: ...@@ -1700,6 +1700,8 @@ private:
" template <typename, ::capnp::Kind>\n" " template <typename, ::capnp::Kind>\n"
" friend struct ::capnp::ToDynamic_;\n" " friend struct ::capnp::ToDynamic_;\n"
" friend class ::capnp::Orphanage;\n", " friend class ::capnp::Orphanage;\n",
" template <typename, ::capnp::Kind>\n"
" friend struct ::capnp::_::PointerHelpers;\n"
"};\n" "};\n"
"\n"); "\n");
} }
......
...@@ -251,6 +251,7 @@ struct WirePointer { ...@@ -251,6 +251,7 @@ struct WirePointer {
// our "null" value. // our "null" value.
return (offsetAndKind.get() == 0) & (upper32Bits == 0); return (offsetAndKind.get() == 0) & (upper32Bits == 0);
} }
}; };
static_assert(sizeof(WirePointer) == sizeof(word), static_assert(sizeof(WirePointer) == sizeof(word),
"capnp::WirePointer is not exactly one word. This will probably break everything."); "capnp::WirePointer is not exactly one word. This will probably break everything.");
...@@ -2155,6 +2156,20 @@ bool PointerBuilder::isNull() { ...@@ -2155,6 +2156,20 @@ bool PointerBuilder::isNull() {
return pointer->isNull(); return pointer->isNull();
} }
bool PointerBuilder::isStruct() {
word* refTarget;
WirePointer* ptr = pointer;
WireHelpers::followFars(ptr, refTarget, segment);
return ptr->kind() == WirePointer::Kind::STRUCT;
}
bool PointerBuilder::isList() {
word* refTarget;
WirePointer* ptr = pointer;
WireHelpers::followFars(ptr, refTarget, segment);
return ptr->kind() == WirePointer::Kind::LIST;
}
void PointerBuilder::transferFrom(PointerBuilder other) { void PointerBuilder::transferFrom(PointerBuilder other) {
if (!pointer->isNull()) { if (!pointer->isNull()) {
WireHelpers::zeroObject(segment, pointer); WireHelpers::zeroObject(segment, pointer);
...@@ -2238,6 +2253,22 @@ bool PointerReader::isNull() const { ...@@ -2238,6 +2253,22 @@ bool PointerReader::isNull() const {
return pointer == nullptr || pointer->isNull(); return pointer == nullptr || pointer->isNull();
} }
bool PointerReader::isStruct() const {
word* refTarget;
const WirePointer* ptr = pointer;
SegmentReader* sgmt = segment;
WireHelpers::followFars(ptr, refTarget, sgmt);
return ptr->kind() == WirePointer::Kind::STRUCT;
}
bool PointerReader::isList() const {
word* refTarget;
const WirePointer* ptr = pointer;
SegmentReader* sgmt = segment;
WireHelpers::followFars(ptr, refTarget, sgmt);
return ptr->kind() == WirePointer::Kind::LIST;
}
kj::Maybe<Arena&> PointerReader::getArena() const { kj::Maybe<Arena&> PointerReader::getArena() const {
return segment == nullptr ? nullptr : segment->getArena(); return segment == nullptr ? nullptr : segment->getArena();
} }
......
...@@ -324,6 +324,8 @@ public: ...@@ -324,6 +324,8 @@ public:
// location. // location.
bool isNull(); bool isNull();
bool isStruct();
bool isList();
StructBuilder getStruct(StructSize size, const word* defaultValue); StructBuilder getStruct(StructSize size, const word* defaultValue);
ListBuilder getList(FieldSize elementSize, const word* defaultValue); ListBuilder getList(FieldSize elementSize, const word* defaultValue);
...@@ -402,6 +404,8 @@ public: ...@@ -402,6 +404,8 @@ public:
// exception if it overruns. // exception if it overruns.
bool isNull() const; bool isNull() const;
bool isStruct() const;
bool isList() const;
StructReader getStruct(const word* defaultValue) const; StructReader getStruct(const word* defaultValue) const;
ListReader getList(FieldSize expectedElementSize, const word* defaultValue) const; ListReader getList(FieldSize expectedElementSize, const word* defaultValue) const;
...@@ -452,6 +456,7 @@ public: ...@@ -452,6 +456,7 @@ public:
inline BitCount getDataSectionSize() const { return dataSize; } inline BitCount getDataSectionSize() const { return dataSize; }
inline WirePointerCount getPointerSectionSize() const { return pointerCount; } inline WirePointerCount getPointerSectionSize() const { return pointerCount; }
inline Data::Builder getDataSectionAsBlob(); inline Data::Builder getDataSectionAsBlob();
inline _::ListBuilder getPointerSectionAsList();
template <typename T> template <typename T>
KJ_ALWAYS_INLINE(bool hasDataField(ElementCount offset)); KJ_ALWAYS_INLINE(bool hasDataField(ElementCount offset));
...@@ -532,6 +537,7 @@ public: ...@@ -532,6 +537,7 @@ public:
inline BitCount getDataSectionSize() const { return dataSize; } inline BitCount getDataSectionSize() const { return dataSize; }
inline WirePointerCount getPointerSectionSize() const { return pointerCount; } inline WirePointerCount getPointerSectionSize() const { return pointerCount; }
inline Data::Reader getDataSectionAsBlob(); inline Data::Reader getDataSectionAsBlob();
inline _::ListReader getPointerSectionAsList();
template <typename T> template <typename T>
KJ_ALWAYS_INLINE(bool hasDataField(ElementCount offset) const); KJ_ALWAYS_INLINE(bool hasDataField(ElementCount offset) const);
...@@ -662,6 +668,7 @@ private: ...@@ -662,6 +668,7 @@ private:
friend class StructBuilder; friend class StructBuilder;
friend struct WireHelpers; friend struct WireHelpers;
friend class OrphanBuilder; friend class OrphanBuilder;
friend class AnyStruct;
}; };
class ListReader { class ListReader {
...@@ -846,6 +853,10 @@ inline Data::Builder StructBuilder::getDataSectionAsBlob() { ...@@ -846,6 +853,10 @@ inline Data::Builder StructBuilder::getDataSectionAsBlob() {
return Data::Builder(reinterpret_cast<byte*>(data), dataSize / BITS_PER_BYTE / BYTES); return Data::Builder(reinterpret_cast<byte*>(data), dataSize / BITS_PER_BYTE / BYTES);
} }
inline _::ListBuilder StructBuilder::getPointerSectionAsList() {
return _::ListBuilder(segment, pointers, pointerCount * BITS_PER_WORD / ELEMENTS, pointerCount, 0, 1, FieldSize::POINTER);
}
template <typename T> template <typename T>
inline bool StructBuilder::hasDataField(ElementCount offset) { inline bool StructBuilder::hasDataField(ElementCount offset) {
return getDataField<Mask<T>>(offset) != 0; return getDataField<Mask<T>>(offset) != 0;
...@@ -924,6 +935,10 @@ inline Data::Reader StructReader::getDataSectionAsBlob() { ...@@ -924,6 +935,10 @@ inline Data::Reader StructReader::getDataSectionAsBlob() {
return Data::Reader(reinterpret_cast<const byte*>(data), dataSize / BITS_PER_BYTE / BYTES); return Data::Reader(reinterpret_cast<const byte*>(data), dataSize / BITS_PER_BYTE / BYTES);
} }
inline _::ListReader StructReader::getPointerSectionAsList() {
return _::ListReader(segment, pointers, pointerCount, pointerCount * BITS_PER_WORD / ELEMENTS, 0, 1, FieldSize::POINTER, nestingLimit);
}
template <typename T> template <typename T>
inline bool StructReader::hasDataField(ElementCount offset) const { inline bool StructReader::hasDataField(ElementCount offset) const {
return getDataField<Mask<T>>(offset) != 0; return getDataField<Mask<T>>(offset) != 0;
......
...@@ -163,6 +163,8 @@ struct List<T, Kind::PRIMITIVE> { ...@@ -163,6 +163,8 @@ struct List<T, Kind::PRIMITIVE> {
private: private:
_::ListBuilder builder; _::ListBuilder builder;
template <typename U, Kind K>
friend struct _::PointerHelpers;
friend class Orphanage; friend class Orphanage;
template <typename U, Kind K> template <typename U, Kind K>
friend struct ToDynamic_; friend struct ToDynamic_;
...@@ -282,6 +284,8 @@ struct List<T, Kind::STRUCT> { ...@@ -282,6 +284,8 @@ struct List<T, Kind::STRUCT> {
private: private:
_::ListBuilder builder; _::ListBuilder builder;
template <typename U, Kind K>
friend struct _::PointerHelpers;
friend class Orphanage; friend class Orphanage;
template <typename U, Kind K> template <typename U, Kind K>
friend struct ToDynamic_; friend struct ToDynamic_;
...@@ -391,6 +395,8 @@ struct List<List<T>, Kind::LIST> { ...@@ -391,6 +395,8 @@ struct List<List<T>, Kind::LIST> {
private: private:
_::ListBuilder builder; _::ListBuilder builder;
template <typename U, Kind K>
friend struct _::PointerHelpers;
friend class Orphanage; friend class Orphanage;
template <typename U, Kind K> template <typename U, Kind K>
friend struct ToDynamic_; friend struct ToDynamic_;
...@@ -487,6 +493,8 @@ struct List<T, Kind::BLOB> { ...@@ -487,6 +493,8 @@ struct List<T, Kind::BLOB> {
private: private:
_::ListBuilder builder; _::ListBuilder builder;
template <typename U, Kind K>
friend struct _::PointerHelpers;
friend class Orphanage; friend class Orphanage;
template <typename U, Kind K> template <typename U, Kind K>
friend struct ToDynamic_; friend struct ToDynamic_;
......
...@@ -24,6 +24,7 @@ ...@@ -24,6 +24,7 @@
#include "layout.h" #include "layout.h"
#include "list.h" #include "list.h"
// #include "any.h"
namespace capnp { namespace capnp {
namespace _ { // private namespace _ { // private
...@@ -53,13 +54,12 @@ struct PointerHelpers<T, Kind::STRUCT> { ...@@ -53,13 +54,12 @@ struct PointerHelpers<T, Kind::STRUCT> {
static inline Orphan<T> disown(PointerBuilder builder) { static inline Orphan<T> disown(PointerBuilder builder) {
return Orphan<T>(builder.disown()); return Orphan<T>(builder.disown());
} }
static inline _::StructReader getInternalReader(const typename T::Reader& reader) { static inline _::StructReader getInternalReader(const typename T::Reader& reader) {
// TODO(cleanup): This is used by RpcSystem::Connect, but perhaps it should be used more
// broadly so that we can reduce the number of friends declared by every Reader type.
return reader._reader; return reader._reader;
} }
static inline _::StructBuilder getInternalBuilder(typename T::Builder&& builder) {
return builder._builder;
}
}; };
template <typename T> template <typename T>
...@@ -91,6 +91,12 @@ struct PointerHelpers<List<T>, Kind::LIST> { ...@@ -91,6 +91,12 @@ struct PointerHelpers<List<T>, Kind::LIST> {
static inline Orphan<List<T>> disown(PointerBuilder builder) { static inline Orphan<List<T>> disown(PointerBuilder builder) {
return Orphan<List<T>>(builder.disown()); return Orphan<List<T>>(builder.disown());
} }
static inline _::ListReader getInternalReader(const typename List<T>::Reader& reader) {
return reader.reader;
}
static inline _::ListBuilder getInternalBuilder(typename List<T>::Builder&& builder) {
return builder.builder;
}
}; };
template <typename T> template <typename T>
......
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