text: #include <sstream>
  
  #include "emitterutils.h"
  #include "indentation.h"  // IWYU pragma: keep
  #include "yaml/emitter.h"
  #include "yaml/emitterdef.h"
  #include "yaml/emittermanip.h"
  #include "yaml/exceptions.h"  // IWYU pragma: keep
  
  namespace zeus::yaml {
  class Binary;
  struct _Null;
  
  Emitter::Emitter() : m_pState(new EmitterState), m_stream{} {}
  
  Emitter::Emitter(std::ostream& stream)
      : m_pState(new EmitterState), m_stream(stream) {}
  
  Emitter::~Emitter() = default;
  
  const char* Emitter::c_str() const { return m_stream.str(); }
  
  std::size_t Emitter::size() const { return m_stream.pos(); }
  
  // state checking
  bool Emitter::good() const { return m_pState->good(); }
  
  const std::string Emitter::GetLastError() const {
    return m_pState->GetLastError();
  }
  
  // global setters
  bool Emitter::SetOutputCharset(EMITTER_MANIP value) {
    return m_pState->SetOutputCharset(value, FmtScope::Global);
  }
  
  bool Emitter::SetStringFormat(EMITTER_MANIP value) {
    return m_pState->SetStringFormat(value, FmtScope::Global);
  }
  
  bool Emitter::SetBoolFormat(EMITTER_MANIP value) {
    bool ok = false;
    if (m_pState->SetBoolFormat(value, FmtScope::Global))
      ok = true;
    if (m_pState->SetBoolCaseFormat(value, FmtScope::Global))
      ok = true;
    if (m_pState->SetBoolLengthFormat(value, FmtScope::Global))
      ok = true;
    return ok;
  }
  
  bool Emitter::SetIntBase(EMITTER_MANIP value) {
    return m_pState->SetIntFormat(value, FmtScope::Global);
  }
  
  bool Emitter::SetSeqFormat(EMITTER_MANIP value) {
    return m_pState->SetFlowType(GroupType::Seq, value, FmtScope::Global);
  }
  
  bool Emitter::SetMapFormat(EMITTER_MANIP value) {
    bool ok = false;
    if (m_pState->SetFlowType(GroupType::Map, value, FmtScope::Global))
      ok = true;
    if (m_pState->SetMapKeyFormat(value, FmtScope::Global))
      ok = true;
    return ok;
  }
  
  bool Emitter::SetIndent(std::size_t n) {
    return m_pState->SetIndent(n, FmtScope::Global);
  }
  
  bool Emitter::SetPreCommentIndent(std::size_t n) {
    return m_pState->SetPreCommentIndent(n, FmtScope::Global);
  }
  
  bool Emitter::SetPostCommentIndent(std::size_t n) {
    return m_pState->SetPostCommentIndent(n, FmtScope::Global);
  }
  
  bool Emitter::SetFloatPrecision(std::size_t n) {
    return m_pState->SetFloatPrecision(n, FmtScope::Global);
  }
  
  bool Emitter::SetDoublePrecision(std::size_t n) {
    return m_pState->SetDoublePrecision(n, FmtScope::Global);
  }
  
  // SetLocalValue
  // . Either start/end a group, or set a modifier locally
  Emitter& Emitter::SetLocalValue(EMITTER_MANIP value) {
    if (!good())
      return *this;
  
    switch (value) {
      case BeginDoc:
        EmitBeginDoc();
        break;
      case EndDoc:
        EmitEndDoc();
        break;
      case BeginSeq:
        EmitBeginSeq();
        break;
      case EndSeq:
        EmitEndSeq();
        break;
      case BeginMap:
        EmitBeginMap();
        break;
      case EndMap:
        EmitEndMap();
        break;
      case Key:
      case Value:
        // deprecated (these can be deduced by the parity of nodes in a map)
        break;
      case TagByKind:
        EmitKindTag();
        break;
      case Newline:
        EmitNewline();
        break;
      default:
        m_pState->SetLocalValue(value);
        break;
    }
    return *this;
  }
  
  Emitter& Emitter::SetLocalIndent(const _Indent& indent) {
    m_pState->SetIndent(indent.value, FmtScope::Local);
    return *this;
  }
  
  Emitter& Emitter::SetLocalPrecision(const _Precision& precision) {
    if (precision.floatPrecision >= 0)
      m_pState->SetFloatPrecision(precision.floatPrecision, FmtScope::Local);
    if (precision.doublePrecision >= 0)
      m_pState->SetDoublePrecision(precision.doublePrecision, FmtScope::Local);
    return *this;
  }
  
  // EmitBeginDoc
  void Emitter::EmitBeginDoc() {
    if (!good())
      return;
  
    if (m_pState->CurGroupType() != GroupType::NoType) {
      m_pState->SetError("Unexpected begin document");
      return;
    }
  
    if (m_pState->HasAnchor() || m_pState->HasTag()) {
      m_pState->SetError("Unexpected begin document");
      return;
    }
  
    if (m_stream.col() > 0)
      m_stream << "\n";
    m_stream << "---\n";
  
    m_pState->StartedDoc();
  }
  
  // EmitEndDoc
  void Emitter::EmitEndDoc() {
    if (!good())
      return;
  
    if (m_pState->CurGroupType() != GroupType::NoType) {
      m_pState->SetError("Unexpected begin document");
      return;
    }
  
    if (m_pState->HasAnchor() || m_pState->HasTag()) {
      m_pState->SetError("Unexpected begin document");
      return;
    }
  
    if (m_stream.col() > 0)
      m_stream << "\n";
    m_stream << "...\n";
  }
  
  // EmitBeginSeq
  void Emitter::EmitBeginSeq() {
    if (!good())
      return;
  
    PrepareNode(m_pState->NextGroupType(GroupType::Seq));
  
    m_pState->StartedGroup(GroupType::Seq);
  }
  
  // EmitEndSeq
  void Emitter::EmitEndSeq() {
    if (!good())
      return;
  
    if (m_pState->CurGroupChildCount() == 0)
      m_pState->ForceFlow();
  
    if (m_pState->CurGroupFlowType() == FlowType::Flow) {
      if (m_stream.comment())
        m_stream << "\n";
      m_stream << IndentTo(m_pState->CurIndent());
      if (m_pState->CurGroupChildCount() == 0)
        m_stream << "[";
      m_stream << "]";
    }
  
    m_pState->EndedGroup(GroupType::Seq);
  }
  
  // EmitBeginMap
  void Emitter::EmitBeginMap() {
    if (!good())
      return;
  
    PrepareNode(m_pState->NextGroupType(GroupType::Map));
  
    m_pState->StartedGroup(GroupType::Map);
  }
  
  // EmitEndMap
  void Emitter::EmitEndMap() {
    if (!good())
      return;
  
    if (m_pState->CurGroupChildCount() == 0)
      m_pState->ForceFlow();
  
    if (m_pState->CurGroupFlowType() == FlowType::Flow) {
      if (m_stream.comment())
        m_stream << "\n";
      m_stream << IndentTo(m_pState->CurIndent());
      if (m_pState->CurGroupChildCount() == 0)
        m_stream << "{";
      m_stream << "}";
    }
  
    m_pState->EndedGroup(GroupType::Map);
  }
  
  // EmitNewline
  void Emitter::EmitNewline() {
    if (!good())
      return;
  
    PrepareNode(EmitterNodeType::NoType);
    m_stream << "\n";
    m_pState->SetNonContent();
  }
  
  bool Emitter::CanEmitNewline() const { return true; }
  
  // Put the stream in a state so we can simply write the next node
  // E.g., if we're in a sequence, write the "- "
  void Emitter::PrepareNode(EmitterNodeType::value child) {
    switch (m_pState->CurGroupNodeType()) {
      case EmitterNodeType::NoType:
        PrepareTopNode(child);
        break;
      case EmitterNodeType::FlowSeq:
        FlowSeqPrepareNode(child);
        break;
      case EmitterNodeType::BlockSeq:
        BlockSeqPrepareNode(child);
        break;
      case EmitterNodeType::FlowMap:
        FlowMapPrepareNode(child);
        break;
      case EmitterNodeType::BlockMap:
        BlockMapPrepareNode(child);
        break;
      case EmitterNodeType::Property:
      case EmitterNodeType::Scalar:
        assert(false);
        break;
    }
  }
  
  void Emitter::PrepareTopNode(EmitterNodeType::value child) {
    if (child == EmitterNodeType::NoType)
      return;
  
    if (m_pState->CurGroupChildCount() > 0 && m_stream.col() > 0)
      EmitBeginDoc();
  
    switch (child) {
      case EmitterNodeType::NoType:
        break;
      case EmitterNodeType::Property:
      case EmitterNodeType::Scalar:
      case EmitterNodeType::FlowSeq:
      case EmitterNodeType::FlowMap:
        // TODO: if we were writing null, and
        // we wanted it blank, we wouldn't want a space
        SpaceOrIndentTo(m_pState->HasBegunContent(), 0);
        break;
      case EmitterNodeType::BlockSeq:
      case EmitterNodeType::BlockMap:
        if (m_pState->HasBegunNode())
          m_stream << "\n";
        break;
    }
  }
  
  void Emitter::FlowSeqPrepareNode(EmitterNodeType::value child) {
    const std::size_t lastIndent = m_pState->LastIndent();
  
    if (!m_pState->HasBegunNode()) {
      if (m_stream.comment())
        m_stream << "\n";
      m_stream << IndentTo(lastIndent);
      if (m_pState->CurGroupChildCount() == 0)
        m_stream << "[";
      else
        m_stream << ",";
    }
  
    switch (child) {
      case EmitterNodeType::NoType:
        break;
      case EmitterNodeType::Property:
      case EmitterNodeType::Scalar:
      case EmitterNodeType::FlowSeq:
      case EmitterNodeType::FlowMap:
        SpaceOrIndentTo(
            m_pState->HasBegunContent() || m_pState->CurGroupChildCount() > 0,
            lastIndent);
        break;
      case EmitterNodeType::BlockSeq:
      case EmitterNodeType::BlockMap:
        assert(false);
        break;
    }
  }
  
  void Emitter::BlockSeqPrepareNode(EmitterNodeType::value child) {
    const std::size_t curIndent = m_pState->CurIndent();
    const std::size_t nextIndent = curIndent + m_pState->CurGroupIndent();
  
    if (child == EmitterNodeType::NoType)
      return;
  
    if (!m_pState->HasBegunContent()) {
      if (m_pState->CurGroupChildCount() > 0 || m_stream.comment()) {
        m_stream << "\n";
      }
      m_stream << IndentTo(curIndent);
      m_stream << "-";
    }
  
    switch (child) {
      case EmitterNodeType::NoType:
        break;
      case EmitterNodeType::Property:
      case EmitterNodeType::Scalar:
      case EmitterNodeType::FlowSeq:
      case EmitterNodeType::FlowMap:
        SpaceOrIndentTo(m_pState->HasBegunContent(), nextIndent);
        break;
      case EmitterNodeType::BlockSeq:
        m_stream << "\n";
        break;
      case EmitterNodeType::BlockMap:
        if (m_pState->HasBegunContent() || m_stream.comment())
          m_stream << "\n";
        break;
    }
  }
  
  void Emitter::FlowMapPrepareNode(EmitterNodeType::value child) {
    if (m_pState->CurGroupChildCount() % 2 == 0) {
      if (m_pState->GetMapKeyFormat() == LongKey)
        m_pState->SetLongKey();
  
      if (m_pState->CurGroupLongKey())
        FlowMapPrepareLongKey(child);
      else
        FlowMapPrepareSimpleKey(child);
    } else {
      if (m_pState->CurGroupLongKey())
        FlowMapPrepareLongKeyValue(child);
      else
        FlowMapPrepareSimpleKeyValue(child);
    }
  }
  
  void Emitter::FlowMapPrepareLongKey(EmitterNodeType::value child) {
    const std::size_t lastIndent = m_pState->LastIndent();
  
    if (!m_pState->HasBegunNode()) {
      if (m_stream.comment())
        m_stream << "\n";
      m_stream << IndentTo(lastIndent);
      if (m_pState->CurGroupChildCount() == 0)
        m_stream << "{ ?";
      else
        m_stream << ", ?";
    }
  
    switch (child) {
      case EmitterNodeType::NoType:
        break;
      case EmitterNodeType::Property:
      case EmitterNodeType::Scalar:
      case EmitterNodeType::FlowSeq:
      case EmitterNodeType::FlowMap:
        SpaceOrIndentTo(
            m_pState->HasBegunContent() || m_pState->CurGroupChildCount() > 0,
            lastIndent);
        break;
      case EmitterNodeType::BlockSeq:
      case EmitterNodeType::BlockMap:
        assert(false);
        break;
    }
  }
  
  void Emitter::FlowMapPrepareLongKeyValue(EmitterNodeType::value child) {
    const std::size_t lastIndent = m_pState->LastIndent();
  
    if (!m_pState->HasBegunNode()) {
      if (m_stream.comment())
        m_stream << "\n";
      m_stream << IndentTo(lastIndent);
      m_stream << ":";
    }
  
    switch (child) {
      case EmitterNodeType::NoType:
        break;
      case EmitterNodeType::Property:
      case EmitterNodeType::Scalar:
      case EmitterNodeType::FlowSeq:
      case EmitterNodeType::FlowMap:
        SpaceOrIndentTo(
            m_pState->HasBegunContent() || m_pState->CurGroupChildCount() > 0,
            lastIndent);
        break;
      case EmitterNodeType::BlockSeq:
      case EmitterNodeType::BlockMap:
        assert(false);
        break;
    }
  }
  
  void Emitter::FlowMapPrepareSimpleKey(EmitterNodeType::value child) {
    const std::size_t lastIndent = m_pState->LastIndent();
  
    if (!m_pState->HasBegunNode()) {
      if (m_stream.comment())
        m_stream << "\n";
      m_stream << IndentTo(lastIndent);
      if (m_pState->CurGroupChildCount() == 0)
        m_stream << "{";
      else
        m_stream << ",";
    }
  
    switch (child) {
      case EmitterNodeType::NoType:
        break;
      case EmitterNodeType::Property:
      case EmitterNodeType::Scalar:
      case EmitterNodeType::FlowSeq:
      case EmitterNodeType::FlowMap:
        SpaceOrIndentTo(
            m_pState->HasBegunContent() || m_pState->CurGroupChildCount() > 0,
            lastIndent);
        break;
      case EmitterNodeType::BlockSeq:
      case EmitterNodeType::BlockMap:
        assert(false);
        break;
    }
  }
  
  void Emitter::FlowMapPrepareSimpleKeyValue(EmitterNodeType::value child) {
    const std::size_t lastIndent = m_pState->LastIndent();
  
    if (!m_pState->HasBegunNode()) {
      if (m_stream.comment())
        m_stream << "\n";
      m_stream << IndentTo(lastIndent);
      m_stream << ":";
    }
  
    switch (child) {
      case EmitterNodeType::NoType:
        break;
      case EmitterNodeType::Property:
      case EmitterNodeType::Scalar:
      case EmitterNodeType::FlowSeq:
      case EmitterNodeType::FlowMap:
        SpaceOrIndentTo(
            m_pState->HasBegunContent() || m_pState->CurGroupChildCount() > 0,
            lastIndent);
        break;
      case EmitterNodeType::BlockSeq:
      case EmitterNodeType::BlockMap:
        assert(false);
        break;
    }
  }
  
  void Emitter::BlockMapPrepareNode(EmitterNodeType::value child) {
    if (m_pState->CurGroupChildCount() % 2 == 0) {
      if (m_pState->GetMapKeyFormat() == LongKey)
        m_pState->SetLongKey();
      if (child == EmitterNodeType::BlockSeq ||
          child == EmitterNodeType::BlockMap)
        m_pState->SetLongKey();
  
      if (m_pState->CurGroupLongKey())
        BlockMapPrepareLongKey(child);
      else
        BlockMapPrepareSimpleKey(child);
    } else {
      if (m_pState->CurGroupLongKey())
        BlockMapPrepareLongKeyValue(child);
      else
        BlockMapPrepareSimpleKeyValue(child);
    }
  }
  
  void Emitter::BlockMapPrepareLongKey(EmitterNodeType::value child) {
    const std::size_t curIndent = m_pState->CurIndent();
    const std::size_t childCount = m_pState->CurGroupChildCount();
  
    if (child == EmitterNodeType::NoType)
      return;
  
    if (!m_pState->HasBegunContent()) {
      if (childCount > 0) {
        m_stream << "\n";
      }
      if (m_stream.comment()) {
        m_stream << "\n";
      }
      m_stream << IndentTo(curIndent);
      m_stream << "?";
    }
  
    switch (child) {
      case EmitterNodeType::NoType:
        break;
      case EmitterNodeType::Property:
      case EmitterNodeType::Scalar:
      case EmitterNodeType::FlowSeq:
      case EmitterNodeType::FlowMap:
        SpaceOrIndentTo(true, curIndent + 1);
        break;
      case EmitterNodeType::BlockSeq:
      case EmitterNodeType::BlockMap:
        break;
    }
  }
  
  void Emitter::BlockMapPrepareLongKeyValue(EmitterNodeType::value child) {
    const std::size_t curIndent = m_pState->CurIndent();
  
    if (child == EmitterNodeType::NoType)
      return;
  
    if (!m_pState->HasBegunContent()) {
      m_stream << "\n";
      m_stream << IndentTo(curIndent);
      m_stream << ":";
    }
  
    switch (child) {
      case EmitterNodeType::NoType:
        break;
      case EmitterNodeType::Property:
      case EmitterNodeType::Scalar:
      case EmitterNodeType::FlowSeq:
      case EmitterNodeType::FlowMap:
      case EmitterNodeType::BlockSeq:
      case EmitterNodeType::BlockMap:
        SpaceOrIndentTo(true, curIndent + 1);
        break;
    }
  }
  
  void Emitter::BlockMapPrepareSimpleKey(EmitterNodeType::value child) {
    const std::size_t curIndent = m_pState->CurIndent();
    const std::size_t childCount = m_pState->CurGroupChildCount();
  
    if (child == EmitterNodeType::NoType)
      return;
  
    if (!m_pState->HasBegunNode()) {
      if (childCount > 0) {
        m_stream << "\n";
      }
    }
  
    switch (child) {
      case EmitterNodeType::NoType:
        break;
      case EmitterNodeType::Property:
      case EmitterNodeType::Scalar:
      case EmitterNodeType::FlowSeq:
      case EmitterNodeType::FlowMap:
        SpaceOrIndentTo(m_pState->HasBegunContent(), curIndent);
        break;
      case EmitterNodeType::BlockSeq:
      case EmitterNodeType::BlockMap:
        break;
    }
  }
  
  void Emitter::BlockMapPrepareSimpleKeyValue(EmitterNodeType::value child) {
    const std::size_t curIndent = m_pState->CurIndent();
    const std::size_t nextIndent = curIndent + m_pState->CurGroupIndent();
  
    if (!m_pState->HasBegunNode()) {
      m_stream << ":";
    }
  
    switch (child) {
      case EmitterNodeType::NoType:
        break;
      case EmitterNodeType::Property:
      case EmitterNodeType::Scalar:
      case EmitterNodeType::FlowSeq:
      case EmitterNodeType::FlowMap:
        SpaceOrIndentTo(true, nextIndent);
        break;
      case EmitterNodeType::BlockSeq:
      case EmitterNodeType::BlockMap:
        m_stream << "\n";
        break;
    }
  }
  
  // SpaceOrIndentTo
  // . Prepares for some more content by proper spacing
  void Emitter::SpaceOrIndentTo(bool requireSpace, std::size_t indent) {
    if (m_stream.comment())
      m_stream << "\n";
    if (m_stream.col() > 0 && requireSpace)
      m_stream << " ";
    m_stream << IndentTo(indent);
  }
  
  void Emitter::PrepareIntegralStream(std::stringstream& stream) const {
  
    switch (m_pState->GetIntFormat()) {
      case Dec:
        stream << std::dec;
        break;
      case Hex:
        stream << "0x";
        stream << std::hex;
        break;
      case Oct:
        stream << "0";
        stream << std::oct;
        break;
      default:
        assert(false);
    }
  }
  
  void Emitter::StartedScalar() { m_pState->StartedScalar(); }
  
  // *******************************************************************************************
  // overloads of Write
  
  Emitter& Emitter::Write(const std::string& str) {
    if (!good())
      return *this;
  
    const bool escapeNonAscii = m_pState->GetOutputCharset() == EscapeNonAscii;
    const StringFormat::value strFormat =
        Utils::ComputeStringFormat(str, m_pState->GetStringFormat(),
                                   m_pState->CurGroupFlowType(), escapeNonAscii);
  
    if (strFormat == StringFormat::Literal)
      m_pState->SetMapKeyFormat(zeus::yaml::LongKey, FmtScope::Local);
  
    PrepareNode(EmitterNodeType::Scalar);
  
    switch (strFormat) {
      case StringFormat::Plain:
        m_stream << str;
        break;
      case StringFormat::SingleQuoted:
        Utils::WriteSingleQuotedString(m_stream, str);
        break;
      case StringFormat::DoubleQuoted:
        Utils::WriteDoubleQuotedString(m_stream, str, escapeNonAscii);
        break;
      case StringFormat::Literal:
        Utils::WriteLiteralString(m_stream, str,
                                  m_pState->CurIndent() + m_pState->GetIndent());
        break;
    }
  
    StartedScalar();
  
    return *this;
  }
  
  std::size_t Emitter::GetFloatPrecision() const {
    return m_pState->GetFloatPrecision();
  }
  
  std::size_t Emitter::GetDoublePrecision() const {
    return m_pState->GetDoublePrecision();
  }
  
  const char* Emitter::ComputeFullBoolName(bool b) const {
    const EMITTER_MANIP mainFmt = (m_pState->GetBoolLengthFormat() == ShortBool
                                       ? YesNoBool
                                       : m_pState->GetBoolFormat());
    const EMITTER_MANIP caseFmt = m_pState->GetBoolCaseFormat();
    switch (mainFmt) {
      case YesNoBool:
        switch (caseFmt) {
          case UpperCase:
            return b ? "YES" : "NO";
          case CamelCase:
            return b ? "Yes" : "No";
          case LowerCase:
            return b ? "yes" : "no";
          default:
            break;
        }
        break;
      case OnOffBool:
        switch (caseFmt) {
          case UpperCase:
            return b ? "ON" : "OFF";
          case CamelCase:
            return b ? "On" : "Off";
          case LowerCase:
            return b ? "on" : "off";
          default:
            break;
        }
        break;
      case TrueFalseBool:
        switch (caseFmt) {
          case UpperCase:
            return b ? "TRUE" : "FALSE";
          case CamelCase:
            return b ? "True" : "False";
          case LowerCase:
            return b ? "true" : "false";
          default:
            break;
        }
        break;
      default:
        break;
    }
    return b ? "y" : "n";  // should never get here, but it can't hurt to give
                           // these answers
  }
  
  Emitter& Emitter::Write(bool b) {
    if (!good())
      return *this;
  
    PrepareNode(EmitterNodeType::Scalar);
  
    const char* name = ComputeFullBoolName(b);
    if (m_pState->GetBoolLengthFormat() == ShortBool)
      m_stream << name[0];
    else
      m_stream << name;
  
    StartedScalar();
  
    return *this;
  }
  
  Emitter& Emitter::Write(char ch) {
    if (!good())
      return *this;
  
    PrepareNode(EmitterNodeType::Scalar);
    Utils::WriteChar(m_stream, ch);
    StartedScalar();
  
    return *this;
  }
  
  Emitter& Emitter::Write(const _Alias& alias) {
    if (!good())
      return *this;
  
    if (m_pState->HasAnchor() || m_pState->HasTag()) {
      m_pState->SetError(ErrorMsg::INVALID_ALIAS);
      return *this;
    }
  
    PrepareNode(EmitterNodeType::Scalar);
  
    if (!Utils::WriteAlias(m_stream, alias.content)) {
      m_pState->SetError(ErrorMsg::INVALID_ALIAS);
      return *this;
    }
  
    StartedScalar();
  
    return *this;
  }
  
  Emitter& Emitter::Write(const _Anchor& anchor) {
    if (!good())
      return *this;
  
    if (m_pState->HasAnchor()) {
      m_pState->SetError(ErrorMsg::INVALID_ANCHOR);
      return *this;
    }
  
    PrepareNode(EmitterNodeType::Property);
  
    if (!Utils::WriteAnchor(m_stream, anchor.content)) {
      m_pState->SetError(ErrorMsg::INVALID_ANCHOR);
      return *this;
    }
  
    m_pState->SetAnchor();
  
    return *this;
  }
  
  Emitter& Emitter::Write(const _Tag& tag) {
    if (!good())
      return *this;
  
    if (m_pState->HasTag()) {
      m_pState->SetError(ErrorMsg::INVALID_TAG);
      return *this;
    }
  
    PrepareNode(EmitterNodeType::Property);
  
    bool success = false;
    if (tag.type == _Tag::Type::Verbatim)
      success = Utils::WriteTag(m_stream, tag.content, true);
    else if (tag.type == _Tag::Type::PrimaryHandle)
      success = Utils::WriteTag(m_stream, tag.content, false);
    else
      success = Utils::WriteTagWithPrefix(m_stream, tag.prefix, tag.content);
  
    if (!success) {
      m_pState->SetError(ErrorMsg::INVALID_TAG);
      return *this;
    }
  
    m_pState->SetTag();
  
    return *this;
  }
  
  void Emitter::EmitKindTag() { Write(LocalTag("")); }
  
  Emitter& Emitter::Write(const _Comment& comment) {
    if (!good())
      return *this;
  
    PrepareNode(EmitterNodeType::NoType);
  
    if (m_stream.col() > 0)
      m_stream << Indentation(m_pState->GetPreCommentIndent());
    Utils::WriteComment(m_stream, comment.content,
                        m_pState->GetPostCommentIndent());
  
    m_pState->SetNonContent();
  
    return *this;
  }
  
  Emitter& Emitter::Write(const _Null& /*null*/) {
    if (!good())
      return *this;
  
    PrepareNode(EmitterNodeType::Scalar);
  
    m_stream << "~";
  
    StartedScalar();
  
    return *this;
  }
  
  Emitter& Emitter::Write(const Binary& binary) {
    Write(SecondaryTag("binary"));
  
    if (!good())
      return *this;
  
    PrepareNode(EmitterNodeType::Scalar);
    Utils::WriteBinary(m_stream, binary);
    StartedScalar();
  
    return *this;
  }
  }  // namespace zeus::yaml
  