Commit 449f4b23 authored by Kenton Varda's avatar Kenton Varda

Allow automatic conversions between numeric types in DynamicValue.

parent 4b771dcd
...@@ -85,12 +85,28 @@ void SchemaPool::addNoCopy(schema::Node::Reader node) { ...@@ -85,12 +85,28 @@ void SchemaPool::addNoCopy(schema::Node::Reader node) {
// TODO(soon): Check if node is in base. // TODO(soon): Check if node is in base.
// TODO(soon): Check if existing node came from generated code. // TODO(soon): Check if existing node came from generated code.
auto entry = std::make_pair(node.getId(), node); uint64_t id = node.getId();
auto entry = std::make_pair(id, node);
auto ins = impl->nodeMap.insert(entry); auto ins = impl->nodeMap.insert(entry);
if (!ins.second) { if (!ins.second) {
// TODO(soon): Check for compatibility. // TODO(soon): Check for compatibility.
FAIL_CHECK("TODO: Check schema compatibility when adding."); FAIL_CHECK("TODO: Check schema compatibility when adding.");
} }
switch (node.getBody().which()) {
case schema::Node::Body::STRUCT_NODE:
for (auto member: node.getBody().getStructNode().getMembers()) {
impl->memberMap[std::pair<uint64_t, Text::Reader>(id, member.getName())] = member;
}
break;
case schema::Node::Body::ENUM_NODE:
for (auto enumerant: node.getBody().getEnumNode().getEnumerants()) {
impl->enumerantMap[std::pair<uint64_t, Text::Reader>(id, enumerant.getName())] = enumerant;
}
break;
default:
break;
}
} }
Maybe<schema::Node::Reader> SchemaPool::tryGetNode(uint64_t id) const { Maybe<schema::Node::Reader> SchemaPool::tryGetNode(uint64_t id) const {
...@@ -645,7 +661,7 @@ void DynamicStruct::Builder::setFieldImpl( ...@@ -645,7 +661,7 @@ void DynamicStruct::Builder::setFieldImpl(
case schema::Type::Body::discrim##_TYPE: \ case schema::Type::Body::discrim##_TYPE: \
builder.setDataField<type>( \ builder.setDataField<type>( \
field.getOffset() * ELEMENTS, value.as<type>(), \ field.getOffset() * ELEMENTS, value.as<type>(), \
bitCast<internal::Mask<type> >(dval.get##titleCase##Value())); bitCast<internal::Mask<type> >(dval.get##titleCase##Value())); \
break; break;
HANDLE_TYPE(BOOL, Bool, bool) HANDLE_TYPE(BOOL, Bool, bool)
...@@ -1133,16 +1149,104 @@ void DynamicList::Builder::verifySchema(internal::ListSchema schema) { ...@@ -1133,16 +1149,104 @@ void DynamicList::Builder::verifySchema(internal::ListSchema schema) {
// ======================================================================================= // =======================================================================================
namespace {
template <typename T>
T signedToUnsigned(long long value) {
VALIDATE_INPUT(value >= 0 && T(value) == value,
"Value out-of-range for requested type.", value) {
// Use it anyway.
}
return value;
}
template <>
uint64_t signedToUnsigned<uint64_t>(long long value) {
VALIDATE_INPUT(value >= 0, "Value out-of-range for requested type.", value) {
// Use it anyway.
}
return value;
}
template <typename T>
T unsignedToSigned(unsigned long long value) {
VALIDATE_INPUT(T(value) >= 0 && (unsigned long long)T(value) == value,
"Value out-of-range for requested type.", value) {
// Use it anyway.
}
return value;
}
template <>
int64_t unsignedToSigned<int64_t>(unsigned long long value) {
VALIDATE_INPUT(int64_t(value) >= 0, "Value out-of-range for requested type.", value) {
// Use it anyway.
}
return value;
}
template <typename T, typename U>
T checkRoundTrip(U value) {
VALIDATE_INPUT(T(value) == value,
"Value out-of-range for requested type.", value) {
// Use it anyway.
}
return value;
}
} // namespace
#define HANDLE_NUMERIC_TYPE(typeName, ifInt, ifUint, ifFloat) \
typeName DynamicValue::Reader::AsImpl<typeName>::apply(Reader reader) { \
switch (reader.type) { \
case INT: \
return ifInt<typeName>(reader.intValue); \
case UINT: \
return ifUint<typeName>(reader.uintValue); \
case FLOAT: \
return ifFloat<typeName>(reader.floatValue); \
default: \
FAIL_VALIDATE_INPUT("Type mismatch when using DynamicValue::Reader::as()."); \
return 0; \
} \
} \
typeName DynamicValue::Builder::AsImpl<typeName>::apply(Builder builder) { \
switch (builder.type) { \
case INT: \
return ifInt<typeName>(builder.intValue); \
case UINT: \
return ifUint<typeName>(builder.uintValue); \
case FLOAT: \
return ifFloat<typeName>(builder.floatValue); \
default: \
FAIL_VALIDATE_INPUT("Type mismatch when using DynamicValue::Builder::as()."); \
return 0; \
} \
}
HANDLE_NUMERIC_TYPE(int8_t, checkRoundTrip, unsignedToSigned, checkRoundTrip)
HANDLE_NUMERIC_TYPE(int16_t, checkRoundTrip, unsignedToSigned, checkRoundTrip)
HANDLE_NUMERIC_TYPE(int32_t, checkRoundTrip, unsignedToSigned, checkRoundTrip)
HANDLE_NUMERIC_TYPE(int64_t, implicit_cast, unsignedToSigned, checkRoundTrip)
HANDLE_NUMERIC_TYPE(uint8_t, signedToUnsigned, checkRoundTrip, checkRoundTrip)
HANDLE_NUMERIC_TYPE(uint16_t, signedToUnsigned, checkRoundTrip, checkRoundTrip)
HANDLE_NUMERIC_TYPE(uint32_t, signedToUnsigned, checkRoundTrip, checkRoundTrip)
HANDLE_NUMERIC_TYPE(uint64_t, signedToUnsigned, implicit_cast, checkRoundTrip)
HANDLE_NUMERIC_TYPE(float, implicit_cast, implicit_cast, implicit_cast)
HANDLE_NUMERIC_TYPE(double, implicit_cast, implicit_cast, implicit_cast)
#undef HANDLE_NUMERIC_TYPE
#define HANDLE_TYPE(name, discrim, typeName) \ #define HANDLE_TYPE(name, discrim, typeName) \
ReaderFor<typeName> DynamicValue::Reader::asImpl<typeName>::apply(Reader reader) { \ ReaderFor<typeName> DynamicValue::Reader::AsImpl<typeName>::apply(Reader reader) { \
VALIDATE_INPUT(reader.type == schema::Type::Body::discrim##_TYPE, \ VALIDATE_INPUT(reader.type == discrim, \
"Type mismatch when using DynamicValue::Reader::as().") { \ "Type mismatch when using DynamicValue::Reader::as().") { \
return ReaderFor<typeName>(); \ return ReaderFor<typeName>(); \
} \ } \
return reader.name##Value; \ return reader.name##Value; \
} \ } \
BuilderFor<typeName> DynamicValue::Builder::asImpl<typeName>::apply(Builder builder) { \ BuilderFor<typeName> DynamicValue::Builder::AsImpl<typeName>::apply(Builder builder) { \
VALIDATE_INPUT(builder.type == schema::Type::Body::discrim##_TYPE, \ VALIDATE_INPUT(builder.type == discrim, \
"Type mismatch when using DynamicValue::Builder::as().") { \ "Type mismatch when using DynamicValue::Builder::as().") { \
return BuilderFor<typeName>(); \ return BuilderFor<typeName>(); \
} \ } \
...@@ -1151,16 +1255,6 @@ BuilderFor<typeName> DynamicValue::Builder::asImpl<typeName>::apply(Builder buil ...@@ -1151,16 +1255,6 @@ BuilderFor<typeName> DynamicValue::Builder::asImpl<typeName>::apply(Builder buil
//HANDLE_TYPE(void, VOID, Void) //HANDLE_TYPE(void, VOID, Void)
HANDLE_TYPE(bool, BOOL, bool) HANDLE_TYPE(bool, BOOL, bool)
HANDLE_TYPE(int8, INT8, int8_t)
HANDLE_TYPE(int16, INT16, int16_t)
HANDLE_TYPE(int32, INT32, int32_t)
HANDLE_TYPE(int64, INT64, int64_t)
HANDLE_TYPE(uint8, UINT8, uint8_t)
HANDLE_TYPE(uint16, UINT16, uint16_t)
HANDLE_TYPE(uint32, UINT32, uint32_t)
HANDLE_TYPE(uint64, UINT64, uint64_t)
HANDLE_TYPE(float32, FLOAT32, float)
HANDLE_TYPE(float64, FLOAT64, double)
HANDLE_TYPE(text, TEXT, Text) HANDLE_TYPE(text, TEXT, Text)
HANDLE_TYPE(data, DATA, Data) HANDLE_TYPE(data, DATA, Data)
...@@ -1168,19 +1262,20 @@ HANDLE_TYPE(list, LIST, DynamicList) ...@@ -1168,19 +1262,20 @@ HANDLE_TYPE(list, LIST, DynamicList)
HANDLE_TYPE(struct, STRUCT, DynamicStruct) HANDLE_TYPE(struct, STRUCT, DynamicStruct)
HANDLE_TYPE(enum, ENUM, DynamicEnum) HANDLE_TYPE(enum, ENUM, DynamicEnum)
HANDLE_TYPE(object, OBJECT, DynamicObject) HANDLE_TYPE(object, OBJECT, DynamicObject)
HANDLE_TYPE(union, UNION, DynamicUnion)
#undef HANDLE_TYPE #undef HANDLE_TYPE
// As in the header, HANDLE_TYPE(void, VOID, Void) crashes GCC 4.7. // As in the header, HANDLE_TYPE(void, VOID, Void) crashes GCC 4.7.
Void DynamicValue::Reader::asImpl<Void>::apply(Reader reader) { Void DynamicValue::Reader::AsImpl<Void>::apply(Reader reader) {
VALIDATE_INPUT(reader.type == schema::Type::Body::VOID_TYPE, VALIDATE_INPUT(reader.type == VOID,
"Type mismatch when using DynamicValue::Reader::as().") { "Type mismatch when using DynamicValue::Reader::as().") {
return Void(); return Void();
} }
return reader.voidValue; return reader.voidValue;
} }
Void DynamicValue::Builder::asImpl<Void>::apply(Builder builder) { Void DynamicValue::Builder::AsImpl<Void>::apply(Builder builder) {
VALIDATE_INPUT(builder.type == schema::Type::Body::VOID_TYPE, VALIDATE_INPUT(builder.type == VOID,
"Type mismatch when using DynamicValue::Builder::as().") { "Type mismatch when using DynamicValue::Builder::as().") {
return Void(); return Void();
} }
......
...@@ -45,6 +45,22 @@ class MessageReader; ...@@ -45,6 +45,22 @@ class MessageReader;
class MessageBuilder; class MessageBuilder;
struct DynamicValue { struct DynamicValue {
enum Type {
VOID,
BOOL,
INT,
UINT,
FLOAT,
TEXT,
DATA,
LIST,
ENUM,
STRUCT,
UNION,
INTERFACE,
OBJECT
};
class Reader; class Reader;
class Builder; class Builder;
}; };
...@@ -269,7 +285,7 @@ public: ...@@ -269,7 +285,7 @@ public:
Reader() = default; Reader() = default;
template <typename T> template <typename T>
inline typename T::Reader as() { return asImpl<T>::apply(*this); } inline typename T::Reader as() { return AsImpl<T>::apply(*this); }
// Convert the object to the given struct, list, or blob type. // Convert the object to the given struct, list, or blob type.
DynamicStruct::Reader asStruct(schema::Node::Reader schema); DynamicStruct::Reader asStruct(schema::Node::Reader schema);
...@@ -282,7 +298,7 @@ private: ...@@ -282,7 +298,7 @@ private:
inline Reader(const SchemaPool* pool, internal::ObjectReader reader) inline Reader(const SchemaPool* pool, internal::ObjectReader reader)
: pool(pool), reader(reader) {} : pool(pool), reader(reader) {}
template <typename T, Kind kind = kind<T>()> struct asImpl; template <typename T, Kind kind = kind<T>()> struct AsImpl;
// Implementation backing the as() method. Needs to be a struct to allow partial // Implementation backing the as() method. Needs to be a struct to allow partial
// specialization. Has a method apply() which does the work. // specialization. Has a method apply() which does the work.
...@@ -298,7 +314,7 @@ public: ...@@ -298,7 +314,7 @@ public:
Builder() = default; Builder() = default;
template <typename T> template <typename T>
inline typename T::Builder as() { return asImpl<T>::apply(*this); } inline typename T::Builder as() { return AsImpl<T>::apply(*this); }
// Convert the object to the given struct, list, or blob type. // Convert the object to the given struct, list, or blob type.
DynamicStruct::Builder asStruct(schema::Node::Reader schema); DynamicStruct::Builder asStruct(schema::Node::Reader schema);
...@@ -311,7 +327,7 @@ private: ...@@ -311,7 +327,7 @@ private:
inline Builder(const SchemaPool* pool, internal::ObjectBuilder builder) inline Builder(const SchemaPool* pool, internal::ObjectBuilder builder)
: pool(pool), builder(builder) {} : pool(pool), builder(builder) {}
template <typename T, Kind kind = kind<T>()> struct asImpl; template <typename T, Kind kind = kind<T>()> struct AsImpl;
// Implementation backing the as() method. Needs to be a struct to allow partial // Implementation backing the as() method. Needs to be a struct to allow partial
// specialization. Has a method apply() which does the work. // specialization. Has a method apply() which does the work.
...@@ -635,125 +651,128 @@ struct MaybeReaderBuilder<DynamicList, Kind::UNKNOWN> { ...@@ -635,125 +651,128 @@ struct MaybeReaderBuilder<DynamicList, Kind::UNKNOWN> {
class DynamicValue::Reader { class DynamicValue::Reader {
public: public:
inline Reader(Void voidValue = Void::VOID); inline Reader(Void value = Void::VOID);
inline Reader(bool boolValue); inline Reader(bool value);
inline Reader(int8_t int8Value); inline Reader(char value);
inline Reader(int16_t int16Value); inline Reader(signed char value);
inline Reader(int32_t int32Value); inline Reader(short value);
inline Reader(int64_t int64Value); inline Reader(int value);
inline Reader(uint8_t uint8Value); inline Reader(long value);
inline Reader(uint16_t uint16Value); inline Reader(long long value);
inline Reader(uint32_t uint32Value); inline Reader(unsigned char value);
inline Reader(uint64_t uint64Value); inline Reader(unsigned short value);
inline Reader(float float32Value); inline Reader(unsigned int value);
inline Reader(double float64Value); inline Reader(unsigned long value);
inline Reader(Text::Reader textValue); inline Reader(unsigned long long value);
inline Reader(Data::Reader dataValue); inline Reader(float value);
inline Reader(DynamicList::Reader listValue); inline Reader(double value);
inline Reader(DynamicEnum enumValue); inline Reader(Text::Reader value);
inline Reader(DynamicStruct::Reader structValue); inline Reader(Data::Reader value);
inline Reader(DynamicObject::Reader objectValue); inline Reader(DynamicList::Reader value);
inline Reader(DynamicEnum value);
inline Reader(DynamicStruct::Reader value);
inline Reader(DynamicUnion::Reader value);
inline Reader(DynamicObject::Reader value);
template <typename T> template <typename T>
inline ReaderFor<T> as() { return asImpl<T>::apply(*this); } inline ReaderFor<T> as() { return AsImpl<T>::apply(*this); }
// Use to interpret the value as some type. Allowed types are: // Use to interpret the value as some Cap'n Proto type. Allowed types are:
// - Void, bool, [u]int{8,16,32,64}_t, float, double, any enum: Returns the raw value. // - Void, bool, [u]int{8,16,32,64}_t, float, double, any enum: Returns the raw value.
// - Text, Data, any struct type: Returns the corresponding Reader. // - Text, Data, any struct type: Returns the corresponding Reader.
// - List<T> for any T listed above: Returns List<T>::Reader. // - List<T> for any T listed above: Returns List<T>::Reader.
// - DynamicEnum: Returns DynamicEnum. // - DynamicEnum: Returns DynamicEnum.
// - DynamicStruct, DynamicList, DynamicObject: Returns the corresponding Reader. // - DynamicStruct, DynamicList, DynamicObject, DynamicUnion: Returns the corresponding Reader.
// If the requested type does not match the underlying data, the result is unspecified: it may //
// throw an exception, it may return a garbage value, or it may return a composite value that // DynamicValue allows various implicit conversions:
// when traversed throws exceptions or returns garbage values. Under none of these // - Any integer can be converted to any other integer type so long as the actual value is within
// circumstances will the program crash. // the new type's range.
// - Floating-point types can be converted to integers as long as no information would be lost
// in the conversion.
// - Integers can be converted to floating points. This may lose information, but won't throw.
// - Float32/Float64 can be converted between each other. Converting Float64 -> Float32 may lose
// information, but won't throw.
//
// Any other conversion attempt will throw an exception.
inline schema::Type::Body::Which getType() { return type; } inline Type getType() { return type; }
// Get the type of this value. // Get the type of this value.
private: private:
schema::Type::Body::Which type; Type type;
union { union {
Void voidValue; Void voidValue;
bool boolValue; bool boolValue;
int8_t int8Value; int64_t intValue;
int16_t int16Value; uint64_t uintValue;
int32_t int32Value; double floatValue;
int64_t int64Value;
uint8_t uint8Value;
uint16_t uint16Value;
uint32_t uint32Value;
uint64_t uint64Value;
float float32Value;
double float64Value;
Text::Reader textValue; Text::Reader textValue;
Data::Reader dataValue; Data::Reader dataValue;
DynamicList::Reader listValue; DynamicList::Reader listValue;
DynamicEnum enumValue; DynamicEnum enumValue;
DynamicStruct::Reader structValue; DynamicStruct::Reader structValue;
DynamicUnion::Reader unionValue;
DynamicObject::Reader objectValue; DynamicObject::Reader objectValue;
}; };
template <typename T, Kind kind = kind<T>()> struct asImpl; template <typename T, Kind kind = kind<T>()> struct AsImpl;
// Implementation backing the as() method. Needs to be a struct to allow partial // Implementation backing the as() method. Needs to be a struct to allow partial
// specialization. Has a method apply() which does the work. // specialization. Has a method apply() which does the work.
}; };
class DynamicValue::Builder { class DynamicValue::Builder {
public: public:
inline Builder(Void voidValue = Void::VOID); inline Builder(Void value = Void::VOID);
inline Builder(bool boolValue); inline Builder(bool value);
inline Builder(int8_t int8Value); inline Builder(char value);
inline Builder(int16_t int16Value); inline Builder(signed char value);
inline Builder(int32_t int32Value); inline Builder(short value);
inline Builder(int64_t int64Value); inline Builder(int value);
inline Builder(uint8_t uint8Value); inline Builder(long value);
inline Builder(uint16_t uint16Value); inline Builder(long long value);
inline Builder(uint32_t uint32Value); inline Builder(unsigned char value);
inline Builder(uint64_t uint64Value); inline Builder(unsigned short value);
inline Builder(float float32Value); inline Builder(unsigned int value);
inline Builder(double float64Value); inline Builder(unsigned long value);
inline Builder(Text::Builder textValue); inline Builder(unsigned long long value);
inline Builder(Data::Builder dataValue); inline Builder(float value);
inline Builder(DynamicList::Builder listValue); inline Builder(double value);
inline Builder(DynamicEnum enumValue); inline Builder(Text::Builder value);
inline Builder(DynamicStruct::Builder structValue); inline Builder(Data::Builder value);
inline Builder(DynamicObject::Builder objectValue); inline Builder(DynamicList::Builder value);
inline Builder(DynamicEnum value);
inline Builder(DynamicStruct::Builder value);
inline Builder(DynamicUnion::Builder value);
inline Builder(DynamicObject::Builder value);
template <typename T> template <typename T>
inline BuilderFor<T> as() { return asImpl<T>::apply(*this); } inline BuilderFor<T> as() { return AsImpl<T>::apply(*this); }
// See DynamicValue::Reader::as(). // See DynamicValue::Reader::as().
inline schema::Type::Body::Which getType() { return type; } inline Type getType() { return type; }
// Get the type of this value. // Get the type of this value.
Reader asReader(); Reader asReader();
private: private:
schema::Type::Body::Which type; Type type;
union { union {
Void voidValue; Void voidValue;
bool boolValue; bool boolValue;
int8_t int8Value; int64_t intValue;
int16_t int16Value; uint64_t uintValue;
int32_t int32Value; double floatValue;
int64_t int64Value;
uint8_t uint8Value;
uint16_t uint16Value;
uint32_t uint32Value;
uint64_t uint64Value;
float float32Value;
double float64Value;
Text::Builder textValue; Text::Builder textValue;
Data::Builder dataValue; Data::Builder dataValue;
DynamicList::Builder listValue; DynamicList::Builder listValue;
DynamicEnum enumValue; DynamicEnum enumValue;
DynamicStruct::Builder structValue; DynamicStruct::Builder structValue;
DynamicUnion::Builder unionValue;
DynamicObject::Builder objectValue; DynamicObject::Builder objectValue;
}; };
template <typename T, Kind kind = kind<T>()> struct asImpl; template <typename T, Kind kind = kind<T>()> struct AsImpl;
// Implementation backing the as() method. Needs to be a struct to allow partial // Implementation backing the as() method. Needs to be a struct to allow partial
// specialization. Has a method apply() which does the work. // specialization. Has a method apply() which does the work.
}; };
...@@ -831,17 +850,52 @@ BuilderFor<DynamicTypeFor<FromBuilder<T>>> SchemaPool::toDynamic(T&& value) cons ...@@ -831,17 +850,52 @@ BuilderFor<DynamicTypeFor<FromBuilder<T>>> SchemaPool::toDynamic(T&& value) cons
return ToDynamicImpl<FromBuilder<T>>::apply(this, value); return ToDynamicImpl<FromBuilder<T>>::apply(this, value);
} }
#define CAPNPROTO_DECLARE_DYNAMIC_VALUE_CONSTRUCTOR(cppType, typeTag, fieldName) \
inline DynamicValue::Reader::Reader(cppType value) \
: type(typeTag), fieldName##Value(value) {} \
inline DynamicValue::Builder::Builder(cppType value) \
: type(typeTag), fieldName##Value(value) {}
CAPNPROTO_DECLARE_DYNAMIC_VALUE_CONSTRUCTOR(Void, VOID, void);
CAPNPROTO_DECLARE_DYNAMIC_VALUE_CONSTRUCTOR(bool, BOOL, bool);
CAPNPROTO_DECLARE_DYNAMIC_VALUE_CONSTRUCTOR(char, INT, int);
CAPNPROTO_DECLARE_DYNAMIC_VALUE_CONSTRUCTOR(signed char, INT, int);
CAPNPROTO_DECLARE_DYNAMIC_VALUE_CONSTRUCTOR(short, INT, int);
CAPNPROTO_DECLARE_DYNAMIC_VALUE_CONSTRUCTOR(int, INT, int);
CAPNPROTO_DECLARE_DYNAMIC_VALUE_CONSTRUCTOR(long, INT, int);
CAPNPROTO_DECLARE_DYNAMIC_VALUE_CONSTRUCTOR(long long, INT, int);
CAPNPROTO_DECLARE_DYNAMIC_VALUE_CONSTRUCTOR(unsigned char, UINT, uint);
CAPNPROTO_DECLARE_DYNAMIC_VALUE_CONSTRUCTOR(unsigned short, UINT, uint);
CAPNPROTO_DECLARE_DYNAMIC_VALUE_CONSTRUCTOR(unsigned int, UINT, uint);
CAPNPROTO_DECLARE_DYNAMIC_VALUE_CONSTRUCTOR(unsigned long, UINT, uint);
CAPNPROTO_DECLARE_DYNAMIC_VALUE_CONSTRUCTOR(unsigned long long, UINT, uint);
CAPNPROTO_DECLARE_DYNAMIC_VALUE_CONSTRUCTOR(float, FLOAT, float);
CAPNPROTO_DECLARE_DYNAMIC_VALUE_CONSTRUCTOR(double, FLOAT, float);
CAPNPROTO_DECLARE_DYNAMIC_VALUE_CONSTRUCTOR(DynamicEnum, ENUM, enum);
#undef CAPNPROTO_DECLARE_DYNAMIC_VALUE_CONSTRUCTOR
#define CAPNPROTO_DECLARE_DYNAMIC_VALUE_CONSTRUCTOR(cppType, typeTag, fieldName) \
inline DynamicValue::Reader::Reader(cppType::Reader value) \
: type(typeTag), fieldName##Value(value) {} \
inline DynamicValue::Builder::Builder(cppType::Builder value) \
: type(typeTag), fieldName##Value(value) {}
CAPNPROTO_DECLARE_DYNAMIC_VALUE_CONSTRUCTOR(Text, TEXT, text);
CAPNPROTO_DECLARE_DYNAMIC_VALUE_CONSTRUCTOR(Data, DATA, data);
CAPNPROTO_DECLARE_DYNAMIC_VALUE_CONSTRUCTOR(DynamicList, LIST, list);
CAPNPROTO_DECLARE_DYNAMIC_VALUE_CONSTRUCTOR(DynamicStruct, STRUCT, struct);
CAPNPROTO_DECLARE_DYNAMIC_VALUE_CONSTRUCTOR(DynamicUnion, UNION, union);
CAPNPROTO_DECLARE_DYNAMIC_VALUE_CONSTRUCTOR(DynamicObject, OBJECT, object);
#undef CAPNPROTO_DECLARE_DYNAMIC_VALUE_CONSTRUCTOR
#define CAPNPROTO_DECLARE_TYPE(name, discrim, typeName) \ #define CAPNPROTO_DECLARE_TYPE(name, discrim, typeName) \
inline DynamicValue::Reader::Reader(ReaderFor<typeName> name##Value) \
: type(schema::Type::Body::discrim##_TYPE), name##Value(name##Value) {} \
inline DynamicValue::Builder::Builder(BuilderFor<typeName> name##Value) \
: type(schema::Type::Body::discrim##_TYPE), name##Value(name##Value) {} \
template <> \ template <> \
struct DynamicValue::Reader::asImpl<typeName> { \ struct DynamicValue::Reader::AsImpl<typeName> { \
static ReaderFor<typeName> apply(Reader reader); \ static ReaderFor<typeName> apply(Reader reader); \
}; \ }; \
template <> \ template <> \
struct DynamicValue::Builder::asImpl<typeName> { \ struct DynamicValue::Builder::AsImpl<typeName> { \
static BuilderFor<typeName> apply(Builder builder); \ static BuilderFor<typeName> apply(Builder builder); \
}; };
...@@ -864,57 +918,54 @@ CAPNPROTO_DECLARE_TYPE(list, LIST, DynamicList) ...@@ -864,57 +918,54 @@ CAPNPROTO_DECLARE_TYPE(list, LIST, DynamicList)
CAPNPROTO_DECLARE_TYPE(struct, STRUCT, DynamicStruct) CAPNPROTO_DECLARE_TYPE(struct, STRUCT, DynamicStruct)
CAPNPROTO_DECLARE_TYPE(enum, ENUM, DynamicEnum) CAPNPROTO_DECLARE_TYPE(enum, ENUM, DynamicEnum)
CAPNPROTO_DECLARE_TYPE(object, OBJECT, DynamicObject) CAPNPROTO_DECLARE_TYPE(object, OBJECT, DynamicObject)
CAPNPROTO_DECLARE_TYPE(union, UNION, DynamicUnion)
#undef CAPNPROTO_DECLARE_TYPE #undef CAPNPROTO_DECLARE_TYPE
// CAPNPROTO_DECLARE_TYPE(Void) causes gcc 4.7 to segfault. If I do it manually and remove the // CAPNPROTO_DECLARE_TYPE(Void) causes gcc 4.7 to segfault. If I do it manually and remove the
// ReaderFor<> and BuilderFor<> wrappers, it works. // ReaderFor<> and BuilderFor<> wrappers, it works.
inline DynamicValue::Reader::Reader(Void voidValue) \
: type(schema::Type::Body::VOID_TYPE), voidValue(voidValue) {} \
inline DynamicValue::Builder::Builder(Void voidValue) \
: type(schema::Type::Body::VOID_TYPE), voidValue(voidValue) {} \
template <> template <>
struct DynamicValue::Reader::asImpl<Void> { struct DynamicValue::Reader::AsImpl<Void> {
static Void apply(Reader reader); static Void apply(Reader reader);
}; };
template <> template <>
struct DynamicValue::Builder::asImpl<Void> { struct DynamicValue::Builder::AsImpl<Void> {
static Void apply(Builder builder); static Void apply(Builder builder);
}; };
template <typename T> template <typename T>
struct DynamicValue::Reader::asImpl<T, Kind::ENUM> { struct DynamicValue::Reader::AsImpl<T, Kind::ENUM> {
static T apply(Reader reader) { static T apply(Reader reader) {
return reader.as<DynamicEnum>().as<T>(); return reader.as<DynamicEnum>().as<T>();
} }
}; };
template <typename T> template <typename T>
struct DynamicValue::Builder::asImpl<T, Kind::ENUM> { struct DynamicValue::Builder::AsImpl<T, Kind::ENUM> {
static T apply(Builder builder) { static T apply(Builder builder) {
return builder.as<DynamicEnum>().as<T>(); return builder.as<DynamicEnum>().as<T>();
} }
}; };
template <typename T> template <typename T>
struct DynamicValue::Reader::asImpl<T, Kind::STRUCT> { struct DynamicValue::Reader::AsImpl<T, Kind::STRUCT> {
static T apply(Reader reader) { static T apply(Reader reader) {
return reader.as<DynamicStruct>().as<T>(); return reader.as<DynamicStruct>().as<T>();
} }
}; };
template <typename T> template <typename T>
struct DynamicValue::Builder::asImpl<T, Kind::STRUCT> { struct DynamicValue::Builder::AsImpl<T, Kind::STRUCT> {
static T apply(Builder builder) { static T apply(Builder builder) {
return builder.as<DynamicStruct>().as<T>(); return builder.as<DynamicStruct>().as<T>();
} }
}; };
template <typename T> template <typename T>
struct DynamicValue::Reader::asImpl<T, Kind::LIST> { struct DynamicValue::Reader::AsImpl<T, Kind::LIST> {
static T apply(Reader reader) { static T apply(Reader reader) {
return reader.as<DynamicList>().as<T>(); return reader.as<DynamicList>().as<T>();
} }
}; };
template <typename T> template <typename T>
struct DynamicValue::Builder::asImpl<T, Kind::LIST> { struct DynamicValue::Builder::AsImpl<T, Kind::LIST> {
static T apply(Builder builder) { static T apply(Builder builder) {
return builder.as<DynamicList>().as<T>(); return builder.as<DynamicList>().as<T>();
} }
...@@ -923,26 +974,26 @@ struct DynamicValue::Builder::asImpl<T, Kind::LIST> { ...@@ -923,26 +974,26 @@ struct DynamicValue::Builder::asImpl<T, Kind::LIST> {
// ------------------------------------------------------------------- // -------------------------------------------------------------------
template <typename T> template <typename T>
struct DynamicObject::Reader::asImpl<T, Kind::STRUCT> { struct DynamicObject::Reader::AsImpl<T, Kind::STRUCT> {
static T apply(Reader reader) { static T apply(Reader reader) {
return reader.asStruct(typeId<T>()).as<T>(); return reader.asStruct(typeId<T>()).as<T>();
} }
}; };
template <typename T> template <typename T>
struct DynamicObject::Builder::asImpl<T, Kind::STRUCT> { struct DynamicObject::Builder::AsImpl<T, Kind::STRUCT> {
static T apply(Builder builder) { static T apply(Builder builder) {
return builder.asStruct(typeId<T>()).as<T>(); return builder.asStruct(typeId<T>()).as<T>();
} }
}; };
template <typename T> template <typename T>
struct DynamicObject::Reader::asImpl<List<T>, Kind::LIST> { struct DynamicObject::Reader::AsImpl<List<T>, Kind::LIST> {
static T apply(Reader reader) { static T apply(Reader reader) {
return reader.asList(internal::ListSchemaForElement<T>::schema).as<T>(); return reader.asList(internal::ListSchemaForElement<T>::schema).as<T>();
} }
}; };
template <typename T> template <typename T>
struct DynamicObject::Builder::asImpl<List<T>, Kind::LIST> { struct DynamicObject::Builder::AsImpl<List<T>, Kind::LIST> {
static T apply(Builder builder) { static T apply(Builder builder) {
return builder.asList(internal::ListSchemaForElement<T>::schema).as<T>(); return builder.asList(internal::ListSchemaForElement<T>::schema).as<T>();
} }
......
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