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) {
// TODO(soon): Check if node is in base.
// 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);
if (!ins.second) {
// TODO(soon): Check for compatibility.
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 {
......@@ -645,7 +661,7 @@ void DynamicStruct::Builder::setFieldImpl(
case schema::Type::Body::discrim##_TYPE: \
builder.setDataField<type>( \
field.getOffset() * ELEMENTS, value.as<type>(), \
bitCast<internal::Mask<type> >(dval.get##titleCase##Value()));
bitCast<internal::Mask<type> >(dval.get##titleCase##Value())); \
break;
HANDLE_TYPE(BOOL, Bool, bool)
......@@ -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) \
ReaderFor<typeName> DynamicValue::Reader::asImpl<typeName>::apply(Reader reader) { \
VALIDATE_INPUT(reader.type == schema::Type::Body::discrim##_TYPE, \
ReaderFor<typeName> DynamicValue::Reader::AsImpl<typeName>::apply(Reader reader) { \
VALIDATE_INPUT(reader.type == discrim, \
"Type mismatch when using DynamicValue::Reader::as().") { \
return ReaderFor<typeName>(); \
} \
return reader.name##Value; \
} \
BuilderFor<typeName> DynamicValue::Builder::asImpl<typeName>::apply(Builder builder) { \
VALIDATE_INPUT(builder.type == schema::Type::Body::discrim##_TYPE, \
BuilderFor<typeName> DynamicValue::Builder::AsImpl<typeName>::apply(Builder builder) { \
VALIDATE_INPUT(builder.type == discrim, \
"Type mismatch when using DynamicValue::Builder::as().") { \
return BuilderFor<typeName>(); \
} \
......@@ -1151,16 +1255,6 @@ BuilderFor<typeName> DynamicValue::Builder::asImpl<typeName>::apply(Builder buil
//HANDLE_TYPE(void, VOID, Void)
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(data, DATA, Data)
......@@ -1168,19 +1262,20 @@ HANDLE_TYPE(list, LIST, DynamicList)
HANDLE_TYPE(struct, STRUCT, DynamicStruct)
HANDLE_TYPE(enum, ENUM, DynamicEnum)
HANDLE_TYPE(object, OBJECT, DynamicObject)
HANDLE_TYPE(union, UNION, DynamicUnion)
#undef HANDLE_TYPE
// As in the header, HANDLE_TYPE(void, VOID, Void) crashes GCC 4.7.
Void DynamicValue::Reader::asImpl<Void>::apply(Reader reader) {
VALIDATE_INPUT(reader.type == schema::Type::Body::VOID_TYPE,
Void DynamicValue::Reader::AsImpl<Void>::apply(Reader reader) {
VALIDATE_INPUT(reader.type == VOID,
"Type mismatch when using DynamicValue::Reader::as().") {
return Void();
}
return reader.voidValue;
}
Void DynamicValue::Builder::asImpl<Void>::apply(Builder builder) {
VALIDATE_INPUT(builder.type == schema::Type::Body::VOID_TYPE,
Void DynamicValue::Builder::AsImpl<Void>::apply(Builder builder) {
VALIDATE_INPUT(builder.type == VOID,
"Type mismatch when using DynamicValue::Builder::as().") {
return Void();
}
......
......@@ -45,6 +45,22 @@ class MessageReader;
class MessageBuilder;
struct DynamicValue {
enum Type {
VOID,
BOOL,
INT,
UINT,
FLOAT,
TEXT,
DATA,
LIST,
ENUM,
STRUCT,
UNION,
INTERFACE,
OBJECT
};
class Reader;
class Builder;
};
......@@ -269,7 +285,7 @@ public:
Reader() = default;
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.
DynamicStruct::Reader asStruct(schema::Node::Reader schema);
......@@ -282,7 +298,7 @@ private:
inline Reader(const SchemaPool* pool, internal::ObjectReader 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
// specialization. Has a method apply() which does the work.
......@@ -298,7 +314,7 @@ public:
Builder() = default;
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.
DynamicStruct::Builder asStruct(schema::Node::Reader schema);
......@@ -311,7 +327,7 @@ private:
inline Builder(const SchemaPool* pool, internal::ObjectBuilder 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
// specialization. Has a method apply() which does the work.
......@@ -635,125 +651,128 @@ struct MaybeReaderBuilder<DynamicList, Kind::UNKNOWN> {
class DynamicValue::Reader {
public:
inline Reader(Void voidValue = Void::VOID);
inline Reader(bool boolValue);
inline Reader(int8_t int8Value);
inline Reader(int16_t int16Value);
inline Reader(int32_t int32Value);
inline Reader(int64_t int64Value);
inline Reader(uint8_t uint8Value);
inline Reader(uint16_t uint16Value);
inline Reader(uint32_t uint32Value);
inline Reader(uint64_t uint64Value);
inline Reader(float float32Value);
inline Reader(double float64Value);
inline Reader(Text::Reader textValue);
inline Reader(Data::Reader dataValue);
inline Reader(DynamicList::Reader listValue);
inline Reader(DynamicEnum enumValue);
inline Reader(DynamicStruct::Reader structValue);
inline Reader(DynamicObject::Reader objectValue);
inline Reader(Void value = Void::VOID);
inline Reader(bool value);
inline Reader(char value);
inline Reader(signed char value);
inline Reader(short value);
inline Reader(int value);
inline Reader(long value);
inline Reader(long long value);
inline Reader(unsigned char value);
inline Reader(unsigned short value);
inline Reader(unsigned int value);
inline Reader(unsigned long value);
inline Reader(unsigned long long value);
inline Reader(float value);
inline Reader(double value);
inline Reader(Text::Reader value);
inline Reader(Data::Reader value);
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>
inline ReaderFor<T> as() { return asImpl<T>::apply(*this); }
// Use to interpret the value as some type. Allowed types are:
inline ReaderFor<T> as() { return AsImpl<T>::apply(*this); }
// 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.
// - Text, Data, any struct type: Returns the corresponding Reader.
// - List<T> for any T listed above: Returns List<T>::Reader.
// - DynamicEnum: Returns DynamicEnum.
// - DynamicStruct, DynamicList, DynamicObject: 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
// when traversed throws exceptions or returns garbage values. Under none of these
// circumstances will the program crash.
// - DynamicStruct, DynamicList, DynamicObject, DynamicUnion: Returns the corresponding Reader.
//
// DynamicValue allows various implicit conversions:
// - Any integer can be converted to any other integer type so long as the actual value is within
// 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.
private:
schema::Type::Body::Which type;
Type type;
union {
Void voidValue;
bool boolValue;
int8_t int8Value;
int16_t int16Value;
int32_t int32Value;
int64_t int64Value;
uint8_t uint8Value;
uint16_t uint16Value;
uint32_t uint32Value;
uint64_t uint64Value;
float float32Value;
double float64Value;
int64_t intValue;
uint64_t uintValue;
double floatValue;
Text::Reader textValue;
Data::Reader dataValue;
DynamicList::Reader listValue;
DynamicEnum enumValue;
DynamicStruct::Reader structValue;
DynamicUnion::Reader unionValue;
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
// specialization. Has a method apply() which does the work.
};
class DynamicValue::Builder {
public:
inline Builder(Void voidValue = Void::VOID);
inline Builder(bool boolValue);
inline Builder(int8_t int8Value);
inline Builder(int16_t int16Value);
inline Builder(int32_t int32Value);
inline Builder(int64_t int64Value);
inline Builder(uint8_t uint8Value);
inline Builder(uint16_t uint16Value);
inline Builder(uint32_t uint32Value);
inline Builder(uint64_t uint64Value);
inline Builder(float float32Value);
inline Builder(double float64Value);
inline Builder(Text::Builder textValue);
inline Builder(Data::Builder dataValue);
inline Builder(DynamicList::Builder listValue);
inline Builder(DynamicEnum enumValue);
inline Builder(DynamicStruct::Builder structValue);
inline Builder(DynamicObject::Builder objectValue);
inline Builder(Void value = Void::VOID);
inline Builder(bool value);
inline Builder(char value);
inline Builder(signed char value);
inline Builder(short value);
inline Builder(int value);
inline Builder(long value);
inline Builder(long long value);
inline Builder(unsigned char value);
inline Builder(unsigned short value);
inline Builder(unsigned int value);
inline Builder(unsigned long value);
inline Builder(unsigned long long value);
inline Builder(float value);
inline Builder(double value);
inline Builder(Text::Builder value);
inline Builder(Data::Builder value);
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>
inline BuilderFor<T> as() { return asImpl<T>::apply(*this); }
inline BuilderFor<T> as() { return AsImpl<T>::apply(*this); }
// See DynamicValue::Reader::as().
inline schema::Type::Body::Which getType() { return type; }
inline Type getType() { return type; }
// Get the type of this value.
Reader asReader();
private:
schema::Type::Body::Which type;
Type type;
union {
Void voidValue;
bool boolValue;
int8_t int8Value;
int16_t int16Value;
int32_t int32Value;
int64_t int64Value;
uint8_t uint8Value;
uint16_t uint16Value;
uint32_t uint32Value;
uint64_t uint64Value;
float float32Value;
double float64Value;
int64_t intValue;
uint64_t uintValue;
double floatValue;
Text::Builder textValue;
Data::Builder dataValue;
DynamicList::Builder listValue;
DynamicEnum enumValue;
DynamicStruct::Builder structValue;
DynamicUnion::Builder unionValue;
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
// specialization. Has a method apply() which does the work.
};
......@@ -831,17 +850,52 @@ BuilderFor<DynamicTypeFor<FromBuilder<T>>> SchemaPool::toDynamic(T&& value) cons
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) \
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 <> \
struct DynamicValue::Reader::asImpl<typeName> { \
struct DynamicValue::Reader::AsImpl<typeName> { \
static ReaderFor<typeName> apply(Reader reader); \
}; \
template <> \
struct DynamicValue::Builder::asImpl<typeName> { \
struct DynamicValue::Builder::AsImpl<typeName> { \
static BuilderFor<typeName> apply(Builder builder); \
};
......@@ -864,57 +918,54 @@ CAPNPROTO_DECLARE_TYPE(list, LIST, DynamicList)
CAPNPROTO_DECLARE_TYPE(struct, STRUCT, DynamicStruct)
CAPNPROTO_DECLARE_TYPE(enum, ENUM, DynamicEnum)
CAPNPROTO_DECLARE_TYPE(object, OBJECT, DynamicObject)
CAPNPROTO_DECLARE_TYPE(union, UNION, DynamicUnion)
#undef CAPNPROTO_DECLARE_TYPE
// CAPNPROTO_DECLARE_TYPE(Void) causes gcc 4.7 to segfault. If I do it manually and remove the
// 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 <>
struct DynamicValue::Reader::asImpl<Void> {
struct DynamicValue::Reader::AsImpl<Void> {
static Void apply(Reader reader);
};
template <>
struct DynamicValue::Builder::asImpl<Void> {
struct DynamicValue::Builder::AsImpl<Void> {
static Void apply(Builder builder);
};
template <typename T>
struct DynamicValue::Reader::asImpl<T, Kind::ENUM> {
struct DynamicValue::Reader::AsImpl<T, Kind::ENUM> {
static T apply(Reader reader) {
return reader.as<DynamicEnum>().as<T>();
}
};
template <typename T>
struct DynamicValue::Builder::asImpl<T, Kind::ENUM> {
struct DynamicValue::Builder::AsImpl<T, Kind::ENUM> {
static T apply(Builder builder) {
return builder.as<DynamicEnum>().as<T>();
}
};
template <typename T>
struct DynamicValue::Reader::asImpl<T, Kind::STRUCT> {
struct DynamicValue::Reader::AsImpl<T, Kind::STRUCT> {
static T apply(Reader reader) {
return reader.as<DynamicStruct>().as<T>();
}
};
template <typename T>
struct DynamicValue::Builder::asImpl<T, Kind::STRUCT> {
struct DynamicValue::Builder::AsImpl<T, Kind::STRUCT> {
static T apply(Builder builder) {
return builder.as<DynamicStruct>().as<T>();
}
};
template <typename T>
struct DynamicValue::Reader::asImpl<T, Kind::LIST> {
struct DynamicValue::Reader::AsImpl<T, Kind::LIST> {
static T apply(Reader reader) {
return reader.as<DynamicList>().as<T>();
}
};
template <typename T>
struct DynamicValue::Builder::asImpl<T, Kind::LIST> {
struct DynamicValue::Builder::AsImpl<T, Kind::LIST> {
static T apply(Builder builder) {
return builder.as<DynamicList>().as<T>();
}
......@@ -923,26 +974,26 @@ struct DynamicValue::Builder::asImpl<T, Kind::LIST> {
// -------------------------------------------------------------------
template <typename T>
struct DynamicObject::Reader::asImpl<T, Kind::STRUCT> {
struct DynamicObject::Reader::AsImpl<T, Kind::STRUCT> {
static T apply(Reader reader) {
return reader.asStruct(typeId<T>()).as<T>();
}
};
template <typename T>
struct DynamicObject::Builder::asImpl<T, Kind::STRUCT> {
struct DynamicObject::Builder::AsImpl<T, Kind::STRUCT> {
static T apply(Builder builder) {
return builder.asStruct(typeId<T>()).as<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) {
return reader.asList(internal::ListSchemaForElement<T>::schema).as<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) {
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