// Copyright 2017 The Fuchsia Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

#ifndef PERIDOT_LIB_FIDL_JSON_XDR_H_
#define PERIDOT_LIB_FIDL_JSON_XDR_H_

#include <lib/fidl/cpp/string.h>
#include <src/lib/fxl/logging.h>
#include <src/lib/fxl/macros.h>

#include <array>
#include <map>
#include <string>
#include <type_traits>
#include <vector>

#include "peridot/lib/rapidjson/rapidjson.h"
#include "rapidjson/document.h"

namespace modular {

// This file provides a tool to serialize arbitrary data structures
// into JSON, and back. It specifically supports serialization of FIDL
// data (structs, arrays, maps, and combinations thereof), but FIDL is
// not a requirement. For example, support for STL containers in
// addition to FIDL containers is easy to add once we need it.
//
// We use JSON as the serialization format to store structured values
// (and at times also structured keys) in the ledger.
//
// The design is inspired by Sun RPC's XDR, specifically the definiton
// of "filters". A filter function takes an operation and a data
// pointer, and depending on the operation parameter either serializes
// or deserializes the data. There is one such filter function for
// every data type. A filter for a simple data type does different
// things for serialization and deserialization, so having a single
// one for both operations instead of two separate functions barely
// reduces code size. However, the efficiency of this design shows in
// composition: A filter for a struct can be written by simply calling
// the filters for each field of the struct and passing the operation
// parameter down. Thus, a filter function for a struct is half the
// code size of a pair of serialization/deserialization functions.
//
// NOTES:
//
// XDR is not sync: Although the XDR operation can be applied to an
// existing instance of the output end (an existing FIDL struct, or an
// existing JSON AST), full synchronization of the data structure is
// not guaranteed. All data that exist in the input are added to the
// output, but not necessarily all data that don't exist in the input
// are removed from the output. Also, if an error occurs, the output
// is left in some intermediate state. The most suitable use for
// updates as of now is to always create a fresh output instance, and
// if the transciption succeeds, replace the previous instance by the
// fresh instance.
//
// XDR is not about resolving conflicts: If an existing output
// instance is updated using XDR, we might improve accuracy of
// removing data that no longer exist, but it is out of the scope of
// XDR (at least for now) to note that input data conflict with
// existing output data, and resolving the conflict. Conflict
// resolution between different versions of data is most likely
// handled outside XDR.
//
// It may be that we will use XDR to support conflict resolution in a
// data type agnostic way: Instead of defining a conflict resolution
// between e.g. STL or FIDL data structures, we might instead define
// XDR filters for them, translate all values to JSON, apply conflict
// resolution to JSON, and translate the result back.
//
// SCHEMA VERSION BACK COMPATIBILITY:
//
// The schema of the persistent data is defined in terms of filter functions. In
// order to support new versions of the code reading versions of the data
// written by old versions of the code, filter functions are always defined by
// the client at the top level entry points as lists, never as single functions.
//
// The lists contain the filter for the current version of the schema at the
// top, and filters for reading previous versions into the current version of
// the code below.
//
// Whenever the storage schema changes, a new version of the filter is created
// and add it to the version list.
//
// If the memory schema changes, filters of all versions are adjusted as
// necessary.
//
// Filters that don't change can be reused between versions. If a filter does
// not change, but the ones that it uses do change, templates can be used to
// save on code duplication.
//
// TODO(mesch): Right now there is no way to ensure that old versions of the
// code will never read new versions of the data. Support for this is expected
// from the Ledger, and partially from an upcoming API for explicit version
// numbers.
//
// See comments on XdrFilterType, XdrRead(), and XdrWrite() for details.

class XdrContext;

// The two operations: reading from JSON or writing to JSON.
enum class XdrOp {
  TO_JSON = 0,
  FROM_JSON = 1,
};

// Custom types are serialized by passing a function of this type to a method on
// XdrContext. Note this is a pointer type that points to a const (an existing
// function). So we will never use a reference or a const of it. However,
// argument values of such will still be defined const.
//
// The top level entry functions used by clients never pass a single filter
// function alone, but always a list of filters for different versions of the
// data, such that the reading code can fall back to functions reading
// previously written versions. Such lists can (and should) be defined
// statically as constexpr:
//
//   void XdrFoo_v1(XdrContext* const xdr, Foo* const data) { ... }
//   void XdrFoo_v2(XdrContext* const xdr, Foo* const data) { ... }
//
//   constexpr XdrFilterType<Foo> XdrFoo[] = {
//     XdrFoo_v1,
//     XdrFoo_v2,
//     nullptr,
//   };
//
//   Foo foo;
//   XdrRead(json, &foo, XdrFoo);
//
// XdrRead and XdrWrite are defined to take an XdrFilterList<> argument, which
// that constexpr can be passed to. See Definition of XdrRead(), below.
template <typename T>
using XdrFilterType = void (*)(XdrContext*, T*);

template <typename T>
using XdrFilterList = void (*const*)(XdrContext*, T*);

// A generic implementation of such a filter, which works for simple
// types. (The implementation uses XdrContext, so it's below.)
template <typename V>
void XdrFilter(XdrContext* xdr, V* value);

// XdrContext holds on to a JSON document as well as a specific
// position inside the document on which its methods operate, as well
// as the operation (writing to JSON, reading from JSON) that is
// executed when methods are called.
//
// There are two kinds of methods: Value() and Field(). Value()
// affects the current JSON value itself. Field() assumes the current
// JSON value is an Object, accesses a property on it and affects the
// value of the property.
//
// Clients usually call Value(); filters for custom types usually call
// Field().
class XdrContext {
 public:
  XdrContext(XdrOp op, JsonDoc* doc, std::string* error);

  ~XdrContext();

  // Returns the XdrOp that this XdrContext was created with.
  //
  // This is required by some XdrFilters that cannot use the same code to set or
  // get data from objects. However, in general, try to avoid special-casing
  // an XdrFilter to change behavior based on whether it's translating to or
  // from JSON.
  XdrOp op() const { return op_; }

  // Below are methods to handle values on properties of objects for
  // handling standalone values. These methods are called by filter
  // code during a serialization/deserialization operation.

  // The version of a struct. On Write, the version number is written and it
  // always returns true. On Read, raises an error and returns false if the
  // version number read doesn't match the version number passed in. Thus it
  // gives an explicit way to a filter function to force an error.
  //
  // The filter should also return early so as to not partially read data.
  //
  // This can be applied at any level, but only when it happens as the first
  // call in the top level filter will it fully prevent partial reads.
  //
  // How it should be used:
  //
  //   void XdrFoo_v1(XdrContext* const xdr, Foo* const data) { ... }
  //   void XdrFoo_v2(XdrContext* const xdr, Foo* const data) {
  //      if (!xdr->Version(2)) {
  //        return;
  //      }
  //      ...
  //   }
  //
  //   constexpr XdrFilterType<Foo> XdrFoo[] = {
  //     XdrFoo_v2,
  //     XdrFoo_v1,
  //     nullptr,
  //   };
  //
  //   Foo foo;
  //   XdrRead(json, &foo, XdrFoo);
  //
  // Notice that _v1 doesn't need to have a Version() call. This is usual when
  // the first use of the data predates the introduction of the Version()
  // mechanism.
  //
  // This method cannot be used (and returns false and logs an error) in a
  // context that is not Object.
  //
  // It writes the reserved field name "@version" to the current Object context.
  //
  // The value passed to the call inside the Xdr filter function should never be
  // defined as a constant outside of the filter function, because then it
  // becomes tempting to change it to a new version number without creating a
  // copy of the filter function for the previous version number.
  bool Version(uint32_t version);

  // A field of a struct. The value type V is assumed to be one of the
  // primitive JSON data types. If anything else is passed here and
  // not to the method below with a custom filter, the rapidjson code
  // will fail to compile.
  template <typename V>
  void Field(const char field[], V* const data) {
    Field(field).Value(data);
  }

  // Same as Field(), but allows a default value to be specified.
  //
  // |field| is the name of the JSON field to be read or written to
  // |data| is a pointer to the fidl field to be read or written to
  // |use_data| when set to true, set the JSON field to the value of data
  // |default_value| the value data should be defaulted to if the field doesn't
  //   exist in JSON
  //
  // IMPORTANT: calling mutable_field() on a fidl table forces a default value
  // on the field resulting in has_field() to return true. The value of
  // has_field() will need to be stored in a separate variable to avoid this.
  // Example:
  // bool has_field = data->has_field();
  // xdr->FieldWithDefault("field", data->mutable_field(), has_field, "value");
  template <typename V>
  void FieldWithDefault(const char field[], V* const data, bool use_data,
                        V default_value) {
    FieldWithDefault(field).ValueWithDefault(data, use_data, default_value);
  }

  // If we supply a custom filter for the value of a field, the data
  // type of the field very often does not match directly the data
  // type for which we write a filter, therefore this template has two
  // type parameters. This happens in several situations:
  //
  // 1. Fields with fidl struct types. The field data type, which we pass the
  //    data for, is a std::unique_ptr<X>, but the filter supplied is for X (and
  //    thus takes X*).
  //
  // 2. Fields with fidl array types. The filter is for an element,
  //    but the field is the array type.
  //
  // 3. Fields with STL container types. The filter is for an element,
  //    but the field is the container type.
  //
  // We could handle this by specialization, it's much simpler to just cover all
  // possible combinations with a template of higher dimension, at the expense
  // of covering also a few impossible cases.
  template <typename D, typename V>
  void Field(const char field[], D* const data, XdrFilterType<V> const filter) {
    Field(field).Value(data, filter);
  }

  // Same as Field(), but allows for a default value to be specified. If
  // |use_data| is false, the supplied |default_value| is used. Otherwise,
  // |data| is used.
  template <typename D, typename V>
  void FieldWithDefault(const char field[], D* const data,
                        XdrFilterType<V> const filter, bool use_data,
                        D default_value) {
    FieldWithDefault(field).ValueWithDefault(data, filter, use_data,
                                             std::move(default_value));
  }

  // Below are methods analog to those for values on properties of
  // objects for handling standalone values. These methods are called
  // by XdrContext client code such as XdrRead() and XdrWrite() to
  // start a serialization/deserialization operation.

  // A simple value is mapped to the corresponding JSON type (int,
  // float, bool) directly.
  template <typename V>
  typename std::enable_if<!std::is_enum<V>::value>::type Value(V* data) {
    V default_value = V();
    ValueWithDefault(data, true, std::move(default_value));
  }

  // An enum is mapped to a JSON int.
  template <typename V>
  typename std::enable_if<std::is_enum<V>::value>::type Value(V* const data) {
    V default_value = V();
    ValueWithDefault(data, true, std::move(default_value));
  }

  // This function used when |data| is not an enum. It maps type V to its
  // corresponding JSON type (int, float, bool). If |use_data| is true, read
  // from |data|, otherwise, use |default_value|.
  template <typename V>
  typename std::enable_if<!std::is_enum<V>::value>::type ValueWithDefault(
      V* data, bool use_data, V default_value) {
    switch (op_) {
      case XdrOp::TO_JSON:
        use_data ? value_->Set(*data, allocator())
                 : value_->Set(default_value, allocator());
        break;

      case XdrOp::FROM_JSON:
        if (!value_->Is<V>()) {
          if (use_data) {
            AddError("Unexpected type.");
            return;
          }
          *data = std::move(default_value);
          return;
        }
        *data = value_->Get<V>();
    }
  }

  // This function is used when |data| is an enum. It maps enums to a JSON int.
  // If |use_data| is true, read from |data|, otherwise, use |default_value|.
  template <typename V>
  typename std::enable_if<std::is_enum<V>::value>::type ValueWithDefault(
      V* const data, bool use_data, V default_value) {
    switch (op_) {
      case XdrOp::TO_JSON:
        use_data ? value_->Set(static_cast<int>(*data), allocator())
                 : value_->Set(static_cast<int>(default_value), allocator());
        break;

      case XdrOp::FROM_JSON:
        if (!value_->Is<int>()) {
          if (use_data) {
            AddError("Unexpected type.");
            return;
          }
          *data = std::move(default_value);
          return;
        }
        *data = static_cast<V>(value_->Get<int>());
    }
  }

  // Bytes and shorts, both signed and unsigned, are mapped to JSON int, since
  // they are not directly supported in the rapidjson API.
  void Value(unsigned char* data);
  void Value(int8_t* data);
  void Value(unsigned short* data);
  void Value(short* data);

  // A fidl String is mapped to either (i.e., the union type of) JSON
  // null or JSON string.
  void Value(fidl::StringPtr* data);

  // An STL string is mapped to a JSON string.
  void Value(std::string* data);

  // Allows for default values to be specified for the following types.
  // These follow the mapping properties listed in Value().
  void ValueWithDefault(unsigned char* data, bool use_data,
                        unsigned char default_value);
  void ValueWithDefault(int8_t* data, bool use_data, int8_t default_value);
  void ValueWithDefault(unsigned short* data, bool use_data,
                        unsigned short default_value);
  void ValueWithDefault(short* data, bool use_data, short default_value);
  void ValueWithDefault(fidl::StringPtr* data, bool use_data,
                        fidl::StringPtr default_value);
  void ValueWithDefault(std::string* data, bool use_data,
                        std::string default_value);

  // A value of a custom type is mapped using the custom filter. See
  // the corresponding Field() method for why there are two type
  // parameters here.
  template <typename D, typename V>
  void Value(D* data, XdrFilterType<V> filter) {
    filter(this, data);
  }

  // Same as Value() but allows a default value to be specified.
  template <typename D, typename V>
  void ValueWithDefault(D* data, XdrFilterType<V> filter, bool use_data,
                        D default_value) {
    switch (op_) {
      case XdrOp::TO_JSON: {
        if (use_data) {
          filter(this, data);
          break;
        }
        filter(this, &default_value);
        break;
      }

      case XdrOp::FROM_JSON: {
        if (value_->IsNull()) {
          *data = std::move(default_value);
          break;
        }
        filter(this, data);
      }
    }
  }

  // Operator & may be overloaded to return a type that acts like a pointer, but
  // isn't one, and therefore is not matched by the Value<D,V>(data, filter)
  // method above. In that case, we need to exercise the operator * of the
  // pointer type explicitly.
  //
  // This is needed for example for std::vector<bool>, where &at(i) is a bit
  // iterator, not a bool*.
  template <typename Ptr, typename V>
  void Value(Ptr data, XdrFilterType<V> filter) {
    switch (op_) {
      case XdrOp::TO_JSON: {
        V value = *data;
        filter(this, &value);
        break;
      }

      case XdrOp::FROM_JSON: {
        V value;
        filter(this, &value);
        *data = std::move(value);
      }
    }
  }

  template <typename S>
  void Value(std::unique_ptr<S>* data, XdrFilterType<S> filter) {
    switch (op_) {
      case XdrOp::TO_JSON:
        if (!data->get()) {
          value_->SetNull();
        } else {
          value_->SetObject();
          filter(this, data->get());
        }
        break;

      case XdrOp::FROM_JSON:
        if (value_->IsNull()) {
          data->reset();
        } else {
          if (!value_->IsObject()) {
            AddError("Object type expected.");
            return;
          }

          *data = std::make_unique<S>();
          filter(this, data->get());
        }
    }
  }

  // A fidl vector is mapped to JSON null and JSON Array with a custom
  // filter for the elements.
  template <typename D, typename V>
  void Value(fidl::VectorPtr<D>* const data, const XdrFilterType<V> filter) {
    switch (op_) {
      case XdrOp::TO_JSON:
        if (data->is_null()) {
          value_->SetNull();

        } else {
          value_->SetArray();
          value_->Reserve((*data)->size(), allocator());

          for (size_t i = 0; i < (*data)->size(); ++i) {
            Element(i).Value(&(*data)->at(i), filter);
          }
        }
        break;

      case XdrOp::FROM_JSON:
        if (value_->IsNull()) {
          data->reset();

        } else {
          if (!value_->IsArray()) {
            AddError("Array type expected.");
            return;
          }

          // The resize() call has two purposes:
          //
          // (1) Setting data to non-null, even if there are only zero
          //     elements. This is essential, otherwise the FIDL output
          //     is wrong (i.e., the FIDL output cannot be used in FIDL
          //     method calls without crashing).
          //
          // (2) It saves on allocations for growing the underlying
          //     vector one by one.
          data->resize(value_->Size());

          for (size_t i = 0; i < value_->Size(); ++i) {
            Element(i).Value(&(*data)->at(i), filter);
          }
        }
    }
  }

  // A fidl array with a simple element type can infer its element
  // value filter from the type parameters of the array.
  template <typename V>
  void Value(fidl::VectorPtr<V>* const data) {
    Value(data, XdrFilter<V>);
  }

  // A fidl array is mapped to JSON null and JSON Array with a custom
  // filter for the elements.
  template <typename D, size_t N, typename V>
  void Value(std::array<D, N>* const data, const XdrFilterType<V> filter) {
    switch (op_) {
      case XdrOp::TO_JSON: {
        value_->SetArray();
        value_->Reserve(N, allocator());

        for (size_t i = 0; i < N; ++i) {
          Element(i).Value(&data->at(i), filter);
        }
        break;
      }

      case XdrOp::FROM_JSON: {
        if (!value_->IsArray()) {
          AddError("Array type expected.");
          return;
        }

        if (value_->Size() != N) {
          AddError(std::string("Array size unexpected: found ") +
                   std::to_string(value_->Size()) + " expected " +
                   std::to_string(N));
          return;
        }

        for (size_t i = 0; i < N; ++i) {
          Element(i).Value(&data->at(i), filter);
        }
      }
    }
  }

  // A fidl array with a simple element type can infer its element
  // value filter from the type parameters of the array.
  template <typename V, size_t N>
  void Value(std::array<V, N>* const data) {
    Value(data, XdrFilter<V>);
  }

  // An STL vector is mapped to JSON Array with a custom filter for the
  // elements.
  template <typename D, typename V>
  void Value(std::vector<D>* const data, const XdrFilterType<V> filter) {
    switch (op_) {
      case XdrOp::TO_JSON:
        value_->SetArray();
        value_->Reserve(data->size(), allocator());

        for (size_t i = 0; i < data->size(); ++i) {
          Element(i).Value(&data->at(i), filter);
        }
        break;

      case XdrOp::FROM_JSON:
        if (!value_->IsArray()) {
          AddError("Array type expected.");
          return;
        }

        data->resize(value_->Size());

        for (size_t i = 0; i < value_->Size(); ++i) {
          Element(i).Value(&data->at(i), filter);
        }
    }
  }

  // Allows for a default value to be specified for STL vectors mapped to JSON
  // arrays with a custom filter for the elements. This only supports vectors
  // with simple types.
  template <typename D, typename V>
  void ValueWithDefault(std::vector<D>* const data,
                        const XdrFilterType<V> filter, bool use_data,
                        std::vector<D> default_value) {
    switch (op_) {
      case XdrOp::TO_JSON:
        if (use_data) {
          value_->SetArray();
          value_->Reserve(data->size(), allocator());

          for (size_t i = 0; i < data->size(); ++i) {
            Element(i).Value(&data->at(i), filter);
          }
          break;
        }
        data->resize(default_value.size());
        for (size_t i = 0; i < default_value.size(); ++i) {
          ElementWithDefault(i).ValueWithDefault(
              &data->at(i), filter, use_data, std::move(default_value.at(i)));
        }
        break;

      case XdrOp::FROM_JSON:
        if (!value_->IsArray()) {
          if (use_data) {
            AddError("Array type expected.");
            return;
          }
          data->resize(default_value.size());
          for (size_t i = 0; i < default_value.size(); ++i) {
            ElementWithDefault(i).ValueWithDefault(
                &data->at(i), filter, use_data, std::move(default_value.at(i)));
          }
          return;
        }
        data->resize(value_->Size());
        for (size_t i = 0; i < value_->Size(); ++i) {
          Element(i).Value(&data->at(i), filter);
        }
    }
  }

  // An STL vector with a simple element type can infer its element value filter
  // from the type parameters of the array.
  template <typename V>
  void Value(std::vector<V>* const data) {
    Value(data, XdrFilter<V>);
  }

  // Allows for a default value to be specified for STL vector with a simple
  // element type
  template <typename V>
  void ValueWithDefault(std::vector<V>* const data, bool use_data,
                        std::vector<V> default_value) {
    ValueWithDefault(data, XdrFilter<V>, use_data, default_value);
  }

  // An STL map is mapped to an array of pairs of key and value, because maps
  // can have non-string keys. There are two filters, for the key type and the
  // value type.
  template <typename K, typename V>
  void Value(std::map<K, V>* const data, XdrFilterType<K> const key_filter,
             XdrFilterType<V> const value_filter) {
    switch (op_) {
      case XdrOp::TO_JSON: {
        value_->SetArray();
        value_->Reserve(data->size(), allocator());

        size_t index = 0;
        for (auto i = data->begin(); i != data->end(); ++i) {
          XdrContext&& element = Element(index++);
          element.value_->SetObject();

          K k{i->first};
          element.Field("@k").Value(&k, key_filter);

          V v{i->second};
          element.Field("@v").Value(&v, value_filter);
        }
        break;
      }

      case XdrOp::FROM_JSON: {
        if (!value_->IsArray()) {
          AddError("Array type expected.");
          return;
        }

        // Erase existing data in case there are some left.
        data->clear();

        size_t index = 0;
        for (auto i = value_->Begin(); i != value_->End(); ++i) {
          XdrContext&& element = Element(index++);

          K k;
          element.Field("@k").Value(&k, key_filter);

          V v;
          element.Field("@v").Value(&v, value_filter);

          data->emplace(std::move(k), std::move(v));
        }
      }
    }
  }

  // An STL map with only simple values can infer its key value filters from the
  // type parameters of the map.
  template <typename K, typename V>
  void Value(std::map<K, V>* const data) {
    Value(data, XdrFilter<K>, XdrFilter<V>);
  }

 private:
  XdrContext(XdrContext* parent, const char* name, XdrOp op, JsonDoc* doc,
             JsonValue* value);
  JsonDoc::AllocatorType& allocator() const { return doc_->GetAllocator(); }
  XdrContext Field(const char field[]);
  XdrContext FieldWithDefault(const char field[]);
  XdrContext Element(size_t i);
  XdrContext ElementWithDefault(size_t i);

  // Error reporting: Recursively requests the error string from the
  // parent, and on the way back appends a description of the current
  // JSON context hierarchy.
  void AddError(const std::string& message);
  std::string* AddError();

  // Return the root error string so that IgnoreError() can manipulate it.
  std::string* GetError();

  // The root of the context tree (where parent_ == nullptr) keeps a
  // string to write errors to. In an error situation the chain of
  // parent contexts is traversed up in order to (1) access the error
  // string to write to, (2) record the current context hierarchy in
  // an error message. Each level in the context hierarchy is
  // described using the type of value_ and, if present, name_. name_
  // is the name of the field for contexts that are values of a field,
  // otherwise nullptr.
  XdrContext* const parent_;
  const char* const name_;
  std::string* const error_;

  // These three fields represent the context itself: The operation to
  // perform (read or write), the value it will be performed on, and
  // the document the value is part of, in order to access the
  // allocator.
  const XdrOp op_;
  JsonDoc* const doc_;
  JsonValue* const value_;

  // A JSON value to continue processing on when the expected one is
  // not found in the JSON AST, to avoid value_ becoming null. It
  // needs to be thread local because it is a global that's modified
  // potentially by every ongoing XDR invocation.
  static thread_local JsonValue null_;

  // All Xdr* functions take a XdrContext* and pass it on. We might
  // want to change this once we support asynchronous input/output
  // operations, for example directly to/from a Ledger page rather
  // than just the JSON DOM.
  FXL_DISALLOW_COPY_AND_ASSIGN(XdrContext);
};

// This filter function works for all types for which XdrContext has a Value()
// method defined.
template <typename V>
void XdrFilter(XdrContext* const xdr, V* const value) {
  xdr->Value(value);
}

// Clients use the following functions as entry points.

// A wrapper function to read data from a JSON document. This may fail if the
// JSON document doesn't match the structure required by any of the filter
// versions. In that case it logs an error and returns false. Clients are
// expected to either crash or recover e.g. by ignoring the value.
//
// The items in the filter versions list are tried in turn until one succeeds.
// The filter versions list must end with a nullptr entry to mark the end.
template <typename D, typename V>
bool XdrRead(JsonDoc* const doc, D* const data,
             XdrFilterList<V> filter_versions) {
  std::vector<std::string> errors;
  for (XdrFilterList<V> filter = filter_versions; *filter; ++filter) {
    std::string error;
    XdrContext xdr(XdrOp::FROM_JSON, doc, &error);
    xdr.Value(data, *filter);

    if (error.empty()) {
      return true;
    }

    FXL_LOG(INFO) << "Filter failed, trying previous version.";
    errors.emplace_back(std::move(error));
  }

  FXL_LOG(ERROR) << "XdrRead: No filter version succeeded"
                 << " to extract data from JSON: "
                 << JsonValueToPrettyString(*doc) << std::endl;
  for (const std::string& error : errors) {
    FXL_LOG(INFO) << "XdrRead error message: " << error;
  }

  return false;
}

// A wrapper function to read data from a JSON string. This may fail if the JSON
// doesn't parse or doesn't match the structure required by the filter version
// list. In that case it logs an error and returns false. Clients are expected
// to either crash or recover e.g. by ignoring the value.
template <typename D, typename V>
bool XdrRead(const std::string& json, D* const data,
             XdrFilterList<V> filter_versions) {
  JsonDoc doc;
  doc.Parse(json);
  if (doc.HasParseError()) {
    FXL_LOG(ERROR) << "Unable to parse data as JSON: " << json;
    return false;
  }

  return XdrRead(&doc, data, filter_versions);
}

// A wrapper function to write data as JSON doc. This never fails. It always
// only uses the first version of the filter. It takes a filter version list
// anyway for symmetry with XdrRead(), so that the same filter version list
// constant can be passed to both XdrRead and XdrWrite.
template <typename D, typename V>
void XdrWrite(JsonDoc* const doc, D* const data,
              XdrFilterList<V> filter_versions) {
  std::string error;
  XdrContext xdr(XdrOp::TO_JSON, doc, &error);
  xdr.Value(data, filter_versions[0]);
  FXL_DCHECK(error.empty())
      << "There are no errors possible in XdrOp::TO_JSON: " << std::endl
      << error << std::endl
      << JsonValueToPrettyString(*doc) << std::endl;
}

// A wrapper function to write data as JSON to a string. This never fails.
template <typename D, typename V>
void XdrWrite(std::string* const json, D* const data,
              XdrFilterList<V> filter_versions) {
  JsonDoc doc;
  XdrWrite(&doc, data, filter_versions);
  *json = JsonValueToString(doc);
}

// A wrapper function to return data as a JSON string. This never fails.
template <typename D, typename V>
std::string XdrWrite(D* const data, XdrFilterList<V> filter_versions) {
  std::string json;
  XdrWrite(&json, data, filter_versions);
  return json;
}

}  // namespace modular

#endif  // PERIDOT_LIB_FIDL_JSON_XDR_H_
