//===- TextStubV5.cpp -----------------------------------------------------===//
//
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
// See https://llvm.org/LICENSE.txt for license information.
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
//
//===----------------------------------------------------------------------===//
//
// Implements Text Stub JSON mappings.
//
//===----------------------------------------------------------------------===//
#include "TextStubCommon.h"
#include "llvm/ADT/StringSwitch.h"
#include "llvm/Support/JSON.h"
#include <utility>

// clang-format off
/*

JSON Format specification.

All library level keys, accept target values and are defaulted if not specified. 

{
"tapi_tbd_version": 5,                            # Required: TBD version for all documents in file
"main_library": {                                 # Required: top level library
  "target_info": [                                # Required: target information 
    {
      "target": "x86_64-macos",
      "min_deployment": "10.14"                   # Optional: minOS defaults to 0
    },
    {
      "target": "arm64-macos",
      "min_deployment": "10.14"
    },
    {
      "target": "arm64-maccatalyst",
      "min_deployment": "12.1"
    }],
  "flags":[{"attributes": ["flat_namespace"]}],     # Optional:
  "install_names":[{"name":"/S/L/F/Foo.fwk/Foo"}],  # Required: library install name 
  "current_versions":[{"version": "1.2"}],          # Optional: defaults to 1
  "compatibility_versions":[{ "version": "1.1"}],   # Optional: defaults to 1
  "rpaths": [                                       # Optional: 
    {
      "targets": ["x86_64-macos"],                  # Optional: defaults to targets in `target-info`
      "paths": ["@executable_path/.../Frameworks"]
    }],
  "parent_umbrellas": [{"umbrella": "System"}],
  "allowable_clients": [{"clients": ["ClientA"]}],
  "reexported_libraries": [{"names": ["/u/l/l/foo.dylib"]}],
  "exported_symbols": [{                            # List of export symbols section
      "targets": ["x86_64-macos", "arm64-macos"],   # Optional: defaults to targets in `target-info`
        "text": {                                   # List of Text segment symbols 
          "global": [ "_func" ],
          "weak": [],
          "thread_local": []
        },
        "data": { ... },                            # List of Data segment symbols
   }],
  "reexported_symbols": [{  ... }],                 # List of reexported symbols section
  "undefined_symbols": [{ ... }]                    # List of undefined symbols section
},
"libraries": [                                      # Optional: Array of inlined libraries
  {...}, {...}, {...}
]
}
*/
// clang-format on

using namespace llvm;
using namespace llvm::json;
using namespace llvm::MachO;

namespace {
struct JSONSymbol {
  EncodeKind Kind;
  std::string Name;
  SymbolFlags Flags;
};

using AttrToTargets = std::map<std::string, TargetList>;
using TargetsToSymbols =
    SmallVector<std::pair<TargetList, std::vector<JSONSymbol>>>;

/// Wrapper over a vector for handling textstub attributes, mapped to target
/// triples, that require insertion order to be intact in the resulting \c
/// InterfaceFile.
class InOrderAttrToTargets {
  using EntryT = std::pair<std::string, TargetList>;

public:
  void insert(EntryT &&Entry) {
    auto &Element = get(Entry.first);
    Element.second = Entry.second;
  }

  const EntryT *begin() { return Container.begin(); }
  const EntryT *end() { return Container.end(); }

private:
  EntryT &get(std::string &Key) {
    auto *It = find_if(Container,
                       [&Key](EntryT &Input) { return Input.first == Key; });
    if (It != Container.end())
      return *It;
    Container.push_back(EntryT(Key, {}));
    return Container.back();
  }
  llvm::SmallVector<EntryT> Container;
};

enum TBDKey : size_t {
  TBDVersion = 0U,
  MainLibrary,
  Documents,
  TargetInfo,
  Targets,
  Target,
  Deployment,
  Flags,
  Attributes,
  InstallName,
  CurrentVersion,
  CompatibilityVersion,
  Version,
  SwiftABI,
  ABI,
  ParentUmbrella,
  Umbrella,
  AllowableClients,
  Clients,
  ReexportLibs,
  Names,
  Name,
  Exports,
  Reexports,
  Undefineds,
  Data,
  Text,
  Weak,
  ThreadLocal,
  Globals,
  ObjCClass,
  ObjCEHType,
  ObjCIvar,
  RPath,
  Paths,
};

std::array<StringRef, 64> Keys = {
    "tapi_tbd_version",
    "main_library",
    "libraries",
    "target_info",
    "targets",
    "target",
    "min_deployment",
    "flags",
    "attributes",
    "install_names",
    "current_versions",
    "compatibility_versions",
    "version",
    "swift_abi",
    "abi",
    "parent_umbrellas",
    "umbrella",
    "allowable_clients",
    "clients",
    "reexported_libraries",
    "names",
    "name",
    "exported_symbols",
    "reexported_symbols",
    "undefined_symbols",
    "data",
    "text",
    "weak",
    "thread_local",
    "global",
    "objc_class",
    "objc_eh_type",
    "objc_ivar",
    "rpaths",
    "paths",
};

static llvm::SmallString<128> getParseErrorMsg(TBDKey Key) {
  return {"invalid ", Keys[Key], " section"};
}

static llvm::SmallString<128> getSerializeErrorMsg(TBDKey Key) {
  return {"missing ", Keys[Key], " information"};
}

class JSONStubError : public llvm::ErrorInfo<llvm::json::ParseError> {
public:
  JSONStubError(Twine ErrMsg) : Message(ErrMsg.str()) {}

  void log(llvm::raw_ostream &OS) const override { OS << Message << "\n"; }
  std::error_code convertToErrorCode() const override {
    return llvm::inconvertibleErrorCode();
  }

private:
  std::string Message;
};

template <typename JsonT, typename StubT = JsonT>
Expected<StubT> getRequiredValue(
    TBDKey Key, const Object *Obj,
    std::function<std::optional<JsonT>(const Object *, StringRef)> GetValue,
    std::function<std::optional<StubT>(JsonT)> Validate = nullptr) {
  std::optional<JsonT> Val = GetValue(Obj, Keys[Key]);
  if (!Val)
    return make_error<JSONStubError>(getParseErrorMsg(Key));

  if (Validate == nullptr)
    return static_cast<StubT>(*Val);

  std::optional<StubT> Result = Validate(*Val);
  if (!Result.has_value())
    return make_error<JSONStubError>(getParseErrorMsg(Key));
  return Result.value();
}

template <typename JsonT, typename StubT = JsonT>
Expected<StubT> getRequiredValue(
    TBDKey Key, const Object *Obj,
    std::function<std::optional<JsonT>(const Object *, StringRef)> const
        GetValue,
    StubT DefaultValue, function_ref<std::optional<StubT>(JsonT)> Validate) {
  std::optional<JsonT> Val = GetValue(Obj, Keys[Key]);
  if (!Val)
    return DefaultValue;

  std::optional<StubT> Result;
  Result = Validate(*Val);
  if (!Result.has_value())
    return make_error<JSONStubError>(getParseErrorMsg(Key));
  return Result.value();
}

Error collectFromArray(TBDKey Key, const Object *Obj,
                       function_ref<void(StringRef)> Append,
                       bool IsRequired = false) {
  const auto *Values = Obj->getArray(Keys[Key]);
  if (!Values) {
    if (IsRequired)
      return make_error<JSONStubError>(getParseErrorMsg(Key));
    return Error::success();
  }

  for (const Value &Val : *Values) {
    auto ValStr = Val.getAsString();
    if (!ValStr.has_value())
      return make_error<JSONStubError>(getParseErrorMsg(Key));
    Append(ValStr.value());
  }

  return Error::success();
}

namespace StubParser {

Expected<FileType> getVersion(const Object *File) {
  auto VersionOrErr = getRequiredValue<int64_t, FileType>(
      TBDKey::TBDVersion, File, &Object::getInteger,
      [](int64_t Val) -> std::optional<FileType> {
        unsigned Result = Val;
        if (Result != 5)
          return std::nullopt;
        return FileType::TBD_V5;
      });

  if (!VersionOrErr)
    return VersionOrErr.takeError();
  return *VersionOrErr;
}

Expected<TargetList> getTargets(const Object *Section) {
  const auto *Targets = Section->getArray(Keys[TBDKey::Targets]);
  if (!Targets)
    return make_error<JSONStubError>(getParseErrorMsg(TBDKey::Targets));

  TargetList IFTargets;
  for (const Value &JSONTarget : *Targets) {
    auto TargetStr = JSONTarget.getAsString();
    if (!TargetStr.has_value())
      return make_error<JSONStubError>(getParseErrorMsg(TBDKey::Target));
    auto TargetOrErr = Target::create(TargetStr.value());
    if (!TargetOrErr)
      return make_error<JSONStubError>(getParseErrorMsg(TBDKey::Target));
    IFTargets.push_back(*TargetOrErr);
  }
  return std::move(IFTargets);
}

Expected<TargetList> getTargetsSection(const Object *Section) {
  const Array *Targets = Section->getArray(Keys[TBDKey::TargetInfo]);
  if (!Targets)
    return make_error<JSONStubError>(getParseErrorMsg(TBDKey::Targets));

  TargetList IFTargets;
  for (const Value &JSONTarget : *Targets) {
    const auto *Obj = JSONTarget.getAsObject();
    if (!Obj)
      return make_error<JSONStubError>(getParseErrorMsg(TBDKey::Target));
    auto TargetStr =
        getRequiredValue<StringRef>(TBDKey::Target, Obj, &Object::getString);
    if (!TargetStr)
      return make_error<JSONStubError>(getParseErrorMsg(TBDKey::Target));
    auto TargetOrErr = Target::create(*TargetStr);
    if (!TargetOrErr)
      return make_error<JSONStubError>(getParseErrorMsg(TBDKey::Target));

    auto VersionStr = Obj->getString(Keys[TBDKey::Deployment]);
    VersionTuple Version;
    if (VersionStr && Version.tryParse(*VersionStr))
      return make_error<JSONStubError>(getParseErrorMsg(TBDKey::Deployment));
    TargetOrErr->MinDeployment = Version;

    // Convert to LLVM::Triple to accurately compute minOS + platform + arch
    // pairing.
    IFTargets.push_back(
        MachO::Target(Triple(getTargetTripleName(*TargetOrErr))));
  }
  return std::move(IFTargets);
}

Error collectSymbolsFromSegment(const Object *Segment, TargetsToSymbols &Result,
                                SymbolFlags SectionFlag) {
  auto Err = collectFromArray(
      TBDKey::Globals, Segment, [&Result, &SectionFlag](StringRef Name) {
        JSONSymbol Sym = {EncodeKind::GlobalSymbol, Name.str(), SectionFlag};
        Result.back().second.emplace_back(Sym);
      });
  if (Err)
    return Err;

  Err = collectFromArray(
      TBDKey::ObjCClass, Segment, [&Result, &SectionFlag](StringRef Name) {
        JSONSymbol Sym = {EncodeKind::ObjectiveCClass, Name.str(), SectionFlag};
        Result.back().second.emplace_back(Sym);
      });
  if (Err)
    return Err;

  Err = collectFromArray(TBDKey::ObjCEHType, Segment,
                         [&Result, &SectionFlag](StringRef Name) {
                           JSONSymbol Sym = {EncodeKind::ObjectiveCClassEHType,
                                             Name.str(), SectionFlag};
                           Result.back().second.emplace_back(Sym);
                         });
  if (Err)
    return Err;

  Err = collectFromArray(
      TBDKey::ObjCIvar, Segment, [&Result, &SectionFlag](StringRef Name) {
        JSONSymbol Sym = {EncodeKind::ObjectiveCInstanceVariable, Name.str(),
                          SectionFlag};
        Result.back().second.emplace_back(Sym);
      });
  if (Err)
    return Err;

  SymbolFlags WeakFlag =
      SectionFlag |
      (((SectionFlag & SymbolFlags::Undefined) == SymbolFlags::Undefined)
           ? SymbolFlags::WeakReferenced
           : SymbolFlags::WeakDefined);
  Err = collectFromArray(
      TBDKey::Weak, Segment, [&Result, WeakFlag](StringRef Name) {
        JSONSymbol Sym = {EncodeKind::GlobalSymbol, Name.str(), WeakFlag};
        Result.back().second.emplace_back(Sym);
      });
  if (Err)
    return Err;

  Err = collectFromArray(
      TBDKey::ThreadLocal, Segment, [&Result, SectionFlag](StringRef Name) {
        JSONSymbol Sym = {EncodeKind::GlobalSymbol, Name.str(),
                          SymbolFlags::ThreadLocalValue | SectionFlag};
        Result.back().second.emplace_back(Sym);
      });
  if (Err)
    return Err;

  return Error::success();
}

Expected<StringRef> getNameSection(const Object *File) {
  const Array *Section = File->getArray(Keys[TBDKey::InstallName]);
  if (!Section)
    return make_error<JSONStubError>(getParseErrorMsg(TBDKey::InstallName));

  assert(!Section->empty() && "unexpected missing install name");
  // TODO: Just take first for now.
  const auto *Obj = Section->front().getAsObject();
  if (!Obj)
    return make_error<JSONStubError>(getParseErrorMsg(TBDKey::InstallName));

  return getRequiredValue<StringRef>(TBDKey::Name, Obj, &Object::getString);
}

Expected<TargetsToSymbols> getSymbolSection(const Object *File, TBDKey Key,
                                            TargetList &Targets) {

  const Array *Section = File->getArray(Keys[Key]);
  if (!Section)
    return TargetsToSymbols();

  SymbolFlags SectionFlag;
  switch (Key) {
  case TBDKey::Reexports:
    SectionFlag = SymbolFlags::Rexported;
    break;
  case TBDKey::Undefineds:
    SectionFlag = SymbolFlags::Undefined;
    break;
  default:
    SectionFlag = SymbolFlags::None;
    break;
  };

  TargetsToSymbols Result;
  TargetList MappedTargets;
  for (auto Val : *Section) {
    auto *Obj = Val.getAsObject();
    if (!Obj)
      continue;

    auto TargetsOrErr = getTargets(Obj);
    if (!TargetsOrErr) {
      MappedTargets = Targets;
      consumeError(TargetsOrErr.takeError());
    } else {
      MappedTargets = *TargetsOrErr;
    }
    Result.emplace_back(
        std::make_pair(std::move(MappedTargets), std::vector<JSONSymbol>()));

    auto *DataSection = Obj->getObject(Keys[TBDKey::Data]);
    auto *TextSection = Obj->getObject(Keys[TBDKey::Text]);
    // There should be at least one valid section.
    if (!DataSection && !TextSection)
      return make_error<JSONStubError>(getParseErrorMsg(Key));

    if (DataSection) {
      auto Err = collectSymbolsFromSegment(DataSection, Result,
                                           SectionFlag | SymbolFlags::Data);
      if (Err)
        return std::move(Err);
    }
    if (TextSection) {
      auto Err = collectSymbolsFromSegment(TextSection, Result,
                                           SectionFlag | SymbolFlags::Text);
      if (Err)
        return std::move(Err);
    }
  }

  return std::move(Result);
}

template <typename ReturnT = AttrToTargets>
Expected<ReturnT> getLibSection(const Object *File, TBDKey Key, TBDKey SubKey,
                                const TargetList &Targets) {
  auto *Section = File->getArray(Keys[Key]);
  if (!Section)
    return ReturnT();

  ReturnT Result;
  TargetList MappedTargets;
  for (auto Val : *Section) {
    auto *Obj = Val.getAsObject();
    if (!Obj)
      continue;

    auto TargetsOrErr = getTargets(Obj);
    if (!TargetsOrErr) {
      MappedTargets = Targets;
      consumeError(TargetsOrErr.takeError());
    } else {
      MappedTargets = *TargetsOrErr;
    }
    auto Err =
        collectFromArray(SubKey, Obj, [&Result, &MappedTargets](StringRef Key) {
          Result.insert({Key.str(), MappedTargets});
        });
    if (Err)
      return std::move(Err);
  }

  return std::move(Result);
}

Expected<AttrToTargets> getUmbrellaSection(const Object *File,
                                           const TargetList &Targets) {
  const auto *Umbrella = File->getArray(Keys[TBDKey::ParentUmbrella]);
  if (!Umbrella)
    return AttrToTargets();

  AttrToTargets Result;
  TargetList MappedTargets;
  for (auto Val : *Umbrella) {
    auto *Obj = Val.getAsObject();
    if (!Obj)
      return make_error<JSONStubError>(
          getParseErrorMsg(TBDKey::ParentUmbrella));

    // Get Targets section.
    auto TargetsOrErr = getTargets(Obj);
    if (!TargetsOrErr) {
      MappedTargets = Targets;
      consumeError(TargetsOrErr.takeError());
    } else {
      MappedTargets = *TargetsOrErr;
    }

    auto UmbrellaOrErr =
        getRequiredValue<StringRef>(TBDKey::Umbrella, Obj, &Object::getString);
    if (!UmbrellaOrErr)
      return UmbrellaOrErr.takeError();
    Result[UmbrellaOrErr->str()] = Targets;
  }
  return std::move(Result);
}

Expected<uint8_t> getSwiftVersion(const Object *File) {
  const Array *Versions = File->getArray(Keys[TBDKey::SwiftABI]);
  if (!Versions)
    return 0;

  for (const auto &Val : *Versions) {
    const auto *Obj = Val.getAsObject();
    if (!Obj)
      return make_error<JSONStubError>(getParseErrorMsg(TBDKey::SwiftABI));

    // TODO: Take first for now.
    return getRequiredValue<int64_t, uint8_t>(TBDKey::ABI, Obj,
                                              &Object::getInteger);
  }

  return 0;
}

Expected<PackedVersion> getPackedVersion(const Object *File, TBDKey Key) {
  const Array *Versions = File->getArray(Keys[Key]);
  if (!Versions)
    return PackedVersion(1, 0, 0);

  for (const auto &Val : *Versions) {
    const auto *Obj = Val.getAsObject();
    if (!Obj)
      return make_error<JSONStubError>(getParseErrorMsg(Key));

    auto ValidatePV = [](StringRef Version) -> std::optional<PackedVersion> {
      PackedVersion PV;
      auto [success, truncated] = PV.parse64(Version);
      if (!success || truncated)
        return std::nullopt;
      return PV;
    };
    // TODO: Take first for now.
    return getRequiredValue<StringRef, PackedVersion>(
        TBDKey::Version, Obj, &Object::getString, PackedVersion(1, 0, 0),
        ValidatePV);
  }

  return PackedVersion(1, 0, 0);
}

Expected<TBDFlags> getFlags(const Object *File) {
  TBDFlags Flags = TBDFlags::None;
  const Array *Section = File->getArray(Keys[TBDKey::Flags]);
  if (!Section || Section->empty())
    return Flags;

  for (auto &Val : *Section) {
    // FIXME: Flags currently apply to all target triples.
    const auto *Obj = Val.getAsObject();
    if (!Obj)
      return make_error<JSONStubError>(getParseErrorMsg(TBDKey::Flags));

    auto FlagsOrErr =
        collectFromArray(TBDKey::Attributes, Obj, [&Flags](StringRef Flag) {
          TBDFlags TBDFlag =
              StringSwitch<TBDFlags>(Flag)
                  .Case("flat_namespace", TBDFlags::FlatNamespace)
                  .Case("not_app_extension_safe",
                        TBDFlags::NotApplicationExtensionSafe)
                  .Case("sim_support", TBDFlags::SimulatorSupport)
                  .Case("not_for_dyld_shared_cache",
                        TBDFlags::OSLibNotForSharedCache)
                  .Default(TBDFlags::None);
          Flags |= TBDFlag;
        });

    if (FlagsOrErr)
      return std::move(FlagsOrErr);

    return Flags;
  }

  return Flags;
}

using IFPtr = std::unique_ptr<InterfaceFile>;
Expected<IFPtr> parseToInterfaceFile(const Object *File) {
  auto TargetsOrErr = getTargetsSection(File);
  if (!TargetsOrErr)
    return TargetsOrErr.takeError();
  TargetList Targets = *TargetsOrErr;

  auto NameOrErr = getNameSection(File);
  if (!NameOrErr)
    return NameOrErr.takeError();
  StringRef Name = *NameOrErr;

  auto CurrVersionOrErr = getPackedVersion(File, TBDKey::CurrentVersion);
  if (!CurrVersionOrErr)
    return CurrVersionOrErr.takeError();
  PackedVersion CurrVersion = *CurrVersionOrErr;

  auto CompVersionOrErr = getPackedVersion(File, TBDKey::CompatibilityVersion);
  if (!CompVersionOrErr)
    return CompVersionOrErr.takeError();
  PackedVersion CompVersion = *CompVersionOrErr;

  auto SwiftABIOrErr = getSwiftVersion(File);
  if (!SwiftABIOrErr)
    return SwiftABIOrErr.takeError();
  uint8_t SwiftABI = *SwiftABIOrErr;

  auto FlagsOrErr = getFlags(File);
  if (!FlagsOrErr)
    return FlagsOrErr.takeError();
  TBDFlags Flags = *FlagsOrErr;

  auto UmbrellasOrErr = getUmbrellaSection(File, Targets);
  if (!UmbrellasOrErr)
    return UmbrellasOrErr.takeError();
  const AttrToTargets &Umbrellas = *UmbrellasOrErr;

  auto ClientsOrErr =
      getLibSection(File, TBDKey::AllowableClients, TBDKey::Clients, Targets);
  if (!ClientsOrErr)
    return ClientsOrErr.takeError();
  const AttrToTargets &Clients = *ClientsOrErr;

  auto RLOrErr =
      getLibSection(File, TBDKey::ReexportLibs, TBDKey::Names, Targets);
  if (!RLOrErr)
    return RLOrErr.takeError();
  AttrToTargets ReexportLibs = std::move(*RLOrErr);

  auto RPathsOrErr = getLibSection<InOrderAttrToTargets>(
      File, TBDKey::RPath, TBDKey::Paths, Targets);
  if (!RPathsOrErr)
    return RPathsOrErr.takeError();
  InOrderAttrToTargets RPaths = std::move(*RPathsOrErr);

  auto ExportsOrErr = getSymbolSection(File, TBDKey::Exports, Targets);
  if (!ExportsOrErr)
    return ExportsOrErr.takeError();
  TargetsToSymbols Exports = std::move(*ExportsOrErr);

  auto ReexportsOrErr = getSymbolSection(File, TBDKey::Reexports, Targets);
  if (!ReexportsOrErr)
    return ReexportsOrErr.takeError();
  TargetsToSymbols Reexports = std::move(*ReexportsOrErr);

  auto UndefinedsOrErr = getSymbolSection(File, TBDKey::Undefineds, Targets);
  if (!UndefinedsOrErr)
    return UndefinedsOrErr.takeError();
  TargetsToSymbols Undefineds = std::move(*UndefinedsOrErr);

  IFPtr F(new InterfaceFile);
  F->setInstallName(Name);
  F->setCurrentVersion(CurrVersion);
  F->setCompatibilityVersion(CompVersion);
  F->setSwiftABIVersion(SwiftABI);
  F->setTwoLevelNamespace(!(Flags & TBDFlags::FlatNamespace));
  F->setApplicationExtensionSafe(
      !(Flags & TBDFlags::NotApplicationExtensionSafe));
  F->setSimulatorSupport((Flags & TBDFlags::SimulatorSupport));
  F->setOSLibNotForSharedCache((Flags & TBDFlags::OSLibNotForSharedCache));
  for (auto &T : Targets)
    F->addTarget(T);
  for (auto &[Lib, Targets] : Clients)
    for (auto Target : Targets)
      F->addAllowableClient(Lib, Target);
  for (auto &[Lib, Targets] : ReexportLibs)
    for (auto Target : Targets)
      F->addReexportedLibrary(Lib, Target);
  for (auto &[Lib, Targets] : Umbrellas)
    for (auto Target : Targets)
      F->addParentUmbrella(Target, Lib);
  for (auto &[Path, Targets] : RPaths)
    for (auto Target : Targets)
      F->addRPath(Path, Target);
  for (auto &[Targets, Symbols] : Exports)
    for (auto &Sym : Symbols)
      F->addSymbol(Sym.Kind, Sym.Name, Targets, Sym.Flags);
  for (auto &[Targets, Symbols] : Reexports)
    for (auto &Sym : Symbols)
      F->addSymbol(Sym.Kind, Sym.Name, Targets, Sym.Flags);
  for (auto &[Targets, Symbols] : Undefineds)
    for (auto &Sym : Symbols)
      F->addSymbol(Sym.Kind, Sym.Name, Targets, Sym.Flags);

  return std::move(F);
}

Expected<std::vector<IFPtr>> getInlinedLibs(const Object *File) {
  std::vector<IFPtr> IFs;
  const Array *Files = File->getArray(Keys[TBDKey::Documents]);
  if (!Files)
    return std::move(IFs);

  for (auto Lib : *Files) {
    auto IFOrErr = parseToInterfaceFile(Lib.getAsObject());
    if (!IFOrErr)
      return IFOrErr.takeError();
    auto IF = std::move(*IFOrErr);
    IFs.emplace_back(std::move(IF));
  }
  return std::move(IFs);
}

} // namespace StubParser
} // namespace

Expected<std::unique_ptr<InterfaceFile>>
MachO::getInterfaceFileFromJSON(StringRef JSON) {
  auto ValOrErr = parse(JSON);
  if (!ValOrErr)
    return ValOrErr.takeError();

  auto *Root = ValOrErr->getAsObject();
  auto VersionOrErr = StubParser::getVersion(Root);
  if (!VersionOrErr)
    return VersionOrErr.takeError();
  FileType Version = *VersionOrErr;

  Object *MainLib = Root->getObject(Keys[TBDKey::MainLibrary]);
  auto IFOrErr = StubParser::parseToInterfaceFile(MainLib);
  if (!IFOrErr)
    return IFOrErr.takeError();
  (*IFOrErr)->setFileType(Version);
  std::unique_ptr<InterfaceFile> IF(std::move(*IFOrErr));

  auto IFsOrErr = StubParser::getInlinedLibs(Root);
  if (!IFsOrErr)
    return IFsOrErr.takeError();
  for (auto &File : *IFsOrErr) {
    File->setFileType(Version);
    IF->addDocument(std::shared_ptr<InterfaceFile>(std::move(File)));
  }
  return std::move(IF);
}

namespace {

template <typename ContainerT = Array>
bool insertNonEmptyValues(Object &Obj, TBDKey Key, ContainerT &&Contents) {
  if (Contents.empty())
    return false;
  Obj[Keys[Key]] = std::move(Contents);
  return true;
}

std::string getFormattedStr(const MachO::Target &Targ) {
  std::string PlatformStr = Targ.Platform == PLATFORM_MACCATALYST
                                ? "maccatalyst"
                                : getOSAndEnvironmentName(Targ.Platform);
  return (getArchitectureName(Targ.Arch) + "-" + PlatformStr).str();
}

template <typename AggregateT>
std::vector<std::string> serializeTargets(const AggregateT Targets,
                                          const TargetList &ActiveTargets) {
  std::vector<std::string> TargetsStr;
  if (Targets.size() == ActiveTargets.size())
    return TargetsStr;

  for (const MachO::Target &Target : Targets)
    TargetsStr.emplace_back(getFormattedStr(Target));

  return TargetsStr;
}

Array serializeTargetInfo(const TargetList &ActiveTargets) {
  Array Targets;
  for (const auto Targ : ActiveTargets) {
    Object TargetInfo;
    if (!Targ.MinDeployment.empty())
      TargetInfo[Keys[TBDKey::Deployment]] = Targ.MinDeployment.getAsString();
    TargetInfo[Keys[TBDKey::Target]] = getFormattedStr(Targ);
    Targets.emplace_back(std::move(TargetInfo));
  }
  return Targets;
}

template <typename ValueT, typename EntryT = ValueT>
Array serializeScalar(TBDKey Key, ValueT Value, ValueT Default = ValueT()) {
  if (Value == Default)
    return {};
  Array Container;
  Object ScalarObj({Object::KV({Keys[Key], EntryT(Value)})});

  Container.emplace_back(std::move(ScalarObj));
  return Container;
}

using TargetsToValuesMap =
    std::map<std::vector<std::string>, std::vector<std::string>>;

template <typename AggregateT = TargetsToValuesMap>
Array serializeAttrToTargets(AggregateT &Entries, TBDKey Key) {
  Array Container;
  for (const auto &[Targets, Values] : Entries) {
    Object Obj;
    insertNonEmptyValues(Obj, TBDKey::Targets, std::move(Targets));
    Obj[Keys[Key]] = Values;
    Container.emplace_back(std::move(Obj));
  }
  return Container;
}

/// When there is no significance in order, the common case, serialize all
/// attributes in a stable order.
template <typename ValueT = std::string,
          typename AggregateT = std::vector<std::pair<MachO::Target, ValueT>>>
Array serializeField(TBDKey Key, const AggregateT &Values,
                     const TargetList &ActiveTargets, bool IsArray = true) {
  std::map<ValueT, std::set<MachO::Target>> Entries;
  for (const auto &[Target, Val] : Values)
    Entries[Val].insert(Target);

  if (!IsArray) {
    std::map<std::vector<std::string>, std::string> FinalEntries;
    for (const auto &[Val, Targets] : Entries)
      FinalEntries[serializeTargets(Targets, ActiveTargets)] = Val;
    return serializeAttrToTargets(FinalEntries, Key);
  }

  TargetsToValuesMap FinalEntries;
  for (const auto &[Val, Targets] : Entries)
    FinalEntries[serializeTargets(Targets, ActiveTargets)].emplace_back(Val);
  return serializeAttrToTargets(FinalEntries, Key);
}

Array serializeField(TBDKey Key, const std::vector<InterfaceFileRef> &Values,
                     const TargetList &ActiveTargets) {
  TargetsToValuesMap FinalEntries;
  for (const auto &Ref : Values) {
    TargetList Targets{Ref.targets().begin(), Ref.targets().end()};
    FinalEntries[serializeTargets(Targets, ActiveTargets)].emplace_back(
        Ref.getInstallName());
  }
  return serializeAttrToTargets(FinalEntries, Key);
}

template <
    typename AggregateT = std::vector<std::pair<MachO::Target, std::string>>>
Array serializeFieldInInsertionOrder(TBDKey Key, const AggregateT &Values,
                                     const TargetList &ActiveTargets) {
  MapVector<StringRef, std::set<MachO::Target>> Entries;
  for (const auto &[Target, Val] : Values)
    Entries[Val].insert(Target);

  TargetsToValuesMap FinalEntries;
  for (const auto &[Val, Targets] : Entries)
    FinalEntries[serializeTargets(Targets, ActiveTargets)].emplace_back(
        Val.str());
  return serializeAttrToTargets(FinalEntries, Key);
}

struct SymbolFields {
  struct SymbolTypes {
    std::vector<StringRef> Weaks;
    std::vector<StringRef> Globals;
    std::vector<StringRef> TLV;
    std::vector<StringRef> ObjCClasses;
    std::vector<StringRef> IVars;
    std::vector<StringRef> EHTypes;

    bool empty() const {
      return Weaks.empty() && Globals.empty() && TLV.empty() &&
             ObjCClasses.empty() && IVars.empty() && EHTypes.empty();
    }
  };
  SymbolTypes Data;
  SymbolTypes Text;
};

Array serializeSymbols(InterfaceFile::const_filtered_symbol_range Symbols,
                       const TargetList &ActiveTargets) {
  auto AssignForSymbolType = [](SymbolFields::SymbolTypes &Assignment,
                                const Symbol *Sym) {
    switch (Sym->getKind()) {
    case EncodeKind::ObjectiveCClass:
      Assignment.ObjCClasses.emplace_back(Sym->getName());
      return;
    case EncodeKind::ObjectiveCClassEHType:
      Assignment.EHTypes.emplace_back(Sym->getName());
      return;
    case EncodeKind::ObjectiveCInstanceVariable:
      Assignment.IVars.emplace_back(Sym->getName());
      return;
    case EncodeKind::GlobalSymbol: {
      if (Sym->isWeakReferenced() || Sym->isWeakDefined())
        Assignment.Weaks.emplace_back(Sym->getName());
      else if (Sym->isThreadLocalValue())
        Assignment.TLV.emplace_back(Sym->getName());
      else
        Assignment.Globals.emplace_back(Sym->getName());
      return;
    }
    }
  };

  std::map<std::vector<std::string>, SymbolFields> Entries;
  for (const auto *Sym : Symbols) {
    std::set<MachO::Target> Targets{Sym->targets().begin(),
                                    Sym->targets().end()};
    auto JSONTargets = serializeTargets(Targets, ActiveTargets);
    if (Sym->isData())
      AssignForSymbolType(Entries[std::move(JSONTargets)].Data, Sym);
    else if (Sym->isText())
      AssignForSymbolType(Entries[std::move(JSONTargets)].Text, Sym);
    else
      llvm_unreachable("unexpected symbol type");
  }

  auto InsertSymbolsToJSON = [](Object &SymSection, TBDKey SegmentKey,
                                SymbolFields::SymbolTypes &SymField) {
    if (SymField.empty())
      return;
    llvm::sort(SymField.Globals);
    llvm::sort(SymField.TLV);
    llvm::sort(SymField.Weaks);
    llvm::sort(SymField.ObjCClasses);
    llvm::sort(SymField.EHTypes);
    llvm::sort(SymField.IVars);
    Object Segment;
    insertNonEmptyValues(Segment, TBDKey::Globals, std::move(SymField.Globals));
    insertNonEmptyValues(Segment, TBDKey::ThreadLocal, std::move(SymField.TLV));
    insertNonEmptyValues(Segment, TBDKey::Weak, std::move(SymField.Weaks));
    insertNonEmptyValues(Segment, TBDKey::ObjCClass,
                         std::move(SymField.ObjCClasses));
    insertNonEmptyValues(Segment, TBDKey::ObjCEHType,
                         std::move(SymField.EHTypes));
    insertNonEmptyValues(Segment, TBDKey::ObjCIvar, std::move(SymField.IVars));
    insertNonEmptyValues(SymSection, SegmentKey, std::move(Segment));
  };

  Array SymbolSection;
  for (auto &[Targets, Fields] : Entries) {
    Object AllSyms;
    insertNonEmptyValues(AllSyms, TBDKey::Targets, std::move(Targets));
    InsertSymbolsToJSON(AllSyms, TBDKey::Data, Fields.Data);
    InsertSymbolsToJSON(AllSyms, TBDKey::Text, Fields.Text);
    SymbolSection.emplace_back(std::move(AllSyms));
  }

  return SymbolSection;
}

Array serializeFlags(const InterfaceFile *File) {
  // TODO: Give all Targets the same flags for now.
  Array Flags;
  if (!File->isTwoLevelNamespace())
    Flags.emplace_back("flat_namespace");
  if (!File->isApplicationExtensionSafe())
    Flags.emplace_back("not_app_extension_safe");
  if (File->hasSimulatorSupport())
    Flags.emplace_back("sim_support");
  if (File->isOSLibNotForSharedCache())
    Flags.emplace_back("not_for_dyld_shared_cache");
  return serializeScalar(TBDKey::Attributes, std::move(Flags));
}

Expected<Object> serializeIF(const InterfaceFile *File) {
  Object Library;

  // Handle required keys.
  TargetList ActiveTargets{File->targets().begin(), File->targets().end()};
  if (!insertNonEmptyValues(Library, TBDKey::TargetInfo,
                            serializeTargetInfo(ActiveTargets)))
    return make_error<JSONStubError>(getSerializeErrorMsg(TBDKey::TargetInfo));

  Array Name = serializeScalar<StringRef>(TBDKey::Name, File->getInstallName());
  if (!insertNonEmptyValues(Library, TBDKey::InstallName, std::move(Name)))
    return make_error<JSONStubError>(getSerializeErrorMsg(TBDKey::InstallName));

  // Handle optional keys.
  Array Flags = serializeFlags(File);
  insertNonEmptyValues(Library, TBDKey::Flags, std::move(Flags));

  Array CurrentV = serializeScalar<PackedVersion, std::string>(
      TBDKey::Version, File->getCurrentVersion(), PackedVersion(1, 0, 0));
  insertNonEmptyValues(Library, TBDKey::CurrentVersion, std::move(CurrentV));

  Array CompatV = serializeScalar<PackedVersion, std::string>(
      TBDKey::Version, File->getCompatibilityVersion(), PackedVersion(1, 0, 0));
  insertNonEmptyValues(Library, TBDKey::CompatibilityVersion,
                       std::move(CompatV));

  Array SwiftABI = serializeScalar<uint8_t, int64_t>(
      TBDKey::ABI, File->getSwiftABIVersion(), 0u);
  insertNonEmptyValues(Library, TBDKey::SwiftABI, std::move(SwiftABI));

  Array RPaths = serializeFieldInInsertionOrder(TBDKey::Paths, File->rpaths(),
                                                ActiveTargets);
  insertNonEmptyValues(Library, TBDKey::RPath, std::move(RPaths));

  Array Umbrellas = serializeField(TBDKey::Umbrella, File->umbrellas(),
                                   ActiveTargets, /*IsArray=*/false);
  insertNonEmptyValues(Library, TBDKey::ParentUmbrella, std::move(Umbrellas));

  Array Clients =
      serializeField(TBDKey::Clients, File->allowableClients(), ActiveTargets);
  insertNonEmptyValues(Library, TBDKey::AllowableClients, std::move(Clients));

  Array ReexportLibs =
      serializeField(TBDKey::Names, File->reexportedLibraries(), ActiveTargets);
  insertNonEmptyValues(Library, TBDKey::ReexportLibs, std::move(ReexportLibs));

  // Handle symbols.
  Array Exports = serializeSymbols(File->exports(), ActiveTargets);
  insertNonEmptyValues(Library, TBDKey::Exports, std::move(Exports));

  Array Reexports = serializeSymbols(File->reexports(), ActiveTargets);
  insertNonEmptyValues(Library, TBDKey::Reexports, std::move(Reexports));

  if (!File->isTwoLevelNamespace()) {
    Array Undefineds = serializeSymbols(File->undefineds(), ActiveTargets);
    insertNonEmptyValues(Library, TBDKey::Undefineds, std::move(Undefineds));
  }

  return std::move(Library);
}

Expected<Object> getJSON(const InterfaceFile *File, const FileType FileKind) {
  assert(FileKind == FileType::TBD_V5 && "unexpected json file format version");
  Object Root;

  auto MainLibOrErr = serializeIF(File);
  if (!MainLibOrErr)
    return MainLibOrErr;
  Root[Keys[TBDKey::MainLibrary]] = std::move(*MainLibOrErr);
  Array Documents;
  for (const auto &Doc : File->documents()) {
    auto LibOrErr = serializeIF(Doc.get());
    if (!LibOrErr)
      return LibOrErr;
    Documents.emplace_back(std::move(*LibOrErr));
  }

  Root[Keys[TBDKey::TBDVersion]] = 5;
  insertNonEmptyValues(Root, TBDKey::Documents, std::move(Documents));
  return std::move(Root);
}

} // namespace

Error MachO::serializeInterfaceFileToJSON(raw_ostream &OS,
                                          const InterfaceFile &File,
                                          const FileType FileKind,
                                          bool Compact) {
  auto TextFile = getJSON(&File, FileKind);
  if (!TextFile)
    return TextFile.takeError();
  if (Compact)
    OS << formatv("{0}", Value(std::move(*TextFile))) << "\n";
  else
    OS << formatv("{0:2}", Value(std::move(*TextFile))) << "\n";
  return Error::success();
}
