// Copyright 2019 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.

#include "src/lib/fidl_codec/library_loader.h"

#include <zircon/assert.h>
#include <zircon/rights.h>

#include <fstream>
#include <ios>
#include <sstream>

#include <rapidjson/error/en.h>

#include "src/lib/fidl_codec/builtin_semantic.h"
#include "src/lib/fidl_codec/logger.h"
#include "src/lib/fidl_codec/semantic_parser.h"
#include "src/lib/fidl_codec/wire_types.h"

// See library_loader.h for details.

namespace fidl_codec {

EnumOrBits::EnumOrBits(const rapidjson::Value* json_definition)
    : json_definition_(json_definition) {}

EnumOrBits::EnumOrBits(std::string name, uint64_t size, std::unique_ptr<Type> type,
                       std::vector<EnumOrBitsMember> members)
    : json_definition_(nullptr),
      name_(std::move(name)),
      size_(size),
      type_(std::move(type)),
      members_(std::move(members)) {}

EnumOrBits::~EnumOrBits() = default;

Enum::Enum(std::string name, uint64_t size, std::unique_ptr<Type> type,
           std::vector<EnumOrBitsMember> members)
    : EnumOrBits(std::move(name), size, std::move(type), std::move(members)) {}

const Enum& Enum::FrameworkErrorEnum() {
  static Enum result("FrameworkError", 4, std::make_unique<Int32Type>(),
                     {EnumOrBitsMember("UNKNOWN_METHOD", 2, true)});
  return result;
}

void EnumOrBits::DecodeTypes(bool is_scalar, const std::string& supertype_name,
                             Library* enclosing_library) {
  if (json_definition_ == nullptr) {
    return;
  }
  const rapidjson::Value* json_definition = json_definition_;
  // Reset json_definition_ member to allow recursive declarations.
  json_definition_ = nullptr;
  name_ = enclosing_library->ExtractString(json_definition, supertype_name, "<unknown>", "name");
  if (is_scalar) {
    type_ = enclosing_library->ExtractScalarType(json_definition, supertype_name, name_, "type");
  } else {
    type_ = enclosing_library->ExtractType(json_definition, supertype_name, name_, "type");
  }

  if (!json_definition->HasMember("members")) {
    enclosing_library->FieldNotFound(supertype_name, name_, "members");
  } else {
    if (json_definition->HasMember("members")) {
      for (auto& member : (*json_definition)["members"].GetArray()) {
        if (member.HasMember("value") && member["value"].HasMember("literal")) {
          if (!member.HasMember("name")) {
            continue;
          }

          const char* data = member["value"]["literal"]["value"].GetString();
          bool negative = false;
          if (*data == '-') {
            ++data;
            negative = true;
          }
          std::stringstream stream;
          stream.str(std::string(data));
          uint64_t absolute_value;
          stream >> absolute_value;
          members_.emplace_back(member["name"].GetString(), absolute_value, negative);
        }
      }
    }
  }

  size_ = type_->InlineSize(WireVersion::kWireV2);
}

std::string Enum::GetName(uint64_t absolute_value, bool negative) const {
  for (auto& member : members()) {
    if ((member.absolute_value() == absolute_value) && (member.negative() == negative)) {
      return member.name();
    }
  }
  return "<unknown>";
}

std::string Bits::GetName(uint64_t absolute_value, bool negative) const {
  std::ostringstream os;
  auto emit = [&os, first = true]() mutable -> std::ostringstream& {
    if (!first) {
      os << '|';
    }
    first = false;
    return os;
  };
  if (!negative) {
    for (const auto& member : members()) {
      if (member.negative()) {
        continue;
      }
      if (absolute_value & member.absolute_value()) {
        emit() << member.name();
      }
      absolute_value &= ~member.absolute_value();
    }
    if (absolute_value) {
      emit() << std::hex << std::showbase << absolute_value;
    }
  }

  std::string str = os.str();
  if (!str.empty()) {
    return str;
  }
  return "<none>";
}

UnionMember::UnionMember(const Union& union_definition, Library* enclosing_library,
                         const rapidjson::Value* json_definition)
    : union_definition_(union_definition),
      name_(enclosing_library->ExtractString(json_definition, "union member", "<unknown>", "name")),
      ordinal_(enclosing_library->ExtractUint64(json_definition, "union member", name_, "ordinal")),
      type_(enclosing_library->ExtractType(json_definition, "union member", name_, "type")) {}

Union::Union(Library* enclosing_library, const rapidjson::Value* json_definition)
    : enclosing_library_(enclosing_library), json_definition_(json_definition) {}

void Union::DecodeTypes() {
  if (json_definition_ == nullptr) {
    return;
  }
  const rapidjson::Value* json_definition = json_definition_;
  // Reset json_definition_ member to allow recursive declarations.
  json_definition_ = nullptr;
  name_ = enclosing_library_->ExtractString(json_definition, "union", "<unknown>", "name");

  if (!json_definition->HasMember("members")) {
    enclosing_library_->FieldNotFound("union", name_, "members");
  } else {
    auto member_arr = (*json_definition)["members"].GetArray();
    members_.reserve(member_arr.Size());
    for (auto& member : member_arr) {
      members_.push_back(std::make_unique<UnionMember>(*this, enclosing_library_, &member));
    }
  }
}

const UnionMember* Union::MemberFromOrdinal(Ordinal64 ordinal) const {
  for (const auto& member : members_) {
    if (member->ordinal() == ordinal) {
      return member.get();
    }
  }
  return nullptr;
}

UnionMember* Union::SearchMember(std::string_view name) const {
  for (const auto& member : members_) {
    if (member->name() == name) {
      return member.get();
    }
  }
  return nullptr;
}

std::string Union::ToString(bool expand) const {
  UnionType type(*this, false);
  return type.ToString(expand);
}

StructMember::StructMember(Library* enclosing_library, const rapidjson::Value* json_definition)
    : name_(
          enclosing_library->ExtractString(json_definition, "struct member", "<unknown>", "name")),
      offset_(enclosing_library->ExtractFieldOffset(json_definition, "struct member", name_,
                                                    "field_shape_v2")),
      type_(enclosing_library->ExtractType(json_definition, "struct member", name_, "type")) {}

StructMember::StructMember(std::string_view name, std::unique_ptr<Type> type)
    : name_(name), type_(std::move(type)) {}

StructMember::StructMember(std::string_view name, std::unique_ptr<Type> type, uint8_t id)
    : name_(name), type_(std::move(type)), id_(id) {}

void StructMember::reset_type() { type_ = nullptr; }

Struct::Struct(Library* enclosing_library, const rapidjson::Value* json_definition)
    : enclosing_library_(enclosing_library), json_definition_(json_definition) {}

Struct::Struct(std::string_view name)
    : enclosing_library_(nullptr), json_definition_(nullptr), name_(name) {}

void Struct::AddMember(std::string_view name, std::unique_ptr<Type> type, uint32_t id) {
  members_.emplace_back(std::make_unique<StructMember>(name, std::move(type), id));
}

void Struct::DecodeTypes() {
  if (json_definition_ == nullptr) {
    return;
  }
  const rapidjson::Value* json_definition = json_definition_;
  // Reset json_definition_ member to allow recursive declarations.
  json_definition_ = nullptr;
  name_ = enclosing_library_->ExtractString(json_definition, "struct", "<unknown>", "name");

  if (!json_definition->HasMember("type_shape_v2")) {
    enclosing_library_->FieldNotFound("struct", name_, "type_shape_v2");
  } else {
    const rapidjson::Value& type_shape = (*json_definition)["type_shape_v2"];
    size_ = static_cast<uint32_t>(
        enclosing_library_->ExtractUint64(&type_shape, "struct", name_, "inline_size"));
  }

  if (!json_definition->HasMember("members")) {
    enclosing_library_->FieldNotFound("struct", name_, "members");
  } else {
    auto member_arr = (*json_definition)["members"].GetArray();
    members_.reserve(member_arr.Size());
    for (auto& member : member_arr) {
      members_.push_back(std::make_unique<StructMember>(enclosing_library_, &member));
    }
  }
}

StructMember* Struct::SearchMember(std::string_view name, uint32_t id) const {
  for (const auto& member : members_) {
    if (member->name() == name && member->id() == id) {
      return member.get();
    }
  }
  return nullptr;
}

uint32_t Struct::Size(WireVersion version) const { return size_; }

std::string Struct::ToString(bool expand) const {
  StructType type(*this, false);
  return type.ToString(expand);
}

TableMember::TableMember(Library* enclosing_library, const rapidjson::Value* json_definition)
    : name_(enclosing_library->ExtractString(json_definition, "table member", "<unknown>", "name")),
      ordinal_(enclosing_library->ExtractUint32(json_definition, "table member", name_, "ordinal")),
      type_(enclosing_library->ExtractType(json_definition, "table member", name_, "type")) {}

Table::Table(Library* enclosing_library, const rapidjson::Value* json_definition)
    : enclosing_library_(enclosing_library), json_definition_(json_definition) {}

void Table::DecodeTypes() {
  if (json_definition_ == nullptr) {
    return;
  }
  const rapidjson::Value* json_definition = json_definition_;
  // Reset json_definition_ member to allow recursive declarations.
  json_definition_ = nullptr;
  name_ = enclosing_library_->ExtractString(json_definition, "table", "<unknown>", "name");

  if (!json_definition->HasMember("members")) {
    enclosing_library_->FieldNotFound("table", name_, "members");
  } else {
    auto member_arr = (*json_definition)["members"].GetArray();
    for (auto& member : member_arr) {
      auto table_member = std::make_unique<TableMember>(enclosing_library_, &member);
      Ordinal32 ordinal = table_member->ordinal();
      if (ordinal >= members_.size()) {
        members_.resize(ordinal + 1);
      }
      members_[ordinal] = std::move(table_member);
    }
  }
}

const TableMember* Table::MemberFromOrdinal(Ordinal64 ordinal) const {
  if (ordinal >= members_.size()) {
    return nullptr;
  }
  return members_[ordinal].get();
}

const TableMember* Table::SearchMember(std::string_view name) const {
  for (const auto& member : members_) {
    if ((member != nullptr) && (member->name() == name)) {
      return member.get();
    }
  }
  return nullptr;
}

std::string Table::ToString(bool expand) const {
  TableType type(*this);
  return type.ToString(expand);
}

ProtocolMethod::ProtocolMethod(Library* enclosing_library, const Protocol& protocol,
                               const rapidjson::Value* json_definition)
    : json_definition_(json_definition),
      enclosing_protocol_(&protocol),
      name_(protocol.enclosing_library()->ExtractString(json_definition, "method", "<unknown>",
                                                        "name")),
      ordinal_(
          protocol.enclosing_library()->ExtractUint64(json_definition, "method", name_, "ordinal")),
      is_composed_(protocol.enclosing_library()->ExtractBool(json_definition, "method", name_,
                                                             "is_composed")),
      has_request_(protocol.enclosing_library()->ExtractBool(json_definition, "method", name_,
                                                             "has_request")),
      has_response_(protocol.enclosing_library()->ExtractBool(json_definition, "method", name_,
                                                              "has_response")) {}

static std::unique_ptr<Type> GetPayloadType(LibraryLoader* loader,
                                            const rapidjson::Value* json_definition,
                                            const char* key) {
  if (json_definition->HasMember(key)) {
    return Type::GetType(loader, (*json_definition)[key]);
  }
  return std::make_unique<EmptyPayloadType>();
}

void ProtocolMethod::ProtocolMethod::DecodeTypes() {
  if (json_definition_ == nullptr) {
    return;
  }
  const rapidjson::Value* json_definition = json_definition_;
  // Reset json_definition_ member to allow recursive declarations.
  json_definition_ = nullptr;

  LibraryLoader* loader = enclosing_protocol_->enclosing_library()->enclosing_loader();
  if (has_request_) {
    request_ = GetPayloadType(loader, json_definition, "maybe_request_payload");
  }
  if (has_response_) {
    response_ = GetPayloadType(loader, json_definition, "maybe_response_payload");
  }
}

ProtocolMethod::~ProtocolMethod() = default;

std::string ProtocolMethod::fully_qualified_name() const {
  std::string fqn(enclosing_protocol_->name());
  fqn.append(".");
  fqn.append(name());
  return fqn;
}

void Protocol::AddMethodsToIndex(LibraryLoader* library_loader) {
  for (auto& protocol_method : protocol_methods_) {
    library_loader->AddMethod(protocol_method.get());
  }
}

bool Protocol::GetMethodByFullName(const std::string& name,
                                   const ProtocolMethod** method_ptr) const {
  for (const auto& method : methods()) {
    if (method->fully_qualified_name() == name) {
      method->DecodeTypes();
      *method_ptr = method.get();
      return true;
    }
  }
  return false;
}

ProtocolMethod* Protocol::GetMethodByName(std::string_view name) const {
  for (const auto& method : methods()) {
    if (method->name() == name) {
      method->DecodeTypes();
      return method.get();
    }
  }
  return nullptr;
}

Library::Library(std::string source, LibraryLoader* enclosing_loader,
                 rapidjson::Document& json_definition)
    : enclosing_loader_(enclosing_loader),
      json_definition_(std::move(json_definition)),
      source_(std::move(source)) {
  if (!json_definition_.HasMember("struct_declarations")) {
    FieldNotFound("library", name_, "struct_declarations");
  } else if (!json_definition_.HasMember("external_struct_declarations")) {
    FieldNotFound("library", name_, "external_struct_declarations");
  } else if (!json_definition_.HasMember("table_declarations")) {
    FieldNotFound("library", name_, "table_declarations");
  } else if (!json_definition_.HasMember("union_declarations")) {
    FieldNotFound("library", name_, "union_declarations");
  }

  auto protocols_array = json_definition_["protocol_declarations"].GetArray();
  protocols_.reserve(protocols_array.Size());

  for (auto& decl : protocols_array) {
    protocols_.emplace_back(new Protocol(this, decl));
    protocols_.back()->AddMethodsToIndex(enclosing_loader);
  }
}

Library::~Library() { enclosing_loader()->Delete(this); }

void Library::DecodeTypes() {
  if (decoded_) {
    return;
  }
  decoded_ = true;
  name_ = ExtractString(&json_definition_, "library", "<unknown>", "name");

  if (!json_definition_.HasMember("enum_declarations")) {
    FieldNotFound("library", name_, "enum_declarations");
  } else {
    for (auto& enu : json_definition_["enum_declarations"].GetArray()) {
      enums_.emplace(std::piecewise_construct, std::forward_as_tuple(enu["name"].GetString()),
                     std::forward_as_tuple(new Enum(&enu)));
    }
  }

  if (!json_definition_.HasMember("bits_declarations")) {
    FieldNotFound("library", name_, "bits_declarations");
  } else {
    for (auto& bits : json_definition_["bits_declarations"].GetArray()) {
      bits_.emplace(std::piecewise_construct, std::forward_as_tuple(bits["name"].GetString()),
                    std::forward_as_tuple(new Bits(&bits)));
    }
  }

  if (!json_definition_.HasMember("struct_declarations")) {
    FieldNotFound("library", name_, "struct_declarations");
  } else {
    for (auto& str : json_definition_["struct_declarations"].GetArray()) {
      structs_.emplace(std::piecewise_construct, std::forward_as_tuple(str["name"].GetString()),
                       std::forward_as_tuple(new Struct(this, &str)));
    }
  }

  if (!json_definition_.HasMember("external_struct_declarations")) {
    FieldNotFound("library", name_, "external_struct_declarations");
  } else {
    for (auto& str : json_definition_["external_struct_declarations"].GetArray()) {
      structs_.emplace(std::piecewise_construct, std::forward_as_tuple(str["name"].GetString()),
                       std::forward_as_tuple(new Struct(this, &str)));
    }
  }

  if (!json_definition_.HasMember("table_declarations")) {
    FieldNotFound("library", name_, "table_declarations");
  } else {
    for (auto& tab : json_definition_["table_declarations"].GetArray()) {
      tables_.emplace(std::piecewise_construct, std::forward_as_tuple(tab["name"].GetString()),
                      std::forward_as_tuple(new Table(this, &tab)));
    }
  }

  if (!json_definition_.HasMember("union_declarations")) {
    FieldNotFound("library", name_, "union_declarations");
  } else {
    for (auto& uni : json_definition_["union_declarations"].GetArray()) {
      unions_.emplace(std::piecewise_construct, std::forward_as_tuple(uni["name"].GetString()),
                      std::forward_as_tuple(new Union(this, &uni)));
    }
  }
}

bool Library::DecodeAll() {
  DecodeTypes();
  for (const auto& tmp : structs_) {
    tmp.second->DecodeTypes();
  }
  for (const auto& tmp : enums_) {
    tmp.second->DecodeTypes(this);
  }
  for (const auto& tmp : bits_) {
    tmp.second->DecodeTypes(this);
  }
  for (const auto& tmp : tables_) {
    tmp.second->DecodeTypes();
  }
  for (const auto& tmp : unions_) {
    tmp.second->DecodeTypes();
  }
  for (const auto& protocol : protocols_) {
    for (const auto& method : protocol->methods()) {
      method->DecodeTypes();
    }
  }
  return !has_errors_;
}

std::unique_ptr<Type> Library::TypeFromIdentifier(bool is_nullable, const std::string& identifier) {
  auto str = structs_.find(identifier);
  if (str != structs_.end()) {
    str->second->DecodeTypes();
    std::unique_ptr<Type> type(new StructType(std::ref(*str->second), is_nullable));
    return type;
  }
  auto enu = enums_.find(identifier);
  if (enu != enums_.end()) {
    enu->second->DecodeTypes(this);
    return std::make_unique<EnumType>(std::ref(*enu->second));
  }
  auto bits = bits_.find(identifier);
  if (bits != bits_.end()) {
    bits->second->DecodeTypes(this);
    return std::make_unique<BitsType>(std::ref(*bits->second));
  }
  auto tab = tables_.find(identifier);
  if (tab != tables_.end()) {
    tab->second->DecodeTypes();
    return std::make_unique<TableType>(std::ref(*tab->second));
  }
  auto uni = unions_.find(identifier);
  if (uni != unions_.end()) {
    uni->second->DecodeTypes();
    return std::make_unique<UnionType>(std::ref(*uni->second), is_nullable);
  }
  Protocol* ifc;
  if (GetProtocolByName(identifier, &ifc)) {
    return std::make_unique<HandleType>(ZX_DEFAULT_CHANNEL_RIGHTS, ZX_OBJ_TYPE_CHANNEL,
                                        is_nullable);
  }
  return std::make_unique<InvalidType>();
}

bool Library::GetProtocolByName(std::string_view name, Protocol** ptr) const {
  for (const auto& protocol : protocols()) {
    if (protocol->name() == name) {
      *ptr = protocol.get();
      return true;
    }
  }
  return false;
}

bool Library::ExtractBool(const rapidjson::Value* json_definition, std::string_view container_type,
                          std::string_view container_name, const char* field_name) {
  if (!json_definition->HasMember(field_name)) {
    FieldNotFound(container_type, container_name, field_name);
    return false;
  }
  return (*json_definition)[field_name].GetBool();
}

std::string Library::ExtractString(const rapidjson::Value* json_definition,
                                   std::string_view container_type, std::string_view container_name,
                                   const char* field_name) {
  if (!json_definition->HasMember(field_name)) {
    FieldNotFound(container_type, container_name, field_name);
    return "<unknown>";
  }
  return (*json_definition)["name"].GetString();
}

uint64_t Library::ExtractUint64(const rapidjson::Value* json_definition,
                                std::string_view container_type, std::string_view container_name,
                                const char* field_name) {
  if (!json_definition->HasMember(field_name)) {
    FieldNotFound(container_type, container_name, field_name);
    return 0;
  }
  return std::strtoll((*json_definition)[field_name].GetString(), nullptr, kDecimalBase);
}

uint32_t Library::ExtractUint32(const rapidjson::Value* json_definition,
                                std::string_view container_type, std::string_view container_name,
                                const char* field_name) {
  if (!json_definition->HasMember(field_name)) {
    FieldNotFound(container_type, container_name, field_name);
    return 0;
  }
  return static_cast<uint32_t>(
      std::strtoul((*json_definition)[field_name].GetString(), nullptr, kDecimalBase));
}

std::unique_ptr<Type> Library::ExtractScalarType(const rapidjson::Value* json_definition,
                                                 std::string_view container_type,
                                                 std::string_view container_name,
                                                 const char* field_name) {
  if (!json_definition->HasMember(field_name)) {
    FieldNotFound(container_type, container_name, field_name);
    return std::make_unique<InvalidType>();
  }
  return Type::ScalarTypeFromName((*json_definition)[field_name].GetString());
}

std::unique_ptr<Type> Library::ExtractType(const rapidjson::Value* json_definition,
                                           std::string_view container_type,
                                           std::string_view container_name,
                                           const char* field_name) {
  if (!json_definition->HasMember(field_name)) {
    FieldNotFound(container_type, container_name, field_name);
    return std::make_unique<InvalidType>();
  }
  return Type::GetType(enclosing_loader(), (*json_definition)[field_name]);
}

uint64_t Library::ExtractFieldOffset(const rapidjson::Value* json_definition,
                                     std::string_view container_type,
                                     std::string_view container_name, const char* field_name) {
  if (!json_definition->HasMember(field_name)) {
    FieldNotFound(container_type, container_name, field_name);
    return 0;
  }
  return ExtractUint64(&(*json_definition)[field_name], container_type, container_name, "offset");
}

void Library::FieldNotFound(std::string_view container_type, std::string_view container_name,
                            const char* field_name) {
  has_errors_ = true;
  FX_LOGS_OR_CAPTURE(ERROR) << "File " << name() << " field '" << field_name << "' missing for "
                            << container_type << ' ' << container_name;
}

LibraryLoader::LibraryLoader(const std::vector<std::string>& library_paths, LibraryReadError* err) {
  AddAll(library_paths, err);
}

bool LibraryLoader::AddAll(const std::vector<std::string>& library_paths, LibraryReadError* err) {
  bool ok = true;
  // Go backwards through the streams; we refuse to load the same library twice, and the last
  // one wins.
  for (auto path = library_paths.rbegin(); path != library_paths.rend(); ++path) {
    AddPath(*path, err);
    if (err->value != LibraryReadError::kOk) {
      ok = false;
    }
  }
  return ok;
}

bool LibraryLoader::DecodeAll() {
  bool ok = true;
  for (const auto& representation : representations_) {
    Library* library = representation.second.get();
    if (!library->DecodeAll()) {
      ok = false;
    }
  }
  return ok;
}

void LibraryLoader::AddPath(const std::string& path, LibraryReadError* err) {
  std::ifstream infile(path.c_str());
  std::string content(std::istreambuf_iterator<char>(infile), {});
  if (infile.fail()) {
    err->value = LibraryReadError ::kIoError;
    err->errno_value = errno;
    return;
  }
  AddContent(content, err, path);
  if (err->value != LibraryReadError::kOk) {
    FX_LOGS_OR_CAPTURE(ERROR) << path << ": JSON parse error: "
                              << rapidjson::GetParseError_En(err->parse_result.Code())
                              << " at offset " << err->parse_result.Offset();
    return;
  }
}

void LibraryLoader::AddContent(const std::string& content, LibraryReadError* err,
                               std::string source) {
  rapidjson::Document document;
  err->parse_result = document.Parse<rapidjson::kParseNumbersAsStringsFlag>(content.c_str());
  // TODO: This would be a good place to validate that the resulting JSON
  // matches the schema in tools/fidl/fidlc/schema.json.  If there are
  // errors, we will currently get mysterious crashes.
  if (document.HasParseError()) {
    err->value = LibraryReadError::kParseError;
    return;
  }
  std::string library_name = document["name"].GetString();
  if (representations_.find(library_name) == representations_.end()) {
    representations_.emplace(std::piecewise_construct, std::forward_as_tuple(library_name),
                             std::forward_as_tuple(new Library(std::move(source), this, document)));
  }
  err->value = LibraryReadError::kOk;
}

void LibraryLoader::AddMethod(ProtocolMethod* method) {
  if (ordinal_map_[method->ordinal()] == nullptr) {
    ordinal_map_[method->ordinal()] = std::make_unique<std::vector<ProtocolMethod*>>();
  }
  // Ensure composed methods come after non-composed methods.  The fidl_codec
  // libraries pick the first one they find.
  if (method->is_composed()) {
    ordinal_map_[method->ordinal()]->push_back(method);
  } else {
    ordinal_map_[method->ordinal()]->insert(ordinal_map_[method->ordinal()]->begin(), method);
  }
}

void LibraryLoader::ParseBuiltinSemantic() {
  semantic::ParserErrors parser_errors;
  {
    semantic::SemanticParser parser(this, semantic::builtin_semantic_fuchsia_io, &parser_errors);
    parser.ParseSemantic();
  }
}

}  // namespace fidl_codec
