// Copyright 2021 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 <lib/fidl/cpp/wire/status.h>
#include <lib/fit/nullable.h>
#include <zircon/compiler.h>

#include <array>
#include <iostream>
#include <string>
#include <string_view>

namespace fidl {

namespace internal {

const char* const kErrorInvalidHeader = "invalid header";
const char* const kErrorUnknownTxId = "unknown txid";
const char* const kErrorUnknownOrdinal = "unknown ordinal";
const char* const kErrorTransport = "underlying transport I/O error";
const char* const kErrorChannelUnbound = "unbound endpoint";
const char* const kErrorWaitOneFailed = "failed waiting to read from endpoint";
const char* const kErrorSyncEventBufferTooSmall =
    "received a larger message than allowed by the events";
const char* const kErrorSyncEventUnhandledTransitionalEvent = "unhandled transitional event";
const char* const kCallerAllocatedBufferTooSmall =
    "buffer provided to caller-allocating flavor is too small";
const char* const kUnknownMethod = "server did not recognize this method";
const char* const kUnsupportedFrameworkError =
    "server sent a framework_err value that is not supported";

bool IsFatalErrorUniversal(fidl::Reason error) {
  switch (error) {
    case Reason::__DoNotUse:
    case Reason::kCanceledDueToOtherError:
    case Reason::kUnknownMethod:
    case Reason::kPendingTwoWayCallPreventsUnbind:
      // These are not concrete errors.
      __builtin_abort();
    case Reason::kUnbind:
    case Reason::kClose:
    case Reason::kPeerClosedWhileReading:
    case Reason::kDispatcherError:
    case Reason::kTransportError:
      return true;
    case Reason::kUnexpectedMessage:
    case Reason::kEncodeError:
    case Reason::kDecodeError:
    case Reason::kAbandonedAsyncReply:
      return false;
  }
}

fidl::Status ErrorFromUnbindInfo(fidl::UnbindInfo info) {
  // Depending on what kind of error caused teardown, we may want to propagate
  // the error to all other outstanding contexts.
  if (IsFatalErrorUniversal(info.reason())) {
    return info.ToError();
  }
  // These errors are specific to one call, whose corresponding context
  // would have been notified during |Dispatch| or making the call.
  return fidl::Status::Canceled(info);
}

fidl::OneWayStatus OneWayErrorFromUnbindInfo(fidl::UnbindInfo info) {
  fidl::Status error = ErrorFromUnbindInfo(info);
  if (error.is_peer_closed()) {
    return fidl::OneWayStatus{fidl::Status::Ok()};
  }
  return fidl::OneWayStatus{error};
}

}  // namespace internal

namespace {

constexpr const char* DescribeReason(Reason reason) {
  // The error descriptions are quite terse to save binary size.
  switch (reason) {
    case internal::kUninitializedReason:
      return nullptr;
    case Reason::kUnbind:
      return "user initiated unbind";
    case Reason::kClose:
      return "(server) user initiated close with epitaph";
    case Reason::kPendingTwoWayCallPreventsUnbind:
      return "pending two-way calls renders unbinding unsafe";
    case Reason::kCanceledDueToOtherError:
      return "being canceled by failure from another operation: ";
    case Reason::kPeerClosedWhileReading:
      return "peer closed";
    case Reason::kDispatcherError:
      return "dispatcher error";
    case Reason::kTransportError:
      return internal::kErrorTransport;
    case Reason::kEncodeError:
      return "encode error";
    case Reason::kDecodeError:
      return "decode error";
    case Reason::kUnexpectedMessage:
      return "unexpected message";
    case Reason::kUnknownMethod:
      return "unknown interaction";
    case Reason::kAbandonedAsyncReply:
      return "(server) async completer is discarded without a reply";
  }
}

// A buffer of 256 bytes is sufficient for all tested results.
// If the description exceeds this length at runtime,
// the output will be truncated.
// We can increase the size if necessary.
using StatusFormattingBuffer = std::array<char, 256>;

}  // namespace

Status Status::Canceled(UnbindInfo cause) {
  Status status = cause.ToError();
  // Universal errors should be directly passed instead of tucked under a nested error.
  ZX_DEBUG_ASSERT(!internal::IsFatalErrorUniversal(status.reason_));
  return Status(ZX_ERR_CANCELED, Reason::kCanceledDueToOtherError, status.reason_, status.error_);
}

[[nodiscard]] std::string Status::FormatDescription() const {
  StatusFormattingBuffer buf;
  size_t length = FormatImpl(&*buf.begin(), sizeof(buf), /* from_unbind_info */ false);
  return std::string(&*buf.begin(), length);
}

[[nodiscard]] const char* Status::lossy_description() const {
  // If an error string was explicitly specified, use that.
  if (error_) {
    return error_;
  }
  // Otherwise, derive an error from |reason_|.
  return reason_description();
}

[[nodiscard]] const char* Status::reason_description() const { return DescribeReason(reason_); }

[[nodiscard]] const char* Status::underlying_reason_description() const {
  ZX_DEBUG_ASSERT(underlying_reason_ != Reason::kCanceledDueToOtherError);
  return DescribeReason(underlying_reason_);
}

size_t Status::FormatImpl(char* destination, size_t length, bool from_unbind_info) const {
  ZX_ASSERT(length > 0);
  int num_would_write = 0;

  // We use |snprintf| since it minimizes allocation and is faster
  // than output streams.
  if (!from_unbind_info && status_ == ZX_OK && reason_ == internal::kUninitializedReason) {
    num_would_write = snprintf(destination, length, "FIDL success");
  } else {
    const char* prelude = from_unbind_info ? "FIDL endpoint was unbound" : "FIDL operation failed";

    const char* status_meaning = [&] {
      switch (reason_) {
        // This reason may only appear in an |UnbindInfo|.
        case Reason::kClose:
          ZX_DEBUG_ASSERT(from_unbind_info);
          return "status of sending epitaph";
        case Reason::kPeerClosedWhileReading:
          if (status_ != ZX_ERR_PEER_CLOSED) {
            return "epitaph";
          }
          break;
        default:
          break;
      }
      return "status";
    }();

    const char* detail_prefix = error_ ? ", detail: " : "";
    const char* detail = error_ ? error_ : "";

    const char* underlying_description = underlying_reason_description();
    if (!underlying_description) {
      underlying_description = "";
    }

#ifdef __Fuchsia__
    num_would_write = snprintf(destination, length, "%s due to %s%s, %s: %s (%d)%s%s", prelude,
                               reason_description(), underlying_description, status_meaning,
                               zx_status_get_string(status_), status_, detail_prefix, detail);
#else
    num_would_write =
        snprintf(destination, length, "%s due to %s%s, %s: %d%s%s", prelude, reason_description(),
                 underlying_description, status_meaning, status_, detail_prefix, detail);
#endif  // __Fuchsia__
  }

  ZX_ASSERT(num_would_write > 0);
  return static_cast<size_t>(num_would_write) >= length ? length - 1 : num_would_write;
}

std::ostream& operator<<(std::ostream& ostream, const Status& result) {
  StatusFormattingBuffer buf;
  size_t length = result.FormatImpl(&*buf.begin(), sizeof(buf), /* from_unbind_info */ false);
  ostream << std::string_view(&*buf.begin(), length);
  return ostream;
}

[[nodiscard]] std::string UnbindInfo::FormatDescription() const {
  StatusFormattingBuffer buf;
  size_t length = FormatImpl(&*buf.begin(), sizeof(buf), /* from_unbind_info */ true);
  return std::string(&*buf.begin(), length);
}

std::ostream& operator<<(std::ostream& ostream, const UnbindInfo& info) {
  StatusFormattingBuffer buf;
  size_t length = info.Status::FormatImpl(&*buf.begin(), sizeof(buf), /* from_unbind_info */ true);
  ostream << std::string_view(&*buf.begin(), length);
  return ostream;
}

size_t fidl::internal::DisplayError<fidl::Status>::Format(const fidl::Status& value,
                                                          char* destination, size_t capacity) {
  return value.FormatImpl(destination, capacity, false);
}

}  // namespace fidl
