serialize.hpp 6.33 KB
Newer Older
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
/*
 * The MIT License (MIT)
 *
 * Copyright (c) 2015-2022 Advanced Micro Devices, Inc. All rights reserved.
 *
 * Permission is hereby granted, free of charge, to any person obtaining a copy
 * of this software and associated documentation files (the "Software"), to deal
 * in the Software without restriction, including without limitation the rights
 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
 * copies of the Software, and to permit persons to whom the Software is
 * furnished to do so, subject to the following conditions:
 *
 * The above copyright notice and this permission notice shall be included in
 * all copies or substantial portions of the Software.
 *
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL THE
 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
 * THE SOFTWARE.
 */
24
25
26
27
28
29
30
31
32
33
34
35
36
#ifndef MIGRAPHX_GUARD_RTGLIB_SERIALIZE_HPP
#define MIGRAPHX_GUARD_RTGLIB_SERIALIZE_HPP

#include <migraphx/config.hpp>
#include <migraphx/value.hpp>
#include <migraphx/reflect.hpp>
#include <migraphx/requires.hpp>
#include <migraphx/rank.hpp>
#include <type_traits>

namespace migraphx {
inline namespace MIGRAPHX_INLINE_NS {

37
38
39
40
// Avoid implicit conversion with ADL lookup
template <class T>
void migraphx_to_value(value&, const T&) = delete;

41
42
43
44
45
46
47
48
49
template <class T>
value to_value(const T& x);

template <class T>
void from_value(const value& v, T& x);

template <class T>
T from_value(const value& v)
{
50
    T x{};
51
52
53
54
55
56
57
58
59
60
61
62
    from_value(v, x);
    return x;
}

namespace detail {

template <class T, MIGRAPHX_REQUIRES(std::is_empty<T>{})>
value to_value_impl(rank<0>, const T&)
{
    return value::object{};
}

Paul's avatar
Format  
Paul committed
63
64
template <class T>
auto to_value_impl(rank<1>, const T& x) -> decltype(std::tuple_size<T>{}, value{})
65
{
Paul's avatar
Format  
Paul committed
66
67
68
69
70
    value result = value::array{};
    repeat_c<std::tuple_size<T>{}>([&](auto i) {
        result.push_back(to_value(std::get<i>(x)));
    });
    return result;
71
72
73
74
75
}

template <class T>
auto to_value_impl(rank<2>, const T& x) -> decltype(x.begin(), x.end(), value{})
{
76
    value result = value::array{};
77
78
79
80
81
82
83
84
85
86
    for(auto&& y : x)
    {
        result.insert(to_value(y));
    }
    return result;
}

template <class T, MIGRAPHX_REQUIRES(is_reflectable<T>{})>
value to_value_impl(rank<3>, const T& x)
{
87
    value result = value::object{};
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
    reflect_each(x, [&](auto&& y, std::string name) { result.emplace(name, to_value(y)); });
    return result;
}

template <class T, MIGRAPHX_REQUIRES(std::is_signed<T>{})>
value to_value_impl(rank<4>, const T& x)
{
    return std::int64_t{x};
}

template <class T, MIGRAPHX_REQUIRES(std::is_unsigned<T>{})>
value to_value_impl(rank<5>, const T& x)
{
    return std::uint64_t{x};
}

template <class T, MIGRAPHX_REQUIRES(std::is_floating_point<T>{})>
value to_value_impl(rank<6>, const T& x)
{
    return double{x};
}

template <class T, MIGRAPHX_REQUIRES(std::is_enum<T>{})>
value to_value_impl(rank<7>, const T& x)
{
113
    return x;
114
115
116
117
118
119
120
121
122
123
124
}

inline value to_value_impl(rank<8>, const std::string& x) { return x; }

template <class T>
auto to_value_impl(rank<9>, const T& x) -> decltype(migraphx_to_value(x))
{
    return migraphx_to_value(x);
}

template <class T>
125
126
127
128
129
130
131
auto to_value_impl(rank<10>, const T& x) -> decltype(x.to_value())
{
    return x.to_value();
}

template <class T>
auto to_value_impl(rank<11>, const T& x)
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
    -> decltype(migraphx_to_value(std::declval<value&>(), x), value{})
{
    value v;
    migraphx_to_value(v, x);
    return v;
}

template <class T, MIGRAPHX_REQUIRES(std::is_empty<T>{})>
void from_value_impl(rank<0>, const value& v, T& x)
{
    if(not v.is_object())
        MIGRAPHX_THROW("Expected an object");
    if(not v.get_object().empty())
        MIGRAPHX_THROW("Expected an empty object");
    x = T{};
}

template <class T>
auto from_value_impl(rank<1>, const value& v, T& x)
Paul's avatar
Format  
Paul committed
151
152
153
154
155
156
157
158
159
    -> 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)
160
161
162
163
164
165
166
    -> decltype(x.insert(x.end(), *x.begin()), void())
{
    x.clear();
    for(auto&& e : v)
        x.insert(x.end(), from_value<typename T::value_type>(e));
}

167
template <class T, MIGRAPHX_REQUIRES(std::is_arithmetic<typename T::value_type>{})>
Paul's avatar
Format  
Paul committed
168
auto from_value_impl(rank<3>, const value& v, T& x)
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
    -> decltype(x.insert(x.end(), *x.begin()), void())
{
    x.clear();
    if(v.is_binary())
    {
        for(auto&& e : v.get_binary())
            x.insert(x.end(), e);
    }
    else
    {
        for(auto&& e : v)
            x.insert(x.end(), from_value<typename T::value_type>(e));
    }
}

184
template <class T>
Paul's avatar
Format  
Paul committed
185
auto from_value_impl(rank<4>, const value& v, T& x) -> decltype(x.insert(*x.begin()), void())
186
187
188
189
190
191
192
{
    x.clear();
    for(auto&& e : v)
        x.emplace(e.get_key(), from_value<typename T::mapped_type>(e));
}

template <class T, MIGRAPHX_REQUIRES(is_reflectable<T>{})>
Paul's avatar
Format  
Paul committed
193
void from_value_impl(rank<5>, const value& v, T& x)
194
{
195
    reflect_each(x, [&](auto& y, const std::string& name) {
196
        using type = std::decay_t<decltype(y)>;
197
198
        if(v.contains(name))
            y = from_value<type>(v.at(name).without_key());
199
200
201
202
    });
}

template <class T, MIGRAPHX_REQUIRES(std::is_arithmetic<T>{})>
Paul's avatar
Format  
Paul committed
203
void from_value_impl(rank<6>, const value& v, T& x)
204
205
206
207
208
{
    x = v.to<T>();
}

template <class T, MIGRAPHX_REQUIRES(std::is_enum<T>{})>
Paul's avatar
Format  
Paul committed
209
void from_value_impl(rank<7>, const value& v, T& x)
210
{
211
    x = v.to<T>();
212
213
}

Paul's avatar
Format  
Paul committed
214
inline void from_value_impl(rank<8>, const value& v, std::string& x) { x = v.to<std::string>(); }
215
216

template <class T>
Paul's avatar
Format  
Paul committed
217
auto from_value_impl(rank<9>, const value& v, T& x) -> decltype(x.from_value(v), void())
218
219
220
221
222
{
    x.from_value(v);
}

template <class T>
Paul's avatar
Format  
Paul committed
223
auto from_value_impl(rank<10>, const value& v, T& x) -> decltype(migraphx_from_value(v, x), void())
224
225
226
227
228
229
230
231
232
{
    migraphx_from_value(v, x);
}

} // namespace detail

template <class T>
value to_value(const T& x)
{
233
    return detail::to_value_impl(rank<11>{}, x);
234
235
236
237
238
}

template <class T>
void from_value(const value& v, T& x)
{
Paul's avatar
Format  
Paul committed
239
    detail::from_value_impl(rank<10>{}, v, x);
240
241
242
243
244
245
}

} // namespace MIGRAPHX_INLINE_NS
} // namespace migraphx

#endif