// Copyright 2017 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 <inttypes.h>
#include <lib/fidl/coding.h>
#include <lib/fidl/internal.h>
#include <stdarg.h>
#include <stdio.h>
#include <string.h>
#include <zircon/assert.h>
#include <zircon/compiler.h>

namespace {

class StringBuilder {
 public:
  StringBuilder(char* buffer, size_t capacity) : buffer_(buffer), capacity_(capacity) {}

  size_t length() const { return length_; }

  void Append(const char* data, size_t length) {
    size_t remaining = capacity_ - length_;
    if (length > remaining) {
      length = remaining;
    }
    memcpy(buffer_ + length_, data, length);
    length_ += length;
  }

  void Append(const char* data) { Append(data, strlen(data)); }

  void AppendPrintf(const char* format, ...) __PRINTFLIKE(2, 3) {
    va_list ap;
    va_start(ap, format);
    AppendVPrintf(format, ap);
    va_end(ap);
  }

  void AppendVPrintf(const char* format, va_list ap) {
    size_t remaining = capacity_ - length_;
    if (remaining == 0u) {
      return;
    }
    int count = vsnprintf(buffer_ + length_, remaining, format, ap);
    if (count <= 0) {
      return;
    }
    size_t length = static_cast<size_t>(count);
    length_ += (length >= remaining ? remaining : length);
  }

 private:
  char* buffer_;
  size_t capacity_;
  size_t length_ = 0u;
};

void FormatNullability(StringBuilder* str, FidlNullability nullable) {
  if (nullable == kFidlNullability_Nullable) {
    str->Append("?");
  }
}

void FormatEnumName(StringBuilder* str, const FidlCodedEnum* coded_enum) {
  if (coded_enum->name) {
    str->Append(coded_enum->name);
  } else {
    str->Append("enum");
  }
}

void FormatBitsName(StringBuilder* str, const FidlCodedBits* coded_bits) {
  if (coded_bits->name) {
    str->Append(coded_bits->name);
  } else {
    str->Append("bits");
  }
}

void FormatStructName(StringBuilder* str, const FidlCodedStruct* coded_struct) {
  if (coded_struct->name) {
    str->Append(coded_struct->name);
  } else {
    str->Append("struct");
  }
}

void FormatTableName(StringBuilder* str, const FidlCodedTable* coded_table) {
  if (coded_table->name) {
    str->Append(coded_table->name);
  } else {
    str->Append("table");
  }
}

void FormatXUnionName(StringBuilder* str, const FidlCodedXUnion* coded_xunion) {
  if (coded_xunion->name) {
    str->Append(coded_xunion->name);
  } else {
    str->Append("xunion");
  }
}

void FormatTypeName(StringBuilder* str, const fidl_type_t* type);
void FormatElementName(StringBuilder* str, const fidl_type_t* type) {
  if (type) {
    FormatTypeName(str, type);
  } else {
    // TODO(jeffbrown): Print the actual primitive type name, assuming we
    // start recording that information in the tables.
    str->Append("primitive");
  }
}

void FormatTypeName(StringBuilder* str, const fidl_type_t* type) {
  switch (type->type_tag()) {
    case kFidlTypeEnum:
      FormatEnumName(str, &type->coded_enum());
      break;
    case kFidlTypeBits:
      FormatBitsName(str, &type->coded_bits());
      break;
    case kFidlTypeStruct:
      FormatStructName(str, &type->coded_struct());
      break;
    case kFidlTypeStructPointer:
      FormatStructName(str, type->coded_struct_pointer().struct_type);
      str->Append("?");
      break;
    case kFidlTypeArray:
      str->Append("array<");
      FormatElementName(str, type->coded_array().element);
      str->Append(">");
      str->AppendPrintf(":%" PRIu32,
                        type->coded_array().array_size / type->coded_array().element_size);
      break;
    case kFidlTypeString:
      str->Append("string");
      if (type->coded_string().max_size != FIDL_MAX_SIZE) {
        str->AppendPrintf(":%" PRIu32, type->coded_string().max_size);
      }
      FormatNullability(str, type->coded_string().nullable);
      break;
    case kFidlTypeHandle:
      str->Append("handle");
      if (type->coded_handle().handle_subtype) {
        str->Append("<");
        switch (type->coded_handle().handle_subtype) {
          case ZX_OBJ_TYPE_NONE:
            str->Append("handle");
            break;
          case ZX_OBJ_TYPE_BTI:
            str->Append("bti");
            break;
          case ZX_OBJ_TYPE_CHANNEL:
            str->Append("channel");
            break;
          case ZX_OBJ_TYPE_CLOCK:
            str->Append("clock");
            break;
          case ZX_OBJ_TYPE_EVENT:
            str->Append("event");
            break;
          case ZX_OBJ_TYPE_EVENTPAIR:
            str->Append("eventpair");
            break;
          case ZX_OBJ_TYPE_EXCEPTION:
            str->Append("exception");
            break;
          case ZX_OBJ_TYPE_FIFO:
            str->Append("fifo");
            break;
          case ZX_OBJ_TYPE_GUEST:
            str->Append("guest");
            break;
          case ZX_OBJ_TYPE_INTERRUPT:
            str->Append("interrupt");
            break;
          case ZX_OBJ_TYPE_IOMMU:
            str->Append("iommu");
            break;
          case ZX_OBJ_TYPE_JOB:
            str->Append("job");
            break;
          case ZX_OBJ_TYPE_LOG:
            str->Append("log");
            break;
          case ZX_OBJ_TYPE_PAGER:
            str->Append("pager");
            break;
          case ZX_OBJ_TYPE_PCI_DEVICE:
            str->Append("pcidevice");
            break;
          case ZX_OBJ_TYPE_PMT:
            str->Append("pmt");
            break;
          case ZX_OBJ_TYPE_PORT:
            str->Append("port");
            break;
          case ZX_OBJ_TYPE_PROCESS:
            str->Append("process");
            break;
          case ZX_OBJ_TYPE_PROFILE:
            str->Append("profile");
            break;
          case ZX_OBJ_TYPE_RESOURCE:
            str->Append("resource");
            break;
          case ZX_OBJ_TYPE_SOCKET:
            str->Append("socket");
            break;
          case ZX_OBJ_TYPE_SUSPEND_TOKEN:
            str->Append("suspendtoken");
            break;
          case ZX_OBJ_TYPE_THREAD:
            str->Append("thread");
            break;
          case ZX_OBJ_TYPE_TIMER:
            str->Append("timer");
            break;
          case ZX_OBJ_TYPE_VCPU:
            str->Append("vcpu");
            break;
          case ZX_OBJ_TYPE_VMAR:
            str->Append("vmar");
            break;
          case ZX_OBJ_TYPE_VMO:
            str->Append("vmo");
            break;
          default:
            str->AppendPrintf("%" PRIu32, type->coded_handle().handle_subtype);
            break;
        }
        str->Append(">");
      }
      FormatNullability(str, type->coded_handle().nullable);
      break;
    case kFidlTypeVector:
      str->Append("vector<");
      FormatElementName(str, type->coded_vector().element);
      str->Append(">");
      if (type->coded_vector().max_count != FIDL_MAX_SIZE) {
        str->AppendPrintf(":%" PRIu32, type->coded_vector().max_count);
      }
      FormatNullability(str, type->coded_vector().nullable);
      break;
    case kFidlTypeTable:
      FormatTableName(str, &type->coded_table());
      break;
    case kFidlTypeXUnion:
      FormatXUnionName(str, &type->coded_xunion());
      break;
    case kFidlTypePrimitive:
      ZX_PANIC("unrecognized tag");
      break;
  }
}

}  // namespace

size_t fidl_format_type_name(const fidl_type_t* type, char* buffer, size_t capacity) {
  if (!type || !buffer || !capacity) {
    return 0u;
  }

  StringBuilder str(buffer, capacity);
  FormatTypeName(&str, type);
  return str.length();
}
