Commit 9c54bce6 authored by Kenton Varda's avatar Kenton Varda

Fix problems with AnyStruct / AnyList change.

parent fff8e987
...@@ -177,10 +177,11 @@ struct AnyPointer { ...@@ -177,10 +177,11 @@ 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); inline AnyList::Builder initAsAnyList(ElementSize elementSize, uint elementCount);
// Note: Does not accept INLINE_COMPOSITE for elementSize. // Note: Does not accept INLINE_COMPOSITE for elementSize.
inline List<AnyStruct>::Builder initAsListOfAnyStruct(uint dataWordCount, uint pointerCount, uint elementCount); inline List<AnyStruct>::Builder initAsListOfAnyStruct(
uint dataWordCount, uint pointerCount, uint elementCount);
inline AnyStruct::Builder initAsAnyStruct(uint dataWordCount, uint pointerCount); inline AnyStruct::Builder initAsAnyStruct(uint dataWordCount, uint pointerCount);
...@@ -540,10 +541,8 @@ public: ...@@ -540,10 +541,8 @@ public:
Reader() = default; Reader() = default;
inline Reader(_::ListReader reader): _reader(reader) {} inline Reader(_::ListReader reader): _reader(reader) {}
_::FieldSize getElementSize(); inline ElementSize getElementSize() { return _reader.getElementSize(); }
ElementCount size() { inline uint size() { return _reader.size() / ELEMENTS; }
return _reader.size();
}
template <typename T> ReaderFor<T> as() { template <typename T> ReaderFor<T> as() {
// T must be List<U>. // T must be List<U>.
...@@ -556,13 +555,10 @@ private: ...@@ -556,13 +555,10 @@ private:
class AnyList::Builder { class AnyList::Builder {
public: public:
inline Builder(decltype(nullptr)) {} 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) {} inline Builder(_::ListBuilder builder): _builder(builder) {}
_::FieldSize getElementSize(); inline ElementSize getElementSize() { return _builder.getElementSize(); }
ElementCount size() { inline uint size() { return _builder.size() / ELEMENTS; }
return _builder.size();
}
template <typename T> BuilderFor<T> as() { template <typename T> BuilderFor<T> as() {
// T must be List<U>. // T must be List<U>.
...@@ -576,39 +572,49 @@ private: ...@@ -576,39 +572,49 @@ private:
_::ListBuilder _builder; _::ListBuilder _builder;
}; };
namespace _ { // (private) namespace _ { // (private)
template <> template <>
struct PointerHelpers<AnyStruct, Kind::OTHER> { struct PointerHelpers<AnyStruct, Kind::OTHER> {
static inline typename AnyStruct::Reader get(PointerReader reader, const word* defaultValue = nullptr) { static inline typename AnyStruct::Reader get(
PointerReader reader, const word* defaultValue = nullptr) {
return typename AnyStruct::Reader(reader.getStruct(defaultValue)); return typename AnyStruct::Reader(reader.getStruct(defaultValue));
} }
static inline typename AnyStruct::Builder get(PointerBuilder builder, static inline typename AnyStruct::Builder get(
const word* defaultValue = nullptr) { PointerBuilder builder, const word* defaultValue = nullptr) {
return typename AnyStruct::Builder(builder, /* TODO: allow specifying the size! */ _::StructSize(0, 0), defaultValue); // TODO(someday): allow specifying the size
return typename AnyStruct::Builder(
builder, _::StructSize(0 * WORDS, 0 * POINTERS), defaultValue);
} }
static inline typename AnyStruct::Builder init(PointerBuilder builder, uint dataWordCount, uint pointerCount) { static inline typename AnyStruct::Builder init(
return typename AnyStruct::Builder(builder.initStruct(StructSize(dataWordCount, pointerCount))); PointerBuilder builder, uint dataWordCount, uint pointerCount) {
return typename AnyStruct::Builder(builder.initStruct(
StructSize(dataWordCount * WORDS, pointerCount * POINTERS)));
} }
}; };
template <> template <>
struct PointerHelpers<AnyList, Kind::OTHER> { struct PointerHelpers<AnyList, Kind::OTHER> {
static inline typename AnyList::Reader get(PointerReader reader, const word* defaultValue = nullptr) { static inline typename AnyList::Reader get(
return typename AnyList::Reader(reader.getList(/* TODO: allow specifying the size! */ FieldSize::VOID, defaultValue)); PointerReader reader, const word* defaultValue = nullptr) {
return typename AnyList::Reader(reader.getListAnySize(defaultValue));
} }
static inline typename AnyList::Builder get(PointerBuilder builder, static inline typename AnyList::Builder get(
const word* defaultValue = nullptr) { PointerBuilder builder, const word* defaultValue = nullptr) {
return typename AnyList::Builder(builder, /* TODO: allow specifying the size! */ FieldSize::VOID, defaultValue); return typename AnyList::Builder(builder.getListAnySize(defaultValue));
} }
static inline typename AnyList::Builder init(PointerBuilder builder, FieldSize elementSize, uint elementCount) { static inline typename AnyList::Builder init(
return typename AnyList::Builder(builder.initList(elementSize, elementCount)); PointerBuilder builder, ElementSize elementSize, uint elementCount) {
return typename AnyList::Builder(builder.initList(elementSize, elementCount * ELEMENTS));
} }
static inline typename AnyList::Builder init(PointerBuilder builder, uint dataWordCount, uint pointerCount, uint elementCount) { static inline typename AnyList::Builder init(
PointerBuilder builder, uint dataWordCount, uint pointerCount, uint elementCount) {
return typename AnyList::Builder(builder.initStructList( return typename AnyList::Builder(builder.initStructList(
elementCount, elementCount * ELEMENTS, StructSize(dataWordCount * WORDS, pointerCount * POINTERS)));
StructSize(dataWordCount, pointerCount)));
} }
}; };
} // end namespace _ (private)
} // namespace _ (private)
// ======================================================================================= // =======================================================================================
// Pipeline helpers // Pipeline helpers
...@@ -701,14 +707,20 @@ inline BuilderFor<T> AnyPointer::Builder::initAs(uint elementCount) { ...@@ -701,14 +707,20 @@ 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) { inline AnyList::Builder AnyPointer::Builder::initAsAnyList(
return _::PointerHelpers<AnyList>::init(builder, elementSize, elementCount); ElementSize elementSize, uint elementCount) {
return AnyList::Builder(builder.initList(elementSize, elementCount * ELEMENTS));
} }
// inline List<AnyStruct>::Builder AnyPointer::Builder::initAsListOfAnyStruct(uint dataWordCount, uint pointerCount, uint elementCount); inline List<AnyStruct>::Builder AnyPointer::Builder::initAsListOfAnyStruct(
uint dataWordCount, uint pointerCount, uint elementCount) {
return List<AnyStruct>::Builder(builder.initStructList(elementCount * ELEMENTS,
_::StructSize(dataWordCount * WORDS, pointerCount * POINTERS)));
}
inline AnyStruct::Builder AnyPointer::Builder::initAsAnyStruct(uint dataWordCount, uint pointerCount) { inline AnyStruct::Builder AnyPointer::Builder::initAsAnyStruct(uint dataWordCount, uint pointerCount) {
return _::PointerHelpers<AnyStruct>::init(builder, dataWordCount, pointerCount); return AnyStruct::Builder(builder.initStruct(
_::StructSize(dataWordCount * WORDS, pointerCount * POINTERS)));
} }
template <typename T> template <typename T>
......
...@@ -80,6 +80,21 @@ enum class Kind: uint8_t { ...@@ -80,6 +80,21 @@ enum class Kind: uint8_t {
// special handling. This includes types like AnyPointer, Dynamic*, etc. // special handling. This includes types like AnyPointer, Dynamic*, etc.
}; };
enum class ElementSize: uint8_t {
// Size of a list element.
VOID = 0,
BIT = 1,
BYTE = 2,
TWO_BYTES = 3,
FOUR_BYTES = 4,
EIGHT_BYTES = 5,
POINTER = 6,
INLINE_COMPOSITE = 7
};
namespace schemas { namespace schemas {
template <typename T> template <typename T>
......
This diff is collapsed.
...@@ -78,51 +78,10 @@ class BuilderArena; ...@@ -78,51 +78,10 @@ class BuilderArena;
// ============================================================================= // =============================================================================
enum class FieldSize: uint8_t { using FieldSize = capnp::ElementSize;
// TODO(cleanup): Rename to FieldLayout or maybe ValueLayout. // Legacy typedef.
//
// Notice that each member of this enum, when representing a list element size, represents a // TODO(cleanup): Replace all uses.
// size that is greater than or equal to the previous members, since INLINE_COMPOSITE is used
// only for multi-word structs. This is important because it allows us to compare FieldSize
// values for the purpose of deciding when we need to upgrade a list.
VOID = 0,
BIT = 1,
BYTE = 2,
TWO_BYTES = 3,
FOUR_BYTES = 4,
EIGHT_BYTES = 5,
POINTER = 6, // Indicates that the field lives in the pointer section, not the data section.
INLINE_COMPOSITE = 7
// A composite type of fixed width. This serves two purposes:
// 1) For lists of composite types where all the elements would have the exact same width,
// allocating a list of pointers which in turn point at the elements would waste space. We
// can avoid a layer of indirection by placing all the elements in a flat sequence, and only
// indicating the element properties (e.g. field count for structs) once.
//
// Specifically, a list pointer indicating INLINE_COMPOSITE element size actually points to
// a "tag" describing one element. This tag is formatted like a wire pointer, but the
// "offset" instead stores the element count of the list. The flat list of elements appears
// immediately after the tag. In the list pointer itself, the element count is replaced with
// a word count for the whole list (excluding tag). This allows the tag and elements to be
// precached in a single step rather than two sequential steps.
//
// It is NOT intended to be possible to substitute an INLINE_COMPOSITE list for a POINTER
// list or vice-versa without breaking recipients. Recipients expect one or the other
// depending on the message definition.
//
// However, it IS allowed to substitute an INLINE_COMPOSITE list -- specifically, of structs --
// when a list was expected, or vice versa, with the assumption that the first field of the
// struct (field number zero) correspond to the element type. This allows a list of
// primitives to be upgraded to a list of structs, avoiding the need to use parallel arrays
// when you realize that you need to attach some extra information to each element of some
// primitive list.
//
// 2) At one point there was a notion of "inline" struct fields, but it was deemed too much of
// an implementation burden for too little gain, and so was deleted.
};
typedef decltype(BITS / ELEMENTS) BitsPerElement; typedef decltype(BITS / ELEMENTS) BitsPerElement;
typedef decltype(POINTERS / ELEMENTS) PointersPerElement; typedef decltype(POINTERS / ELEMENTS) PointersPerElement;
...@@ -330,6 +289,7 @@ public: ...@@ -330,6 +289,7 @@ public:
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);
ListBuilder getStructList(StructSize elementSize, const word* defaultValue); ListBuilder getStructList(StructSize elementSize, const word* defaultValue);
ListBuilder getListAnySize(const word* defaultValue);
template <typename T> typename T::Builder getBlob(const void* defaultValue,ByteCount defaultSize); template <typename T> typename T::Builder getBlob(const void* defaultValue,ByteCount defaultSize);
#if !CAPNP_LITE #if !CAPNP_LITE
kj::Own<ClientHook> getCapability(); kj::Own<ClientHook> getCapability();
...@@ -409,6 +369,7 @@ public: ...@@ -409,6 +369,7 @@ public:
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;
ListReader getListAnySize(const word* defaultValue) const;
template <typename T> template <typename T>
typename T::Reader getBlob(const void* defaultValue, ByteCount defaultSize) const; typename T::Reader getBlob(const void* defaultValue, ByteCount defaultSize) const;
#if !CAPNP_LITE #if !CAPNP_LITE
...@@ -612,6 +573,8 @@ public: ...@@ -612,6 +573,8 @@ public:
} }
} }
inline ElementSize getElementSize() const { return elementSize; }
inline ElementCount size() const; inline ElementCount size() const;
// The number of elements in the list. // The number of elements in the list.
...@@ -680,6 +643,8 @@ public: ...@@ -680,6 +643,8 @@ public:
inline ElementCount size() const; inline ElementCount size() const;
// The number of elements in the list. // The number of elements in the list.
inline ElementSize getElementSize() const { return elementSize; }
Text::Reader asText(); Text::Reader asText();
Data::Reader asData(); Data::Reader asData();
// Reinterpret the list as a blob. Throws an exception if the elements are not byte-sized. // Reinterpret the list as a blob. Throws an exception if the elements are not byte-sized.
...@@ -854,7 +819,9 @@ inline Data::Builder StructBuilder::getDataSectionAsBlob() { ...@@ -854,7 +819,9 @@ inline Data::Builder StructBuilder::getDataSectionAsBlob() {
} }
inline _::ListBuilder StructBuilder::getPointerSectionAsList() { inline _::ListBuilder StructBuilder::getPointerSectionAsList() {
return _::ListBuilder(segment, pointers, pointerCount * BITS_PER_WORD / ELEMENTS, pointerCount, 0, 1, FieldSize::POINTER); return _::ListBuilder(segment, pointers, pointerCount * BITS_PER_POINTER / ELEMENTS,
pointerCount * (1 * ELEMENTS / POINTERS),
0 * BITS, 1 * POINTERS, FieldSize::POINTER);
} }
template <typename T> template <typename T>
...@@ -936,7 +903,9 @@ inline Data::Reader StructReader::getDataSectionAsBlob() { ...@@ -936,7 +903,9 @@ inline Data::Reader StructReader::getDataSectionAsBlob() {
} }
inline _::ListReader StructReader::getPointerSectionAsList() { inline _::ListReader StructReader::getPointerSectionAsList() {
return _::ListReader(segment, pointers, pointerCount, pointerCount * BITS_PER_WORD / ELEMENTS, 0, 1, FieldSize::POINTER, nestingLimit); return _::ListReader(segment, pointers, pointerCount * (1 * ELEMENTS / POINTERS),
pointerCount * BITS_PER_POINTER / ELEMENTS,
0 * BITS, 1 * POINTERS, FieldSize::POINTER, nestingLimit);
} }
template <typename T> template <typename T>
......
...@@ -24,7 +24,6 @@ ...@@ -24,7 +24,6 @@
#include "layout.h" #include "layout.h"
#include "list.h" #include "list.h"
// #include "any.h"
namespace capnp { namespace capnp {
namespace _ { // private namespace _ { // private
......
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