Commit 5f08f50d authored by Kenton Varda's avatar Kenton Varda

Get rid of stupid hacks to allow single-bit structs.

parent dcfd0915
......@@ -294,7 +294,6 @@ TEST(Encoding, InlineStructUnionLayout) {
initUnion<TestInlineUnions>([](TestInlineUnions::Builder b) {b.setter;})
EXPECT_EQ(UnionState({ 0,0,0,0}, -1), INIT_UNION(getUnion0().initF0()));
EXPECT_EQ(UnionState({ 1,0,0,0}, 0), INIT_UNION(getUnion0().initF1().setF(1)));
EXPECT_EQ(UnionState({ 2,0,0,0}, 0), INIT_UNION(getUnion0().initF8().setF0(true)));
EXPECT_EQ(UnionState({ 3,0,0,0}, 0), INIT_UNION(getUnion0().initF16().setF0(1)));
EXPECT_EQ(UnionState({ 4,0,0,0}, 0), INIT_UNION(getUnion0().initF32().setF0(1)));
......@@ -303,7 +302,6 @@ TEST(Encoding, InlineStructUnionLayout) {
EXPECT_EQ(UnionState({ 7,0,0,0}, 0), INIT_UNION(getUnion0().initF192().setF0(1)));
EXPECT_EQ(UnionState({ 8,0,0,0}, -1), INIT_UNION(getUnion0().initF0p().initF()));
EXPECT_EQ(UnionState({ 9,0,0,0}, 0), INIT_UNION(getUnion0().initF1p().initF().setF(1)));
EXPECT_EQ(UnionState({10,0,0,0}, 0), INIT_UNION(getUnion0().initF8p().initF().setF0(true)));
EXPECT_EQ(UnionState({11,0,0,0}, 0), INIT_UNION(getUnion0().initF16p().initF().setF0(1)));
EXPECT_EQ(UnionState({12,0,0,0}, 0), INIT_UNION(getUnion0().initF32p().initF().setF0(1)));
......@@ -312,7 +310,6 @@ TEST(Encoding, InlineStructUnionLayout) {
EXPECT_EQ(UnionState({15,0,0,0}, 0), INIT_UNION(getUnion0().initF192p().initF().setF0(1)));
EXPECT_EQ(UnionState({ 8,0,0,0}, ptr(0)), INIT_UNION(getUnion0().initF0p().setP0("1")));
EXPECT_EQ(UnionState({ 9,0,0,0}, ptr(0)), INIT_UNION(getUnion0().initF1p().setP0("1")));
EXPECT_EQ(UnionState({10,0,0,0}, ptr(0)), INIT_UNION(getUnion0().initF8p().setP0("1")));
EXPECT_EQ(UnionState({11,0,0,0}, ptr(0)), INIT_UNION(getUnion0().initF16p().setP0("1")));
EXPECT_EQ(UnionState({12,0,0,0}, ptr(0)), INIT_UNION(getUnion0().initF32p().setP0("1")));
......@@ -321,7 +318,6 @@ TEST(Encoding, InlineStructUnionLayout) {
EXPECT_EQ(UnionState({15,0,0,0}, ptr(0)), INIT_UNION(getUnion0().initF192p().setP0("1")));
EXPECT_EQ(UnionState({0, 0,0,0}, -1), INIT_UNION(getUnion1().initF0()));
EXPECT_EQ(UnionState({0, 1,0,0}, 193), INIT_UNION(getUnion1().initF1().setF(1)));
EXPECT_EQ(UnionState({0, 2,0,0}, 200), INIT_UNION(getUnion1().initF8().setF0(true)));
EXPECT_EQ(UnionState({0, 3,0,0}, 208), INIT_UNION(getUnion1().initF16().setF0(1)));
EXPECT_EQ(UnionState({0, 4,0,0}, 224), INIT_UNION(getUnion1().initF32().setF0(1)));
......@@ -329,8 +325,6 @@ TEST(Encoding, InlineStructUnionLayout) {
EXPECT_EQ(UnionState({0, 6,0,0}, 256), INIT_UNION(getUnion1().initF128().setF0(1)));
EXPECT_EQ(UnionState({0, 7,0,0}, 256), INIT_UNION(getUnion1().initF192().setF0(1)));
EXPECT_EQ(UnionState({0,0, 0,0}, 448), INIT_UNION(getUnion2().initF1p().initF().setF(1)));
EXPECT_EQ(UnionState({0,0,0, 0}, 449), INIT_UNION(getUnion3().initF1p().initF().setF(1)));
EXPECT_EQ(UnionState({0,0, 1,0}, 456), INIT_UNION(getUnion2().initF8p().initF().setF0(true)));
EXPECT_EQ(UnionState({0,0,0, 1}, 464), INIT_UNION(getUnion3().initF8p().initF().setF0(true)));
EXPECT_EQ(UnionState({0,0, 2,0}, 480), INIT_UNION(getUnion2().initF16p().initF().setF0(1)));
......@@ -344,8 +338,6 @@ TEST(Encoding, InlineStructUnionLayout) {
EXPECT_EQ(UnionState({0,0, 6,0}, 960), INIT_UNION(getUnion2().initF192p().initF().setF0(1)));
EXPECT_EQ(UnionState({0,0,0, 6},1152), INIT_UNION(getUnion3().initF192p().initF().setF0(1)));
EXPECT_EQ(UnionState({0,0, 0,0}, ptr( 3)), INIT_UNION(getUnion2().initF1p().setP0("1")));
EXPECT_EQ(UnionState({0,0,0, 0}, ptr( 4)), INIT_UNION(getUnion3().initF1p().setP0("1")));
EXPECT_EQ(UnionState({0,0, 1,0}, ptr( 3)), INIT_UNION(getUnion2().initF8p().setP0("1")));
EXPECT_EQ(UnionState({0,0,0, 1}, ptr( 4)), INIT_UNION(getUnion3().initF8p().setP0("1")));
EXPECT_EQ(UnionState({0,0, 2,0}, ptr( 5)), INIT_UNION(getUnion2().initF16p().setP0("1")));
......@@ -367,9 +359,7 @@ TEST(Encoding, InitInlineStruct) {
auto root = builder.getRoot<TestInlineLayout>();
// Set as many bits as we can.
root.initF1().setF(true);
root.initF1Offset().setF(true);
root.setBit(true);
root.setPad1(0xffu);
root.initF8().setF0(true);
root.getF8().setF1(true);
root.getF8().setF2(true);
......@@ -386,8 +376,8 @@ TEST(Encoding, InitInlineStruct) {
root.getF192().setF2(0xffffffffffffffffull);
root.initF0p().setP0("foo");
root.initF1p().setP0("foo");
root.getF1p().initF().setF(true);
root.setPad2(0xffu);
root.setPadP("foo");
root.initF8p().setP0("foo");
root.initF16p().setP0("foo");
root.getF16p().setP1("foo");
......@@ -403,21 +393,10 @@ TEST(Encoding, InitInlineStruct) {
root.getF192p().setP2("foo");
// Now try re-initializing each thing and making sure the surrounding things aren't modified.
EXPECT_FALSE(root.initF1().getF());
EXPECT_TRUE(root.getF1Offset().getF());
root.getF1().setF(true);
EXPECT_FALSE(root.initF1Offset().getF());
EXPECT_TRUE(root.getF1().getF());
EXPECT_TRUE(root.getBit());
EXPECT_TRUE(root.getF8().getF0());
root.getF1Offset().setF(true);
EXPECT_FALSE(root.initF8().getF0());
EXPECT_FALSE(root.getF8().getF1());
EXPECT_FALSE(root.getF8().getF2());
EXPECT_TRUE(root.getF1().getF());
EXPECT_TRUE(root.getBit());
EXPECT_EQ(0xffu, root.getPad1());
EXPECT_EQ(0xffu, root.getF16().getF0());
root.initF8().setF0(true);
root.getF8().setF1(true);
......@@ -461,22 +440,17 @@ TEST(Encoding, InitInlineStruct) {
EXPECT_EQ(0u, root.getF192().getF2());
EXPECT_EQ(0xffffffffffffffffull, root.getF128().getF0());
EXPECT_EQ(0xffffffffffffffffull, root.getF128().getF1());
EXPECT_TRUE(root.getF1p().getF().getF());
EXPECT_EQ(0xffu, root.getPad2());
root.getF192().setF0(0xffffffffffffffffull);
root.getF192().setF1(0xffffffffffffffffull);
root.getF192().setF2(0xffffffffffffffffull);
EXPECT_EQ("", root.initF0p().getP0());
EXPECT_EQ("foo", root.getF1p().getP0());
EXPECT_EQ("foo", root.getPadP());
root.getF0p().setP0("foo");
EXPECT_EQ("", root.initF1p().getP0());
EXPECT_EQ("foo", root.getF0p().getP0());
EXPECT_EQ("foo", root.getF8p().getP0());
root.getF1p().setP0("foo");
EXPECT_EQ("", root.initF8p().getP0());
EXPECT_EQ("foo", root.getF1p().getP0());
EXPECT_EQ("foo", root.getPadP());
EXPECT_EQ("foo", root.getF16p().getP0());
root.initF8p().setP0("foo");
......@@ -525,7 +499,6 @@ TEST(Encoding, InlineDefaults) {
{
auto normal = reader.getNormal();
EXPECT_TRUE(normal.getF1().getF());
EXPECT_TRUE(normal.getF8().getF0());
EXPECT_FALSE(normal.getF8().getF1());
EXPECT_TRUE(normal.getF8().getF2());
......@@ -541,7 +514,6 @@ TEST(Encoding, InlineDefaults) {
EXPECT_EQ(2345678901234ull, normal.getF192().getF1());
EXPECT_EQ(5678901234567ull, normal.getF192().getF2());
EXPECT_FALSE(normal.getF1p().getF().getF());
EXPECT_TRUE(normal.getF8p().getF().getF0());
EXPECT_TRUE(normal.getF8p().getF().getF1());
EXPECT_FALSE(normal.getF8p().getF().getF2());
......@@ -558,7 +530,6 @@ TEST(Encoding, InlineDefaults) {
EXPECT_EQ(5432109876543ull, normal.getF192p().getF().getF2());
EXPECT_EQ("foo", normal.getF0p().getP0());
EXPECT_EQ("bar", normal.getF1p().getP0());
EXPECT_EQ("baz", normal.getF8p().getP0());
EXPECT_EQ("qux", normal.getF16p().getP0());
EXPECT_EQ("quux", normal.getF16p().getP1());
......@@ -585,9 +556,6 @@ TEST(Encoding, InlineDefaults) {
EXPECT_EQ(1234567890123ull, unions.getUnion1().getF128().getF0());
EXPECT_EQ(4567890123456ull, unions.getUnion1().getF128().getF1());
ASSERT_EQ(TestInlineUnions::Union2::F1P, unions.getUnion2().which());
EXPECT_EQ("foo", unions.getUnion2().getF1p().getP0());
ASSERT_EQ(TestInlineUnions::Union3::F16P, unions.getUnion3().which());
EXPECT_EQ(98u, unions.getUnion3().getF16p().getF().getF0());
EXPECT_EQ(76u, unions.getUnion3().getF16p().getF().getF1());
......@@ -659,10 +627,6 @@ TEST(Encoding, InlineDefaults) {
EXPECT_EQ(Void::VOID, lists.getStructList0()[0].getF());
EXPECT_EQ(Void::VOID, lists.getStructList0()[1].getF());
EXPECT_TRUE(lists.getStructList1()[0].getF());
EXPECT_FALSE(lists.getStructList1()[1].getF());
// EXPECT_TRUE(lists.getStructList1()[2].getF());
EXPECT_TRUE (lists.getStructList8()[0].getF0());
EXPECT_FALSE(lists.getStructList8()[0].getF1());
EXPECT_FALSE(lists.getStructList8()[0].getF2());
......@@ -717,10 +681,6 @@ TEST(Encoding, InlineDefaults) {
EXPECT_EQ("baz", lists.getStructList0p()[2].getP0());
EXPECT_EQ("qux", lists.getStructList0p()[3].getP0());
EXPECT_TRUE(lists.getStructList1p()[0].getF().getF());
EXPECT_EQ("quux", lists.getStructList1p()[0].getP0());
EXPECT_EQ("corge", lists.getStructList1p()[1].getP0());
EXPECT_TRUE(lists.getStructList8p()[0].getF().getF0());
EXPECT_EQ("grault", lists.getStructList8p()[0].getP0());
EXPECT_EQ("garply", lists.getStructList8p()[1].getP0());
......
......@@ -102,7 +102,7 @@ static const AlignedData<2> SUBSTRUCT_DEFAULT = {{0,0,0,0,1,0,0,0, 0,0,0,0,0,0,
static const AlignedData<2> STRUCTLIST_ELEMENT_SUBSTRUCT_DEFAULT =
{{0,0,0,0,1,0,0,0, 0,0,0,0,0,0,0,0}};
static constexpr StructSize STRUCTLIST_ELEMENT_SIZE(1 * WORDS, 1 * REFERENCES, 64 * BITS);
static constexpr StructSize STRUCTLIST_ELEMENT_SIZE(1 * WORDS, 1 * REFERENCES, 8 * BYTES);
static void setupStruct(StructBuilder builder) {
builder.setDataField<uint64_t>(0 * ELEMENTS, 0x1011121314151617ull);
......@@ -120,7 +120,7 @@ static void setupStruct(StructBuilder builder) {
{
StructBuilder subStruct = builder.initStructField(
0 * REFERENCES, StructSize(1 * WORDS, 0 * REFERENCES, 64 * BITS));
0 * REFERENCES, StructSize(1 * WORDS, 0 * REFERENCES, 8 * BYTES));
subStruct.setDataField<uint32_t>(0 * ELEMENTS, 123);
}
......@@ -139,7 +139,7 @@ static void setupStruct(StructBuilder builder) {
for (int i = 0; i < 4; i++) {
StructBuilder element = list.getStructElement(i * ELEMENTS, STRUCTLIST_ELEMENT_SIZE);
element.setDataField<int32_t>(0 * ELEMENTS, 300 + i);
element.initStructField(0 * REFERENCES, StructSize(1 * WORDS, 0 * REFERENCES, 64 * BITS))
element.initStructField(0 * REFERENCES, StructSize(1 * WORDS, 0 * REFERENCES, 8 * BYTES))
.setDataField<int32_t>(0 * ELEMENTS, 400 + i);
}
}
......@@ -174,7 +174,7 @@ static void checkStruct(StructBuilder builder) {
{
StructBuilder subStruct = builder.getStructField(
0 * REFERENCES, StructSize(1 * WORDS, 0 * REFERENCES, 64 * BITS), SUBSTRUCT_DEFAULT.words);
0 * REFERENCES, StructSize(1 * WORDS, 0 * REFERENCES, 8 * BYTES), SUBSTRUCT_DEFAULT.words);
EXPECT_EQ(123u, subStruct.getDataField<uint32_t>(0 * ELEMENTS));
}
......@@ -193,7 +193,7 @@ static void checkStruct(StructBuilder builder) {
StructBuilder element = list.getStructElement(i * ELEMENTS, STRUCTLIST_ELEMENT_SIZE);
EXPECT_EQ(300 + i, element.getDataField<int32_t>(0 * ELEMENTS));
EXPECT_EQ(400 + i,
element.getStructField(0 * REFERENCES, StructSize(1 * WORDS, 0 * REFERENCES, 64 * BITS),
element.getStructField(0 * REFERENCES, StructSize(1 * WORDS, 0 * REFERENCES, 8 * BYTES),
STRUCTLIST_ELEMENT_SUBSTRUCT_DEFAULT.words)
.getDataField<int32_t>(0 * ELEMENTS));
}
......@@ -272,7 +272,7 @@ TEST(WireFormat, StructRoundTrip_OneSegment) {
word* rootLocation = segment->allocate(1 * WORDS);
StructBuilder builder = StructBuilder::initRoot(
segment, rootLocation, StructSize(2 * WORDS, 4 * REFERENCES, 128 * BITS));
segment, rootLocation, StructSize(2 * WORDS, 4 * REFERENCES, 16 * BYTES));
setupStruct(builder);
// word count:
......@@ -308,7 +308,7 @@ TEST(WireFormat, StructRoundTrip_OneSegmentPerAllocation) {
word* rootLocation = segment->allocate(1 * WORDS);
StructBuilder builder = StructBuilder::initRoot(
segment, rootLocation, StructSize(2 * WORDS, 4 * REFERENCES, 128 * BITS));
segment, rootLocation, StructSize(2 * WORDS, 4 * REFERENCES, 16 * BYTES));
setupStruct(builder);
// Verify that we made 15 segments.
......@@ -345,7 +345,7 @@ TEST(WireFormat, StructRoundTrip_MultipleSegmentsWithMultipleAllocations) {
word* rootLocation = segment->allocate(1 * WORDS);
StructBuilder builder = StructBuilder::initRoot(
segment, rootLocation, StructSize(2 * WORDS, 4 * REFERENCES, 128 * BITS));
segment, rootLocation, StructSize(2 * WORDS, 4 * REFERENCES, 16 * BYTES));
setupStruct(builder);
// Verify that we made 6 segments.
......
......@@ -415,7 +415,7 @@ struct WireHelpers {
ref->structRef.set(size);
// Build the StructBuilder.
return StructBuilder(segment, ptr, reinterpret_cast<WireReference*>(ptr + size.data), 0 * BITS,
return StructBuilder(segment, ptr, reinterpret_cast<WireReference*>(ptr + size.data),
size.pointers);
}
......@@ -443,7 +443,7 @@ struct WireHelpers {
"Trying to update struct with incorrect reference count.");
}
return StructBuilder(segment, ptr, reinterpret_cast<WireReference*>(ptr + size.data), 0 * BITS,
return StructBuilder(segment, ptr, reinterpret_cast<WireReference*>(ptr + size.data),
size.pointers);
}
......@@ -466,7 +466,7 @@ struct WireHelpers {
// Build the ListBuilder.
return ListBuilder(segment, ptr, reinterpret_cast<WireReference*>(ptr),
step, step / BITS_PER_REFERENCE, elementCount);
step / BITS_PER_BYTE, step / BITS_PER_REFERENCE, elementCount);
}
static CAPNPROTO_ALWAYS_INLINE(ListBuilder initStructListReference(
......@@ -479,13 +479,12 @@ struct WireHelpers {
if (elementSize.pointers == 1 * REFERENCES) {
primitiveElementSize = FieldSize::REFERENCE;
} else {
switch (elementSize.dataBits / BITS) {
switch (elementSize.dataBytes / BYTES) {
case 0: primitiveElementSize = FieldSize::VOID; break;
case 1: primitiveElementSize = FieldSize::BIT; break;
case 8: primitiveElementSize = FieldSize::BYTE; break;
case 16: primitiveElementSize = FieldSize::TWO_BYTES; break;
case 32: primitiveElementSize = FieldSize::FOUR_BYTES; break;
case 64: primitiveElementSize = FieldSize::EIGHT_BYTES; break;
case 1: primitiveElementSize = FieldSize::BYTE; break;
case 2: primitiveElementSize = FieldSize::TWO_BYTES; break;
case 4: primitiveElementSize = FieldSize::FOUR_BYTES; break;
case 8: primitiveElementSize = FieldSize::EIGHT_BYTES; break;
default: FAIL_PRECOND("Invalid struct size."); break;
}
}
......@@ -510,7 +509,7 @@ struct WireHelpers {
// Build the ListBuilder.
return ListBuilder(segment, ptr, reinterpret_cast<WireReference*>(ptr + elementSize.data),
wordsPerElement * BITS_PER_WORD, wordsPerElement / WORDS_PER_REFERENCE,
wordsPerElement * BYTES_PER_WORD, wordsPerElement / WORDS_PER_REFERENCE,
elementCount);
}
......@@ -521,7 +520,7 @@ struct WireHelpers {
if (ref->isNull()) {
if (defaultValue == nullptr) {
return ListBuilder(segment, nullptr, nullptr, 0 * BITS / ELEMENTS,
return ListBuilder(segment, nullptr, nullptr, 0 * BYTES / ELEMENTS,
0 * REFERENCES / ELEMENTS, 0 * ELEMENTS);
}
ptr = copyMessage(segment, ref, defaultRef);
......@@ -543,12 +542,12 @@ struct WireHelpers {
WireReference* pointers = reinterpret_cast<WireReference*>(
data + tag->structRef.dataSize.get());
auto step = tag->structRef.wordSize() / ELEMENTS;
return ListBuilder(segment, data, pointers, step * BITS_PER_WORD, step / WORDS_PER_REFERENCE,
return ListBuilder(segment, data, pointers, step * BYTES_PER_WORD, step / WORDS_PER_REFERENCE,
tag->inlineCompositeListElementCount());
} else {
decltype(BITS/ELEMENTS) step = bitsPerElement(ref->listRef.elementSize());
auto step = bytesPerElement(ref->listRef.elementSize());
return ListBuilder(segment, ptr, reinterpret_cast<WireReference*>(ptr),
step, step / BITS_PER_REFERENCE,
step, step / BYTES_PER_REFERENCE,
ref->listRef.elementCount());
}
}
......@@ -637,7 +636,7 @@ struct WireHelpers {
if (ref == nullptr || ref->isNull()) {
useDefault:
if (defaultValue == nullptr) {
return StructReader(nullptr, nullptr, nullptr, 0 * BITS, 0 * REFERENCES, 0 * BITS,
return StructReader(nullptr, nullptr, nullptr, 0 * BYTES, 0 * REFERENCES,
std::numeric_limits<int>::max());
}
segment = nullptr;
......@@ -671,9 +670,9 @@ struct WireHelpers {
return StructReader(
segment, ptr, reinterpret_cast<const WireReference*>(ptr + ref->structRef.dataSize.get()),
ref->structRef.dataSize.get() * BITS_PER_WORD,
ref->structRef.dataSize.get() * BYTES_PER_WORD,
ref->structRef.refCount.get(),
0 * BITS, nestingLimit - 1);
nestingLimit - 1);
}
static CAPNPROTO_ALWAYS_INLINE(ListReader readListReference(
......@@ -684,7 +683,7 @@ struct WireHelpers {
useDefault:
if (defaultValue == nullptr) {
return ListReader(nullptr, nullptr, nullptr, 0 * ELEMENTS,
0 * BITS / ELEMENTS, 0 * REFERENCES / ELEMENTS,
0 * BYTES / ELEMENTS, 0 * REFERENCES / ELEMENTS,
nestingLimit - 1);
}
segment = nullptr;
......@@ -751,6 +750,11 @@ struct WireHelpers {
break;
case FieldSize::BIT:
FAIL_VALIDATE_INPUT("Expected a bit list, but got a list of structs.") {
goto useDefault;
}
break;
case FieldSize::BYTE:
case FieldSize::TWO_BYTES:
case FieldSize::FOUR_BYTES:
......@@ -790,13 +794,13 @@ struct WireHelpers {
return ListReader(
segment, ptr,
reinterpret_cast<const WireReference*>(ptr + tag->structRef.dataSize.get()),
size, wordsPerElement * BITS_PER_WORD, wordsPerElement / WORDS_PER_REFERENCE,
tag->structRef.dataSize.get() * BITS_PER_WORD,
size, wordsPerElement * BYTES_PER_WORD, wordsPerElement / WORDS_PER_REFERENCE,
tag->structRef.dataSize.get() * BYTES_PER_WORD,
tag->structRef.refCount.get(), nestingLimit - 1);
} else {
// The elements of the list are NOT structs.
decltype(BITS/ELEMENTS) step = bitsPerElement(ref->listRef.elementSize());
auto step = bitsPerElement(ref->listRef.elementSize());
if (segment != nullptr) {
VALIDATE_INPUT(segment->containsInterval(ptr, ptr +
......@@ -808,34 +812,39 @@ struct WireHelpers {
if (ref->listRef.elementSize() == expectedElementSize) {
return ListReader(segment, ptr, reinterpret_cast<const WireReference*>(ptr),
ref->listRef.elementCount(), step, step / BITS_PER_REFERENCE,
nestingLimit - 1);
ref->listRef.elementCount(), step / BITS_PER_BYTE,
step / BITS_PER_REFERENCE, nestingLimit - 1);
} else if (expectedElementSize == FieldSize::INLINE_COMPOSITE) {
// We were expecting a struct list, but we received a list of some other type. Perhaps a
// non-struct list was recently upgraded to a struct list, but the sender is using the
// old version of the protocol. We need to verify that the struct's first field matches
// what the sender sent us.
BitCount dataSize = 0 * BITS;
ByteCount dataSize = 0 * BYTES;
WireReferenceCount referenceCount = 0 * REFERENCES;
switch (ref->listRef.elementSize()) {
case FieldSize::VOID: break;
case FieldSize::BIT: dataSize = 1 * BITS; break;
case FieldSize::BYTE: dataSize = 8 * BITS; break;
case FieldSize::TWO_BYTES: dataSize = 16 * BITS; break;
case FieldSize::FOUR_BYTES: dataSize = 32 * BITS; break;
case FieldSize::EIGHT_BYTES: dataSize = 64 * BITS; break;
case FieldSize::BYTE: dataSize = 1 * BYTES; break;
case FieldSize::TWO_BYTES: dataSize = 2 * BYTES; break;
case FieldSize::FOUR_BYTES: dataSize = 4 * BYTES; break;
case FieldSize::EIGHT_BYTES: dataSize = 8 * BYTES; break;
case FieldSize::REFERENCE: referenceCount = 1 * REFERENCES; break;
case FieldSize::BIT:
FAIL_VALIDATE_INPUT("Message contained a bit list where a struct list was expected.") {
dataSize = 0 * BYTES;
}
break;
case FieldSize::INLINE_COMPOSITE:
FAIL_CHECK();
break;
}
return ListReader(segment, ptr, reinterpret_cast<const WireReference*>(ptr),
ref->listRef.elementCount(), step, step / BITS_PER_REFERENCE,
dataSize, referenceCount, nestingLimit - 1);
ref->listRef.elementCount(), step / BITS_PER_BYTE,
step / BITS_PER_REFERENCE, dataSize, referenceCount, nestingLimit - 1);
} else {
PRECOND(segment != nullptr, "Trusted message had incompatible list element type.");
goto useDefault;
......@@ -1010,7 +1019,7 @@ StructReader StructBuilder::asReader() const {
static_assert(sizeof(WireReference::structRef.refCount) == 2,
"Has the maximum reference count changed?");
return StructReader(segment, data, references,
0xffffffff * BITS, 0xffff * REFERENCES, 0 * BITS, std::numeric_limits<int>::max());
0xffffffff * BYTES, 0xffff * REFERENCES, std::numeric_limits<int>::max());
}
StructReader StructReader::readRootTrusted(const word* location) {
......@@ -1030,7 +1039,7 @@ StructReader StructReader::readRoot(
}
StructReader StructReader::readEmpty() {
return StructReader(nullptr, nullptr, nullptr, 0 * BITS, 0 * REFERENCES, 0 * BITS,
return StructReader(nullptr, nullptr, nullptr, 0 * BYTES, 0 * REFERENCES,
std::numeric_limits<int>::max());
}
......@@ -1061,11 +1070,10 @@ Data::Reader StructReader::getDataField(
StructBuilder ListBuilder::getStructElement(ElementCount index, StructSize elementSize) const {
// TODO: Inline this method?
BitCount64 indexBit = ElementCount64(index) * stepBits;
byte* structData = reinterpret_cast<byte*>(data) + indexBit / BITS_PER_BYTE;
ByteCount indexByte = ElementCount64(index) * stepBytes;
byte* structData = reinterpret_cast<byte*>(data) + indexByte;
WireReference* structPointers = pointers + index * stepPointers;
return StructBuilder(segment, structData, structPointers, indexBit % BITS_PER_BYTE,
elementSize.pointers);
return StructBuilder(segment, structData, structPointers, elementSize.pointers);
}
ListBuilder ListBuilder::initListElement(
......@@ -1117,13 +1125,13 @@ ListReader ListBuilder::asReader(FieldSize elementSize) const {
// TODO: For INLINE_COMPOSITE I suppose we could just check the tag?
PRECOND(elementSize != FieldSize::INLINE_COMPOSITE,
"Need to call the other asReader() overload for INLINE_COMPOSITE lists.");
return ListReader(segment, data, pointers, elementCount, stepBits, stepPointers,
return ListReader(segment, data, pointers, elementCount, stepBytes, stepPointers,
std::numeric_limits<int>::max());
}
ListReader ListBuilder::asReader(StructSize elementSize) const {
return ListReader(segment, data, pointers, elementCount, stepBits, stepPointers,
elementSize.dataBits, elementSize.pointers, std::numeric_limits<int>::max());
return ListReader(segment, data, pointers, elementCount, stepBytes, stepPointers,
elementSize.dataBytes, elementSize.pointers, std::numeric_limits<int>::max());
}
StructReader ListReader::getStructElement(ElementCount index) const {
......@@ -1133,11 +1141,11 @@ StructReader ListReader::getStructElement(ElementCount index) const {
return StructReader::readEmpty();
}
BitCount64 indexBit = ElementCount64(index) * stepBits;
const byte* structData = reinterpret_cast<const byte*>(data) + indexBit / BITS_PER_BYTE;
ByteCount indexByte = index * stepBytes;
const byte* structData = reinterpret_cast<const byte*>(data) + indexByte;
return StructReader(
segment, structData, pointers + index * stepPointers,
structDataSize, structReferenceCount, indexBit % BITS_PER_BYTE, nestingLimit - 1);
structDataSize, structReferenceCount, nestingLimit - 1);
}
ListReader ListReader::getListElement(
......
......@@ -101,6 +101,7 @@ enum class FieldSize: uint8_t {
};
typedef decltype(BITS / ELEMENTS) BitsPerElement;
typedef decltype(BYTES / ELEMENTS) BytesPerElement;
namespace internal {
static constexpr BitsPerElement BITS_PER_ELEMENT_TABLE[8] = {
......@@ -119,6 +120,13 @@ inline constexpr BitsPerElement bitsPerElement(FieldSize size) {
return internal::BITS_PER_ELEMENT_TABLE[static_cast<int>(size)];
}
inline constexpr BytesPerElement bytesPerElement(FieldSize size) {
// BIT gets rounded down to zero bytes. This is OK because bytesPerElement() is only used in
// cases where this doesn't matter, e.g. for computing stepBytes which is ignored by bit ops
// anyway.
return bitsPerElement(size) / BITS_PER_BYTE;
}
template <int wordCount>
union AlignedData {
// Useful for declaring static constant data blobs as an array of bytes, but forcing those
......@@ -132,15 +140,15 @@ struct StructSize {
WordCount16 data;
WireReferenceCount16 pointers;
BitCount32 dataBits;
// If data == 1 word, dataBits may be 1, 8, 16, 32, or 64. Otherwise, it is data * BITS_PER_WORD.
// This is used when packing inline structs.
ByteCount32 dataBytes;
// Number of bytes in the data section. Must be data * 8 except when data == 1 in which case
// this can be 1, 2, 4, or 8.
inline constexpr WordCount total() const { return data + pointers * WORDS_PER_REFERENCE; }
StructSize() = default;
inline constexpr StructSize(WordCount data, WireReferenceCount pointers, BitCount dataBits)
: data(data), pointers(pointers), dataBits(dataBits) {}
inline constexpr StructSize(WordCount data, WireReferenceCount pointers, ByteCount dataBytes)
: data(data), pointers(pointers), dataBytes(dataBytes) {}
};
template <typename T>
......@@ -286,13 +294,13 @@ public:
// or to the empty state if defaultValue is nullptr.
CAPNPROTO_ALWAYS_INLINE(StructBuilder initInlineStructField(
BitCount dataOffset, BitCount inlineDataSize,
ByteCount dataOffset, ByteCount inlineDataSize,
WireReferenceCount refIndex, WireReferenceCount inlineRefCount) const);
// Initialize an inlined struct field, given the position and size of the data and pointer
// sections.
CAPNPROTO_ALWAYS_INLINE(StructBuilder getInlineStructField(
BitCount dataOffset, BitCount inlineDataSize,
ByteCount dataOffset, ByteCount inlineDataSize,
WireReferenceCount refIndex, WireReferenceCount inlineRefCount) const);
// Gets an inlined struct field, given the position and size of the data and pointer sections.
......@@ -312,7 +320,7 @@ public:
// message). If the default value is null, an empty list is used.
CAPNPROTO_ALWAYS_INLINE(ListBuilder initInlineDataListField(
BitCount offset, BitCount inlineSize,
ByteCount offset, ByteCount inlineSize,
ElementCount elementCount, FieldSize elementSize) const);
// Initialize an inline list field.
......@@ -322,12 +330,12 @@ public:
// Initialize an inline list field.
CAPNPROTO_ALWAYS_INLINE(ListBuilder initInlineStructListField(
BitCount dataOffset, WireReferenceCount ptrOffset, ElementCount elementCount,
ByteCount dataOffset, WireReferenceCount ptrOffset, ElementCount elementCount,
StructSize elementSize) const);
// Initialize an inline struct list field.
CAPNPROTO_ALWAYS_INLINE(ListBuilder getInlineDataListField(
BitCount offset, ElementCount elementCount, FieldSize elementSize) const);
ByteCount offset, ElementCount elementCount, FieldSize elementSize) const);
// Get an already-initialized inline list field.
CAPNPROTO_ALWAYS_INLINE(ListBuilder getInlinePointerListField(
......@@ -335,7 +343,7 @@ public:
// Get an already-initialized inline list field.
CAPNPROTO_ALWAYS_INLINE(ListBuilder getInlineStructListField(
BitCount dataOffset, WireReferenceCount ptrOffset, ElementCount elementCount,
ByteCount dataOffset, WireReferenceCount ptrOffset, ElementCount elementCount,
StructSize elementSize) const);
// Get an already-initialized inline struct list field.
......@@ -366,16 +374,12 @@ private:
void* data; // Pointer to the encoded data.
WireReference* references; // Pointer to the encoded references.
BitCount8 bit0Offset;
// A special hack: When accessing a boolean with field number zero, pretend its offset is this
// instead of the usual zero. This is needed to support 1-bit inline structs.
WireReferenceCount16 referenceCount;
// Size of the pointer segment, available only for the sake of computing size of List(Inline(T)).
inline StructBuilder(SegmentBuilder* segment, void* data, WireReference* references,
BitCount8 bit0Offset, WireReferenceCount referenceCount)
: segment(segment), data(data), references(references), bit0Offset(bit0Offset),
WireReferenceCount referenceCount)
: segment(segment), data(data), references(references),
referenceCount(referenceCount) {}
friend class ListBuilder;
......@@ -386,7 +390,7 @@ class StructReader {
public:
inline StructReader()
: segment(nullptr), data(nullptr), references(nullptr), dataSize(0),
referenceCount(0), bit0Offset(0 * BITS), nestingLimit(0) {}
referenceCount(0), nestingLimit(0) {}
static StructReader readRootTrusted(const word* location);
static StructReader readRoot(const word* location, SegmentReader* segment, int nestingLimit);
......@@ -411,7 +415,7 @@ public:
// be null, in which case an empty struct is used.
CAPNPROTO_ALWAYS_INLINE(StructReader getInlineStructField(
BitCount dataOffset, BitCount inlineDataSize,
ByteCount dataOffset, ByteCount inlineDataSize,
WireReferenceCount refIndex, WireReferenceCount inlineRefCount) const);
// Gets an inlined struct field, given the position and size of the data and pointer sections.
......@@ -421,7 +425,7 @@ public:
// initialized. The default value is allowed to be null, in which case an empty list is used.
CAPNPROTO_ALWAYS_INLINE(ListReader getInlineDataListField(
BitCount offset, ElementCount elementCount, FieldSize elementSize) const);
ByteCount offset, ElementCount elementCount, FieldSize elementSize) const);
// Get an inline list field.
CAPNPROTO_ALWAYS_INLINE(ListReader getInlinePointerListField(
......@@ -429,7 +433,7 @@ public:
// Get an inline list field.
CAPNPROTO_ALWAYS_INLINE(ListReader getInlineStructListField(
BitCount dataOffset, WireReferenceCount ptrOffset, ElementCount elementCount,
ByteCount dataOffset, WireReferenceCount ptrOffset, ElementCount elementCount,
StructSize elementSize) const);
// Get an inline struct list field.
......@@ -449,24 +453,18 @@ private:
const void* data;
const WireReference* references;
BitCount32 dataSize; // Size of data segment.
ByteCount32 dataSize; // Size of data segment.
WireReferenceCount16 referenceCount; // Size of the reference segment.
BitCount8 bit0Offset;
// A special hack: When accessing a boolean with field number zero, pretend its offset is this
// instead of the usual zero. This is needed to allow a boolean list to be upgraded to a list
// of structs, and to support 1-bit inline structs.
int nestingLimit;
// Limits the depth of message structures to guard against stack-overflow-based DoS attacks.
// Once this reaches zero, further pointers will be pruned.
// TODO: Limit to 8 bits for better alignment?
inline StructReader(SegmentReader* segment, const void* data, const WireReference* references,
BitCount dataSize, WireReferenceCount referenceCount,
BitCount bit0Offset, int nestingLimit)
ByteCount dataSize, WireReferenceCount referenceCount, int nestingLimit)
: segment(segment), data(data), references(references),
dataSize(dataSize), referenceCount(referenceCount), bit0Offset(bit0Offset),
dataSize(dataSize), referenceCount(referenceCount),
nestingLimit(nestingLimit) {}
friend class ListReader;
......@@ -480,7 +478,7 @@ class ListBuilder {
public:
inline ListBuilder()
: segment(nullptr), data(nullptr), pointers(nullptr), elementCount(0 * ELEMENTS),
stepBits(0 * BITS / ELEMENTS), stepPointers(0 * REFERENCES / ELEMENTS) {}
stepBytes(0 * BYTES / ELEMENTS), stepPointers(0 * REFERENCES / ELEMENTS) {}
inline ElementCount size();
// The number of elements in the list.
......@@ -540,15 +538,16 @@ private:
ElementCount elementCount; // Number of elements in the list.
decltype(BITS / ELEMENTS) stepBits;
decltype(BYTES / ELEMENTS) stepBytes;
decltype(REFERENCES / ELEMENTS) stepPointers;
// The distance between elements. Can be tricky e.g. for inlined struct lists.
// Bit lists ignore stepBytes -- they are always tightly-packed.
inline ListBuilder(SegmentBuilder* segment, void* data, WireReference* pointers,
decltype(BITS / ELEMENTS) stepBits,
decltype(BYTES / ELEMENTS) stepBytes,
decltype(REFERENCES / ELEMENTS) stepPointers, ElementCount size)
: segment(segment), data(data), pointers(pointers), elementCount(size),
stepBits(stepBits), stepPointers(stepPointers) {}
stepBytes(stepBytes), stepPointers(stepPointers) {}
friend class StructBuilder;
friend struct WireHelpers;
......@@ -558,7 +557,7 @@ class ListReader {
public:
inline ListReader()
: segment(nullptr), data(nullptr), pointers(nullptr), elementCount(0),
stepBits(0 * BITS / ELEMENTS), stepPointers(0 * REFERENCES / ELEMENTS),
stepBytes(0 * BYTES / ELEMENTS), stepPointers(0 * REFERENCES / ELEMENTS),
structDataSize(0), structReferenceCount(0), nestingLimit(0) {}
inline ElementCount size();
......@@ -589,11 +588,12 @@ private:
ElementCount elementCount; // Number of elements in the list.
decltype(BITS / ELEMENTS) stepBits;
decltype(BYTES / ELEMENTS) stepBytes;
decltype(REFERENCES / ELEMENTS) stepPointers;
// The distance between elements. Can be tricky e.g. for inlined struct lists.
// Bit lists ignore stepBytes -- they are always tightly-packed.
BitCount structDataSize;
ByteCount structDataSize;
WireReferenceCount structReferenceCount;
// If the elements are structs, the properties of the struct.
......@@ -602,17 +602,17 @@ private:
// Once this reaches zero, further pointers will be pruned.
inline ListReader(SegmentReader* segment, const void* data, const WireReference* pointers,
ElementCount elementCount, decltype(BITS / ELEMENTS) stepBits,
ElementCount elementCount, decltype(BYTES / ELEMENTS) stepBytes,
decltype(REFERENCES / ELEMENTS) stepPointers, int nestingLimit)
: segment(segment), data(data), pointers(pointers), elementCount(elementCount),
stepBits(stepBits), stepPointers(stepPointers), structDataSize(0), structReferenceCount(0),
nestingLimit(nestingLimit) {}
stepBytes(stepBytes), stepPointers(stepPointers), structDataSize(0),
structReferenceCount(0), nestingLimit(nestingLimit) {}
inline ListReader(SegmentReader* segment, const void* data, const WireReference* pointers,
ElementCount elementCount, decltype(BITS / ELEMENTS) stepBits,
decltype(REFERENCES / ELEMENTS) stepPointers, BitCount structDataSize,
ElementCount elementCount, decltype(BYTES / ELEMENTS) stepBytes,
decltype(REFERENCES / ELEMENTS) stepPointers, ByteCount structDataSize,
WireReferenceCount structReferenceCount, int nestingLimit)
: segment(segment), data(data), pointers(pointers), elementCount(elementCount),
stepBits(stepBits), stepPointers(stepPointers), structDataSize(structDataSize),
stepBytes(stepBytes), stepPointers(stepPointers), structDataSize(structDataSize),
structReferenceCount(structReferenceCount), nestingLimit(nestingLimit) {}
friend class StructReader;
......@@ -631,10 +631,6 @@ inline T StructBuilder::getDataField(ElementCount offset) const {
template <>
inline bool StructBuilder::getDataField<bool>(ElementCount offset) const {
BitCount boffset = offset * (1 * BITS / ELEMENTS);
// This branch should always be optimized away when inlining.
if (boffset == 0 * BITS) boffset = bit0Offset;
byte* b = reinterpret_cast<byte*>(data) + boffset / BITS_PER_BYTE;
return (*reinterpret_cast<uint8_t*>(b) & (1 << (boffset % BITS_PER_BYTE / BITS))) != 0;
}
......@@ -658,10 +654,6 @@ inline void StructBuilder::setDataField(
template <>
inline void StructBuilder::setDataField<bool>(ElementCount offset, bool value) const {
BitCount boffset = offset * (1 * BITS / ELEMENTS);
// This branch should always be optimized away when inlining.
if (boffset == 0 * BITS) boffset = bit0Offset;
byte* b = reinterpret_cast<byte*>(data) + boffset / BITS_PER_BYTE;
uint bitnum = boffset % BITS_PER_BYTE / BITS;
*reinterpret_cast<uint8_t*>(b) = (*reinterpret_cast<uint8_t*>(b) & ~(1 << bitnum))
......@@ -678,37 +670,29 @@ inline void StructBuilder::setDataField(
}
inline StructBuilder StructBuilder::initInlineStructField(
BitCount dataOffset, BitCount inlineDataSize,
ByteCount dataOffset, ByteCount inlineDataSize,
WireReferenceCount refIndex, WireReferenceCount inlineRefCount) const {
// This branch should be optimized away.
if (inlineDataSize == 1 * BITS) {
setDataField<bool>(dataOffset / (1 * BITS / ELEMENTS), false);
} else {
memset(reinterpret_cast<byte*>(data) + dataOffset / BITS_PER_BYTE / BYTES,
0, inlineDataSize / BITS_PER_BYTE / BYTES);
}
memset(reinterpret_cast<byte*>(data) + dataOffset, 0, inlineDataSize / BYTES);
memset(reinterpret_cast<word*>(references) + refIndex * WORDS_PER_REFERENCE,
0, inlineRefCount * WORDS_PER_REFERENCE * BYTES_PER_WORD / BYTES);
return getInlineStructField(dataOffset, inlineDataSize, refIndex, inlineRefCount);
}
inline StructBuilder StructBuilder::getInlineStructField(
BitCount dataOffset, BitCount inlineDataSize,
ByteCount dataOffset, ByteCount inlineDataSize,
WireReferenceCount refIndex, WireReferenceCount inlineRefCount) const {
return StructBuilder(
segment, reinterpret_cast<byte*>(data) + dataOffset / BITS_PER_BYTE,
segment, reinterpret_cast<byte*>(data) + dataOffset,
// WireReference is incomplete here so we have to cast around... Bah.
reinterpret_cast<WireReference*>(
reinterpret_cast<word*>(references) + refIndex * WORDS_PER_REFERENCE),
dataOffset == 0 * BITS ? BitCount(bit0Offset) : dataOffset % BITS_PER_BYTE,
inlineRefCount);
}
inline ListBuilder StructBuilder::initInlineDataListField(
BitCount offset, BitCount inlineSize,
ByteCount offset, ByteCount inlineSize,
ElementCount elementCount, FieldSize elementSize) const {
memset(reinterpret_cast<byte*>(data) + offset / BITS_PER_BYTE, 0,
inlineSize / BITS_PER_BYTE / BYTES);
memset(reinterpret_cast<byte*>(data) + offset, 0, inlineSize / BYTES);
return getInlineDataListField(offset, elementCount, elementSize);
}
......@@ -721,20 +705,20 @@ inline ListBuilder StructBuilder::initInlinePointerListField(
}
inline ListBuilder StructBuilder::initInlineStructListField(
BitCount dataOffset, WireReferenceCount ptrOffset, ElementCount elementCount,
ByteCount dataOffset, WireReferenceCount ptrOffset, ElementCount elementCount,
StructSize elementSize) const {
memset(reinterpret_cast<byte*>(data) + dataOffset / BITS_PER_BYTE, 0,
elementSize.dataBits / BITS_PER_BYTE / BYTES);
memset(reinterpret_cast<byte*>(data) + dataOffset, 0,
elementSize.dataBytes / BYTES);
memset(reinterpret_cast<word*>(references) + ptrOffset * WORDS_PER_REFERENCE, 0,
elementSize.pointers * BYTES_PER_REFERENCE / BYTES);
return getInlineStructListField(dataOffset, ptrOffset, elementCount, elementSize);
}
inline ListBuilder StructBuilder::getInlineDataListField(
BitCount offset, ElementCount elementCount, FieldSize elementSize) const {
ByteCount offset, ElementCount elementCount, FieldSize elementSize) const {
return ListBuilder(
segment, reinterpret_cast<byte*>(data) + offset / BITS_PER_BYTE, nullptr,
bitsPerElement(elementSize), 0 * REFERENCES / ELEMENTS, elementCount);
segment, reinterpret_cast<byte*>(data) + offset, nullptr,
bytesPerElement(elementSize), 0 * REFERENCES / ELEMENTS, elementCount);
}
inline ListBuilder StructBuilder::getInlinePointerListField(
......@@ -743,17 +727,17 @@ inline ListBuilder StructBuilder::getInlinePointerListField(
segment, nullptr,
reinterpret_cast<WireReference*>(
reinterpret_cast<word*>(references) + offset * WORDS_PER_REFERENCE),
0 * BITS / ELEMENTS, 1 * REFERENCES / ELEMENTS, elementCount);
0 * BYTES / ELEMENTS, 1 * REFERENCES / ELEMENTS, elementCount);
}
inline ListBuilder StructBuilder::getInlineStructListField(
BitCount dataOffset, WireReferenceCount ptrOffset, ElementCount elementCount,
ByteCount dataOffset, WireReferenceCount ptrOffset, ElementCount elementCount,
StructSize elementSize) const {
return ListBuilder(
segment, reinterpret_cast<byte*>(data) + dataOffset / BITS_PER_BYTE,
segment, reinterpret_cast<byte*>(data) + dataOffset,
reinterpret_cast<WireReference*>(
reinterpret_cast<word*>(references) + ptrOffset * WORDS_PER_REFERENCE),
elementSize.dataBits / ELEMENTS, elementSize.pointers / ELEMENTS,
elementSize.dataBytes / ELEMENTS, elementSize.pointers / ELEMENTS,
elementCount);
}
......@@ -761,7 +745,7 @@ inline ListBuilder StructBuilder::getInlineStructListField(
template <typename T>
T StructReader::getDataField(ElementCount offset) const {
if ((offset + 1 * ELEMENTS) * capnproto::bitsPerElement<T>() <= dataSize) {
if ((offset + 1 * ELEMENTS) * capnproto::bytesPerElement<T>() <= dataSize) {
return reinterpret_cast<const WireValue<T>*>(data)[offset / ELEMENTS].get();
} else {
return static_cast<T>(0);
......@@ -771,11 +755,7 @@ T StructReader::getDataField(ElementCount offset) const {
template <>
inline bool StructReader::getDataField<bool>(ElementCount offset) const {
BitCount boffset = offset * (1 * BITS / ELEMENTS);
// This branch should always be optimized away when inlining.
if (boffset == 0 * BITS) boffset = bit0Offset;
if (boffset < dataSize) {
if (boffset < dataSize * BITS_PER_BYTE) {
const byte* b = reinterpret_cast<const byte*>(data) + boffset / BITS_PER_BYTE;
return (*reinterpret_cast<const uint8_t*>(b) & (1 << (boffset % BITS_PER_BYTE / BITS))) != 0;
} else {
......@@ -794,23 +774,22 @@ T StructReader::getDataField(ElementCount offset, typename MaskType<T>::Type mas
}
inline StructReader StructReader::getInlineStructField(
BitCount dataOffset, BitCount inlineDataSize,
ByteCount dataOffset, ByteCount inlineDataSize,
WireReferenceCount refIndex, WireReferenceCount inlineRefCount) const {
return StructReader(
segment, reinterpret_cast<const byte*>(data) + dataOffset / BITS_PER_BYTE,
segment, reinterpret_cast<const byte*>(data) + dataOffset,
// WireReference is incomplete here so we have to cast around... Bah.
reinterpret_cast<const WireReference*>(
reinterpret_cast<const word*>(references) + refIndex * WORDS_PER_REFERENCE),
dataSize, inlineRefCount,
dataOffset == 0 * BITS ? BitCount(bit0Offset) : dataOffset % BITS_PER_BYTE,
nestingLimit);
}
inline ListReader StructReader::getInlineDataListField(
BitCount offset, ElementCount elementCount, FieldSize elementSize) const {
ByteCount offset, ElementCount elementCount, FieldSize elementSize) const {
return ListReader(
segment, reinterpret_cast<const byte*>(data) + offset / BITS_PER_BYTE, nullptr,
elementCount, bitsPerElement(elementSize), 0 * REFERENCES / ELEMENTS,
segment, reinterpret_cast<const byte*>(data) + offset, nullptr,
elementCount, bytesPerElement(elementSize), 0 * REFERENCES / ELEMENTS,
nestingLimit);
}
......@@ -820,19 +799,19 @@ inline ListReader StructReader::getInlinePointerListField(
segment, nullptr,
reinterpret_cast<const WireReference*>(
reinterpret_cast<const word*>(references) + offset * WORDS_PER_REFERENCE),
elementCount, 0 * BITS / ELEMENTS, 1 * REFERENCES / ELEMENTS,
elementCount, 0 * BYTES / ELEMENTS, 1 * REFERENCES / ELEMENTS,
nestingLimit);
}
inline ListReader StructReader::getInlineStructListField(
BitCount dataOffset, WireReferenceCount ptrOffset, ElementCount elementCount,
ByteCount dataOffset, WireReferenceCount ptrOffset, ElementCount elementCount,
StructSize elementSize) const {
return ListReader(
segment, reinterpret_cast<const byte*>(data) + dataOffset / BITS_PER_BYTE,
segment, reinterpret_cast<const byte*>(data) + dataOffset,
reinterpret_cast<const WireReference*>(
reinterpret_cast<const word*>(references) + ptrOffset * WORDS_PER_REFERENCE),
elementCount, elementSize.dataBits / ELEMENTS, elementSize.pointers / ELEMENTS,
elementSize.dataBits, elementSize.pointers, nestingLimit);
elementCount, elementSize.dataBytes / ELEMENTS, elementSize.pointers / ELEMENTS,
elementSize.dataBytes, elementSize.pointers, nestingLimit);
}
// -------------------------------------------------------------------
......@@ -842,12 +821,13 @@ inline ElementCount ListBuilder::size() { return elementCount; }
template <typename T>
inline T ListBuilder::getDataElement(ElementCount index) const {
return reinterpret_cast<WireValue<T>*>(
reinterpret_cast<byte*>(data) + index * stepBits / BITS_PER_BYTE)->get();
reinterpret_cast<byte*>(data) + index * stepBytes)->get();
}
template <>
inline bool ListBuilder::getDataElement<bool>(ElementCount index) const {
BitCount bindex = index * stepBits;
// Ignore stepBytes for bit lists because bit lists cannot be upgraded to struct lists.
BitCount bindex = index * (1 * BITS / ELEMENTS);
byte* b = reinterpret_cast<byte*>(data) + bindex / BITS_PER_BYTE;
return (*reinterpret_cast<uint8_t*>(b) & (1 << (bindex % BITS_PER_BYTE / BITS))) != 0;
}
......@@ -860,12 +840,13 @@ inline Void ListBuilder::getDataElement<Void>(ElementCount index) const {
template <typename T>
inline void ListBuilder::setDataElement(ElementCount index, typename NoInfer<T>::Type value) const {
reinterpret_cast<WireValue<T>*>(
reinterpret_cast<byte*>(data) + index * stepBits / BITS_PER_BYTE)->set(value);
reinterpret_cast<byte*>(data) + index * stepBytes)->set(value);
}
template <>
inline void ListBuilder::setDataElement<bool>(ElementCount index, bool value) const {
BitCount bindex = index * stepBits;
// Ignore stepBytes for bit lists because bit lists cannot be upgraded to struct lists.
BitCount bindex = index * (1 * BITS / ELEMENTS);
byte* b = reinterpret_cast<byte*>(data) + bindex / BITS_PER_BYTE;
uint bitnum = bindex % BITS_PER_BYTE / BITS;
*reinterpret_cast<uint8_t*>(b) = (*reinterpret_cast<uint8_t*>(b) & ~(1 << bitnum))
......@@ -882,12 +863,13 @@ inline ElementCount ListReader::size() { return elementCount; }
template <typename T>
inline T ListReader::getDataElement(ElementCount index) const {
return reinterpret_cast<const WireValue<T>*>(
reinterpret_cast<const byte*>(data) + index * stepBits / BITS_PER_BYTE)->get();
reinterpret_cast<const byte*>(data) + index * stepBytes)->get();
}
template <>
inline bool ListReader::getDataElement<bool>(ElementCount index) const {
BitCount bindex = index * stepBits;
// Ignore stepBytes for bit lists because bit lists cannot be upgraded to struct lists.
BitCount bindex = index * (1 * BITS / ELEMENTS);
const byte* b = reinterpret_cast<const byte*>(data) + bindex / BITS_PER_BYTE;
return (*reinterpret_cast<const uint8_t*>(b) & (1 << (bindex % BITS_PER_BYTE / BITS))) != 0;
}
......
......@@ -276,27 +276,25 @@ struct TestUsing {
innerNestedEnum @0 :NestedEnum = quux;
}
struct TestInline0 fixed(0 bits) { f @0: Void; }
struct TestInline1 fixed(1 bits) { f @0: Bool; }
struct TestInline8 fixed(8 bits) { f0 @0: Bool; f1 @1: Bool; f2 @2: Bool; }
struct TestInline16 fixed(16 bits) { f0 @0: UInt8; f1 @1: UInt8; }
struct TestInline32 fixed(32 bits) { f0 @0: UInt8; f1 @1: UInt16; }
struct TestInline64 fixed(64 bits) { f0 @0: UInt8; f1 @1: UInt32; }
struct TestInline0 fixed() { f @0: Void; }
struct TestInline8 fixed(1 bytes) { f0 @0: Bool; f1 @1: Bool; f2 @2: Bool; }
struct TestInline16 fixed(2 bytes) { f0 @0: UInt8; f1 @1: UInt8; }
struct TestInline32 fixed(4 bytes) { f0 @0: UInt8; f1 @1: UInt16; }
struct TestInline64 fixed(8 bytes) { f0 @0: UInt8; f1 @1: UInt32; }
struct TestInline128 fixed(2 words) { f0 @0: UInt64; f1 @1: UInt64; }
struct TestInline192 fixed(3 words) { f0 @0: UInt64; f1 @1: UInt64; f2 @2: UInt64; }
struct TestInline0p fixed(0 bits, 1 pointers) { f @0 :Inline(TestInline0); p0 @1 :Text; }
struct TestInline1p fixed(1 bits, 1 pointers) { f @0 :Inline(TestInline1); p0 @1 :Text; }
struct TestInline8p fixed(8 bits, 1 pointers) { f @0 :Inline(TestInline8); p0 @1 :Text; }
struct TestInline16p fixed(16 bits, 2 pointers) { f @0 :Inline(TestInline16); p0 @1 :Text; p1 @2 :Text; }
struct TestInline32p fixed(32 bits, 2 pointers) { f @0 :Inline(TestInline32); p0 @1 :Text; p1 @2 :Text; }
struct TestInline64p fixed(64 bits, 2 pointers) { f @0 :Inline(TestInline64); p0 @1 :Text; p1 @2 :Text; }
struct TestInline0p fixed(1 pointers) { f @0 :Inline(TestInline0); p0 @1 :Text; }
struct TestInline8p fixed(1 bytes, 1 pointers) { f @0 :Inline(TestInline8); p0 @1 :Text; }
struct TestInline16p fixed(2 bytes, 2 pointers) { f @0 :Inline(TestInline16); p0 @1 :Text; p1 @2 :Text; }
struct TestInline32p fixed(4 bytes, 2 pointers) { f @0 :Inline(TestInline32); p0 @1 :Text; p1 @2 :Text; }
struct TestInline64p fixed(8 bytes, 2 pointers) { f @0 :Inline(TestInline64); p0 @1 :Text; p1 @2 :Text; }
struct TestInline128p fixed(2 words, 3 pointers) { f @0 :Inline(TestInline128); p0 @1 :Text; p1 @2 :Text; p2 @3 :Text; }
struct TestInline192p fixed(3 words, 3 pointers) { f @0 :Inline(TestInline192); p0 @1 :Text; p1 @2 :Text; p2 @3 :Text; }
struct TestInlineLayout {
f0 @0 :Inline(TestInline0);
f1 @1 :Inline(TestInline1);
pad1 @1 :UInt8;
f8 @2 :Inline(TestInline8);
f16 @3 :Inline(TestInline16);
f32 @4 :Inline(TestInline32);
......@@ -305,22 +303,20 @@ struct TestInlineLayout {
f192 @7 :Inline(TestInline192);
f0p @8 :Inline(TestInline0p);
f1p @9 :Inline(TestInline1p);
f8p @10 :Inline(TestInline8p);
f16p @11 :Inline(TestInline16p);
f32p @12 :Inline(TestInline32p);
f64p @13 :Inline(TestInline64p);
f128p @14 :Inline(TestInline128p);
f192p @15 :Inline(TestInline192p);
f1Offset @16 :Inline(TestInline1);
bit @17 :Bool;
pad2 @9 :UInt8;
padP @10 :Text;
f8p @11 :Inline(TestInline8p);
f16p @12 :Inline(TestInline16p);
f32p @13 :Inline(TestInline32p);
f64p @14 :Inline(TestInline64p);
f128p @15 :Inline(TestInline128p);
f192p @16 :Inline(TestInline192p);
}
struct TestInlineUnions {
union0 @0 union {
f0 @4 :Inline(TestInline0);
f1 @5 :Inline(TestInline1);
f1 @5 :Bool; # There used to be a TestInline1 but it was decided to be a bad idea.
f8 @6 :Inline(TestInline8);
f16 @7 :Inline(TestInline16);
f32 @8 :Inline(TestInline32);
......@@ -329,7 +325,7 @@ struct TestInlineUnions {
f192 @11 :Inline(TestInline192);
f0p @12 :Inline(TestInline0p);
f1p @13 :Inline(TestInline1p);
f1p @13 :Bool;
f8p @14 :Inline(TestInline8p);
f16p @15 :Inline(TestInline16p);
f32p @16 :Inline(TestInline32p);
......@@ -343,7 +339,7 @@ struct TestInlineUnions {
union1 @1 union {
f0 @21 :Inline(TestInline0);
f1 @22 :Inline(TestInline1);
f1 @22 :Bool;
f8 @23 :Inline(TestInline8);
f16 @24 :Inline(TestInline16);
f32 @25 :Inline(TestInline32);
......@@ -362,7 +358,7 @@ struct TestInlineUnions {
# Interleave two unions to be really annoying.
union2 @2 union {
f1p @35 :Inline(TestInline1p);
f1p @35 :Bool;
f8p @37 :Inline(TestInline8p);
f16p @40 :Inline(TestInline16p);
f32p @42 :Inline(TestInline32p);
......@@ -372,7 +368,7 @@ struct TestInlineUnions {
}
union3 @3 union {
f1p @36 :Inline(TestInline1p);
f1p @36 :Bool;
f8p @38 :Inline(TestInline8p);
f16p @41 :Inline(TestInline16p);
f32p @43 :Inline(TestInline32p);
......@@ -394,7 +390,7 @@ struct TestInlineLists {
textList @ 6 : InlineList(Text, 8);
structList0 @ 7 : InlineList(TestInline0, 2);
structList1 @ 8 : InlineList(TestInline1, 3);
structList1 @ 8 : InlineList(Bool, 3);
structList8 @ 9 : InlineList(TestInline8, 4);
structList16 @10 : InlineList(TestInline16, 2);
structList32 @11 : InlineList(TestInline32, 3);
......@@ -403,7 +399,7 @@ struct TestInlineLists {
structList192 @14 : InlineList(TestInline192, 3);
structList0p @15 : InlineList(TestInline0p, 4);
structList1p @16 : InlineList(TestInline1p, 2);
structList1p @16 : InlineList(Bool, 2);
structList8p @17 : InlineList(TestInline8p, 3);
structList16p @18 : InlineList(TestInline16p, 4);
structList32p @19 : InlineList(TestInline32p, 2);
......@@ -435,7 +431,6 @@ struct TestStructLists {
struct TestInlineDefaults {
normal @0 :TestInlineLayout = (
f0 = (f = void),
f1 = (f = true),
f8 = (f0 = true, f1 = false, f2 = true),
f16 = (f0 = 123, f1 = 45),
f32 = (f0 = 67, f1 = 8901),
......@@ -444,7 +439,6 @@ struct TestInlineDefaults {
f192 = (f0 = 7890123456789, f1 = 2345678901234, f2 = 5678901234567),
f0p = (p0 = "foo"),
f1p = (f = (f = false), p0 = "bar"),
f8p = (f = (f0 = true, f1 = true, f2 = false), p0 = "baz"),
f16p = (f = (f0 = 98, f1 = 76), p0 = "qux", p1 = "quux"),
f32p = (f = (f0 = 54, f1 = 32109), p0 = "corge", p1 = "grault"),
......@@ -457,7 +451,7 @@ struct TestInlineDefaults {
unions @1 :TestInlineUnions = (
union0 = f32(f0 = 67, f1 = 8901),
union1 = f128(f0 = 1234567890123, f1 = 4567890123456),
union2 = f1p(p0 = "foo"),
union2 = f8p(p0 = "foo"),
union3 = f16p(f = (f0 = 98, f1 = 76), p0 = "qux", p1 = "quux"));
lists @2 :TestInlineLists = (
......@@ -470,7 +464,6 @@ struct TestInlineDefaults {
textList = ["foo", "bar", "baz", "qux", "quux", "corge", "grault", "garply"],
structList0 = [(f = void), ()],
structList1 = [(f = true), (f = false), (f = true)],
structList8 = [(f0 = true, f1 = false, f2 = false),
(f0 = false, f1 = true, f2 = false),
(f0 = true, f1 = true, f2 = false),
......@@ -487,7 +480,6 @@ struct TestInlineDefaults {
structList0p = [(f = (f = void), p0 = "foo"), (p0 = "bar"),
(f = (), p0 = "baz"), (p0 = "qux")],
structList1p = [(f = (f = true), p0 = "quux"), (p0 = "corge")],
structList8p = [(f = (f0 = true), p0 = "grault"), (p0 = "garply"), (p0 = "waldo")],
structList16p = [(f = (f0 = 123), p0 = "fred", p1 = "plugh"),
(p0 = "xyzzy", p1 = "thud"),
......
......@@ -682,7 +682,8 @@ packUnion :: UnionDesc -> PackingState -> Map.Map Integer UnionPackingState
packUnion _ state unionState = (DataOffset Size16 offset, newState, unionState) where
(offset, newState) = packData Size16 state
stripHolesFromFirstWord Size1 _ = Size1 -- Nothing left to strip.
stripHolesFromFirstWord Size1 _ = error "can't get this far"
stripHolesFromFirstWord Size8 _ = Size8 -- Don't reduce to less than a byte.
stripHolesFromFirstWord size holes = let
nextSize = pred size
in case Map.lookup nextSize holes of
......@@ -717,13 +718,12 @@ enforceFixed Nothing sizes = return sizes
enforceFixed (Just (Located pos (requestedDataSize, requestedPointerCount)))
(actualDataSize, actualPointerCount) = do
validatedRequestedDataSize <- case requestedDataSize of
1 -> return DataSection1
8 -> return DataSection8
16 -> return DataSection16
32 -> return DataSection32
s | mod s 64 == 0 -> return $ DataSectionWords $ div s 64
_ -> makeError pos $ printf "Struct data section size must be a whole number of words \
\or 0, 1, 8, 16, or 32 bits."
\or 0, 1, 2, 4, or 8 bytes."
recover () $ when (dataSectionBits actualDataSize > dataSectionBits validatedRequestedDataSize) $
makeError pos $ printf "Struct data section size is %s which exceeds specified maximum of \
......
......@@ -161,12 +161,12 @@ fieldOffsetInteger VoidOffset = "0"
fieldOffsetInteger (DataOffset _ o) = show o
fieldOffsetInteger (PointerOffset o) = show o
fieldOffsetInteger (InlineCompositeOffset d p ds ps) = let
bitSize = dataSectionBits ds
bitOffset = case ds of
DataSectionWords _ -> d * 64
_ -> d * bitSize
in printf "%d * ::capnproto::BITS, %d * ::capnproto::BITS, \
\%d * ::capnproto::REFERENCES, %d * ::capnproto::REFERENCES" bitOffset bitSize p ps
byteSize = div (dataSectionBits ds) 8
byteOffset = case ds of
DataSectionWords _ -> d * 8
_ -> d * byteSize
in printf "%d * ::capnproto::BYTES, %d * ::capnproto::BYTES, \
\%d * ::capnproto::REFERENCES, %d * ::capnproto::REFERENCES" byteOffset byteSize p ps
isDefaultZero VoidDesc = True
isDefaultZero (BoolDesc b) = not b
......@@ -266,11 +266,11 @@ fieldContext parent desc = mkStrContext context where
_ -> muNull
context "fieldInlineDataOffset" = case fieldOffset desc of
InlineCompositeOffset off _ size _ ->
MuVariable (off * dataSizeInBits (dataSectionAlignment size))
MuVariable (off * div (dataSizeInBits (dataSectionAlignment size)) 8)
_ -> muNull
context "fieldInlineDataSize" = case fieldOffset desc of
InlineCompositeOffset _ _ size _ ->
MuVariable $ dataSectionBits size
MuVariable $ div (dataSectionBits size) 8
_ -> muNull
context "fieldInlinePointerOffset" = case fieldOffset desc of
InlineCompositeOffset _ off _ _ -> MuVariable off
......@@ -330,7 +330,7 @@ structContext parent desc = mkStrContext context where
context "structFields" = MuList $ map (fieldContext context) $ structFields desc
context "structUnions" = MuList $ map (unionContext context) $ structUnions desc
context "structDataSize" = MuVariable $ dataSectionWordSize $ structDataSize desc
context "structDataBits" = MuVariable $ dataSectionBits $ structDataSize desc
context "structDataBytes" = MuVariable (div (dataSectionBits (structDataSize desc)) 8)
context "structReferenceCount" = MuVariable $ structPointerCount desc
context "structNestedEnums" =
MuList $ map (enumContext context) [m | DescEnum m <- structMembers desc]
......
......@@ -254,15 +254,14 @@ combineFixedSizes (_, Just _) (FixedPointers _) =
fixedSize = do
size <- literalInt
(exactIdentifier "bit" >> return (FixedData size))
<|> (exactIdentifier "bits" >> return (FixedData size))
<|> (exactIdentifier "byte" >> return (FixedData (8 * size)))
-- We do not allow single-bit structs because most CPUs cannot address bits.
(exactIdentifier "byte" >> return (FixedData (8 * size)))
<|> (exactIdentifier "bytes" >> return (FixedData (8 * size)))
<|> (exactIdentifier "word" >> return (FixedData (64 * size)))
<|> (exactIdentifier "words" >> return (FixedData (64 * size)))
<|> (exactIdentifier "pointer" >> return (FixedPointers size))
<|> (exactIdentifier "pointers" >> return (FixedPointers size))
<?> "\"bits\", \"bytes\", \"words\", or \"pointers\""
<?> "\"bytes\", \"words\", or \"pointers\""
structLine :: Maybe [Located Statement] -> TokenParser Declaration
structLine Nothing = usingDecl <|> constantDecl <|> fieldDecl <|> annotationDecl
......
......@@ -263,9 +263,9 @@ dataSizeToSectionSize Size32 = DataSection32
dataSizeToSectionSize Size64 = DataSectionWords 1
dataSectionSizeString DataSection1 = "1 bits"
dataSectionSizeString DataSection8 = "8 bits"
dataSectionSizeString DataSection16 = "16 bits"
dataSectionSizeString DataSection32 = "32 bits"
dataSectionSizeString DataSection8 = "1 bytes"
dataSectionSizeString DataSection16 = "2 bytes"
dataSectionSizeString DataSection32 = "4 bytes"
dataSectionSizeString (DataSectionWords n) = show n ++ " words"
data DataSize = Size1 | Size8 | Size16 | Size32 | Size64 deriving(Eq, Ord, Enum)
......@@ -319,9 +319,9 @@ fieldSize (InlineStructType StructDesc { structDataSize = ds, structPointerCount
fieldSize (InterfaceType _) = SizeReference
fieldSize (ListType _) = SizeReference
fieldSize (InlineListType element size) = let
-- We intentionally do not allow single-bit lists because most CPUs cannot address bits.
minDataSectionForBits bits
| bits <= 0 = DataSectionWords 0
| bits <= 1 = DataSection1
| bits <= 8 = DataSection8
| bits <= 16 = DataSection16
| bits <= 32 = DataSection32
......
......@@ -70,7 +70,7 @@ struct {{typeFullName}} {
static constexpr ::capnproto::internal::StructSize STRUCT_SIZE =
::capnproto::internal::StructSize({{structDataSize}} * ::capnproto::WORDS,
{{structReferenceCount}} * ::capnproto::REFERENCES,
{{structDataBits}} * ::capnproto::BITS);
{{structDataBytes}} * ::capnproto::BYTES);
{{/typeStruct}}
{{#typeUnion}}
......@@ -375,7 +375,7 @@ inline {{fieldType}}::Reader {{typeFullName}}::Reader::get{{fieldTitleCase}}() {
"Must check which() before get()ing a union member.");
{{/fieldUnion}}
return {{fieldType}}::Reader(_reader.getInlineDataListField(
{{fieldInlineDataOffset}} * ::capnproto::BITS,
{{fieldInlineDataOffset}} * ::capnproto::BYTES,
{{fieldInlineListSize}} * ::capnproto::ELEMENTS,
::capnproto::internal::FieldSize::{{fieldElementSize}}));
}
......@@ -386,8 +386,8 @@ inline {{fieldType}}::Builder {{typeFullName}}::Builder::init{{fieldTitleCase}}(
{{unionTagOffset}} * ::capnproto::ELEMENTS, {{unionTitleCase}}::{{fieldUpperCase}});
{{/fieldUnion}}
return {{fieldType}}::Builder(_builder.initInlineDataListField(
{{fieldInlineDataOffset}} * ::capnproto::BITS,
{{fieldInlineDataSize}} * ::capnproto::BITS,
{{fieldInlineDataOffset}} * ::capnproto::BYTES,
{{fieldInlineDataSize}} * ::capnproto::BYTES,
{{fieldInlineListSize}} * ::capnproto::ELEMENTS,
::capnproto::internal::FieldSize::{{fieldElementSize}}));
}
......@@ -397,7 +397,7 @@ inline {{fieldType}}::Builder {{typeFullName}}::Builder::get{{fieldTitleCase}}()
"Must check which() before get()ing a union member.");
{{/fieldUnion}}
return {{fieldType}}::Builder(_builder.getInlineDataListField(
{{fieldInlineDataOffset}} * ::capnproto::BITS,
{{fieldInlineDataOffset}} * ::capnproto::BYTES,
{{fieldInlineListSize}} * ::capnproto::ELEMENTS,
::capnproto::internal::FieldSize::{{fieldElementSize}}));
}
......@@ -509,7 +509,7 @@ inline {{fieldType}}::Reader {{typeFullName}}::Reader::get{{fieldTitleCase}}() {
"Must check which() before get()ing a union member.");
{{/fieldUnion}}
return {{fieldType}}::Reader(_reader.getInlineStructListField(
{{fieldInlineDataOffset}} * ::capnproto::BITS,
{{fieldInlineDataOffset}} * ::capnproto::BYTES,
{{fieldInlinePointerOffset}} * ::capnproto::REFERENCES,
{{fieldInlineListSize}} * ::capnproto::ELEMENTS,
{{fieldElementType}}::STRUCT_SIZE));
......@@ -521,7 +521,7 @@ inline {{fieldType}}::Builder {{typeFullName}}::Builder::init{{fieldTitleCase}}(
{{unionTagOffset}} * ::capnproto::ELEMENTS, {{unionTitleCase}}::{{fieldUpperCase}});
{{/fieldUnion}}
return {{fieldType}}::Builder(_builder.initInlineStructListField(
{{fieldInlineDataOffset}} * ::capnproto::BITS,
{{fieldInlineDataOffset}} * ::capnproto::BYTES,
{{fieldInlinePointerOffset}} * ::capnproto::REFERENCES,
{{fieldInlineListSize}} * ::capnproto::ELEMENTS,
{{fieldElementType}}::STRUCT_SIZE));
......@@ -532,7 +532,7 @@ inline {{fieldType}}::Builder {{typeFullName}}::Builder::get{{fieldTitleCase}}()
"Must check which() before get()ing a union member.");
{{/fieldUnion}}
return {{fieldType}}::Builder(_builder.getInlineStructListField(
{{fieldInlineDataOffset}} * ::capnproto::BITS,
{{fieldInlineDataOffset}} * ::capnproto::BYTES,
{{fieldInlinePointerOffset}} * ::capnproto::REFERENCES,
{{fieldInlineListSize}} * ::capnproto::ELEMENTS,
{{fieldElementType}}::STRUCT_SIZE));
......
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