Coverage Report

Created: 2025-10-28 07:12

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/jsoncons/include/jsoncons_ext/msgpack/decode_msgpack.hpp
Line
Count
Source
1
// Copyright 2013-2025 Daniel Parker
2
// Distributed under the Boost license, Version 1.0.
3
// (See accompanying file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
4
5
// See https://github.com/danielaparker/jsoncons for latest version
6
7
#ifndef JSONCONS_EXT_MSGPACK_DECODE_MSGPACK_HPP
8
#define JSONCONS_EXT_MSGPACK_DECODE_MSGPACK_HPP
9
10
#include <istream> // std::basic_istream
11
#include <type_traits> // std::enable_if
12
13
#include <jsoncons/allocator_set.hpp>
14
#include <jsoncons/config/compiler_support.hpp>
15
#include <jsoncons/utility/more_type_traits.hpp>
16
#include <jsoncons/basic_json.hpp>
17
#include <jsoncons/conv_error.hpp>
18
#include <jsoncons/reflect/decode_traits.hpp>
19
#include <jsoncons/ser_util.hpp>
20
#include <jsoncons/source.hpp>
21
22
#include <jsoncons_ext/msgpack/msgpack_cursor.hpp>
23
#include <jsoncons_ext/msgpack/msgpack_encoder.hpp>
24
#include <jsoncons_ext/msgpack/msgpack_reader.hpp>
25
26
namespace jsoncons { 
27
namespace msgpack {
28
29
template <typename T,typename BytesLike>
30
typename std::enable_if<ext_traits::is_basic_json<T>::value &&
31
                        ext_traits::is_byte_sequence<BytesLike>::value,read_result<T>>::type 
32
try_decode_msgpack(const BytesLike& v, 
33
    const msgpack_decode_options& options = msgpack_decode_options())
34
{
35
    using value_type = T;
36
    using result_type = read_result<value_type>;
37
38
    std::error_code ec;   
39
    jsoncons::json_decoder<T> decoder;
40
    auto adaptor = make_json_visitor_adaptor<json_visitor>(decoder);
41
    basic_msgpack_reader<jsoncons::bytes_source> reader(v, adaptor, options);
42
    reader.read(ec);
43
    if (JSONCONS_UNLIKELY(ec))
44
    {
45
        return result_type{jsoncons::unexpect, ec, reader.line(), reader.column()};
46
    }
47
    if (JSONCONS_UNLIKELY(!decoder.is_valid()))
48
    {
49
        return result_type{jsoncons::unexpect, conv_errc::conversion_failed, reader.line(), reader.column()};
50
    }
51
    return result_type{decoder.get_result()};
52
}
53
54
template <typename T,typename BytesLike>
55
typename std::enable_if<!ext_traits::is_basic_json<T>::value &&
56
                        ext_traits::is_byte_sequence<BytesLike>::value,read_result<T>>::type 
57
try_decode_msgpack(const BytesLike& v, 
58
    const msgpack_decode_options& options = msgpack_decode_options())
59
{
60
    using value_type = T;
61
    using result_type = read_result<value_type>;
62
63
    std::error_code ec;   
64
    basic_msgpack_cursor<bytes_source> cursor(v, options, ec);
65
    if (JSONCONS_UNLIKELY(ec))
66
    {
67
        return result_type{jsoncons::unexpect, ec, cursor.line(), cursor.column()};
68
    }
69
70
    return reflect::decode_traits<T>::try_decode(make_alloc_set(), cursor);
71
}
72
73
template <typename T>
74
typename std::enable_if<ext_traits::is_basic_json<T>::value,read_result<T>>::type 
75
try_decode_msgpack(std::istream& is, 
76
    const msgpack_decode_options& options = msgpack_decode_options())
77
6.82k
{
78
6.82k
    using value_type = T;
79
6.82k
    using result_type = read_result<value_type>;
80
81
6.82k
    std::error_code ec;   
82
6.82k
    jsoncons::json_decoder<T> decoder;
83
6.82k
    auto adaptor = make_json_visitor_adaptor<json_visitor>(decoder);
84
6.82k
    msgpack_stream_reader reader(is, adaptor, options);
85
6.82k
    reader.read(ec);
86
6.82k
    if (JSONCONS_UNLIKELY(ec))
87
4.37k
    {
88
4.37k
        return result_type{jsoncons::unexpect, ec, reader.line(), reader.column()};
89
4.37k
    }
90
2.44k
    if (JSONCONS_UNLIKELY(!decoder.is_valid()))
91
0
    {
92
0
        return result_type{jsoncons::unexpect, conv_errc::conversion_failed, reader.line(), reader.column()};
93
0
    }
94
2.44k
    return result_type{decoder.get_result()};
95
2.44k
}
96
97
template <typename T>
98
typename std::enable_if<!ext_traits::is_basic_json<T>::value,read_result<T>>::type 
99
try_decode_msgpack(std::istream& is, 
100
    const msgpack_decode_options& options = msgpack_decode_options())
101
{
102
    using value_type = T;
103
    using result_type = read_result<value_type>;
104
105
    std::error_code ec;   
106
    basic_msgpack_cursor<binary_stream_source> cursor(is, options, ec);
107
    if (JSONCONS_UNLIKELY(ec))
108
    {
109
        return result_type{jsoncons::unexpect, ec, cursor.line(), cursor.column()};
110
    }
111
112
    return reflect::decode_traits<T>::try_decode(make_alloc_set(), cursor);
113
}
114
115
template <typename T,typename InputIt>
116
typename std::enable_if<ext_traits::is_basic_json<T>::value,read_result<T>>::type 
117
try_decode_msgpack(InputIt first, InputIt last,
118
    const msgpack_decode_options& options = msgpack_decode_options())
119
{
120
    using value_type = T;
121
    using result_type = read_result<value_type>;
122
123
    std::error_code ec;   
124
    jsoncons::json_decoder<T> decoder;
125
    auto adaptor = make_json_visitor_adaptor<json_visitor>(decoder);
126
    basic_msgpack_reader<binary_iterator_source<InputIt>> reader(binary_iterator_source<InputIt>(first, last), adaptor, options);
127
    reader.read(ec);
128
    if (JSONCONS_UNLIKELY(ec))
129
    {
130
        return result_type{jsoncons::unexpect, ec, reader.line(), reader.column()};
131
    }
132
    if (JSONCONS_UNLIKELY(!decoder.is_valid()))
133
    {
134
        return result_type{jsoncons::unexpect, conv_errc::conversion_failed, reader.line(), reader.column()};
135
    }
136
    return result_type{decoder.get_result()};
137
}
138
139
template <typename T,typename InputIt>
140
typename std::enable_if<!ext_traits::is_basic_json<T>::value,read_result<T>>::type 
141
try_decode_msgpack(InputIt first, InputIt last,
142
    const msgpack_decode_options& options = msgpack_decode_options())
143
{
144
    using value_type = T;
145
    using result_type = read_result<value_type>;
146
147
    std::error_code ec;   
148
    basic_msgpack_cursor<binary_iterator_source<InputIt>> cursor(binary_iterator_source<InputIt>(first, last), options, ec);
149
    if (JSONCONS_UNLIKELY(ec))
150
    {
151
        return result_type{jsoncons::unexpect, ec, cursor.line(), cursor.column()};
152
    }
153
154
    return reflect::decode_traits<T>::try_decode(make_alloc_set(), cursor);
155
}
156
157
// With leading allocator_set parameter
158
159
template <typename T,typename BytesLike,typename Alloc,typename TempAlloc >
160
typename std::enable_if<ext_traits::is_basic_json<T>::value &&
161
                        ext_traits::is_byte_sequence<BytesLike>::value,read_result<T>>::type 
162
try_decode_msgpack(const allocator_set<Alloc,TempAlloc>& aset,
163
    const BytesLike& v, 
164
    const msgpack_decode_options& options = msgpack_decode_options())
165
{
166
    using value_type = T;
167
    using result_type = read_result<value_type>;
168
169
    std::error_code ec;   
170
    json_decoder<T,TempAlloc> decoder(aset.get_allocator(), aset.get_temp_allocator());
171
    auto adaptor = make_json_visitor_adaptor<json_visitor>(decoder);
172
    basic_msgpack_reader<jsoncons::bytes_source,TempAlloc> reader(v, adaptor, options, aset.get_temp_allocator());
173
    reader.read(ec);
174
    if (JSONCONS_UNLIKELY(ec))
175
    {
176
        return result_type{jsoncons::unexpect, ec, reader.line(), reader.column()};
177
    }
178
    if (JSONCONS_UNLIKELY(!decoder.is_valid()))
179
    {
180
        return result_type{jsoncons::unexpect, conv_errc::conversion_failed, reader.line(), reader.column()};
181
    }
182
    return result_type{decoder.get_result()};
183
}
184
185
template <typename T,typename BytesLike,typename Alloc,typename TempAlloc >
186
typename std::enable_if<!ext_traits::is_basic_json<T>::value &&
187
                        ext_traits::is_byte_sequence<BytesLike>::value,read_result<T>>::type 
188
try_decode_msgpack(const allocator_set<Alloc,TempAlloc>& aset,
189
    const BytesLike& v, 
190
    const msgpack_decode_options& options = msgpack_decode_options())
191
{
192
    using value_type = T;
193
    using result_type = read_result<value_type>;
194
195
    std::error_code ec;   
196
    basic_msgpack_cursor<bytes_source,TempAlloc> cursor(std::allocator_arg, aset.get_temp_allocator(), v, options, ec);
197
    if (JSONCONS_UNLIKELY(ec))
198
    {
199
        return result_type{jsoncons::unexpect, ec, cursor.line(), cursor.column()};
200
    }
201
202
    return reflect::decode_traits<T>::try_decode(aset, cursor);
203
}
204
205
template <typename T,typename Alloc,typename TempAlloc >
206
typename std::enable_if<ext_traits::is_basic_json<T>::value,read_result<T>>::type 
207
try_decode_msgpack(const allocator_set<Alloc,TempAlloc>& aset,
208
    std::istream& is, 
209
    const msgpack_decode_options& options = msgpack_decode_options())
210
{
211
    using value_type = T;
212
    using result_type = read_result<value_type>;
213
    using byte_allocator_type = typename std::allocator_traits<TempAlloc>:: template rebind_alloc<uint8_t>;
214
    using stream_source_type = stream_source<uint8_t,byte_allocator_type>;
215
216
    std::error_code ec;   
217
    json_decoder<T,TempAlloc> decoder(aset.get_allocator(), aset.get_temp_allocator());
218
    auto adaptor = make_json_visitor_adaptor<json_visitor>(decoder);
219
    basic_msgpack_reader<stream_source_type,TempAlloc> reader(stream_source_type(is,aset.get_temp_allocator()), 
220
        adaptor, options, aset.get_temp_allocator());
221
    reader.read(ec);
222
    if (JSONCONS_UNLIKELY(ec))
223
    {
224
        return result_type{jsoncons::unexpect, ec, reader.line(), reader.column()};
225
    }
226
    if (JSONCONS_UNLIKELY(!decoder.is_valid()))
227
    {
228
        return result_type{jsoncons::unexpect, conv_errc::conversion_failed, reader.line(), reader.column()};
229
    }
230
    return result_type{decoder.get_result()};
231
}
232
233
template <typename T,typename Alloc,typename TempAlloc >
234
typename std::enable_if<!ext_traits::is_basic_json<T>::value,read_result<T>>::type 
235
try_decode_msgpack(const allocator_set<Alloc,TempAlloc>& aset,
236
    std::istream& is, 
237
    const msgpack_decode_options& options = msgpack_decode_options())
238
{
239
    using value_type = T;
240
    using result_type = read_result<value_type>;
241
242
    std::error_code ec;   
243
    basic_msgpack_cursor<binary_stream_source,TempAlloc> cursor(
244
        std::allocator_arg, aset.get_temp_allocator(), is, options, ec);
245
    if (JSONCONS_UNLIKELY(ec))
246
    {
247
        return result_type{jsoncons::unexpect, ec, cursor.line(), cursor.column()};
248
    }
249
250
    return reflect::decode_traits<T>::try_decode(aset, cursor);
251
}
252
253
template <typename T, typename... Args>
254
T decode_msgpack(Args&& ... args)
255
6.82k
{
256
6.82k
    auto result = try_decode_msgpack<T>(std::forward<Args>(args)...); 
257
6.82k
    if (!result)
258
4.37k
    {
259
4.37k
        JSONCONS_THROW(ser_error(result.error().code(), result.error().line(), result.error().column()));
260
4.37k
    }
261
2.44k
    return std::move(*result);
262
6.82k
}
263
264
} // namespace msgpack
265
} // namespace jsoncons
266
267
#endif // JSONCONS_EXT_MSGPACK_DECODE_MSGPACK_HPP