1 // Copyright 2020 gRPC authors.
2 //
3 // Licensed under the Apache License, Version 2.0 (the "License");
4 // you may not use this file except in compliance with the License.
5 // You may obtain a copy of the License at
6 //
7 //     http://www.apache.org/licenses/LICENSE-2.0
8 //
9 // Unless required by applicable law or agreed to in writing, software
10 // distributed under the License is distributed on an "AS IS" BASIS,
11 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 // See the License for the specific language governing permissions and
13 // limitations under the License.
14 
15 #ifndef GRPC_SRC_CORE_LIB_JSON_JSON_OBJECT_LOADER_H
16 #define GRPC_SRC_CORE_LIB_JSON_JSON_OBJECT_LOADER_H
17 
18 #include <grpc/support/port_platform.h>
19 
20 #include <cstdint>
21 #include <cstring>
22 #include <map>
23 #include <memory>
24 #include <string>
25 #include <utility>
26 #include <vector>
27 
28 #include "absl/meta/type_traits.h"
29 #include "absl/status/status.h"
30 #include "absl/status/statusor.h"
31 #include "absl/strings/numbers.h"
32 #include "absl/strings/str_cat.h"
33 #include "absl/strings/string_view.h"
34 #include "absl/types/optional.h"
35 
36 #include "src/core/lib/gprpp/no_destruct.h"
37 #include "src/core/lib/gprpp/ref_counted_ptr.h"
38 #include "src/core/lib/gprpp/time.h"
39 #include "src/core/lib/gprpp/validation_errors.h"
40 #include "src/core/lib/json/json.h"
41 #include "src/core/lib/json/json_args.h"
42 
43 // Provides a means to load JSON objects into C++ objects, with the aim of
44 // minimizing object code size.
45 //
46 // Usage:
47 // Given struct Foo:
48 //   struct Foo {
49 //     int a;
50 //     int b;
51 //   };
52 // We add a static JsonLoader() method to Foo to declare how to load the
53 // object from JSON, and an optional JsonPostLoad() method to do any
54 // necessary post-processing:
55 //   struct Foo {
56 //     int a;
57 //     int b;
58 //     static const JsonLoaderInterface* JsonLoader(const JsonArgs& args) {
59 //       // Note: Field names must be string constants; they are not copied.
60 //       static const auto* loader = JsonObjectLoader<Foo>()
61 //           .Field("a", &Foo::a)
62 //           .Field("b", &Foo::b)
63 //           .Finish();
64 //       return loader;
65 //     }
66 //     // Optional; omit if no post-processing needed.
67 //     void JsonPostLoad(const Json& source, const JsonArgs& args,
68 //                       ValidationErrors* errors) {
69 //       ++a;
70 //     }
71 //   };
72 // Now we can load Foo objects from JSON:
73 //   absl::StatusOr<Foo> foo = LoadFromJson<Foo>(json);
74 namespace grpc_core {
75 
76 namespace json_detail {
77 
78 // An un-typed JSON loader.
79 class LoaderInterface {
80  public:
81   // Convert json value to whatever type we're loading at dst.
82   // If errors occur, add them to errors.
83   virtual void LoadInto(const Json& json, const JsonArgs& args, void* dst,
84                         ValidationErrors* errors) const = 0;
85 
86  protected:
87   ~LoaderInterface() = default;
88 };
89 
90 // Loads a scalar (string or number).
91 class LoadScalar : public LoaderInterface {
92  public:
93   void LoadInto(const Json& json, const JsonArgs& args, void* dst,
94                 ValidationErrors* errors) const override;
95 
96  protected:
97   ~LoadScalar() = default;
98 
99  private:
100   // true if we're loading a number, false if we're loading a string.
101   // We use a virtual function to store this decision in a vtable instead of
102   // needing an instance variable.
103   virtual bool IsNumber() const = 0;
104 
105   virtual void LoadInto(const std::string& json, void* dst,
106                         ValidationErrors* errors) const = 0;
107 };
108 
109 // Load a string.
110 class LoadString : public LoadScalar {
111  protected:
112   ~LoadString() = default;
113 
114  private:
115   bool IsNumber() const override;
116   void LoadInto(const std::string& value, void* dst,
117                 ValidationErrors* errors) const override;
118 };
119 
120 // Load a Duration.
121 class LoadDuration : public LoadScalar {
122  protected:
123   ~LoadDuration() = default;
124 
125  private:
126   bool IsNumber() const override;
127   void LoadInto(const std::string& value, void* dst,
128                 ValidationErrors* errors) const override;
129 };
130 
131 // Load a number.
132 class LoadNumber : public LoadScalar {
133  protected:
134   ~LoadNumber() = default;
135 
136  private:
137   bool IsNumber() const override;
138 };
139 
140 // Load a signed number of type T.
141 template <typename T>
142 class TypedLoadSignedNumber : public LoadNumber {
143  protected:
144   ~TypedLoadSignedNumber() = default;
145 
146  private:
LoadInto(const std::string & value,void * dst,ValidationErrors * errors)147   void LoadInto(const std::string& value, void* dst,
148                 ValidationErrors* errors) const override {
149     if (!absl::SimpleAtoi(value, static_cast<T*>(dst))) {
150       errors->AddError("failed to parse number");
151     }
152   }
153 };
154 
155 // Load an unsigned number of type T.
156 template <typename T>
157 class TypedLoadUnsignedNumber : public LoadNumber {
158  protected:
159   ~TypedLoadUnsignedNumber() = default;
160 
161  private:
LoadInto(const std::string & value,void * dst,ValidationErrors * errors)162   void LoadInto(const std::string& value, void* dst,
163                 ValidationErrors* errors) const override {
164     if (!absl::SimpleAtoi(value, static_cast<T*>(dst))) {
165       errors->AddError("failed to parse non-negative number");
166     }
167   }
168 };
169 
170 // Load a float.
171 class LoadFloat : public LoadNumber {
172  protected:
173   ~LoadFloat() = default;
174 
175  private:
LoadInto(const std::string & value,void * dst,ValidationErrors * errors)176   void LoadInto(const std::string& value, void* dst,
177                 ValidationErrors* errors) const override {
178     if (!absl::SimpleAtof(value, static_cast<float*>(dst))) {
179       errors->AddError("failed to parse floating-point number");
180     }
181   }
182 };
183 
184 // Load a double.
185 class LoadDouble : public LoadNumber {
186  protected:
187   ~LoadDouble() = default;
188 
189  private:
LoadInto(const std::string & value,void * dst,ValidationErrors * errors)190   void LoadInto(const std::string& value, void* dst,
191                 ValidationErrors* errors) const override {
192     if (!absl::SimpleAtod(value, static_cast<double*>(dst))) {
193       errors->AddError("failed to parse floating-point number");
194     }
195   }
196 };
197 
198 // Load a bool.
199 class LoadBool : public LoaderInterface {
200  public:
201   void LoadInto(const Json& json, const JsonArgs& /*args*/, void* dst,
202                 ValidationErrors* errors) const override;
203 
204  protected:
205   ~LoadBool() = default;
206 };
207 
208 // Loads an unprocessed JSON object value.
209 class LoadUnprocessedJsonObject : public LoaderInterface {
210  public:
211   void LoadInto(const Json& json, const JsonArgs& /*args*/, void* dst,
212                 ValidationErrors* errors) const override;
213 
214  protected:
215   ~LoadUnprocessedJsonObject() = default;
216 };
217 
218 // Loads an unprocessed JSON array value.
219 class LoadUnprocessedJsonArray : public LoaderInterface {
220  public:
221   void LoadInto(const Json& json, const JsonArgs& /*args*/, void* dst,
222                 ValidationErrors* errors) const override;
223 
224  protected:
225   ~LoadUnprocessedJsonArray() = default;
226 };
227 
228 // Load a vector of some type.
229 class LoadVector : public LoaderInterface {
230  public:
231   void LoadInto(const Json& json, const JsonArgs& args, void* dst,
232                 ValidationErrors* errors) const override;
233 
234  protected:
235   ~LoadVector() = default;
236 
237  private:
238   virtual void* EmplaceBack(void* dst) const = 0;
239   virtual const LoaderInterface* ElementLoader() const = 0;
240 };
241 
242 // Load a map of string->some type.
243 class LoadMap : public LoaderInterface {
244  public:
245   void LoadInto(const Json& json, const JsonArgs& args, void* dst,
246                 ValidationErrors* errors) const override;
247 
248  protected:
249   ~LoadMap() = default;
250 
251  private:
252   virtual void* Insert(const std::string& name, void* dst) const = 0;
253   virtual const LoaderInterface* ElementLoader() const = 0;
254 };
255 
256 // Load a wrapped value of some type.
257 class LoadWrapped : public LoaderInterface {
258  public:
259   void LoadInto(const Json& json, const JsonArgs& args, void* dst,
260                 ValidationErrors* errors) const override;
261 
262  protected:
263   ~LoadWrapped() = default;
264 
265  private:
266   virtual void* Emplace(void* dst) const = 0;
267   virtual void Reset(void* dst) const = 0;
268   virtual const LoaderInterface* ElementLoader() const = 0;
269 };
270 
271 // Fetch a LoaderInterface for some type.
272 template <typename T>
273 const LoaderInterface* LoaderForType();
274 
275 // AutoLoader implements LoaderInterface for a type.
276 // The default asks the type for its LoaderInterface and then uses that.
277 // Classes that load from objects should provide a:
278 // static const JsonLoaderInterface* JsonLoader();
279 template <typename T>
280 class AutoLoader final : public LoaderInterface {
281  public:
LoadInto(const Json & json,const JsonArgs & args,void * dst,ValidationErrors * errors)282   void LoadInto(const Json& json, const JsonArgs& args, void* dst,
283                 ValidationErrors* errors) const override {
284     T::JsonLoader(args)->LoadInto(json, args, dst, errors);
285   }
286 
287  private:
288   ~AutoLoader() = default;
289 };
290 
291 // Specializations of AutoLoader for basic types.
292 template <>
293 class AutoLoader<std::string> final : public LoadString {
294  private:
295   ~AutoLoader() = default;
296 };
297 template <>
298 class AutoLoader<Duration> final : public LoadDuration {
299  private:
300   ~AutoLoader() = default;
301 };
302 template <>
303 class AutoLoader<int32_t> final : public TypedLoadSignedNumber<int32_t> {
304  private:
305   ~AutoLoader() = default;
306 };
307 template <>
308 class AutoLoader<int64_t> final : public TypedLoadSignedNumber<int64_t> {
309  private:
310   ~AutoLoader() = default;
311 };
312 template <>
313 class AutoLoader<uint32_t> final : public TypedLoadUnsignedNumber<uint32_t> {
314  private:
315   ~AutoLoader() = default;
316 };
317 template <>
318 class AutoLoader<uint64_t> final : public TypedLoadUnsignedNumber<uint64_t> {
319  private:
320   ~AutoLoader() = default;
321 };
322 template <>
323 class AutoLoader<float> final : public LoadFloat {
324  private:
325   ~AutoLoader() = default;
326 };
327 template <>
328 class AutoLoader<double> final : public LoadDouble {
329  private:
330   ~AutoLoader() = default;
331 };
332 template <>
333 class AutoLoader<bool> final : public LoadBool {
334  private:
335   ~AutoLoader() = default;
336 };
337 template <>
338 class AutoLoader<Json::Object> final : public LoadUnprocessedJsonObject {
339  private:
340   ~AutoLoader() = default;
341 };
342 template <>
343 class AutoLoader<Json::Array> final : public LoadUnprocessedJsonArray {
344  private:
345   ~AutoLoader() = default;
346 };
347 
348 // Specializations of AutoLoader for vectors.
349 template <typename T>
350 class AutoLoader<std::vector<T>> final : public LoadVector {
351  private:
352   ~AutoLoader() = default;
EmplaceBack(void * dst)353   void* EmplaceBack(void* dst) const final {
354     auto* vec = static_cast<std::vector<T>*>(dst);
355     vec->emplace_back();
356     return &vec->back();
357   }
ElementLoader()358   const LoaderInterface* ElementLoader() const final {
359     return LoaderForType<T>();
360   }
361 };
362 
363 // Specialization of AutoLoader for vector<bool> - we need a different
364 // implementation because, as vector<bool> packs bits in its implementation, the
365 // technique of returning a void* from Emplace() for the generic vector loader
366 // doesn't work.
367 template <>
368 class AutoLoader<std::vector<bool>> final : public LoaderInterface {
369  public:
370   void LoadInto(const Json& json, const JsonArgs& args, void* dst,
371                 ValidationErrors* errors) const override;
372 
373  private:
374   ~AutoLoader() = default;
375 };
376 
377 // Specializations of AutoLoader for maps.
378 template <typename T>
379 class AutoLoader<std::map<std::string, T>> final : public LoadMap {
380  private:
Insert(const std::string & name,void * dst)381   void* Insert(const std::string& name, void* dst) const final {
382     return &static_cast<std::map<std::string, T>*>(dst)
383                 ->emplace(name, T())
384                 .first->second;
385   };
ElementLoader()386   const LoaderInterface* ElementLoader() const final {
387     return LoaderForType<T>();
388   }
389 
390   ~AutoLoader() = default;
391 };
392 
393 // Specializations of AutoLoader for absl::optional<>.
394 template <typename T>
395 class AutoLoader<absl::optional<T>> final : public LoadWrapped {
396  public:
Emplace(void * dst)397   void* Emplace(void* dst) const final {
398     return &static_cast<absl::optional<T>*>(dst)->emplace();
399   }
Reset(void * dst)400   void Reset(void* dst) const final {
401     static_cast<absl::optional<T>*>(dst)->reset();
402   }
ElementLoader()403   const LoaderInterface* ElementLoader() const final {
404     return LoaderForType<T>();
405   }
406 
407  private:
408   ~AutoLoader() = default;
409 };
410 
411 // Specializations of AutoLoader for std::unique_ptr<>.
412 template <typename T>
413 class AutoLoader<std::unique_ptr<T>> final : public LoadWrapped {
414  public:
Emplace(void * dst)415   void* Emplace(void* dst) const final {
416     auto& p = *static_cast<std::unique_ptr<T>*>(dst);
417     p = std::make_unique<T>();
418     return p.get();
419   }
Reset(void * dst)420   void Reset(void* dst) const final {
421     static_cast<std::unique_ptr<T>*>(dst)->reset();
422   }
ElementLoader()423   const LoaderInterface* ElementLoader() const final {
424     return LoaderForType<T>();
425   }
426 
427  private:
428   ~AutoLoader() = default;
429 };
430 
431 // Specializations of AutoLoader for RefCountedPtr<>.
432 template <typename T>
433 class AutoLoader<RefCountedPtr<T>> final : public LoadWrapped {
434  public:
Emplace(void * dst)435   void* Emplace(void* dst) const final {
436     auto& p = *static_cast<RefCountedPtr<T>*>(dst);
437     p = MakeRefCounted<T>();
438     return p.get();
439   }
Reset(void * dst)440   void Reset(void* dst) const final {
441     static_cast<RefCountedPtr<T>*>(dst)->reset();
442   }
ElementLoader()443   const LoaderInterface* ElementLoader() const final {
444     return LoaderForType<T>();
445   }
446 
447  private:
448   ~AutoLoader() = default;
449 };
450 
451 // Implementation of aforementioned LoaderForType.
452 // Simply keeps a static AutoLoader<T> and returns a pointer to that.
453 template <typename T>
LoaderForType()454 const LoaderInterface* LoaderForType() {
455   return NoDestructSingleton<AutoLoader<T>>::Get();
456 }
457 
458 // Element describes one typed field to be loaded from a JSON object.
459 struct Element {
460   Element() = default;
461   template <typename A, typename B>
ElementElement462   Element(const char* name, bool optional, B A::*p,
463           const LoaderInterface* loader, const char* enable_key)
464       : loader(loader),
465         member_offset(static_cast<uint16_t>(
466             reinterpret_cast<uintptr_t>(&(static_cast<A*>(nullptr)->*p)))),
467         optional(optional),
468         name(name),
469         enable_key(enable_key) {}
470   // The loader for this field.
471   const LoaderInterface* loader;
472   // Offset into the destination object to store the field.
473   uint16_t member_offset;
474   // Is this field optional?
475   bool optional;
476   // The name of the field.
477   const char* name;
478   // The key to use with JsonArgs to see if this field is enabled.
479   const char* enable_key;
480 };
481 
482 // Vec<T, kSize> provides a constant array type that can be appended to by
483 // copying. It's setup so that most compilers can optimize away all of its
484 // operations.
485 template <typename T, size_t kSize>
486 class Vec {
487  public:
Vec(const Vec<T,kSize-1> & other,const T & new_value)488   Vec(const Vec<T, kSize - 1>& other, const T& new_value) {
489     for (size_t i = 0; i < other.size(); i++) values_[i] = other.data()[i];
490     values_[kSize - 1] = new_value;
491   }
492 
data()493   const T* data() const { return values_; }
size()494   size_t size() const { return kSize; }
495 
496  private:
497   T values_[kSize];
498 };
499 
500 template <typename T>
501 class Vec<T, 0> {
502  public:
data()503   const T* data() const { return nullptr; }
size()504   size_t size() const { return 0; }
505 };
506 
507 // Given a list of elements, and a destination object, load the elements into
508 // the object from some parsed JSON.
509 // Returns false if the JSON object was not of type Json::Type::kObject.
510 bool LoadObject(const Json& json, const JsonArgs& args, const Element* elements,
511                 size_t num_elements, void* dst, ValidationErrors* errors);
512 
513 // Adaptor type - takes a compile time computed list of elements and
514 // implements LoaderInterface by calling LoadObject.
515 template <typename T, size_t kElemCount, typename Hidden = void>
516 class FinishedJsonObjectLoader final : public LoaderInterface {
517  public:
FinishedJsonObjectLoader(const Vec<Element,kElemCount> & elements)518   explicit FinishedJsonObjectLoader(const Vec<Element, kElemCount>& elements)
519       : elements_(elements) {}
520 
LoadInto(const Json & json,const JsonArgs & args,void * dst,ValidationErrors * errors)521   void LoadInto(const Json& json, const JsonArgs& args, void* dst,
522                 ValidationErrors* errors) const override {
523     LoadObject(json, args, elements_.data(), elements_.size(), dst, errors);
524   }
525 
526  private:
527   GPR_NO_UNIQUE_ADDRESS Vec<Element, kElemCount> elements_;
528 };
529 
530 // Specialization for when the object has a JsonPostLoad function exposed.
531 template <typename T, size_t kElemCount>
532 class FinishedJsonObjectLoader<T, kElemCount,
533                                absl::void_t<decltype(&T::JsonPostLoad)>>
534     final : public LoaderInterface {
535  public:
FinishedJsonObjectLoader(const Vec<Element,kElemCount> & elements)536   explicit FinishedJsonObjectLoader(const Vec<Element, kElemCount>& elements)
537       : elements_(elements) {}
538 
LoadInto(const Json & json,const JsonArgs & args,void * dst,ValidationErrors * errors)539   void LoadInto(const Json& json, const JsonArgs& args, void* dst,
540                 ValidationErrors* errors) const override {
541     // Call JsonPostLoad() only if json is a JSON object.
542     if (LoadObject(json, args, elements_.data(), elements_.size(), dst,
543                    errors)) {
544       static_cast<T*>(dst)->JsonPostLoad(json, args, errors);
545     }
546   }
547 
548  private:
549   GPR_NO_UNIQUE_ADDRESS Vec<Element, kElemCount> elements_;
550 };
551 
552 // Builder type for JSON object loaders.
553 // Concatenate fields with Field, OptionalField, and then call Finish to
554 // obtain an object that implements LoaderInterface.
555 template <typename T, size_t kElemCount = 0>
556 class JsonObjectLoader final {
557  public:
JsonObjectLoader()558   JsonObjectLoader() {
559     static_assert(kElemCount == 0,
560                   "Only initial loader step can have kElemCount==0.");
561   }
562 
Finish()563   FinishedJsonObjectLoader<T, kElemCount>* Finish() const {
564     return new FinishedJsonObjectLoader<T, kElemCount>(elements_);
565   }
566 
567   template <typename U>
568   JsonObjectLoader<T, kElemCount + 1> Field(
569       const char* name, U T::*p, const char* enable_key = nullptr) const {
570     return Field(name, false, p, enable_key);
571   }
572 
573   template <typename U>
574   JsonObjectLoader<T, kElemCount + 1> OptionalField(
575       const char* name, U T::*p, const char* enable_key = nullptr) const {
576     return Field(name, true, p, enable_key);
577   }
578 
JsonObjectLoader(const Vec<Element,kElemCount-1> & elements,Element new_element)579   JsonObjectLoader(const Vec<Element, kElemCount - 1>& elements,
580                    Element new_element)
581       : elements_(elements, new_element) {}
582 
583  private:
584   template <typename U>
Field(const char * name,bool optional,U T::* p,const char * enable_key)585   JsonObjectLoader<T, kElemCount + 1> Field(const char* name, bool optional,
586                                             U T::*p,
587                                             const char* enable_key) const {
588     return JsonObjectLoader<T, kElemCount + 1>(
589         elements_, Element(name, optional, p, LoaderForType<U>(), enable_key));
590   }
591 
592   GPR_NO_UNIQUE_ADDRESS Vec<Element, kElemCount> elements_;
593 };
594 
595 const Json* GetJsonObjectField(const Json::Object& json,
596                                absl::string_view field,
597                                ValidationErrors* errors, bool required);
598 
599 }  // namespace json_detail
600 
601 template <typename T>
602 using JsonObjectLoader = json_detail::JsonObjectLoader<T>;
603 
604 using JsonLoaderInterface = json_detail::LoaderInterface;
605 
606 template <typename T>
607 absl::StatusOr<T> LoadFromJson(
608     const Json& json, const JsonArgs& args = JsonArgs(),
609     absl::string_view error_prefix = "errors validating JSON") {
610   ValidationErrors errors;
611   T result{};
612   json_detail::LoaderForType<T>()->LoadInto(json, args, &result, &errors);
613   if (!errors.ok()) {
614     return errors.status(absl::StatusCode::kInvalidArgument, error_prefix);
615   }
616   return std::move(result);
617 }
618 
619 template <typename T>
LoadFromJson(const Json & json,const JsonArgs & args,ValidationErrors * errors)620 T LoadFromJson(const Json& json, const JsonArgs& args,
621                ValidationErrors* errors) {
622   T result{};
623   json_detail::LoaderForType<T>()->LoadInto(json, args, &result, errors);
624   return result;
625 }
626 
627 template <typename T>
628 absl::optional<T> LoadJsonObjectField(const Json::Object& json,
629                                       const JsonArgs& args,
630                                       absl::string_view field,
631                                       ValidationErrors* errors,
632                                       bool required = true) {
633   ValidationErrors::ScopedField error_field(errors, absl::StrCat(".", field));
634   const Json* field_json =
635       json_detail::GetJsonObjectField(json, field, errors, required);
636   if (field_json == nullptr) return absl::nullopt;
637   T result{};
638   size_t starting_error_size = errors->size();
639   json_detail::LoaderForType<T>()->LoadInto(*field_json, args, &result, errors);
640   if (errors->size() > starting_error_size) return absl::nullopt;
641   return std::move(result);
642 }
643 
644 }  // namespace grpc_core
645 
646 #endif  // GRPC_SRC_CORE_LIB_JSON_JSON_OBJECT_LOADER_H
647