Commit 665f5bd7 authored by Kenton Varda's avatar Kenton Varda

Extend FlatArrayMessageReader to indicate where the message actually ended, in…

Extend FlatArrayMessageReader to indicate where the message actually ended, in case it was not the end of the array.  Useful when reading an mmap'd file with a Cap'n Proto prefix.  Also fix a bug in Maybe dealing with DisallowConstCopy subclasses.
parent 8e84a527
......@@ -69,8 +69,20 @@ TEST(Serialize, FlatArray) {
kj::Array<word> serialized = messageToFlatArray(builder);
FlatArrayMessageReader reader(serialized.asPtr());
checkTestMessage(reader.getRoot<TestAllTypes>());
{
FlatArrayMessageReader reader(serialized.asPtr());
checkTestMessage(reader.getRoot<TestAllTypes>());
EXPECT_EQ(serialized.end(), reader.getEnd());
}
kj::Array<word> serializedWithSuffix = kj::heapArray<word>(serialized.size() + 5);
memcpy(serializedWithSuffix.begin(), serialized.begin(), serialized.size() * sizeof(word));
{
FlatArrayMessageReader reader(serializedWithSuffix.asPtr());
checkTestMessage(reader.getRoot<TestAllTypes>());
EXPECT_EQ(serializedWithSuffix.end() - 5, reader.getEnd());
}
}
TEST(Serialize, FlatArrayOddSegmentCount) {
......@@ -79,8 +91,20 @@ TEST(Serialize, FlatArrayOddSegmentCount) {
kj::Array<word> serialized = messageToFlatArray(builder);
FlatArrayMessageReader reader(serialized.asPtr());
checkTestMessage(reader.getRoot<TestAllTypes>());
{
FlatArrayMessageReader reader(serialized.asPtr());
checkTestMessage(reader.getRoot<TestAllTypes>());
EXPECT_EQ(serialized.end(), reader.getEnd());
}
kj::Array<word> serializedWithSuffix = kj::heapArray<word>(serialized.size() + 5);
memcpy(serializedWithSuffix.begin(), serialized.begin(), serialized.size() * sizeof(word));
{
FlatArrayMessageReader reader(serializedWithSuffix.asPtr());
checkTestMessage(reader.getRoot<TestAllTypes>());
EXPECT_EQ(serializedWithSuffix.end() - 5, reader.getEnd());
}
}
TEST(Serialize, FlatArrayEvenSegmentCount) {
......@@ -89,8 +113,20 @@ TEST(Serialize, FlatArrayEvenSegmentCount) {
kj::Array<word> serialized = messageToFlatArray(builder);
FlatArrayMessageReader reader(serialized.asPtr());
checkTestMessage(reader.getRoot<TestAllTypes>());
{
FlatArrayMessageReader reader(serialized.asPtr());
checkTestMessage(reader.getRoot<TestAllTypes>());
EXPECT_EQ(serialized.end(), reader.getEnd());
}
kj::Array<word> serializedWithSuffix = kj::heapArray<word>(serialized.size() + 5);
memcpy(serializedWithSuffix.begin(), serialized.begin(), serialized.size() * sizeof(word));
{
FlatArrayMessageReader reader(serializedWithSuffix.asPtr());
checkTestMessage(reader.getRoot<TestAllTypes>());
EXPECT_EQ(serializedWithSuffix.end() - 5, reader.getEnd());
}
}
class TestInputStream: public kj::InputStream {
......
......@@ -30,7 +30,7 @@ namespace capnp {
FlatArrayMessageReader::FlatArrayMessageReader(
kj::ArrayPtr<const word> array, ReaderOptions options)
: MessageReader(options) {
: MessageReader(options), end(array.end()) {
if (array.size() < 1) {
// Assume empty message.
return;
......@@ -47,6 +47,7 @@ FlatArrayMessageReader::FlatArrayMessageReader(
}
if (segmentCount == 0) {
end = array.begin() + offset;
return;
}
......@@ -75,6 +76,8 @@ FlatArrayMessageReader::FlatArrayMessageReader(
offset += segmentSize;
}
}
end = array.begin() + offset;
}
kj::ArrayPtr<const word> FlatArrayMessageReader::getSegment(uint id) {
......
......@@ -58,10 +58,17 @@ public:
kj::ArrayPtr<const word> getSegment(uint id) override;
const word* getEnd() const { return end; }
// Get a pointer just past the end of the message as determined by reading the message header.
// This could actually be before the end of the input array. This pointer is useful e.g. if
// you know that the input array has extra stuff appended after the message and you want to
// get at it.
private:
// Optimize for single-segment case.
kj::ArrayPtr<const word> segment0;
kj::Array<kj::ArrayPtr<const word>> moreSegments;
const word* end;
};
kj::Array<word> messageToFlatArray(MessageBuilder& builder);
......
......@@ -650,6 +650,12 @@ public:
ctor(value, other.value);
}
}
inline NullableValue(NullableValue& other)
: isSet(other.isSet) {
if (isSet) {
ctor(value, other.value);
}
}
inline ~NullableValue() noexcept(noexcept(instance<T&>().~T())) {
if (isSet) {
dtor(value);
......@@ -796,6 +802,7 @@ public:
Maybe(const T* t) noexcept: ptr(t) {}
Maybe(Maybe&& other) noexcept(noexcept(T(instance<T&&>()))): ptr(kj::mv(other.ptr)) {}
Maybe(const Maybe& other): ptr(other.ptr) {}
Maybe(Maybe& other): ptr(other.ptr) {}
template <typename U>
Maybe(Maybe<U>&& other) noexcept(noexcept(T(instance<U&&>()))) {
......
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