Bond
 
Loading...
Searching...
No Matches
simple_json_reader.h
1// Copyright (c) Microsoft. All rights reserved.
2// Licensed under the MIT license. See LICENSE file in the project root for full license information.
3
4#pragma once
5
6#include <bond/core/config.h>
7
8#include "detail/rapidjson_helper.h"
9#include "encoding.h"
10
11#include "rapidjson/document.h"
12#include "rapidjson/reader.h"
13
14#include <boost/make_shared.hpp>
15#include <boost/none.hpp>
16#include <boost/optional/optional.hpp>
17
18namespace bond
19{
20
21template <typename BufferT>
22class SimpleJsonWriter;
23
24
26template <typename BufferT>
28{
29public:
30 typedef BufferT Buffer;
31 typedef DOMParser<SimpleJsonReader&> Parser;
33 typedef rapidjson::Value Field;
34
35 BOND_STATIC_CONSTEXPR uint16_t magic = SIMPLE_JSON_PROTOCOL;
36 BOND_STATIC_CONSTEXPR uint16_t version = 0x0001;
37
39 SimpleJsonReader(const Buffer& input)
40 : _value(nullptr),
41 _document(boost::make_shared<rapidjson::Document>()),
42 _streamHolder(input)
43 { }
44
49 SimpleJsonReader(SimpleJsonReader& parent, const Field& value)
50 : _value(&value),
51 _document(parent._document),
52 _streamHolder(parent)
53 {
54 // Must have an already-parsed parent
55 BOOST_ASSERT(parent._value);
56 }
57
58 bool ReadVersion()
59 {
60 return false;
61 }
62
63 void Parse()
64 {
65 // Don't need to reparse for nested fields
66 if (!_value || _value == _document.get())
67 {
68 const unsigned parseFlags = rapidjson::kParseIterativeFlag | rapidjson::kParseStopWhenDoneFlag;
69
70 _document->ParseStream<parseFlags>(_streamHolder.Get());
71
72 // If there were any parse errors, an exception should have been
73 // thrown, as we define RAPIDJSON_PARSE_ERROR
74 BOOST_ASSERT(!_document->HasParseError());
75 _value = _document.get();
76 }
77 }
78
79 const Field* FindField(uint16_t id, const Metadata& metadata, BondDataType type)
80 {
81 // BT_INT32 may be an enum. This allows us to decode symbolic enum values
82 // when parsing using runtime schema. The assumption is that runtime schema
83 // matches JSON payload. If it doesn't, nothing horrible will happen, but
84 // we might not indicate a required field missing for an int32 field if we
85 // mistake a string member with matching name for it.
86 return FindField(id, metadata, type, type == BT_INT32);
87 }
88
89 const Field* FindField(uint16_t id, const Metadata& metadata, BondDataType type, bool is_enum);
90
91
92 template <typename T>
93 void Read(T& var)
94 {
95 detail::Read(*GetValue(), var);
96 }
97
98 template <typename T>
99 void ReadContainerBegin(uint32_t&, T&)
100 {
101 BOOST_ASSERT(false);
102 }
103
104 void ReadContainerEnd()
105 {
106 BOOST_ASSERT(false);
107 }
108
109 template <typename T>
110 void Skip()
111 { }
112
113 template <typename T>
114 void Skip(const T&)
115 { }
116
117
118 bool operator==(const SimpleJsonReader& rhs) const
119 {
120 return _value == rhs._value;
121 }
122
124 const Buffer& GetBuffer() const
125 {
126 return _streamHolder.Get().GetBuffer();
127 }
128
130 Buffer& GetBuffer()
131 {
132 return _streamHolder.Get().GetBuffer();
133 }
134
135private:
136 rapidjson::Value::ConstMemberIterator MemberBegin() const
137 {
138 return GetValue()->IsObject() ? GetValue()->MemberBegin() : rapidjson::Value::ConstMemberIterator();
139 }
140
141 rapidjson::Value::ConstMemberIterator MemberEnd() const
142 {
143 return GetValue()->IsObject() ? GetValue()->MemberEnd() : rapidjson::Value::ConstMemberIterator();
144 }
145
146 rapidjson::Value::ConstValueIterator ArrayBegin() const
147 {
148 return GetValue()->IsArray() ? GetValue()->Begin() : rapidjson::Value::ConstValueIterator();
149 }
150
151 rapidjson::Value::ConstValueIterator ArrayEnd() const
152 {
153 return GetValue()->IsArray() ? GetValue()->End() : rapidjson::Value::ConstValueIterator();
154 }
155
156 uint32_t ArraySize() const
157 {
158 return GetValue()->IsArray() ? GetValue()->Size() : 0;
159 }
160
161 const rapidjson::Value* GetValue() const
162 {
163 BOOST_ASSERT(_value);
164 return _value;
165 }
166
167 template <typename Input>
168 friend struct base_input;
169
170 template <typename Protocols, typename A, typename T, typename Buffer>
171 friend void DeserializeContainer(std::vector<bool, A>&, const T&, SimpleJsonReader<Buffer>&);
172
173 template <typename Protocols, typename T, typename Buffer>
174 friend void DeserializeContainer(blob&, const T&, SimpleJsonReader<Buffer>&);
175
176 template <typename Protocols, typename X, typename T, typename Buffer>
177 friend typename boost::enable_if<is_list_container<X> >::type
178 DeserializeContainer(X&, const T&, SimpleJsonReader<Buffer>&);
179
180 template <typename Protocols, typename X, typename T, typename Buffer>
181 friend typename boost::enable_if<is_set_container<X> >::type
182 DeserializeContainer(X&, const T&, SimpleJsonReader<Buffer>&);
183
184 template <typename Protocols, typename X, typename T, typename Buffer>
185 friend typename boost::enable_if<is_map_container<X> >::type
186 DeserializeMap(X&, BondDataType, const T&, SimpleJsonReader<Buffer>&);
187
188 const rapidjson::Value* _value;
189 boost::shared_ptr<rapidjson::Document> _document;
190
193 class StreamHolder
194 {
195 public:
196 explicit StreamHolder(const Buffer& input)
197 : _stream(),
198 _parent()
199 {
200 // could use boost::in_place to construct this in the
201 // initializer list when the minimum version of Boost is 1.63
202 _stream.emplace(input);
203 BOOST_ASSERT(IsParent());
204 }
205
206 explicit StreamHolder(SimpleJsonReader& parent)
207 : _stream(),
208 // Resolve the real parent
209 _parent(&parent._streamHolder.GetParent())
210 {
211 BOOST_ASSERT(_parent->IsParent());
212 BOOST_ASSERT(!IsParent());
213 }
214
215 // Intentionaly deep copy. Copies of SimpleJsonReader are expected
216 // to be deep copies, even if they're made from children.
217 StreamHolder(const StreamHolder& other)
218 : _stream(other.Get()),
219 _parent()
220 {
221 BOOST_ASSERT(IsParent());
222 }
223
224 StreamHolder& operator=(const StreamHolder& other)
225 {
226 _stream.emplace(other.Get());
227 _parent = nullptr;
228 BOOST_ASSERT(IsParent());
229
230 return *this;
231 }
232
233 StreamHolder(StreamHolder&&) = default;
234 StreamHolder& operator=(StreamHolder&&) = default;
235
236 const detail::RapidJsonInputStream<Buffer>& Get() const
237 {
238 return IsParent() ? _stream.value() : _parent->Get();
239 }
240
241 detail::RapidJsonInputStream<Buffer>& Get()
242 {
243 return IsParent() ? _stream.value() : _parent->Get();
244 }
245
246 private:
247 bool IsParent() const
248 {
249 const bool isParent = _parent == nullptr;
250 BOOST_ASSERT(isParent == static_cast<bool>(_stream)); // parents must have a stream
251 return isParent;
252 }
253
254 StreamHolder& GetParent()
255 {
256 return IsParent() ? *this : *_parent;
257 }
258
259 boost::optional<detail::RapidJsonInputStream<Buffer>> _stream;
260 StreamHolder* _parent;
261 } _streamHolder;
262};
263
264
265template <typename Buffer>
266BOND_CONSTEXPR_OR_CONST uint16_t SimpleJsonReader<Buffer>::magic;
267
268// Disable fast pass-through optimization for Simple JSON
269template <typename Input, typename Output> struct
270is_protocol_same<SimpleJsonReader<Input>, SimpleJsonWriter<Output> >
271 : std::false_type {};
272
273
274} // namespace bond
Reader for Simple JSON.
Definition: simple_json_reader.h:28
SimpleJsonReader(SimpleJsonReader &parent, const Field &value)
Create a "child" SimpleJsonReader to read value, which is known to be a member of the document in par...
Definition: simple_json_reader.h:49
Buffer & GetBuffer()
Access to underlying buffer.
Definition: simple_json_reader.h:130
SimpleJsonReader(const Buffer &input)
Construct from input buffer/stream containing serialized data.
Definition: simple_json_reader.h:39
const Buffer & GetBuffer() const
Access to underlying buffer.
Definition: simple_json_reader.h:124
Writer for Simple JSON.
Definition: simple_json_writer.h:26
namespace bond
Definition: apply.h:17