@@ -28,7 +28,7 @@ namespace service {
2828class schema_exception : public std ::exception
2929{
3030public:
31- schema_exception (const std::vector<std::string>& messages);
31+ schema_exception (std::vector<std::string>& & messages);
3232
3333 const rapidjson::Document& getErrors () const noexcept ;
3434
@@ -62,13 +62,14 @@ using FragmentMap = std::unordered_map<std::string, Fragment>;
6262// a single field.
6363struct ResolverParams
6464{
65+ rapidjson::Document::AllocatorType& allocator;
6566 const rapidjson::Value::ConstObject& arguments;
6667 const peg::ast_node* selection;
6768 const FragmentMap& fragments;
6869 const rapidjson::Value::ConstObject& variables;
6970};
7071
71- using Resolver = std::function<rapidjson::Document (ResolverParams&&)>;
72+ using Resolver = std::function<rapidjson::Value (ResolverParams&&)>;
7273using ResolverMap = std::unordered_map<std::string, Resolver>;
7374
7475// Binary data and opaque strings like IDs are encoded in Base64.
@@ -148,14 +149,14 @@ struct ModifiedArgument
148149 };
149150
150151 // Convert a single value to the specified type.
151- static _Type convert (const rapidjson::Value& value);
152+ static _Type convert (rapidjson::Document::AllocatorType& allocator, const rapidjson::Value& value);
152153
153154 // Call convert on this type without any modifiers.
154- static _Type require (const std::string& name, const rapidjson::Value::ConstObject& arguments)
155+ static _Type require (rapidjson::Document::AllocatorType& allocator, const std::string& name, const rapidjson::Value::ConstObject& arguments)
155156 {
156157 try
157158 {
158- return convert (arguments[name.c_str ()]);
159+ return convert (allocator, arguments[name.c_str ()]);
159160 }
160161 catch (const schema_exception& ex)
161162 {
@@ -167,11 +168,11 @@ struct ModifiedArgument
167168 }
168169
169170 // Wrap require in a try/catch block.
170- static std::pair<_Type, bool > find (const std::string& name, const rapidjson::Value::ConstObject& arguments) noexcept
171+ static std::pair<_Type, bool > find (rapidjson::Document::AllocatorType& allocator, const std::string& name, const rapidjson::Value::ConstObject& arguments) noexcept
171172 {
172173 try
173174 {
174- return { require (name, arguments), true };
175+ return { require (allocator, name, arguments), true };
175176 }
176177 catch (const schema_exception&)
177178 {
@@ -182,16 +183,16 @@ struct ModifiedArgument
182183 // Peel off the none modifier. If it's included, it should always be last in the list.
183184 template <TypeModifier _Modifier = TypeModifier::None , TypeModifier... _Other >
184185 static typename std::enable_if<TypeModifier::None == _Modifier && sizeof ...(_Other) == 0 , _Type>::type require (
185- const std::string& name, const rapidjson::Value::ConstObject& arguments)
186+ rapidjson::Document::AllocatorType& allocator, const std::string& name, const rapidjson::Value::ConstObject& arguments)
186187 {
187188 // Just call through to the non-template method without the modifiers.
188- return require (name, arguments);
189+ return require (allocator, name, arguments);
189190 }
190191
191192 // Peel off nullable modifiers.
192193 template <TypeModifier _Modifier, TypeModifier... _Other>
193194 static typename std::enable_if<TypeModifier::Nullable == _Modifier, typename ArgumentTraits<_Type, _Modifier, _Other...>::type>::type require (
194- const std::string& name, const rapidjson::Value::ConstObject& arguments)
195+ rapidjson::Document::AllocatorType& allocator, const std::string& name, const rapidjson::Value::ConstObject& arguments)
195196 {
196197 const auto & valueItr = arguments.FindMember (name.c_str ());
197198
@@ -201,42 +202,42 @@ struct ModifiedArgument
201202 return nullptr ;
202203 }
203204
204- auto result = require<_Other...>(name, arguments);
205+ auto result = require<_Other...>(allocator, name, arguments);
205206
206207 return std::unique_ptr<decltype (result)> { new decltype (result)(std::move (result)) };
207208 }
208209
209210 // Peel off list modifiers.
210211 template <TypeModifier _Modifier, TypeModifier... _Other>
211212 static typename std::enable_if<TypeModifier::List == _Modifier, typename ArgumentTraits<_Type, _Modifier, _Other...>::type>::type require (
212- const std::string& name, const rapidjson::Value::ConstObject& arguments)
213+ rapidjson::Document::AllocatorType& allocator, const std::string& name, const rapidjson::Value::ConstObject& arguments)
213214 {
214215 const auto & values = arguments[name.c_str ()].GetArray ();
215216 typename ArgumentTraits<_Type, _Modifier, _Other...>::type result (values.Size ());
216217
217218 std::transform (values.begin (), values.end (), result.begin (),
218- [&name](const rapidjson::Value& element)
219+ [&allocator, & name](const rapidjson::Value& element)
219220 {
220- rapidjson::Document single (rapidjson::Type::kObjectType );
221- auto & allocator = single.GetAllocator ();
222- rapidjson::Value value;
221+ rapidjson::Value single (rapidjson::Type::kObjectType );
222+ rapidjson::Value entry;
223223
224- value .CopyFrom (element, allocator);
225- single.AddMember (rapidjson::StringRef (name.c_str ()), value , allocator);
224+ entry .CopyFrom (element, allocator);
225+ single.AddMember (rapidjson::StringRef (name.c_str ()), entry , allocator);
226226
227- return require<_Other...>(name.c_str (), const_cast <const rapidjson::Document &>(single).GetObject ());
227+ return require<_Other...>(allocator, name.c_str (), const_cast <const rapidjson::Value &>(single).GetObject ());
228228 });
229229
230230 return result;
231231 }
232232
233233 // Wrap require with modifiers in a try/catch block.
234234 template <TypeModifier _Modifier, TypeModifier... _Other>
235- static std::pair<typename ArgumentTraits<_Type, _Modifier, _Other...>::type, bool > find (const std::string& name, const rapidjson::Value::ConstObject& arguments) noexcept
235+ static std::pair<typename ArgumentTraits<_Type, _Modifier, _Other...>::type, bool > find (
236+ rapidjson::Document::AllocatorType& allocator, const std::string& name, const rapidjson::Value::ConstObject& arguments) noexcept
236237 {
237238 try
238239 {
239- return { require<_Modifier, _Other...>(name, arguments), true };
240+ return { require<_Modifier, _Other...>(allocator, name, arguments), true };
240241 }
241242 catch (const schema_exception&)
242243 {
@@ -253,7 +254,7 @@ using FloatArgument = ModifiedArgument<double>;
253254using StringArgument = ModifiedArgument<std::string>;
254255using BooleanArgument = ModifiedArgument<bool >;
255256using IdArgument = ModifiedArgument<std::vector<uint8_t >>;
256- using ScalarArgument = ModifiedArgument<rapidjson::Document >;
257+ using ScalarArgument = ModifiedArgument<rapidjson::Value >;
257258
258259// Each type should handle fragments with type conditions matching its own
259260// name and any inheritted interfaces.
@@ -269,7 +270,7 @@ class Object : public std::enable_shared_from_this<Object>
269270 explicit Object (TypeNames&& typeNames, ResolverMap&& resolvers);
270271 virtual ~Object () = default ;
271272
272- rapidjson::Document resolve (const peg::ast_node& selection, const FragmentMap& fragments, const rapidjson::Value::ConstObject& variables) const ;
273+ rapidjson::Value resolve (rapidjson::Document::AllocatorType& allocator, const peg::ast_node& selection, const FragmentMap& fragments, const rapidjson::Value::ConstObject& variables) const ;
273274
274275private:
275276 TypeNames _typeNames;
@@ -311,13 +312,13 @@ struct ModifiedResult
311312 };
312313
313314 // Convert a single value of the specified type to JSON.
314- static rapidjson::Document convert (typename std::conditional<std::is_base_of<Object, _Type>::value, std::shared_ptr<Object>, typename ResultTraits<_Type>::type&&>::type result,
315+ static rapidjson::Value convert (typename std::conditional<std::is_base_of<Object, _Type>::value, std::shared_ptr<Object>, typename ResultTraits<_Type>::type&&>::type result,
315316 ResolverParams&& params);
316317
317318 // Peel off the none modifier. If it's included, it should always be last in the list.
318319 template <TypeModifier _Modifier = TypeModifier::None, TypeModifier... _Other>
319320 static typename std::enable_if<TypeModifier::None == _Modifier && sizeof ...(_Other) == 0 && !std::is_same<Object, _Type>::value && std::is_base_of<Object, _Type>::value,
320- rapidjson::Document >::type convert (typename ResultTraits<_Type>::type&& result, ResolverParams&& params)
321+ rapidjson::Value >::type convert (typename ResultTraits<_Type>::type&& result, ResolverParams&& params)
321322 {
322323 // Call through to the Object specialization with a static_pointer_cast for subclasses of Object.
323324 static_assert (std::is_same<std::shared_ptr<_Type>, typename ResultTraits<_Type>::type>::value, " this is the derived object type" );
@@ -327,7 +328,7 @@ struct ModifiedResult
327328 // Peel off the none modifier. If it's included, it should always be last in the list.
328329 template <TypeModifier _Modifier = TypeModifier::None, TypeModifier... _Other>
329330 static typename std::enable_if<TypeModifier::None == _Modifier && sizeof ...(_Other) == 0 && (std::is_same<Object, _Type>::value || !std::is_base_of<Object, _Type>::value),
330- rapidjson::Document >::type convert (typename ResultTraits<_Type>::type&& result, ResolverParams&& params)
331+ rapidjson::Value >::type convert (typename ResultTraits<_Type>::type&& result, ResolverParams&& params)
331332 {
332333 // Just call through to the partial specialization without the modifier.
333334 return convert (std::move (result), std::move (params));
@@ -336,11 +337,11 @@ struct ModifiedResult
336337 // Peel off final nullable modifiers for std::shared_ptr of Object and subclasses of Object.
337338 template <TypeModifier _Modifier, TypeModifier... _Other>
338339 static typename std::enable_if<TypeModifier::Nullable == _Modifier && std::is_same<std::shared_ptr<_Type>, typename ResultTraits<_Type, _Other...>::type>::value,
339- rapidjson::Document >::type convert (typename ResultTraits<_Type, _Modifier, _Other...>::type&& result, ResolverParams&& params)
340+ rapidjson::Value >::type convert (typename ResultTraits<_Type, _Modifier, _Other...>::type&& result, ResolverParams&& params)
340341 {
341342 if (!result)
342343 {
343- return rapidjson::Document (rapidjson::Type::kNullType );
344+ return rapidjson::Value (rapidjson::Type::kNullType );
344345 }
345346
346347 return convert<_Other...>(std::move (result), std::move (params));
@@ -349,14 +350,14 @@ struct ModifiedResult
349350 // Peel off nullable modifiers for anything else, which should all be std::unique_ptr.
350351 template <TypeModifier _Modifier, TypeModifier... _Other>
351352 static typename std::enable_if<TypeModifier::Nullable == _Modifier && !std::is_same<std::shared_ptr<_Type>, typename ResultTraits<_Type, _Other...>::type>::value,
352- rapidjson::Document >::type convert (typename ResultTraits<_Type, _Modifier, _Other...>::type&& result, ResolverParams&& params)
353+ rapidjson::Value >::type convert (typename ResultTraits<_Type, _Modifier, _Other...>::type&& result, ResolverParams&& params)
353354 {
354355 static_assert (std::is_same<std::unique_ptr<typename ResultTraits<_Type, _Other...>::type>, typename ResultTraits<_Type, _Modifier, _Other...>::type>::value,
355356 " this is the unique_ptr version" );
356357
357358 if (!result)
358359 {
359- return rapidjson::Document (rapidjson::Type::kNullType );
360+ return rapidjson::Value (rapidjson::Type::kNullType );
360361 }
361362
362363 return convert<_Other...>(std::move (*result), std::move (params));
@@ -365,19 +366,15 @@ struct ModifiedResult
365366 // Peel off list modifiers.
366367 template <TypeModifier _Modifier, TypeModifier... _Other>
367368 static typename std::enable_if<TypeModifier::List == _Modifier,
368- rapidjson::Document >::type convert (typename ResultTraits<_Type, _Modifier, _Other...>::type&& result, ResolverParams&& params)
369+ rapidjson::Value >::type convert (typename ResultTraits<_Type, _Modifier, _Other...>::type&& result, ResolverParams&& params)
369370 {
370- auto value = rapidjson::Document (rapidjson::Type::kArrayType );
371- auto & allocator = value.GetAllocator ();
371+ auto value = rapidjson::Value (rapidjson::Type::kArrayType );
372372
373- value.Reserve (result.size (), allocator);
373+ value.Reserve (result.size (), params. allocator );
374374
375375 for (auto & entry : result)
376376 {
377- rapidjson::Value element;
378-
379- element.CopyFrom (convert<_Other...>(std::move (entry), ResolverParams (params)), allocator);
380- value.PushBack (element, allocator);
377+ value.PushBack (convert<_Other...>(std::move (entry), ResolverParams (params)), params.allocator );
381378 }
382379
383380 return value;
@@ -392,7 +389,7 @@ using FloatResult = ModifiedResult<double>;
392389using StringResult = ModifiedResult<std::string>;
393390using BooleanResult = ModifiedResult<bool >;
394391using IdResult = ModifiedResult<std::vector<unsigned char >>;
395- using ScalarResult = ModifiedResult<rapidjson::Document >;
392+ using ScalarResult = ModifiedResult<rapidjson::Value >;
396393using ObjectResult = ModifiedResult<Object>;
397394
398395// Request scans the fragment definitions and finds the right operation definition to interpret
@@ -410,16 +407,16 @@ class Request : public std::enable_shared_from_this<Request>
410407 TypeMap _operations;
411408};
412409
413- // SelectionVisitor visits the AST and resolves a field or fragment, unless its skipped by
410+ // SelectionVisitor visits the AST and resolves a field or fragment, unless it's skipped by
414411// a directive or type condition.
415412class SelectionVisitor
416413{
417414public:
418- SelectionVisitor (const FragmentMap& fragments, const rapidjson::Document::ConstObject& variables, const TypeNames& typeNames, const ResolverMap& resolvers);
415+ SelectionVisitor (rapidjson::Document::AllocatorType& allocator, const FragmentMap& fragments, const rapidjson::Document::ConstObject& variables, const TypeNames& typeNames, const ResolverMap& resolvers);
419416
420417 void visit (const peg::ast_node& selection);
421418
422- rapidjson::Document getValues ();
419+ rapidjson::Value getValues ();
423420
424421private:
425422 bool shouldSkip (const std::vector<std::unique_ptr<peg::ast_node>>* directives) const ;
@@ -428,23 +425,25 @@ class SelectionVisitor
428425 void visitFragmentSpread (const peg::ast_node& fragmentSpread);
429426 void visitInlineFragment (const peg::ast_node& inlineFragment);
430427
428+ rapidjson::Document::AllocatorType& _allocator;
431429 const FragmentMap& _fragments;
432430 const rapidjson::Document::ConstObject& _variables;
433431 const TypeNames& _typeNames;
434432 const ResolverMap& _resolvers;
435- rapidjson::Document _values;
433+
434+ rapidjson::Value _values;
436435};
437436
438437// ValueVisitor visits the AST and builds a JSON representation of any value
439438// hardcoded or referencing a variable in an operation.
440439class ValueVisitor
441440{
442441public:
443- ValueVisitor (const rapidjson::Document::ConstObject& variables);
442+ ValueVisitor (rapidjson::Document::AllocatorType& allocator, const rapidjson::Document::ConstObject& variables);
444443
445444 void visit (const peg::ast_node& value);
446445
447- rapidjson::Document getValue ();
446+ rapidjson::Value getValue ();
448447
449448private:
450449 void visitVariable (const peg::ast_node& variable);
@@ -457,8 +456,9 @@ class ValueVisitor
457456 void visitListValue (const peg::ast_node& listValue);
458457 void visitObjectValue (const peg::ast_node& objectValue);
459458
459+ rapidjson::Document::AllocatorType& _allocator;
460460 const rapidjson::Document::ConstObject& _variables;
461- rapidjson::Document _value;
461+ rapidjson::Value _value;
462462};
463463
464464// FragmentDefinitionVisitor visits the AST and collects all of the fragment
0 commit comments