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
This diff is collapsed.
...@@ -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