// 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 "tools/kazoo/syscall_library.h"

#include <stdio.h>
#include <zircon/assert.h>
#include <zircon/compiler.h>

#include <algorithm>

#include "tools/kazoo/alias_workaround.h"
#include "tools/kazoo/output_util.h"
#include "tools/kazoo/string_util.h"

namespace {

bool ValidateTransport(const rapidjson::Value& interface) {
  if (!interface.HasMember("maybe_attributes")) {
    return false;
  }
  for (const auto& attrib : interface["maybe_attributes"].GetArray()) {
    if (attrib.GetObject()["name"].Get<std::string>() == "Transport") {
      if (attrib.GetObject()["value"].Get<std::string>() == "Syscall") {
        return true;
      }
    }
  }
  return false;
}

std::string StripLibraryName(const std::string& full_name) {
  auto prefix_pos = full_name.find_first_of('/');
  ZX_ASSERT_MSG(prefix_pos != full_name.npos, "%s has no library prefix", full_name.c_str());
  size_t prefix_len = prefix_pos + 1;
  return full_name.substr(prefix_len, full_name.size() - prefix_len);
}

std::string GetCategory(const rapidjson::Value& interface, const std::string& interface_name) {
  if (interface.HasMember("maybe_attributes")) {
    for (const auto& attrib : interface["maybe_attributes"].GetArray()) {
      if (attrib.GetObject()["name"].Get<std::string>() == "NoProtocolPrefix") {
        return std::string();
      }
    }
  }

  return ToLowerAscii(StripLibraryName(interface_name));
}

std::string GetDocAttribute(const rapidjson::Value& method) {
  if (!method.HasMember("maybe_attributes")) {
    return std::string();
  }
  for (const auto& attrib : method["maybe_attributes"].GetArray()) {
    if (attrib.GetObject()["name"].Get<std::string>() == "Doc") {
      return attrib.GetObject()["value"].GetString();
    }
  }
  return std::string();
}

Required GetRequiredAttribute(const rapidjson::Value& field) {
  if (!field.HasMember("maybe_attributes")) {
    return Required::kNo;
  }
  for (const auto& attrib : field["maybe_attributes"].GetArray()) {
    if (attrib.GetObject()["name"].Get<std::string>() == "Required") {
      ZX_ASSERT(attrib.GetObject()["value"].Get<std::string>() == "");
      return Required::kYes;
    }
  }
  return Required::kNo;
}

constexpr char kRightsPrefix[] = " Rights: ";

std::string GetShortDescriptionFromDocAttribute(const std::string& full_doc_attribute) {
  auto lines = SplitString(full_doc_attribute, '\n', kKeepWhitespace);
  if (lines.size() < 1 || lines[0].substr(0, strlen(kRightsPrefix)) == kRightsPrefix) {
    return std::string();
  }
  return TrimString(lines[0], " \t\n");
}

std::vector<std::string> GetCleanDocAttribute(const std::string& full_doc_attribute) {
  auto lines = SplitString(full_doc_attribute, '\n', kTrimWhitespace);
  if (!lines.empty() && lines[lines.size() - 1].empty()) {
    lines.pop_back();
  }
  std::for_each(lines.begin(), lines.end(),
                [](std::string& line) { return TrimString(line, " \t\n"); });
  return lines;
}

std::vector<std::string> GetRightsSpecsFromDocAttribute(const std::string& full_doc_attribute) {
  auto lines = SplitString(full_doc_attribute, '\n', kKeepWhitespace);
  std::vector<std::string> ret;
  for (const auto& line : lines) {
    if (line.substr(0, strlen(kRightsPrefix)) == kRightsPrefix) {
      ret.push_back(line.substr(strlen(kRightsPrefix)));
    }
  }

  return ret;
}

std::optional<Type> PrimitiveTypeFromName(std::string subtype) {
  if (subtype == "uint8") {
    return Type(TypeUint8{});
  } else if (subtype == "uint16") {
    return Type(TypeUint16{});
  } else if (subtype == "int32") {
    return Type(TypeInt32{});
  } else if (subtype == "uint32") {
    return Type(TypeUint32{});
  } else if (subtype == "int64") {
    return Type(TypeInt64{});
  } else if (subtype == "uint64") {
    return Type(TypeUint64{});
  } else if (subtype == "bool") {
    return Type(TypeBool{});
  }

  return std::nullopt;
}

Type TypeFromJson(const SyscallLibrary& library, const rapidjson::Value& type,
                  const rapidjson::Value* type_alias) {
  if (type_alias) {
    // If the "experimental_maybe_from_type_alias" field is non-null, then the source-level has used
    // a type that's declared as "using x = y;". Here, treat various "x"s as special types. This
    // is likely mostly (?) temporary until there's 1) a more nailed down alias implementation in
    // the front end (fidlc) and 2) we move various parts of zx.fidl from being built-in to fidlc to
    // actual source level fidl and shared between the syscall definitions and normal FIDL.
    const std::string full_name((*type_alias)["name"].GetString());
    if (full_name.substr(0, 3) == "zx/") {
      const std::string name = full_name.substr(3);
      if (name == "duration" || name == "Futex" || name == "koid" || name == "paddr" ||
          name == "rights" || name == "signals" || name == "status" || name == "time" ||
          name == "ticks" || name == "vaddr" || name == "VmOption") {
        return Type(TypeZxBasicAlias(CamelToSnake(name)));
      }
    }

    const std::string name = StripLibraryName(full_name);
    if (name == "uintptr") {
      return Type(TypeUintptrT{});
    }

    if (name == "usize") {
      return Type(TypeSizeT{});
    }

    Type workaround_type;
    if (AliasWorkaround(name, library, &workaround_type)) {
      return workaround_type;
    }

    return library.TypeFromIdentifier(full_name);
  }

  if (!type.HasMember("kind")) {
    fprintf(stderr, "type has no 'kind'\n");
    return Type();
  }

  std::string kind = type["kind"].GetString();
  if (kind == "primitive") {
    const rapidjson::Value& subtype_value = type["subtype"];
    ZX_ASSERT(subtype_value.IsString());
    std::string subtype = subtype_value.GetString();
    return PrimitiveTypeFromName(subtype).value();
  } else if (kind == "identifier") {
    std::string id = type["identifier"].GetString();
    return library.TypeFromIdentifier(type["identifier"].GetString());
  } else if (kind == "handle") {
    return Type(TypeHandle(type["subtype"].GetString()));
  } else if (kind == "vector") {
    Type contained_type = TypeFromJson(library, type["element_type"], nullptr);
    return Type(TypeVector(contained_type));
  } else if (kind == "string") {
    return Type(TypeString{});
  }

  ZX_ASSERT_MSG(false, "TODO: kind=%s", kind.c_str());
  return Type();
}

}  // namespace

bool Syscall::HasAttribute(const char* attrib_name) const {
  return attributes_.find(attrib_name) != attributes_.end();
}

std::string Syscall::GetAttribute(const char* attrib_name) const {
  ZX_ASSERT(HasAttribute(attrib_name));
  return attributes_.find(attrib_name)->second;
}

// Converts from FIDL style to C/Kernel style:
// - string to pointer+size
// - vector to pointer+size
// - structs become pointer-to-struct (const on input, mutable on output)
// - etc.
bool Syscall::MapRequestResponseToKernelAbi() {
  ZX_ASSERT(kernel_arguments_.empty());

  // Used for input arguments, which default to const unless alread specified mutable.
  auto default_to_const = [](Constness constness) {
    if (constness == Constness::kUnspecified) {
      return Constness::kConst;
    }
    return constness;
  };

  auto output_optionality = [](Optionality optionality) {
    // If explicitly made optional then leave it alone, otherwise mark non-optional.
    if (optionality == Optionality::kOutputOptional) {
      return optionality;
    }
    return Optionality::kOutputNonOptional;
  };

  auto get_vector_size_name = [](const StructMember& member) {
    std::string prefix, suffix;
    // If it's a char* or void*, blah_size seems more natural, otherwise, num_blahs is moreso.
    if ((member.type().DataAsVector().contained_type().IsChar() ||
         member.type().DataAsVector().contained_type().IsVoid()) &&
        (member.name() != "bytes")) {
      suffix = "_size";
    } else {
      prefix = "num_";
    }
    return std::tuple<std::string, bool>(prefix + member.name() + suffix,
                                         member.type().DataAsVector().uint32_size());
  };

  // Map inputs first, converting vectors, strings, and structs to their corresponding input types
  // as we go.
  for (const auto& m : request_.members()) {
    const Type& type = m.type();
    if (type.IsVector()) {
      Type pointer_to_subtype(
          TypePointer(type.DataAsVector().contained_type(), IsDecayedVectorTag{}),
          default_to_const(type.constness()), Optionality::kInputArgument);
      kernel_arguments_.emplace_back(m.name(), pointer_to_subtype, m.attributes());
      auto [size_name, is_u32] = get_vector_size_name(m);
      kernel_arguments_.emplace_back(size_name, is_u32 ? Type(TypeUint32{}) : Type(TypeSizeT{}),
                                     std::map<std::string, std::string>{});
    } else if (type.IsString()) {
      // char*, using the same constness as the string was specified as.
      kernel_arguments_.emplace_back(
          m.name(), Type(TypePointer(Type(TypeChar{})), default_to_const(type.constness()),
                         Optionality::kInputArgument), m.attributes());
      kernel_arguments_.emplace_back(m.name() + "_size", Type(TypeSizeT{}),
                                     std::map<std::string, std::string>{});
    } else if (type.IsStruct()) {
      // If it's a struct, map to struct*, const unless otherwise specified. The pointer takes the
      // constness of the struct.
      kernel_arguments_.emplace_back(
          m.name(),
          Type(TypePointer(type), default_to_const(type.constness()), Optionality::kInputArgument),
          m.attributes());
    } else {
      // Otherwise, copy it over, unchanged other than to tag it as input.
      kernel_arguments_.emplace_back(m.name(),
                                     Type(type.type_data(), default_to_const(m.type().constness()),
                                          Optionality::kInputArgument),
                                     m.attributes());
    }
  }

  // Similarly for the outputs, but turning buffers into outparams, and with special handling for
  // the C return value.
  size_t start_at;
  if (response_.members().size() == 0 || !response_.members()[0].type().IsSimpleType()) {
    kernel_return_type_ = Type(TypeVoid{});
    start_at = 0;
  } else {
    kernel_return_type_ = response_.members()[0].type();
    start_at = 1;
  }
  for (size_t i = start_at; i < response_.members().size(); ++i) {
    const StructMember& m = response_.members()[i];
    const Type& type = m.type();
    if (type.IsVector()) {
      // TODO(syscall-fidl-transition): These vector types aren't marked as non-optional in
      // abigen, but generally they probably are.
      Type pointer_to_subtype(
          TypePointer(type.DataAsVector().contained_type(), IsDecayedVectorTag{}),
          Constness::kMutable, Optionality::kOutputOptional);
      kernel_arguments_.emplace_back(m.name(), pointer_to_subtype, m.attributes());
      auto [size_name, is_u32] = get_vector_size_name(m);
      kernel_arguments_.emplace_back(size_name, is_u32 ? Type(TypeUint32{}) : Type(TypeSizeT{}),
                                     std::map<std::string, std::string>{});
    } else if (type.IsString()) {
      kernel_arguments_.emplace_back(
          m.name(),
          Type(TypePointer(Type(TypeChar{})), Constness::kMutable, Optionality::kOutputOptional),
          m.attributes());
      kernel_arguments_.emplace_back(m.name() + "_size", Type(TypeSizeT{}),
                                     std::map<std::string, std::string>{});
    } else if (type.IsPointer()) {
      kernel_arguments_.emplace_back(
          m.name(), Type(type.type_data(), Constness::kMutable, Optionality::kOutputOptional),
          m.attributes());
    } else {
      // Everything else becomes a T* (to make it an out parameter).
      kernel_arguments_.emplace_back(m.name(), Type(TypePointer(type), Constness::kMutable,
                                                    output_optionality(type.optionality())),
                                     m.attributes());
    }
  }

  // Now that we've got all the arguments in their natural order, honor the
  // "ArgReorder" attribute, which reorders arguments arbitrarily to match
  // existing declaration order.
  return HandleArgReorder();
}

bool Syscall::HandleArgReorder() {
  constexpr const char kReorderAttribName[] = "ArgReorder";
  if (HasAttribute(kReorderAttribName)) {
    const std::string& target_order_string = GetAttribute(kReorderAttribName);
    std::vector<std::string> target_order = SplitString(target_order_string, ',', kTrimWhitespace);
    if (kernel_arguments_.size() != target_order.size()) {
      fprintf(stderr,
              "Attempting to reorder arguments for '%s', and there's %zu kernel arguments, but %zu "
              "arguments in the reorder spec.\n",
              name().c_str(), kernel_arguments_.size(), target_order.size());
      return false;
    }

    std::vector<StructMember> new_kernel_arguments;
    for (const auto& target : target_order) {
      bool found = false;
      for (const auto& ka : kernel_arguments_) {
        if (ka.name() == target) {
          new_kernel_arguments.push_back(ka);
          found = true;
          break;
        }
      }

      if (!found) {
        fprintf(stderr,
                "Attempting to reorder arguments for '%s', but '%s' wasn't one of the kernel "
                "arguments.\n",
                name().c_str(), target.c_str());
        return false;
      }
    }

    kernel_arguments_ = std::move(new_kernel_arguments);
  }

  return true;
}

void Enum::AddMember(const std::string& member_name, EnumMember member) {
  ZX_ASSERT(!HasMember(member_name));
  members_[member_name] = std::move(member);
  insertion_order_.push_back(member_name);
}

bool Enum::HasMember(const std::string& member_name) const {
  return members_.find(member_name) != members_.end();
}

const EnumMember& Enum::ValueForMember(const std::string& member_name) const {
  ZX_ASSERT(HasMember(member_name));
  return members_.find(member_name)->second;
}

Type SyscallLibrary::TypeFromIdentifier(const std::string& id) const {
  for (const auto& bits : bits_) {
    if (bits->id() == id) {
      // TODO(scottmg): Consider if we need to separate bits from enum here.
      return Type(TypeEnum{bits.get()});
    }
  }

  for (const auto& enm : enums_) {
    if (enm->id() == id) {
      return Type(TypeEnum{enm.get()});
    }
  }

  for (const auto& alias : type_aliases_) {
    if (alias->id() == id) {
      return Type(TypeAlias(alias.get()));
    }
  }

  for (const auto& strukt : structs_) {
    if (strukt->id() == id) {
      return Type(TypeStruct(strukt.get()));
    }
  }

  // TODO: Load struct, union, usings and return one of them here!
  ZX_ASSERT_MSG(false, "unhandled TypeFromIdentifier for %s", id.c_str());
  return Type();
}

Type SyscallLibrary::TypeFromName(const std::string& name) const {
  if (auto primitive = PrimitiveTypeFromName(name); primitive.has_value()) {
    return primitive.value();
  }
  return TypeFromIdentifier(name);
}

void SyscallLibrary::FilterSyscalls(const std::set<std::string>& attributes_to_exclude) {
  std::vector<std::unique_ptr<Syscall>> filtered;
  for (auto& syscall : syscalls_) {
    if (std::any_of(
            attributes_to_exclude.begin(), attributes_to_exclude.end(),
            [&syscall](const std::string& x) { return syscall->HasAttribute(x.c_str()); })) {
      continue;
    }

    filtered.push_back(std::move(syscall));
  }

  syscalls_ = std::move(filtered);
}

// static
bool SyscallLibraryLoader::FromJson(const std::string& json_ir, SyscallLibrary* library) {
  rapidjson::Document document;
  document.Parse(json_ir);

  // Maybe do schema validation here, though we rely on fidlc for many details
  // and general sanity, so probably only in a diagnostic mode.

  if (!document.IsObject()) {
    fprintf(stderr, "Incorrect fidlc JSON IR, wasn't json object.\n");
    return false;
  }

  library->name_ = document["name"].GetString();
  if (library->name_ != "zx" && library->name_ != "zxio") {
    fprintf(stderr, "Library name %s wasn't zx or zxio as expected.\n", library->name_.c_str());
    return false;
  }

  ZX_ASSERT(library->syscalls_.empty());

  // The order of these loads is significant. For example, enums must be loaded to be able to be
  // referred to by interface methods.

  if (!LoadBits(document, library)) {
    return false;
  }

  if (!LoadEnums(document, library)) {
    return false;
  }

  if (!LoadTypeAliases(document, library)) {
    return false;
  }

  if (!LoadStructs(document, library)) {
    return false;
  }

  if (!LoadTables(document, library)) {
    return false;
  }

  if (!LoadInterfaces(document, library)) {
    return false;
  }

  return true;
}

// 'bits' are currently handled the same as enums, so just use Enum for now as the underlying
// data storage.
//
// static
std::unique_ptr<Enum> SyscallLibraryLoader::ConvertBitsOrEnumMember(const rapidjson::Value& json) {
  auto obj = std::make_unique<Enum>();
  std::string full_name = json["name"].GetString();
  obj->id_ = full_name;
  std::string stripped = StripLibraryName(full_name);
  obj->original_name_ = stripped;
  obj->base_name_ = CamelToSnake(stripped);
  std::string doc_attribute = GetDocAttribute(json);
  obj->description_ = GetCleanDocAttribute(doc_attribute);
  const rapidjson::Value& type = json["type"];
  if (type.IsString()) {
    // Enum
    obj->underlying_type_ = PrimitiveTypeFromName(type.GetString()).value();
  } else {
    ZX_ASSERT(type.IsObject());
    // Bits
    ZX_ASSERT_MSG(type["kind"].GetString() == std::string("primitive"),
                  "Enum %s not backed by primitive type", full_name.c_str());
    const rapidjson::Value& subtype_value = type["subtype"];
    ZX_ASSERT(subtype_value.IsString());
    std::string subtype = subtype_value.GetString();
    obj->underlying_type_ = PrimitiveTypeFromName(subtype).value();
  }
  for (const auto& member : json["members"].GetArray()) {
    ZX_ASSERT_MSG(member["value"]["kind"] == "literal", "TODO: More complex value expressions");
    uint64_t member_value;
    std::string decimal = member["value"]["literal"]["value"].GetString();
    if (obj->underlying_type().IsUnsignedInt()) {
      member_value = StringToUInt(decimal);
    } else if (obj->underlying_type().IsSignedInt()) {
      member_value = StringToInt(decimal);
    } else {
      ZX_PANIC("Unreachable");
    }
    std::string doc_attribute = GetDocAttribute(member);
    obj->AddMember(
        member["name"].GetString(),
        EnumMember{.value = member_value, .description = GetCleanDocAttribute(doc_attribute)});
  }
  return obj;
}

// static
bool SyscallLibraryLoader::LoadBits(const rapidjson::Document& document, SyscallLibrary* library) {
  for (const auto& bits_json : document["bits_declarations"].GetArray()) {
    library->bits_.push_back(ConvertBitsOrEnumMember(bits_json));
  }
  return true;
}

// static
bool SyscallLibraryLoader::LoadEnums(const rapidjson::Document& document, SyscallLibrary* library) {
  for (const auto& enum_json : document["enum_declarations"].GetArray()) {
    library->enums_.push_back(ConvertBitsOrEnumMember(enum_json));
  }
  return true;
}

// static
bool SyscallLibraryLoader::LoadInterfaces(const rapidjson::Document& document,
                                          SyscallLibrary* library) {
  for (const auto& interface : document["interface_declarations"].GetArray()) {
    if (!ValidateTransport(interface)) {
      fprintf(stderr, "Expected Transport to be Syscall.\n");
      return false;
    }

    std::string interface_name = interface["name"].GetString();
    std::string category = GetCategory(interface, interface_name);

    for (const auto& method : interface["methods"].GetArray()) {
      auto syscall = std::make_unique<Syscall>();
      syscall->id_ = interface_name;
      syscall->original_name_ = method["name"].GetString();
      syscall->category_ = category;
      std::string snake_name = CamelToSnake(method["name"].GetString());
      if (!StartsWith(snake_name, category)) {
        snake_name = category + (category.empty() ? "" : "_") + snake_name;
      }
      syscall->name_ = snake_name;
      syscall->is_noreturn_ = !method["has_response"].GetBool();
      const auto doc_attribute = GetDocAttribute(method);
      syscall->short_description_ = GetShortDescriptionFromDocAttribute(doc_attribute);
      syscall->rights_specs_ = GetRightsSpecsFromDocAttribute(doc_attribute);
      if (method.HasMember("maybe_attributes")) {
        for (const auto& attrib : method["maybe_attributes"].GetArray()) {
          syscall->attributes_[attrib["name"].GetString()] = attrib["value"].GetString();
        }
      }

      ZX_ASSERT(method["has_request"].GetBool());  // Events are not expected in syscalls.

      auto add_struct_members = [&library](Struct* strukt, const rapidjson::Value& arg) {
        const auto* type_alias = arg.HasMember("experimental_maybe_from_type_alias")
                                     ? &arg["experimental_maybe_from_type_alias"]
                                     : nullptr;
        strukt->members_.emplace_back(arg["name"].GetString(),
                                      TypeFromJson(*library, arg["type"], type_alias),
                                      std::map<std::string, std::string>{});
        if (arg.HasMember("maybe_attributes")) {
          for (const auto& attrib : arg["maybe_attributes"].GetArray()) {
            strukt->members_.back().attributes_[attrib["name"].GetString()] =
                attrib["value"].GetString();
          }
        }
      };

      Struct& req = syscall->request_;
      req.id_ = syscall->original_name_ + "#request";
      for (const auto& arg : method["maybe_request"].GetArray()) {
        add_struct_members(&req, arg);
      }

      if (method["has_response"].GetBool()) {
        Struct& resp = syscall->response_;
        resp.id_ = syscall->original_name_ + "#response";
        for (const auto& arg : method["maybe_response"].GetArray()) {
          add_struct_members(&resp, arg);
        }
      }

      if (!syscall->MapRequestResponseToKernelAbi()) {
        return false;
      }

      library->syscalls_.push_back(std::move(syscall));
    }
  }

  return true;
}

// static
bool SyscallLibraryLoader::LoadTypeAliases(const rapidjson::Document& document,
                                           SyscallLibrary* library) {
  for (const auto& type_alias_json : document["type_alias_declarations"].GetArray()) {
    auto obj = std::make_unique<Alias>();
    std::string full_name = type_alias_json["name"].GetString();
    obj->id_ = full_name;
    std::string stripped = StripLibraryName(full_name);
    obj->original_name_ = stripped;
    obj->base_name_ = CamelToSnake(stripped);
    const rapidjson::Value& partial_type_ctor = type_alias_json["partial_type_ctor"];
    ZX_ASSERT(partial_type_ctor.IsObject());
    obj->partial_type_ctor_ = partial_type_ctor["name"].GetString();
    std::string doc_attribute = GetDocAttribute(type_alias_json);
    obj->description_ = GetCleanDocAttribute(doc_attribute);
    library->type_aliases_.push_back(std::move(obj));
  }
  return true;
}

// static
bool SyscallLibraryLoader::LoadStructs(const rapidjson::Document& document,
                                       SyscallLibrary* library) {
  // TODO(scottmg): In transition, we're still relying on the existing Zircon headers to define all
  // these structures. So we only load their names for the time being, which is enough for now to
  // know that there's something in the .fidl file where the struct is declared. Note also that
  // interface parsing fills out request/response "structs", so that code should likely be shared
  // when this is implemented.
  for (const auto& struct_json : document["struct_declarations"].GetArray()) {
    auto obj = std::make_unique<Struct>();
    std::string full_name = struct_json["name"].GetString();
    obj->id_ = full_name;
    std::string stripped = StripLibraryName(full_name);
    obj->original_name_ = stripped;
    obj->base_name_ = CamelToSnake(stripped);
    library->structs_.push_back(std::move(obj));
  }
  return true;
}

// static
bool SyscallLibraryLoader::LoadTables(const rapidjson::Document& document,
                                      SyscallLibrary* library) {
  for (const auto& json : document["table_declarations"].GetArray()) {
    auto obj = std::make_unique<Table>();
    std::string full_name = json["name"].GetString();
    obj->id_ = full_name;
    std::string stripped = StripLibraryName(full_name);
    obj->original_name_ = stripped;
    obj->base_name_ = CamelToSnake(stripped);
    std::string doc_attribute = GetDocAttribute(json);
    obj->description_ = GetCleanDocAttribute(doc_attribute);
    std::vector<TableMember> members;
    for (const auto& member : json["members"].GetArray()) {
      std::string name = member["name"].GetString();
      const auto* type_alias = member.HasMember("experimental_maybe_from_type_alias")
                                    ? &member["experimental_maybe_from_type_alias"]
                                    : nullptr;
      Type type = TypeFromJson(*library, member["type"], type_alias);
      Required required = GetRequiredAttribute(member);
      std::string doc_attribute = GetDocAttribute(member);
      std::vector<std::string> description = GetCleanDocAttribute(doc_attribute);
      members.emplace_back(std::move(name), std::move(type), std::move(description), required);
    }
    obj->members_ = std::move(members);
    library->tables_.push_back(std::move(obj));
  }
  return true;
}
