//===-- MsgPackDocumentYAML.cpp - MsgPack Document YAML interface -------*-===//
//
// 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
//
//===----------------------------------------------------------------------===//
//
/// This file implements YAMLIO on a msgpack::Document.
//
//===----------------------------------------------------------------------===//

#include "llvm/BinaryFormat/MsgPackDocument.h"
#include "llvm/Support/YAMLTraits.h"

using namespace llvm;
using namespace msgpack;

namespace {

// Struct used to represent scalar node. (MapDocNode and ArrayDocNode already
// exist in MsgPackDocument.h.)
struct ScalarDocNode : DocNode {
  ScalarDocNode(DocNode N) : DocNode(N) {}

  /// Get the YAML tag for this ScalarDocNode. This normally returns ""; it only
  /// returns something else if the result of toString would be ambiguous, e.g.
  /// a string that parses as a number or boolean.
  StringRef getYAMLTag() const;
};

bool isJSONSchemaBoolLiteral(StringRef S) {
  return S == "true" || S == "false";
}

} // namespace

/// Convert this DocNode to a string, assuming it is scalar.
std::string DocNode::toString() const {
  std::string S;
  raw_string_ostream OS(S);
  switch (getKind()) {
  case msgpack::Type::String:
    OS << Raw;
    break;
  case msgpack::Type::Nil:
    break;
  case msgpack::Type::Boolean:
    OS << (Bool ? "true" : "false");
    break;
  case msgpack::Type::Int:
    OS << Int;
    break;
  case msgpack::Type::UInt:
    if (getDocument()->getHexMode())
      OS << format("%#llx", (unsigned long long)UInt);
    else
      OS << UInt;
    break;
  case msgpack::Type::Float:
    OS << Float;
    break;
  default:
    llvm_unreachable("not scalar");
    break;
  }
  return OS.str();
}

/// Convert the StringRef and use it to set this DocNode (assuming scalar). If
/// it is a string, copy the string into the Document's strings list so we do
/// not rely on S having a lifetime beyond this call. Tag is "" or a YAML tag.
StringRef DocNode::fromString(StringRef S, StringRef Tag) {
  if (Tag == "tag:yaml.org,2002:str")
    Tag = "";
  if (Tag == "!int" || Tag == "") {
    // Try unsigned int then signed int.
    *this = getDocument()->getNode(uint64_t(0));
    StringRef Err = yaml::ScalarTraits<uint64_t>::input(S, nullptr, getUInt());
    if (Err != "") {
      *this = getDocument()->getNode(int64_t(0));
      Err = yaml::ScalarTraits<int64_t>::input(S, nullptr, getInt());
    }
    if (Err == "" || Tag != "")
      return Err;
  }
  if (Tag == "!nil") {
    *this = getDocument()->getNode();
    return "";
  }
  if (Tag == "!bool") {
    *this = getDocument()->getNode(false);
    return yaml::ScalarTraits<bool>::input(S, nullptr, getBool());
  }
  // FIXME: This enforces the "JSON Schema" tag resolution for boolean literals,
  // defined at https://yaml.org/spec/1.2.2/#json-schema which we adopt because
  // the more general pre-1.2 resolution includes many common strings (e.g. "n",
  // "no", "y", "yes", ...). This should be handled at the YAMLTraits level, but
  // that change would have a much broader impact.
  if (Tag == "" && isJSONSchemaBoolLiteral(S)) {
    *this = getDocument()->getNode(S == "true");
    return "";
  }
  if (Tag == "!float" || Tag == "") {
    *this = getDocument()->getNode(0.0);
    StringRef Err = yaml::ScalarTraits<double>::input(S, nullptr, getFloat());
    if (Err == "" || Tag != "")
      return Err;
  }
  assert((Tag == "!str" || Tag == "") && "unsupported tag");
  std::string V;
  StringRef Err = yaml::ScalarTraits<std::string>::input(S, nullptr, V);
  if (Err == "")
    *this = getDocument()->getNode(V, /*Copy=*/true);
  return Err;
}

/// Get the YAML tag for this ScalarDocNode. This normally returns ""; it only
/// returns something else if the result of toString would be ambiguous, e.g.
/// a string that parses as a number or boolean.
StringRef ScalarDocNode::getYAMLTag() const {
  if (getKind() == msgpack::Type::Nil)
    return "!nil";
  // Try converting both ways and see if we get the same kind. If not, we need
  // a tag.
  ScalarDocNode N = getDocument()->getNode();
  N.fromString(toString(), "");
  if (N.getKind() == getKind())
    return "";
  // Tolerate signedness of int changing, as tags do not differentiate between
  // them anyway.
  if (N.getKind() == msgpack::Type::UInt && getKind() == msgpack::Type::Int)
    return "";
  if (N.getKind() == msgpack::Type::Int && getKind() == msgpack::Type::UInt)
    return "";
  // We do need a tag.
  switch (getKind()) {
  case msgpack::Type::String:
    return "!str";
  case msgpack::Type::Int:
    return "!int";
  case msgpack::Type::UInt:
    return "!int";
  case msgpack::Type::Boolean:
    return "!bool";
  case msgpack::Type::Float:
    return "!float";
  default:
    llvm_unreachable("unrecognized kind");
  }
}

namespace llvm {
namespace yaml {

/// YAMLIO for DocNode
template <> struct PolymorphicTraits<DocNode> {

  static NodeKind getKind(const DocNode &N) {
    switch (N.getKind()) {
    case msgpack::Type::Map:
      return NodeKind::Map;
    case msgpack::Type::Array:
      return NodeKind::Sequence;
    default:
      return NodeKind::Scalar;
    }
  }

  static MapDocNode &getAsMap(DocNode &N) { return N.getMap(/*Convert=*/true); }

  static ArrayDocNode &getAsSequence(DocNode &N) {
    N.getArray(/*Convert=*/true);
    return *static_cast<ArrayDocNode *>(&N);
  }

  static ScalarDocNode &getAsScalar(DocNode &N) {
    return *static_cast<ScalarDocNode *>(&N);
  }
};

/// YAMLIO for ScalarDocNode
template <> struct TaggedScalarTraits<ScalarDocNode> {

  static void output(const ScalarDocNode &S, void *Ctxt, raw_ostream &OS,
                     raw_ostream &TagOS) {
    TagOS << S.getYAMLTag();
    OS << S.toString();
  }

  static StringRef input(StringRef Str, StringRef Tag, void *Ctxt,
                         ScalarDocNode &S) {
    return S.fromString(Str, Tag);
  }

  static QuotingType mustQuote(const ScalarDocNode &S, StringRef ScalarStr) {
    switch (S.getKind()) {
    case Type::Int:
      return ScalarTraits<int64_t>::mustQuote(ScalarStr);
    case Type::UInt:
      return ScalarTraits<uint64_t>::mustQuote(ScalarStr);
    case Type::Nil:
      return ScalarTraits<StringRef>::mustQuote(ScalarStr);
    case Type::Boolean:
      return ScalarTraits<bool>::mustQuote(ScalarStr);
    case Type::Float:
      return ScalarTraits<double>::mustQuote(ScalarStr);
    case Type::Binary:
    case Type::String:
      return ScalarTraits<std::string>::mustQuote(ScalarStr);
    default:
      llvm_unreachable("unrecognized ScalarKind");
    }
  }
};

/// YAMLIO for MapDocNode
template <> struct CustomMappingTraits<MapDocNode> {

  static void inputOne(IO &IO, StringRef Key, MapDocNode &M) {
    ScalarDocNode KeyObj = M.getDocument()->getNode();
    KeyObj.fromString(Key, "");
    IO.mapRequired(Key, M.getMap()[KeyObj]);
  }

  static void output(IO &IO, MapDocNode &M) {
    for (auto I : M.getMap()) {
      IO.mapRequired(I.first.toString(), I.second);
    }
  }
};

/// YAMLIO for ArrayNode
template <> struct SequenceTraits<ArrayDocNode> {

  static size_t size(IO &IO, ArrayDocNode &A) { return A.size(); }

  static DocNode &element(IO &IO, ArrayDocNode &A, size_t Index) {
    return A[Index];
  }
};

} // namespace yaml
} // namespace llvm

/// Convert MsgPack Document to YAML text.
void msgpack::Document::toYAML(raw_ostream &OS) {
  yaml::Output Yout(OS);
  Yout << getRoot();
}

/// Read YAML text into the MsgPack document. Returns false on failure.
bool msgpack::Document::fromYAML(StringRef S) {
  clear();
  yaml::Input Yin(S);
  Yin >> getRoot();
  return !Yin.error();
}

