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

Fix JSON handler for DynamicStruct. The handler needs to be told the struct's…

Fix JSON handler for DynamicStruct. The handler needs to be told the struct's schema to construct an orphan.

Also improve error message when addTypeHandler() is given a handler for a dynamic type but no specific schema is specified. We could support this eventually but we don't presently.
parent 0c42db54
......@@ -691,6 +691,29 @@ KJ_TEST("register capability handler") {
json.addTypeHandler(handler);
}
class TestDynamicStructHandler: public JsonCodec::Handler<DynamicStruct> {
public:
void encode(const JsonCodec& codec, DynamicStruct::Reader input,
JsonValue::Builder output) const override {
KJ_UNIMPLEMENTED("TestDynamicStructHandler::encode");
}
void decode(const JsonCodec& codec, JsonValue::Reader input,
DynamicStruct::Builder output) const override {
KJ_UNIMPLEMENTED("TestDynamicStructHandler::decode");
}
};
KJ_TEST("register DynamicStruct handler") {
// This test currently only checks that this compiles, which at one point wasn't the caes.
// TODO(test): Actually run some code here.
TestDynamicStructHandler handler;
JsonCodec json;
json.addTypeHandler(Schema::from<TestAllTypes>(), handler);
}
} // namespace
} // namespace _ (private)
} // namespace capnp
......@@ -225,6 +225,7 @@ kj::String JsonCodec::encodeRaw(JsonValue::Reader value) const {
void JsonCodec::encode(DynamicValue::Reader input, Type type, JsonValue::Builder output) const {
// TODO(soon): For interfaces, check for handlers on superclasses, per documentation...
// TODO(soon): For branded types, should we check for handlers on the generic?
// TODO(someday): Allow registering handlers for "all structs", "all lists", etc?
auto iter = impl->typeHandlers.find(type);
if (iter != impl->typeHandlers.end()) {
iter->second->encodeBase(*this, input, output);
......@@ -934,7 +935,7 @@ void JsonCodec::decodeRaw(kj::ArrayPtr<const char> input, JsonValue::Builder out
// -----------------------------------------------------------------------------
Orphan<DynamicValue> JsonCodec::HandlerBase::decodeBase(
const JsonCodec& codec, JsonValue::Reader input, Orphanage orphanage) const {
const JsonCodec& codec, JsonValue::Reader input, Type type, Orphanage orphanage) const {
KJ_FAIL_ASSERT("JSON decoder handler type / value type mismatch");
}
void JsonCodec::HandlerBase::decodeStructBase(
......
......@@ -288,7 +288,7 @@ public:
virtual void encodeBase(const JsonCodec& codec, DynamicValue::Reader input,
JsonValue::Builder output) const = 0;
virtual Orphan<DynamicValue> decodeBase(const JsonCodec& codec, JsonValue::Reader input,
Orphanage orphanage) const;
Type type, Orphanage orphanage) const;
virtual void decodeStructBase(const JsonCodec& codec, JsonValue::Reader input,
DynamicStruct::Builder output) const;
};
......@@ -307,7 +307,7 @@ private:
encode(codec, input.as<T>(), output);
}
Orphan<DynamicValue> decodeBase(const JsonCodec& codec, JsonValue::Reader input,
Orphanage orphanage) const override final {
Type type, Orphanage orphanage) const override final {
return decode(codec, input, orphanage);
}
friend class JsonCodec;
......@@ -334,7 +334,7 @@ private:
encode(codec, input.as<T>(), output);
}
Orphan<DynamicValue> decodeBase(const JsonCodec& codec, JsonValue::Reader input,
Orphanage orphanage) const override final {
Type type, Orphanage orphanage) const override final {
return decode(codec, input, orphanage);
}
void decodeStructBase(const JsonCodec& codec, JsonValue::Reader input,
......@@ -344,6 +344,39 @@ private:
friend class JsonCodec;
};
template <>
class JsonCodec::Handler<DynamicStruct>: private JsonCodec::HandlerBase {
// Almost identical to Style::STRUCT except that we pass the struct type to decode().
public:
virtual void encode(const JsonCodec& codec, DynamicStruct::Reader input,
JsonValue::Builder output) const = 0;
virtual void decode(const JsonCodec& codec, JsonValue::Reader input,
DynamicStruct::Builder output) const = 0;
virtual Orphan<DynamicStruct> decode(const JsonCodec& codec, JsonValue::Reader input,
StructSchema type, Orphanage orphanage) const {
// If subclass does not override, fall back to regular version.
auto result = orphanage.newOrphan(type);
decode(codec, input, result.get());
return result;
}
private:
void encodeBase(const JsonCodec& codec, DynamicValue::Reader input,
JsonValue::Builder output) const override final {
encode(codec, input.as<DynamicStruct>(), output);
}
Orphan<DynamicValue> decodeBase(const JsonCodec& codec, JsonValue::Reader input,
Type type, Orphanage orphanage) const override final {
return decode(codec, input, type.asStruct(), orphanage);
}
void decodeStructBase(const JsonCodec& codec, JsonValue::Reader input,
DynamicStruct::Builder output) const override final {
decode(codec, input, output.as<DynamicStruct>());
}
friend class JsonCodec;
};
template <typename T>
class JsonCodec::Handler<T, Style::PRIMITIVE>: private JsonCodec::HandlerBase {
public:
......@@ -356,7 +389,7 @@ private:
encode(codec, input.as<T>(), output);
}
Orphan<DynamicValue> decodeBase(const JsonCodec& codec, JsonValue::Reader input,
Orphanage orphanage) const override final {
Type type, Orphanage orphanage) const override final {
return decode(codec, input);
}
friend class JsonCodec;
......@@ -375,7 +408,7 @@ private:
encode(codec, input.as<T>(), output);
}
Orphan<DynamicValue> decodeBase(const JsonCodec& codec, JsonValue::Reader input,
Orphanage orphanage) const override final {
Type type, Orphanage orphanage) const override final {
return orphanage.newOrphanCopy(decode(codec, input));
}
friend class JsonCodec;
......@@ -406,6 +439,24 @@ inline void JsonCodec::addFieldHandler(StructSchema::Field field, Handler<T>& ha
addFieldHandlerImpl(field, Type::from<T>(), handler);
}
template <> void JsonCodec::addTypeHandler(Handler<DynamicValue>& handler)
KJ_UNAVAILABLE("JSON handlers for type sets (e.g. all structs, all lists) not implemented; "
"try specifying a specific type schema as the first parameter");
template <> void JsonCodec::addTypeHandler(Handler<DynamicEnum>& handler)
KJ_UNAVAILABLE("JSON handlers for type sets (e.g. all structs, all lists) not implemented; "
"try specifying a specific type schema as the first parameter");
template <> void JsonCodec::addTypeHandler(Handler<DynamicStruct>& handler)
KJ_UNAVAILABLE("JSON handlers for type sets (e.g. all structs, all lists) not implemented; "
"try specifying a specific type schema as the first parameter");
template <> void JsonCodec::addTypeHandler(Handler<DynamicList>& handler)
KJ_UNAVAILABLE("JSON handlers for type sets (e.g. all structs, all lists) not implemented; "
"try specifying a specific type schema as the first parameter");
template <> void JsonCodec::addTypeHandler(Handler<DynamicCapability>& handler)
KJ_UNAVAILABLE("JSON handlers for type sets (e.g. all structs, all lists) not implemented; "
"try specifying a specific type schema as the first parameter");
// TODO(someday): Implement support for registering handlers that cover thinsg like "all structs"
// or "all lists". Currently you can only target a specific struct or list type.
} // namespace capnp
#endif // CAPNP_COMPAT_JSON_H_
......@@ -190,11 +190,15 @@ typedef unsigned char byte;
#if __clang__
#define KJ_DEPRECATED(reason) \
__attribute__((deprecated(reason)))
#define KJ_UNAVAILABLE(reason) \
__attribute__((unavailable(reason)))
#elif __GNUC__
#define KJ_DEPRECATED(reason) \
__attribute__((deprecated))
#define KJ_UNAVAILABLE(reason)
#else
#define KJ_DEPRECATED(reason)
#define KJ_UNAVAILABLE(reason)
// TODO(msvc): Again, here, MSVC prefers a prefix, __declspec(deprecated).
#endif
......
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