Commit 6e4f4207 authored by Andrew Krieger's avatar Andrew Krieger Committed by Facebook Github Bot

Detect identity conversion in toDynamic

Summary:
D4499520 added typedefs to `dynamic` which made it start matching
tests for ranges/containers. However, the typedefs are unconditional on the
actual contents of the `dynamic`. This made toDynamic(dynamic) select the
range-based conversion operator, always, which immediately asserts when
trying to do range-based iteration over an Object or a primitive. Add tests
to the converters that enable/disable depending on whether the object is
already a `dynamic` and early-out in that case.

Reviewed By: mzlee

Differential Revision: D4538617

fbshipit-source-id: f3a5aafab07946a221dcead782fc27de51afa0a6
parent 3751f5de
...@@ -298,10 +298,22 @@ struct DynamicConstructor { ...@@ -298,10 +298,22 @@ struct DynamicConstructor {
} }
}; };
// identity
template <typename C>
struct DynamicConstructor<
C,
typename std::enable_if<std::is_same<C, dynamic>::value>::type> {
static dynamic construct(const C& x) {
return x;
}
};
// maps // maps
template<typename C> template <typename C>
struct DynamicConstructor<C, struct DynamicConstructor<
C,
typename std::enable_if< typename std::enable_if<
!std::is_same<C, dynamic>::value &&
dynamicconverter_detail::is_map<C>::value>::type> { dynamicconverter_detail::is_map<C>::value>::type> {
static dynamic construct(const C& x) { static dynamic construct(const C& x) {
dynamic d = dynamic::object; dynamic d = dynamic::object;
...@@ -313,9 +325,11 @@ struct DynamicConstructor<C, ...@@ -313,9 +325,11 @@ struct DynamicConstructor<C,
}; };
// other ranges // other ranges
template<typename C> template <typename C>
struct DynamicConstructor<C, struct DynamicConstructor<
C,
typename std::enable_if< typename std::enable_if<
!std::is_same<C, dynamic>::value &&
!dynamicconverter_detail::is_map<C>::value && !dynamicconverter_detail::is_map<C>::value &&
!std::is_constructible<StringPiece, const C&>::value && !std::is_constructible<StringPiece, const C&>::value &&
dynamicconverter_detail::is_range<C>::value>::type> { dynamicconverter_detail::is_range<C>::value>::type> {
......
...@@ -396,3 +396,16 @@ TEST(DynamicConverter, errors) { ...@@ -396,3 +396,16 @@ TEST(DynamicConverter, errors) {
dynamic d2 = floatOver; dynamic d2 = floatOver;
EXPECT_THROW(convertTo<float>(d2), std::range_error); EXPECT_THROW(convertTo<float>(d2), std::range_error);
} }
TEST(DynamicConverter, partial_dynamics) {
std::vector<dynamic> c{
dynamic::array(2, 3, 4), dynamic::array(3, 4, 5),
};
dynamic d = dynamic::array(dynamic::array(2, 3, 4), dynamic::array(3, 4, 5));
EXPECT_EQ(d, toDynamic(c));
std::unordered_map<std::string, dynamic> m{{"one", 1}, {"two", 2}};
dynamic md = dynamic::object("one", 1)("two", 2);
EXPECT_EQ(md, toDynamic(m));
}
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