Commit 55e48fc4 authored by Kenton Varda's avatar Kenton Varda

Finish implementing and testing constants.

parent ac1e532d
...@@ -237,6 +237,42 @@ private: ...@@ -237,6 +237,42 @@ private:
KJ_UNREACHABLE; KJ_UNREACHABLE;
} }
kj::StringTree literalValue(schema::Type::Reader type, schema::Value::Reader value) {
switch (value.which()) {
case schema::Value::VOID: return kj::strTree(" ::capnp::VOID");
case schema::Value::BOOL: return kj::strTree(value.getBool() ? "true" : "false");
case schema::Value::INT8: return kj::strTree(value.getInt8());
case schema::Value::INT16: return kj::strTree(value.getInt16());
case schema::Value::INT32: return kj::strTree(value.getInt32());
case schema::Value::INT64: return kj::strTree(value.getInt64(), "ll");
case schema::Value::UINT8: return kj::strTree(value.getUint8(), "u");
case schema::Value::UINT16: return kj::strTree(value.getUint16(), "u");
case schema::Value::UINT32: return kj::strTree(value.getUint32(), "u");
case schema::Value::UINT64: return kj::strTree(value.getUint64(), "llu");
case schema::Value::FLOAT32: return kj::strTree(value.getFloat32(), "f");
case schema::Value::FLOAT64: return kj::strTree(value.getFloat64());
case schema::Value::ENUM: {
EnumSchema schema = schemaLoader.get(type.getEnum()).asEnum();
if (value.getEnum() < schema.getEnumerants().size()) {
return kj::strTree(
cppFullName(schema), "::",
toUpperCase(schema.getEnumerants()[value.getEnum()].getProto().getName()));
} else {
return kj::strTree("static_cast<", cppFullName(schema), ">(", value.getEnum(), ")");
}
}
case schema::Value::TEXT:
case schema::Value::DATA:
case schema::Value::STRUCT:
case schema::Value::INTERFACE:
case schema::Value::LIST:
case schema::Value::OBJECT:
KJ_FAIL_REQUIRE("literalValue() can only be used on primitive types.");
}
KJ_UNREACHABLE;
}
// ----------------------------------------------------------------- // -----------------------------------------------------------------
// Code to deal with "slots" -- determines what to zero out when we clear a group. // Code to deal with "slots" -- determines what to zero out when we clear a group.
...@@ -1057,6 +1093,98 @@ private: ...@@ -1057,6 +1093,98 @@ private:
// ----------------------------------------------------------------- // -----------------------------------------------------------------
struct ConstText {
bool needsSchema;
kj::StringTree decl;
kj::StringTree def;
};
ConstText makeConstText(kj::StringPtr scope, kj::StringPtr name, ConstSchema schema) {
auto proto = schema.getProto();
auto constProto = proto.getConst();
auto type = constProto.getType();
auto typeName_ = typeName(type).flatten();
auto upperCase = toUpperCase(name);
// Linkage qualifier for non-primitive types.
const char* linkage = scope.size() == 0 ? "extern " : "static ";
switch (type.which()) {
case schema::Value::VOID:
case schema::Value::BOOL:
case schema::Value::INT8:
case schema::Value::INT16:
case schema::Value::INT32:
case schema::Value::INT64:
case schema::Value::UINT8:
case schema::Value::UINT16:
case schema::Value::UINT32:
case schema::Value::UINT64:
case schema::Value::FLOAT32:
case schema::Value::FLOAT64:
case schema::Value::ENUM:
return ConstText {
false,
kj::strTree("static constexpr ", typeName_, ' ', upperCase, " = ",
literalValue(constProto.getType(), constProto.getValue()), ";\n"),
scope.size() == 0 ? kj::strTree() : kj::strTree(
"constexpr ", typeName_, ' ', scope, upperCase, ";\n")
};
case schema::Value::TEXT: {
kj::String constType = kj::strTree(
"::capnp::_::ConstText<", schema.as<Text>().size(), ">").flatten();
return ConstText {
true,
kj::strTree(linkage, "const ", constType, ' ', upperCase, ";\n"),
kj::strTree("const ", constType, ' ', scope, upperCase, "(::capnp::schemas::b_",
kj::hex(proto.getId()), ".words + ", schema.getValueSchemaOffset(), ");\n")
};
}
case schema::Value::DATA: {
kj::String constType = kj::strTree(
"::capnp::_::ConstData<", schema.as<Data>().size(), ">").flatten();
return ConstText {
true,
kj::strTree(linkage, "const ", constType, ' ', upperCase, ";\n"),
kj::strTree("const ", constType, ' ', scope, upperCase, "(::capnp::schemas::b_",
kj::hex(proto.getId()), ".words + ", schema.getValueSchemaOffset(), ");\n")
};
}
case schema::Value::STRUCT: {
kj::String constType = kj::strTree(
"::capnp::_::ConstStruct<", typeName_, ">").flatten();
return ConstText {
true,
kj::strTree(linkage, "const ", constType, ' ', upperCase, ";\n"),
kj::strTree("const ", constType, ' ', scope, upperCase, "(::capnp::schemas::b_",
kj::hex(proto.getId()), ".words + ", schema.getValueSchemaOffset(), ");\n")
};
}
case schema::Value::LIST: {
kj::String constType = kj::strTree(
"::capnp::_::ConstList<", typeName(type.getList()), ">").flatten();
return ConstText {
true,
kj::strTree(linkage, "const ", constType, ' ', upperCase, ";\n"),
kj::strTree("const ", constType, ' ', scope, upperCase, "(::capnp::schemas::b_",
kj::hex(proto.getId()), ".words + ", schema.getValueSchemaOffset(), ");\n")
};
}
case schema::Value::OBJECT:
case schema::Value::INTERFACE:
return ConstText { false, kj::strTree(), kj::strTree() };
}
KJ_UNREACHABLE;
}
// -----------------------------------------------------------------
struct NodeText { struct NodeText {
kj::StringTree outerTypeDecl; kj::StringTree outerTypeDecl;
kj::StringTree outerTypeDef; kj::StringTree outerTypeDef;
...@@ -1066,6 +1194,7 @@ private: ...@@ -1066,6 +1194,7 @@ private:
kj::StringTree capnpSchemaDefs; kj::StringTree capnpSchemaDefs;
kj::StringTree capnpPrivateDecls; kj::StringTree capnpPrivateDecls;
kj::StringTree capnpPrivateDefs; kj::StringTree capnpPrivateDefs;
kj::StringTree sourceFileDefs;
}; };
NodeText makeNodeText(kj::StringPtr namespace_, kj::StringPtr scope, NodeText makeNodeText(kj::StringPtr namespace_, kj::StringPtr scope,
...@@ -1231,6 +1360,8 @@ private: ...@@ -1231,6 +1360,8 @@ private:
"CAPNP_DEFINE_STRUCT(\n" "CAPNP_DEFINE_STRUCT(\n"
" ", namespace_, "::", fullName, ");\n", " ", namespace_, "::", fullName, ");\n",
KJ_MAP(n, nestedTexts) { return kj::mv(n.capnpPrivateDefs); }), KJ_MAP(n, nestedTexts) { return kj::mv(n.capnpPrivateDefs); }),
kj::strTree(KJ_MAP(n, nestedTexts) { return kj::mv(n.sourceFileDefs); }),
}; };
} }
...@@ -1266,6 +1397,8 @@ private: ...@@ -1266,6 +1397,8 @@ private:
kj::strTree( kj::strTree(
"CAPNP_DEFINE_ENUM(\n" "CAPNP_DEFINE_ENUM(\n"
" ", namespace_, "::", fullName, ");\n"), " ", namespace_, "::", fullName, ");\n"),
kj::strTree(),
}; };
} }
...@@ -1285,21 +1418,27 @@ private: ...@@ -1285,21 +1418,27 @@ private:
kj::strTree( kj::strTree(
"CAPNP_DEFINE_INTERFACE(\n" "CAPNP_DEFINE_INTERFACE(\n"
" ", namespace_, "::", fullName, ");\n"), " ", namespace_, "::", fullName, ");\n"),
kj::strTree(),
}; };
} }
case schema::Node::CONST: { case schema::Node::CONST: {
auto constText = makeConstText(scope, name, schema.asConst());
return NodeText { return NodeText {
kj::strTree(), scope.size() == 0 ? kj::strTree() : kj::strTree(" ", kj::mv(constText.decl)),
kj::strTree(), scope.size() > 0 ? kj::strTree() : kj::mv(constText.decl),
kj::strTree(), kj::strTree(),
kj::strTree(), kj::strTree(),
kj::mv(schemaDecl), constText.needsSchema ? kj::mv(schemaDecl) : kj::strTree(),
kj::mv(schemaDef), constText.needsSchema ? kj::mv(schemaDef) : kj::strTree(),
kj::strTree(), kj::strTree(),
kj::strTree(), kj::strTree(),
kj::mv(constText.def),
}; };
} }
...@@ -1315,6 +1454,8 @@ private: ...@@ -1315,6 +1454,8 @@ private:
kj::strTree(), kj::strTree(),
kj::strTree(), kj::strTree(),
kj::strTree(),
}; };
} }
} }
...@@ -1376,6 +1517,9 @@ private: ...@@ -1376,6 +1517,9 @@ private:
} }
} }
kj::StringTree sourceDefs = kj::strTree(
KJ_MAP(n, nodeTexts) { return kj::mv(n.sourceFileDefs); });
return FileText { return FileText {
kj::strTree( kj::strTree(
"// Generated by Cap'n Proto compiler, DO NOT EDIT\n" "// Generated by Cap'n Proto compiler, DO NOT EDIT\n"
...@@ -1439,7 +1583,12 @@ private: ...@@ -1439,7 +1583,12 @@ private:
"namespace _ { // private\n", "namespace _ { // private\n",
KJ_MAP(n, nodeTexts) { return kj::mv(n.capnpPrivateDefs); }, KJ_MAP(n, nodeTexts) { return kj::mv(n.capnpPrivateDefs); },
"} // namespace _ (private)\n" "} // namespace _ (private)\n"
"} // namespace capnp\n") "} // namespace capnp\n",
sourceDefs.size() == 0 ? kj::strTree() : kj::strTree(
"\n", separator, "\n",
KJ_MAP(n, namespaceParts) { return kj::strTree("namespace ", n, " {\n"); }, "\n",
kj::mv(sourceDefs), "\n",
KJ_MAP(n, namespaceParts) { return kj::strTree("} // namespace\n"); }, "\n"))
}; };
} }
......
...@@ -1586,6 +1586,128 @@ TEST(Encoding, Threads) { ...@@ -1586,6 +1586,128 @@ TEST(Encoding, Threads) {
// each thread, thus waiting for them all to complete. // each thread, thus waiting for them all to complete.
} }
TEST(Encoding, Constants) {
EXPECT_EQ(VOID, test::TestConstants::VOID_CONST);
EXPECT_EQ(true, test::TestConstants::BOOL_CONST);
EXPECT_EQ(-123, test::TestConstants::INT8_CONST);
EXPECT_EQ(-12345, test::TestConstants::INT16_CONST);
EXPECT_EQ(-12345678, test::TestConstants::INT32_CONST);
EXPECT_EQ(-123456789012345ll, test::TestConstants::INT64_CONST);
EXPECT_EQ(234u, test::TestConstants::UINT8_CONST);
EXPECT_EQ(45678u, test::TestConstants::UINT16_CONST);
EXPECT_EQ(3456789012u, test::TestConstants::UINT32_CONST);
EXPECT_EQ(12345678901234567890ull, test::TestConstants::UINT64_CONST);
EXPECT_FLOAT_EQ(1234.5f, test::TestConstants::FLOAT32_CONST);
EXPECT_DOUBLE_EQ(-123e45, test::TestConstants::FLOAT64_CONST);
EXPECT_EQ("foo", *test::TestConstants::TEXT_CONST);
EXPECT_EQ(data("bar"), test::TestConstants::DATA_CONST);
{
TestAllTypes::Reader subReader = test::TestConstants::STRUCT_CONST;
EXPECT_EQ(VOID, subReader.getVoidField());
EXPECT_EQ(true, subReader.getBoolField());
EXPECT_EQ(-12, subReader.getInt8Field());
EXPECT_EQ(3456, subReader.getInt16Field());
EXPECT_EQ(-78901234, subReader.getInt32Field());
EXPECT_EQ(56789012345678ll, subReader.getInt64Field());
EXPECT_EQ(90u, subReader.getUInt8Field());
EXPECT_EQ(1234u, subReader.getUInt16Field());
EXPECT_EQ(56789012u, subReader.getUInt32Field());
EXPECT_EQ(345678901234567890ull, subReader.getUInt64Field());
EXPECT_FLOAT_EQ(-1.25e-10f, subReader.getFloat32Field());
EXPECT_DOUBLE_EQ(345, subReader.getFloat64Field());
EXPECT_EQ("baz", subReader.getTextField());
EXPECT_EQ(data("qux"), subReader.getDataField());
{
auto subSubReader = subReader.getStructField();
EXPECT_EQ("nested", subSubReader.getTextField());
EXPECT_EQ("really nested", subSubReader.getStructField().getTextField());
}
EXPECT_EQ(TestEnum::BAZ, subReader.getEnumField());
checkList(subReader.getVoidList(), {VOID, VOID, VOID});
checkList(subReader.getBoolList(), {false, true, false, true, true});
checkList(subReader.getInt8List(), {12, -34, -0x80, 0x7f});
checkList(subReader.getInt16List(), {1234, -5678, -0x8000, 0x7fff});
// gcc warns on -0x800... and the only work-around I could find was to do -0x7ff...-1.
checkList(subReader.getInt32List(), {12345678, -90123456, -0x7fffffff - 1, 0x7fffffff});
checkList(subReader.getInt64List(), {123456789012345ll, -678901234567890ll, -0x7fffffffffffffffll-1, 0x7fffffffffffffffll});
checkList(subReader.getUInt8List(), {12u, 34u, 0u, 0xffu});
checkList(subReader.getUInt16List(), {1234u, 5678u, 0u, 0xffffu});
checkList(subReader.getUInt32List(), {12345678u, 90123456u, 0u, 0xffffffffu});
checkList(subReader.getUInt64List(), {123456789012345ull, 678901234567890ull, 0ull, 0xffffffffffffffffull});
checkList(subReader.getFloat32List(), {0.0f, 1234567.0f, 1e37f, -1e37f, 1e-37f, -1e-37f});
checkList(subReader.getFloat64List(), {0.0, 123456789012345.0, 1e306, -1e306, 1e-306, -1e-306});
checkList(subReader.getTextList(), {"quux", "corge", "grault"});
checkList(subReader.getDataList(), {data("garply"), data("waldo"), data("fred")});
{
auto listReader = subReader.getStructList();
ASSERT_EQ(3u, listReader.size());
EXPECT_EQ("x structlist 1", listReader[0].getTextField());
EXPECT_EQ("x structlist 2", listReader[1].getTextField());
EXPECT_EQ("x structlist 3", listReader[2].getTextField());
}
checkList(subReader.getEnumList(), {TestEnum::QUX, TestEnum::BAR, TestEnum::GRAULT});
}
EXPECT_EQ(TestEnum::CORGE, test::TestConstants::ENUM_CONST);
EXPECT_EQ(6u, test::TestConstants::VOID_LIST_CONST->size());
checkList(*test::TestConstants::BOOL_LIST_CONST, {true, false, false, true});
checkList(*test::TestConstants::INT8_LIST_CONST, {111, -111});
checkList(*test::TestConstants::INT16_LIST_CONST, {11111, -11111});
checkList(*test::TestConstants::INT32_LIST_CONST, {111111111, -111111111});
checkList(*test::TestConstants::INT64_LIST_CONST, {1111111111111111111ll, -1111111111111111111ll});
checkList(*test::TestConstants::UINT8_LIST_CONST, {111u, 222u});
checkList(*test::TestConstants::UINT16_LIST_CONST, {33333u, 44444u});
checkList(*test::TestConstants::UINT32_LIST_CONST, {3333333333u});
checkList(*test::TestConstants::UINT64_LIST_CONST, {11111111111111111111ull});
{
List<float>::Reader listReader = test::TestConstants::FLOAT32_LIST_CONST;
ASSERT_EQ(4u, listReader.size());
EXPECT_EQ(5555.5f, listReader[0]);
EXPECT_EQ(std::numeric_limits<float>::infinity(), listReader[1]);
EXPECT_EQ(-std::numeric_limits<float>::infinity(), listReader[2]);
EXPECT_TRUE(listReader[3] != listReader[3]);
}
{
List<double>::Reader listReader = test::TestConstants::FLOAT64_LIST_CONST;
ASSERT_EQ(4u, listReader.size());
EXPECT_EQ(7777.75, listReader[0]);
EXPECT_EQ(std::numeric_limits<double>::infinity(), listReader[1]);
EXPECT_EQ(-std::numeric_limits<double>::infinity(), listReader[2]);
EXPECT_TRUE(listReader[3] != listReader[3]);
}
checkList(*test::TestConstants::TEXT_LIST_CONST, {"plugh", "xyzzy", "thud"});
checkList(*test::TestConstants::DATA_LIST_CONST, {data("oops"), data("exhausted"), data("rfc3092")});
{
List<TestAllTypes>::Reader listReader = test::TestConstants::STRUCT_LIST_CONST;
ASSERT_EQ(3u, listReader.size());
EXPECT_EQ("structlist 1", listReader[0].getTextField());
EXPECT_EQ("structlist 2", listReader[1].getTextField());
EXPECT_EQ("structlist 3", listReader[2].getTextField());
}
checkList(*test::TestConstants::ENUM_LIST_CONST, {TestEnum::FOO, TestEnum::GARPLY});
}
TEST(Encoding, GlobalConstants) {
EXPECT_EQ(12345u, test::GLOBAL_INT);
EXPECT_EQ("foobar", test::GLOBAL_TEXT.get());
EXPECT_EQ(54321, test::GLOBAL_STRUCT->getInt32Field());
TestAllTypes::Reader reader = test::DERIVED_CONSTANT;
EXPECT_EQ(12345, reader.getUInt32Field());
EXPECT_EQ("foo", reader.getTextField());
checkList(reader.getStructField().getTextList(), {"quux", "corge", "grault"});
checkList(reader.getInt16List(), {11111, -11111});
{
List<TestAllTypes>::Reader listReader = reader.getStructList();
ASSERT_EQ(3u, listReader.size());
EXPECT_EQ("structlist 1", listReader[0].getTextField());
EXPECT_EQ("structlist 2", listReader[1].getTextField());
EXPECT_EQ("structlist 3", listReader[2].getTextField());
}
}
} // namespace } // namespace
} // namespace _ (private) } // namespace _ (private)
} // namespace capnp } // namespace capnp
...@@ -228,6 +228,83 @@ inline kj::StringTree structString(StructReader reader) { ...@@ -228,6 +228,83 @@ inline kj::StringTree structString(StructReader reader) {
return structString(reader, rawSchema<T>()); return structString(reader, rawSchema<T>());
} }
template <typename T>
class ConstStruct {
public:
ConstStruct() = delete;
KJ_DISALLOW_COPY(ConstStruct);
inline explicit constexpr ConstStruct(const word* ptr): ptr(ptr) {}
inline typename T::Reader get() const {
return typename T::Reader(StructReader::readRootUnchecked(ptr));
}
inline operator typename T::Reader() const { return get(); }
inline typename T::Reader operator*() const { return get(); }
inline TemporaryPointer<typename T::Reader> operator->() const { return get(); }
private:
const word* ptr;
};
template <typename T>
class ConstList {
public:
ConstList() = delete;
KJ_DISALLOW_COPY(ConstList);
inline explicit constexpr ConstList(const word* ptr): ptr(ptr) {}
inline typename List<T>::Reader get() const {
return typename List<T>::Reader(ListReader::readRootUnchecked(
ptr, elementSizeForType<T>()));
}
inline operator typename List<T>::Reader() const { return get(); }
inline typename List<T>::Reader operator*() const { return get(); }
inline TemporaryPointer<typename List<T>::Reader> operator->() const { return get(); }
private:
const word* ptr;
};
template <size_t size>
class ConstText {
public:
ConstText() = delete;
KJ_DISALLOW_COPY(ConstText);
inline explicit constexpr ConstText(const word* ptr): ptr(ptr) {}
inline Text::Reader get() const {
return Text::Reader(reinterpret_cast<const char*>(ptr), size);
}
inline operator Text::Reader() const { return get(); }
inline Text::Reader operator*() const { return get(); }
inline TemporaryPointer<Text::Reader> operator->() const { return get(); }
private:
const word* ptr;
};
template <size_t size>
class ConstData {
public:
ConstData() = delete;
KJ_DISALLOW_COPY(ConstData);
inline explicit constexpr ConstData(const word* ptr): ptr(ptr) {}
inline Data::Reader get() const {
return Data::Reader(reinterpret_cast<const byte*>(ptr), size);
}
inline operator Data::Reader() const { return get(); }
inline Data::Reader operator*() const { return get(); }
inline TemporaryPointer<Data::Reader> operator->() const { return get(); }
private:
const word* ptr;
};
} // namespace _ (private) } // namespace _ (private)
template <typename T> template <typename T>
......
...@@ -2317,6 +2317,11 @@ WordCount64 StructReader::totalSize() const { ...@@ -2317,6 +2317,11 @@ WordCount64 StructReader::totalSize() const {
// ======================================================================================= // =======================================================================================
// ListBuilder // ListBuilder
ListReader ListReader::readRootUnchecked(const word* location, FieldSize elementSize) {
return WireHelpers::readListPointer(nullptr, reinterpret_cast<const WirePointer*>(location),
nullptr, elementSize, std::numeric_limits<int>::max());
}
Text::Builder ListBuilder::asText() { Text::Builder ListBuilder::asText() {
KJ_REQUIRE(structDataSize == 8 * BITS && structPointerCount == 0 * POINTERS, KJ_REQUIRE(structDataSize == 8 * BITS && structPointerCount == 0 * POINTERS,
"Expected Text, got list of non-bytes.") { "Expected Text, got list of non-bytes.") {
......
...@@ -154,6 +154,11 @@ template <> struct ElementSizeForType<Data> { ...@@ -154,6 +154,11 @@ template <> struct ElementSizeForType<Data> {
static constexpr FieldSize value = FieldSize::POINTER; static constexpr FieldSize value = FieldSize::POINTER;
}; };
template <typename T>
inline constexpr FieldSize elementSizeForType() {
return ElementSizeForType<T>::value;
}
} // namespace _ (private) } // namespace _ (private)
// ============================================================================= // =============================================================================
...@@ -630,6 +635,8 @@ public: ...@@ -630,6 +635,8 @@ public:
: segment(nullptr), ptr(nullptr), elementCount(0), step(0 * BITS / ELEMENTS), : segment(nullptr), ptr(nullptr), elementCount(0), step(0 * BITS / ELEMENTS),
structDataSize(0), structPointerCount(0), nestingLimit(0x7fffffff) {} structDataSize(0), structPointerCount(0), nestingLimit(0x7fffffff) {}
static ListReader readRootUnchecked(const word* location, FieldSize elementSize);
inline ElementCount size() const; inline ElementCount size() const;
// The number of elements in the list. // The number of elements in the list.
......
...@@ -168,28 +168,28 @@ private: ...@@ -168,28 +168,28 @@ private:
inline static _::ListBuilder initAsElementOf( inline static _::ListBuilder initAsElementOf(
_::ListBuilder& builder, uint index, uint size) { _::ListBuilder& builder, uint index, uint size) {
return builder.initListElement( return builder.initListElement(
index * ELEMENTS, _::ElementSizeForType<T>::value, size * ELEMENTS); index * ELEMENTS, _::elementSizeForType<T>(), size * ELEMENTS);
} }
inline static _::ListBuilder getAsElementOf( inline static _::ListBuilder getAsElementOf(
_::ListBuilder& builder, uint index) { _::ListBuilder& builder, uint index) {
return builder.getListElement(index * ELEMENTS, _::ElementSizeForType<T>::value); return builder.getListElement(index * ELEMENTS, _::elementSizeForType<T>());
} }
inline static _::ListReader getAsElementOf( inline static _::ListReader getAsElementOf(
const _::ListReader& reader, uint index) { const _::ListReader& reader, uint index) {
return reader.getListElement(index * ELEMENTS, _::ElementSizeForType<T>::value); return reader.getListElement(index * ELEMENTS, _::elementSizeForType<T>());
} }
inline static _::ListBuilder initAsFieldOf( inline static _::ListBuilder initAsFieldOf(
_::StructBuilder& builder, WirePointerCount index, uint size) { _::StructBuilder& builder, WirePointerCount index, uint size) {
return builder.initListField(index, _::ElementSizeForType<T>::value, size * ELEMENTS); return builder.initListField(index, _::elementSizeForType<T>(), size * ELEMENTS);
} }
inline static _::ListBuilder getAsFieldOf( inline static _::ListBuilder getAsFieldOf(
_::StructBuilder& builder, WirePointerCount index, const word* defaultValue) { _::StructBuilder& builder, WirePointerCount index, const word* defaultValue) {
return builder.getListField(index, _::ElementSizeForType<T>::value, defaultValue); return builder.getListField(index, _::elementSizeForType<T>(), defaultValue);
} }
inline static _::ListReader getAsFieldOf( inline static _::ListReader getAsFieldOf(
const _::StructReader& reader, WirePointerCount index, const word* defaultValue) { const _::StructReader& reader, WirePointerCount index, const word* defaultValue) {
return reader.getListField(index, _::ElementSizeForType<T>::value, defaultValue); return reader.getListField(index, _::elementSizeForType<T>(), defaultValue);
} }
template <typename U, Kind k> template <typename U, Kind k>
......
...@@ -457,3 +457,93 @@ struct TestStructUnion { ...@@ -457,3 +457,93 @@ struct TestStructUnion {
object @2 :TestObject; object @2 :TestObject;
} }
} }
struct TestConstants {
const voidConst :Void = void;
const boolConst :Bool = true;
const int8Const :Int8 = -123;
const int16Const :Int16 = -12345;
const int32Const :Int32 = -12345678;
const int64Const :Int64 = -123456789012345;
const uint8Const :UInt8 = 234;
const uint16Const :UInt16 = 45678;
const uint32Const :UInt32 = 3456789012;
const uint64Const :UInt64 = 12345678901234567890;
const float32Const :Float32 = 1234.5;
const float64Const :Float64 = -123e45;
const textConst :Text = "foo";
const dataConst :Data = "bar";
const structConst :TestAllTypes = (
voidField = void,
boolField = true,
int8Field = -12,
int16Field = 3456,
int32Field = -78901234,
int64Field = 56789012345678,
uInt8Field = 90,
uInt16Field = 1234,
uInt32Field = 56789012,
uInt64Field = 345678901234567890,
float32Field = -1.25e-10,
float64Field = 345,
textField = "baz",
dataField = "qux",
structField = (
textField = "nested",
structField = (textField = "really nested")),
enumField = baz,
# interfaceField can't have a default
voidList = [void, void, void],
boolList = [false, true, false, true, true],
int8List = [12, -34, -0x80, 0x7f],
int16List = [1234, -5678, -0x8000, 0x7fff],
int32List = [12345678, -90123456, -0x80000000, 0x7fffffff],
int64List = [123456789012345, -678901234567890, -0x8000000000000000, 0x7fffffffffffffff],
uInt8List = [12, 34, 0, 0xff],
uInt16List = [1234, 5678, 0, 0xffff],
uInt32List = [12345678, 90123456, 0, 0xffffffff],
uInt64List = [123456789012345, 678901234567890, 0, 0xffffffffffffffff],
float32List = [0, 1234567, 1e37, -1e37, 1e-37, -1e-37],
float64List = [0, 123456789012345, 1e306, -1e306, 1e-306, -1e-306],
textList = ["quux", "corge", "grault"],
dataList = ["garply", "waldo", "fred"],
structList = [
(textField = "x structlist 1"),
(textField = "x structlist 2"),
(textField = "x structlist 3")],
enumList = [qux, bar, grault]
# interfaceList can't have a default
);
const enumConst :TestEnum = corge;
const voidListConst :List(Void) = [void, void, void, void, void, void];
const boolListConst :List(Bool) = [true, false, false, true];
const int8ListConst :List(Int8) = [111, -111];
const int16ListConst :List(Int16) = [11111, -11111];
const int32ListConst :List(Int32) = [111111111, -111111111];
const int64ListConst :List(Int64) = [1111111111111111111, -1111111111111111111];
const uint8ListConst :List(UInt8) = [111, 222] ;
const uint16ListConst :List(UInt16) = [33333, 44444];
const uint32ListConst :List(UInt32) = [3333333333];
const uint64ListConst :List(UInt64) = [11111111111111111111];
const float32ListConst :List(Float32) = [5555.5, inf, -inf, nan];
const float64ListConst :List(Float64) = [7777.75, inf, -inf, nan];
const textListConst :List(Text) = ["plugh", "xyzzy", "thud"];
const dataListConst :List(Data) = ["oops", "exhausted", "rfc3092"];
const structListConst :List(TestAllTypes) = [
(textField = "structlist 1"),
(textField = "structlist 2"),
(textField = "structlist 3")];
const enumListConst :List(TestEnum) = [foo, garply];
}
const globalInt :UInt32 = 12345;
const globalText :Text = "foobar";
const globalStruct :TestAllTypes = (int32Field = 54321);
const derivedConstant :TestAllTypes = (
uInt32Field = .globalInt,
textField = TestConstants.textConst,
structField = TestConstants.structConst,
int16List = TestConstants.int16ListConst,
structList = TestConstants.structListConst);
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