Unverified Commit 41bf982d authored by Paul Fultz II's avatar Paul Fultz II Committed by GitHub
Browse files

Add serialization of tuples and optional types (#1495)

* Add serialization of tuples and optional types
parent fc9ebb06
...@@ -28,6 +28,7 @@ ...@@ -28,6 +28,7 @@
#include <migraphx/value.hpp> #include <migraphx/value.hpp>
#include <migraphx/reflect.hpp> #include <migraphx/reflect.hpp>
#include <migraphx/requires.hpp> #include <migraphx/requires.hpp>
#include <migraphx/optional.hpp>
#include <migraphx/rank.hpp> #include <migraphx/rank.hpp>
#include <type_traits> #include <type_traits>
...@@ -60,11 +61,12 @@ value to_value_impl(rank<0>, const T&) ...@@ -60,11 +61,12 @@ value to_value_impl(rank<0>, const T&)
return value::object{}; return value::object{};
} }
template <class T, class U> template <class T>
value to_value_impl(rank<1>, const std::pair<T, U>& x) auto to_value_impl(rank<1>, const T& x) -> decltype(std::tuple_size<T>{}, value{})
{ {
value result = value::array{};
return {x.first, x.second}; repeat_c<std::tuple_size<T>{}>([&](auto i) { result.push_back(to_value(std::get<i>(x))); });
return result;
} }
template <class T> template <class T>
...@@ -86,46 +88,55 @@ value to_value_impl(rank<3>, const T& x) ...@@ -86,46 +88,55 @@ value to_value_impl(rank<3>, const T& x)
return result; return result;
} }
template <class T>
auto to_value_impl(rank<4>, const optional<T>& x)
{
value result{};
if(x.has_value())
return to_value(*x);
return result;
}
template <class T, MIGRAPHX_REQUIRES(std::is_signed<T>{})> template <class T, MIGRAPHX_REQUIRES(std::is_signed<T>{})>
value to_value_impl(rank<4>, const T& x) value to_value_impl(rank<5>, const T& x)
{ {
return std::int64_t{x}; return std::int64_t{x};
} }
template <class T, MIGRAPHX_REQUIRES(std::is_unsigned<T>{})> template <class T, MIGRAPHX_REQUIRES(std::is_unsigned<T>{})>
value to_value_impl(rank<5>, const T& x) value to_value_impl(rank<6>, const T& x)
{ {
return std::uint64_t{x}; return std::uint64_t{x};
} }
template <class T, MIGRAPHX_REQUIRES(std::is_floating_point<T>{})> template <class T, MIGRAPHX_REQUIRES(std::is_floating_point<T>{})>
value to_value_impl(rank<6>, const T& x) value to_value_impl(rank<7>, const T& x)
{ {
return double{x}; return double{x};
} }
template <class T, MIGRAPHX_REQUIRES(std::is_enum<T>{})> template <class T, MIGRAPHX_REQUIRES(std::is_enum<T>{})>
value to_value_impl(rank<7>, const T& x) value to_value_impl(rank<8>, const T& x)
{ {
return x; return x;
} }
inline value to_value_impl(rank<8>, const std::string& x) { return x; } inline value to_value_impl(rank<9>, const std::string& x) { return x; }
template <class T> template <class T>
auto to_value_impl(rank<9>, const T& x) -> decltype(migraphx_to_value(x)) auto to_value_impl(rank<10>, const T& x) -> decltype(migraphx_to_value(x))
{ {
return migraphx_to_value(x); return migraphx_to_value(x);
} }
template <class T> template <class T>
auto to_value_impl(rank<10>, const T& x) -> decltype(x.to_value()) auto to_value_impl(rank<11>, const T& x) -> decltype(x.to_value())
{ {
return x.to_value(); return x.to_value();
} }
template <class T> template <class T>
auto to_value_impl(rank<11>, const T& x) auto to_value_impl(rank<12>, const T& x)
-> decltype(migraphx_to_value(std::declval<value&>(), x), value{}) -> decltype(migraphx_to_value(std::declval<value&>(), x), value{})
{ {
value v; value v;
...@@ -144,7 +155,14 @@ void from_value_impl(rank<0>, const value& v, T& x) ...@@ -144,7 +155,14 @@ void from_value_impl(rank<0>, const value& v, T& x)
} }
template <class T> template <class T>
auto from_value_impl(rank<1>, const value& v, T& x) auto from_value_impl(rank<1>, const value& v, T& x) -> decltype(std::tuple_size<T>{}, void())
{
repeat_c<std::tuple_size<T>{}>(
[&](auto i) { std::get<i>(x) = from_value<std::tuple_element_t<i, T>>(v[i]); });
}
template <class T>
auto from_value_impl(rank<2>, const value& v, T& x)
-> decltype(x.insert(x.end(), *x.begin()), void()) -> decltype(x.insert(x.end(), *x.begin()), void())
{ {
x.clear(); x.clear();
...@@ -153,7 +171,7 @@ auto from_value_impl(rank<1>, const value& v, T& x) ...@@ -153,7 +171,7 @@ auto from_value_impl(rank<1>, const value& v, T& x)
} }
template <class T, MIGRAPHX_REQUIRES(std::is_arithmetic<typename T::value_type>{})> template <class T, MIGRAPHX_REQUIRES(std::is_arithmetic<typename T::value_type>{})>
auto from_value_impl(rank<2>, const value& v, T& x) auto from_value_impl(rank<3>, const value& v, T& x)
-> decltype(x.insert(x.end(), *x.begin()), void()) -> decltype(x.insert(x.end(), *x.begin()), void())
{ {
x.clear(); x.clear();
...@@ -170,7 +188,7 @@ auto from_value_impl(rank<2>, const value& v, T& x) ...@@ -170,7 +188,7 @@ auto from_value_impl(rank<2>, const value& v, T& x)
} }
template <class T> template <class T>
auto from_value_impl(rank<3>, const value& v, T& x) -> decltype(x.insert(*x.begin()), void()) auto from_value_impl(rank<4>, const value& v, T& x) -> decltype(x.insert(*x.begin()), void())
{ {
x.clear(); x.clear();
for(auto&& e : v) for(auto&& e : v)
...@@ -178,7 +196,7 @@ auto from_value_impl(rank<3>, const value& v, T& x) -> decltype(x.insert(*x.begi ...@@ -178,7 +196,7 @@ auto from_value_impl(rank<3>, const value& v, T& x) -> decltype(x.insert(*x.begi
} }
template <class T, MIGRAPHX_REQUIRES(is_reflectable<T>{})> template <class T, MIGRAPHX_REQUIRES(is_reflectable<T>{})>
void from_value_impl(rank<4>, const value& v, T& x) void from_value_impl(rank<5>, const value& v, T& x)
{ {
reflect_each(x, [&](auto& y, const std::string& name) { reflect_each(x, [&](auto& y, const std::string& name) {
using type = std::decay_t<decltype(y)>; using type = std::decay_t<decltype(y)>;
...@@ -187,28 +205,29 @@ void from_value_impl(rank<4>, const value& v, T& x) ...@@ -187,28 +205,29 @@ void from_value_impl(rank<4>, const value& v, T& x)
}); });
} }
template <class T, MIGRAPHX_REQUIRES(std::is_arithmetic<T>{})> template <class T>
void from_value_impl(rank<5>, const value& v, T& x) void from_value_impl(rank<6>, const value& v, optional<T>& x)
{ {
x = v.to<T>(); if(not v.is_null())
x = from_value<T>(v);
} }
template <class T, MIGRAPHX_REQUIRES(std::is_enum<T>{})> template <class T, MIGRAPHX_REQUIRES(std::is_arithmetic<T>{} or std::is_enum<T>{})>
void from_value_impl(rank<6>, const value& v, T& x) void from_value_impl(rank<7>, const value& v, T& x)
{ {
x = v.to<T>(); x = v.to<T>();
} }
inline void from_value_impl(rank<7>, const value& v, std::string& x) { x = v.to<std::string>(); } inline void from_value_impl(rank<8>, const value& v, std::string& x) { x = v.to<std::string>(); }
template <class T> template <class T>
auto from_value_impl(rank<8>, const value& v, T& x) -> decltype(x.from_value(v), void()) auto from_value_impl(rank<9>, const value& v, T& x) -> decltype(x.from_value(v), void())
{ {
x.from_value(v); x.from_value(v);
} }
template <class T> template <class T>
auto from_value_impl(rank<9>, const value& v, T& x) -> decltype(migraphx_from_value(v, x), void()) auto from_value_impl(rank<10>, const value& v, T& x) -> decltype(migraphx_from_value(v, x), void())
{ {
migraphx_from_value(v, x); migraphx_from_value(v, x);
} }
...@@ -218,13 +237,13 @@ auto from_value_impl(rank<9>, const value& v, T& x) -> decltype(migraphx_from_va ...@@ -218,13 +237,13 @@ auto from_value_impl(rank<9>, const value& v, T& x) -> decltype(migraphx_from_va
template <class T> template <class T>
value to_value(const T& x) value to_value(const T& x)
{ {
return detail::to_value_impl(rank<11>{}, x); return detail::to_value_impl(rank<12>{}, x);
} }
template <class T> template <class T>
void from_value(const value& v, T& x) void from_value(const value& v, T& x)
{ {
detail::from_value_impl(rank<9>{}, v, x); detail::from_value_impl(rank<10>{}, v, x);
} }
} // namespace MIGRAPHX_INLINE_NS } // namespace MIGRAPHX_INLINE_NS
......
...@@ -60,7 +60,9 @@ struct reflectable_type ...@@ -60,7 +60,9 @@ struct reflectable_type
return migraphx::pack(f(self.value, "value")); return migraphx::pack(f(self.value, "value"));
} }
}; };
std::vector<nested_type> nested_types = {}; std::vector<nested_type> nested_types = {};
std::tuple<int, nested_type, std::string> tuple_items = std::make_tuple(0, nested_type{0}, "");
migraphx::optional<int> opt_value = migraphx::nullopt;
template <class Self, class F> template <class Self, class F>
static auto reflect(Self& self, F f) static auto reflect(Self& self, F f)
...@@ -71,7 +73,8 @@ struct reflectable_type ...@@ -71,7 +73,8 @@ struct reflectable_type
f(self.et, "et"), f(self.et, "et"),
f(self.se, "se"), f(self.se, "se"),
f(self.ce, "ce"), f(self.ce, "ce"),
f(self.nested_types, "nested_types")); f(self.nested_types, "nested_types"),
f(self.tuple_items, "tuple_items"));
} }
}; };
...@@ -83,7 +86,9 @@ TEST_CASE(serialize_reflectable_type) ...@@ -83,7 +86,9 @@ TEST_CASE(serialize_reflectable_type)
{}, {},
reflectable_type::simple1, reflectable_type::simple1,
reflectable_type::class_enum::class2, reflectable_type::class_enum::class2,
{{1}, {2}}}; {{1}, {2}},
{5, {4}, "hello"},
{migraphx::nullopt}};
migraphx::value v1 = migraphx::to_value(t1); migraphx::value v1 = migraphx::to_value(t1);
reflectable_type t2 = migraphx::from_value<reflectable_type>(v1); reflectable_type t2 = migraphx::from_value<reflectable_type>(v1);
migraphx::value v2 = migraphx::to_value(t2); migraphx::value v2 = migraphx::to_value(t2);
...@@ -125,6 +130,21 @@ TEST_CASE(serialize_empty_struct) ...@@ -125,6 +130,21 @@ TEST_CASE(serialize_empty_struct)
EXPECT(v.at("a").to<int>() == 1); EXPECT(v.at("a").to<int>() == 1);
} }
TEST_CASE(serialize_empty_optional)
{
migraphx::optional<int> x{};
migraphx::value v = migraphx::to_value(x);
EXPECT(v.is_null());
}
TEST_CASE(serialize_optional)
{
migraphx::optional<int> x{2};
migraphx::value v = migraphx::to_value(x);
EXPECT(v.is_int64());
EXPECT(v.to<int>() == 2);
}
TEST_CASE(from_value_binary) TEST_CASE(from_value_binary)
{ {
std::vector<std::uint8_t> data(10); std::vector<std::uint8_t> data(10);
......
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