Commit c1d973e7 authored by Matthew Maurer's avatar Matthew Maurer

Moved canonicalization onto struct readers.

You can now spawn a canonical message from:
* StructReader
* AnyStruct::Reader
* capnpc-c++ generated Foo::Reader
parent 39a846fa
......@@ -470,6 +470,10 @@ public:
return List<AnyPointer>::Reader(_reader.getPointerSectionAsList());
}
kj::Array<word> canonicalize() {
return _reader.canonicalize();
}
Equality equals(AnyStruct::Reader right);
bool operator==(AnyStruct::Reader right);
inline bool operator!=(AnyStruct::Reader right) {
......
......@@ -27,15 +27,17 @@
namespace capnp {
namespace _ { // private
using test::TestLists;
namespace {
KJ_TEST("canonicalize yields cannonical message") {
MallocMessageBuilder builder;
auto root = builder.initRoot<TestAllTypes>();
initTestMessage(root);
canonicalize(builder);
root.asReader().canonicalize();
//Will assert if canonicalize failed to do so
}
......@@ -118,6 +120,30 @@ KJ_TEST("isCanonical requires truncation of 0-valued struct fields") {
KJ_ASSERT(!nonTruncated.isCanonical());
}
KJ_TEST("upgraded lists can be canonicalized") {
AlignedData<7> upgradedList = {{
//Struct pointer, data immediately follows, 4 pointer fields, no data
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x04, 0x00,
//Three words of default pointers to get to the int16 list
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
//List pointer, 3 int16s.
0x01, 0x00, 0x00, 0x00, 0x33, 0x00, 0x00, 0x00,
//First two elements
0x00, 0x01, 0x02, 0x03, 0x04, 0x04, 0x05, 0x06,
//Last element
0x07, 0x08, 0x09, 0x10, 0x00, 0x00, 0x00, 0x00
}};
kj::ArrayPtr<const word> segments[1] = {
kj::arrayPtr(upgradedList.words, 7)
};
SegmentArrayMessageReader upgraded(kj::arrayPtr(segments, 1));
auto root = upgraded.getRoot<TestLists>();
root.canonicalize();
}
KJ_TEST("isCanonical requires truncation of 0-valued struct fields in all list members") {
AlignedData<6> nonTruncatedList = {{
//List pointer, composite,
......
......@@ -1747,6 +1747,10 @@ private:
" return _reader.totalSize().asPublic();\n"
" }\n"
"\n"
" ::kj::Array<::capnp::word> canonicalize() {\n"
" return _reader.canonicalize();\n"
" }\n"
"\n"
"#if !CAPNP_LITE\n"
" inline ::kj::StringTree toString() const {\n"
" return ::capnp::_::structString(_reader, *_capnpPrivate::brand);\n"
......
......@@ -2732,6 +2732,19 @@ MessageSizeCounts StructReader::totalSize() const {
return result;
}
kj::Array<word> StructReader::canonicalize() {
WordCount size = totalSize().wordCount + POINTER_SIZE_IN_WORDS;
kj::Array<word> backing = kj::heapArray<word>(size / WORDS);
memset(backing.begin(), 0, backing.asBytes().size());
FlatMessageBuilder builder(backing);
_::PointerHelpers<AnyPointer>::getInternalBuilder(builder.initRoot<AnyPointer>()).setStruct(*this, true);
KJ_ASSERT(builder.isCanonical());
auto output = builder.getSegmentsForOutput()[0];
kj::Array<word> trunc = kj::heapArray<word>(output.size());
memcpy(trunc.begin(), output.begin(), output.asBytes().size());
return trunc;
}
CapTableReader* StructReader::getCapTable() {
return capTable;
}
......
......@@ -571,6 +571,8 @@ public:
inline kj::ArrayPtr<const byte> getDataSectionAsBlob();
inline _::ListReader getPointerSectionAsList();
kj::Array<word> canonicalize();
template <typename T>
KJ_ALWAYS_INLINE(bool hasDataField(ElementCount offset) const);
// Return true if the field is set to something other than its default value.
......
......@@ -421,21 +421,6 @@ private:
bool allocated;
};
template <typename MR>
kj::Array<word> canonicalize(MR&& reader) {
AnyPointer::Reader root = reader.template getRoot<AnyPointer>();
WordCount size = root.targetSize().wordCount * WORDS + POINTER_SIZE_IN_WORDS;
kj::Array<word> backing = kj::heapArray<word>(size / WORDS);
bzero(backing.begin(), backing.asBytes().size());
FlatMessageBuilder builder(backing);
builder.initRoot<AnyPointer>().setCanonical(root);
KJ_ASSERT(builder.isCanonical());
auto output = builder.getSegmentsForOutput()[0];
kj::Array<word> trunc = kj::heapArray<word>(output.size());
memcpy(trunc.begin(), output.begin(), output.asBytes().size());
return trunc;
}
// =======================================================================================
// implementation details
......
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