// Copyright 2016 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/trace-engine/fields.h>

#include <string_view>
#include <utility>

#include <fbl/string_printf.h>
#include <trace-reader/reader.h>

namespace trace {

TraceReader::TraceReader(RecordConsumer record_consumer, ErrorHandler error_handler)
    : record_consumer_(std::move(record_consumer)), error_handler_(std::move(error_handler)) {
  // Provider ids begin at 1. We don't have a provider yet but we want to
  // set the current provider. So set it to non-existent provider 0.
  RegisterProvider(0u, "");
}

bool TraceReader::ReadRecords(Chunk& chunk) {
  while (true) {
    if (!pending_header_ && !chunk.ReadUint64(&pending_header_))
      return true;  // need more data

    auto type = RecordFields::Type::Get<RecordType>(pending_header_);

    size_t size;
    if (type != RecordType::kLargeRecord) {
      size = RecordFields::RecordSize::Get<size_t>(pending_header_);
      ZX_DEBUG_ASSERT(size <= RecordFields::kMaxRecordSizeWords);
      static_assert(RecordFields::kMaxRecordSizeBytes <=
                    TRACE_ENCODED_INLINE_LARGE_RECORD_MAX_SIZE);
    } else {
      size = LargeBlobFields::RecordSize::Get<size_t>(pending_header_);
      ZX_DEBUG_ASSERT(size <= BytesToWords(TRACE_ENCODED_INLINE_LARGE_RECORD_MAX_SIZE));
    }
    if (size == 0) {
      ReportError("Unexpected record of size 0");
      return false;  // fatal error
    }

    // TODO(fxbug.dev/23072): Here we assume that the entire blob payload can
    // fit into the read buffer.
    Chunk record;
    if (!chunk.ReadChunk(size - 1, &record))
      return true;  // need more data to decode record

    switch (type) {
      case RecordType::kMetadata: {
        if (!ReadMetadataRecord(record, pending_header_)) {
          ReportError("Failed to read metadata record");
        }
        break;
      }
      case RecordType::kInitialization: {
        if (!ReadInitializationRecord(record, pending_header_)) {
          ReportError("Failed to read initialization record");
        }
        break;
      }
      case RecordType::kString: {
        if (!ReadStringRecord(record, pending_header_)) {
          ReportError("Failed to read string record");
        }
        break;
      }
      case RecordType::kThread: {
        if (!ReadThreadRecord(record, pending_header_)) {
          ReportError("Failed to read thread record");
        }
        break;
      }
      case RecordType::kEvent: {
        if (!ReadEventRecord(record, pending_header_)) {
          ReportError("Failed to read event record");
        }
        break;
      }
      case RecordType::kBlob: {
        void* ptr;
        if (!ReadBlobRecord(record, pending_header_, &ptr)) {
          ReportError("Failed to read blob record");
        }
        break;
      }
      case RecordType::kKernelObject: {
        if (!ReadKernelObjectRecord(record, pending_header_)) {
          ReportError("Failed to read kernel object record");
        }
        break;
      }
      case RecordType::kContextSwitch: {
        if (!ReadContextSwitchRecord(record, pending_header_)) {
          ReportError("Failed to read context switch record");
        }
        break;
      }
      case RecordType::kLog: {
        if (!ReadLogRecord(record, pending_header_)) {
          ReportError("Failed to read log record");
        }
        break;
      }
      case RecordType::kLargeRecord: {
        if (!ReadLargeRecord(record, pending_header_)) {
          ReportError("Failed to read large record");
        }
        break;
      }
      default: {
        // Ignore unknown record types for forward compatibility.
        ReportError(
            fbl::StringPrintf("Skipping record of unknown type %d", static_cast<uint32_t>(type)));
        break;
      }
    }
    pending_header_ = 0u;
  }
}

bool TraceReader::ReadMetadataRecord(Chunk& record, RecordHeader header) {
  auto type = MetadataRecordFields::MetadataType::Get<MetadataType>(header);

  switch (type) {
    case MetadataType::kProviderInfo: {
      auto id = ProviderInfoMetadataRecordFields::Id::Get<ProviderId>(header);
      auto name_length = ProviderInfoMetadataRecordFields::NameLength::Get<size_t>(header);
      std::string_view name_view;
      if (!record.ReadString(name_length, &name_view))
        return false;
      fbl::String name(name_view);

      RegisterProvider(id, name);
      record_consumer_(
          Record(Record::Metadata{MetadataContent(MetadataContent::ProviderInfo{id, name})}));
      break;
    }
    case MetadataType::kProviderSection: {
      auto id = ProviderSectionMetadataRecordFields::Id::Get<ProviderId>(header);

      SetCurrentProvider(id);
      record_consumer_(
          Record(Record::Metadata{MetadataContent(MetadataContent::ProviderSection{id})}));
      break;
    }
    case MetadataType::kProviderEvent: {
      auto id = ProviderEventMetadataRecordFields::Id::Get<ProviderId>(header);
      auto event = ProviderEventMetadataRecordFields::Event::Get<ProviderEventType>(header);
      switch (event) {
        case ProviderEventType::kBufferOverflow:
          record_consumer_(
              Record(Record::Metadata{MetadataContent(MetadataContent::ProviderEvent{id, event})}));
          break;
        default:
          // Ignore unknown event types for forward compatibility.
          ReportError(fbl::StringPrintf("Skipping provider event of unknown type %u",
                                        static_cast<unsigned>(event)));
          break;
      }
      break;
    }
    case MetadataType::kTraceInfo: {
      auto info_type = TraceInfoMetadataRecordFields::TraceInfoType::Get<TraceInfoType>(header);
      switch (info_type) {
        case TraceInfoType::kMagicNumber: {
          auto record_magic = MagicNumberRecordFields::Magic::Get<uint32_t>(header);
          record_consumer_(Record(Record::Metadata{MetadataContent(MetadataContent::TraceInfo{
              TraceInfoContent(TraceInfoContent::MagicNumberInfo{record_magic})})}));
          break;
        }
        default: {
          // Ignore unknown trace info types for forward compatibility.
          ReportError(fbl::StringPrintf("Skipping trace info record of unknown type %u",
                                        static_cast<unsigned>(info_type)));
          break;
        }
      }
      break;
    }
    default: {
      // Ignore unknown metadata types for forward compatibility.
      ReportError(
          fbl::StringPrintf("Skipping metadata of unknown type %d", static_cast<uint32_t>(type)));
      break;
    }
  }
  return true;
}

bool TraceReader::ReadInitializationRecord(Chunk& record, RecordHeader header) {
  trace_ticks_t ticks_per_second;
  if (!record.ReadUint64(&ticks_per_second) || !ticks_per_second)
    return false;

  record_consumer_(Record(Record::Initialization{ticks_per_second}));
  return true;
}

bool TraceReader::ReadStringRecord(Chunk& record, RecordHeader header) {
  auto index = StringRecordFields::StringIndex::Get<trace_string_index_t>(header);
  if (index < TRACE_ENCODED_STRING_REF_MIN_INDEX || index > TRACE_ENCODED_STRING_REF_MAX_INDEX) {
    ReportError("Invalid string index");
    return false;
  }

  auto length = StringRecordFields::StringLength::Get<size_t>(header);
  std::string_view string_view;
  if (!record.ReadString(length, &string_view))
    return false;
  fbl::String string(string_view);

  RegisterString(index, string);
  record_consumer_(Record(Record::String{index, std::move(string)}));
  return true;
}

bool TraceReader::ReadThreadRecord(Chunk& record, RecordHeader header) {
  auto index = ThreadRecordFields::ThreadIndex::Get<trace_thread_index_t>(header);
  if (index < TRACE_ENCODED_THREAD_REF_MIN_INDEX || index > TRACE_ENCODED_THREAD_REF_MAX_INDEX) {
    ReportError("Invalid thread index");
    return false;
  }

  zx_koid_t process_koid, thread_koid;
  if (!record.ReadUint64(&process_koid) || !record.ReadUint64(&thread_koid))
    return false;

  ProcessThread process_thread(process_koid, thread_koid);
  RegisterThread(index, process_thread);
  record_consumer_(Record(Record::Thread{index, process_thread}));
  return true;
}

bool TraceReader::ReadEventRecord(Chunk& record, RecordHeader header) {
  auto type = EventRecordFields::EventType::Get<EventType>(header);
  auto argument_count = EventRecordFields::ArgumentCount::Get<size_t>(header);
  auto thread_ref = EventRecordFields::ThreadRef::Get<trace_encoded_thread_ref_t>(header);
  auto category_ref = EventRecordFields::CategoryStringRef::Get<trace_encoded_string_ref_t>(header);
  auto name_ref = EventRecordFields::NameStringRef::Get<trace_encoded_string_ref_t>(header);

  trace_ticks_t timestamp;
  ProcessThread process_thread;
  fbl::String category;
  fbl::String name;
  fbl::Vector<Argument> arguments;
  if (!record.ReadUint64(&timestamp) || !DecodeThreadRef(record, thread_ref, &process_thread) ||
      !DecodeStringRef(record, category_ref, &category) ||
      !DecodeStringRef(record, name_ref, &name) ||
      !ReadArguments(record, argument_count, &arguments))
    return false;

  switch (type) {
    case EventType::kInstant: {
      uint64_t scope;
      if (!record.ReadUint64(&scope))
        return false;
      record_consumer_(Record(Record::Event{
          timestamp, process_thread, std::move(category), std::move(name), std::move(arguments),
          EventData(EventData::Instant{static_cast<EventScope>(scope)})}));
      break;
    }
    case EventType::kCounter: {
      trace_counter_id_t id;
      if (!record.ReadUint64(&id))
        return false;
      record_consumer_(
          Record(Record::Event{timestamp, process_thread, std::move(category), std::move(name),
                               std::move(arguments), EventData(EventData::Counter{id})}));
      break;
    }
    case EventType::kDurationBegin: {
      record_consumer_(
          Record(Record::Event{timestamp, process_thread, std::move(category), std::move(name),
                               std::move(arguments), EventData(EventData::DurationBegin{})}));
      break;
    }
    case EventType::kDurationEnd: {
      record_consumer_(
          Record(Record::Event{timestamp, process_thread, std::move(category), std::move(name),
                               std::move(arguments), EventData(EventData::DurationEnd{})}));
      break;
    }
    case EventType::kDurationComplete: {
      trace_ticks_t end_time;
      if (!record.ReadUint64(&end_time))
        return false;
      record_consumer_(Record(Record::Event{timestamp, process_thread, std::move(category),
                                            std::move(name), std::move(arguments),
                                            EventData(EventData::DurationComplete{end_time})}));
      break;
    }
    case EventType::kAsyncBegin: {
      trace_async_id_t id;
      if (!record.ReadUint64(&id))
        return false;
      record_consumer_(
          Record(Record::Event{timestamp, process_thread, std::move(category), std::move(name),
                               std::move(arguments), EventData(EventData::AsyncBegin{id})}));
      break;
    }
    case EventType::kAsyncInstant: {
      trace_async_id_t id;
      if (!record.ReadUint64(&id))
        return false;
      record_consumer_(
          Record(Record::Event{timestamp, process_thread, std::move(category), std::move(name),
                               std::move(arguments), EventData(EventData::AsyncInstant{id})}));
      break;
    }
    case EventType::kAsyncEnd: {
      trace_async_id_t id;
      if (!record.ReadUint64(&id))
        return false;
      record_consumer_(
          Record(Record::Event{timestamp, process_thread, std::move(category), std::move(name),
                               std::move(arguments), EventData(EventData::AsyncEnd{id})}));
      break;
    }
    case EventType::kFlowBegin: {
      trace_flow_id_t id;
      if (!record.ReadUint64(&id))
        return false;
      record_consumer_(
          Record(Record::Event{timestamp, process_thread, std::move(category), std::move(name),
                               std::move(arguments), EventData(EventData::FlowBegin{id})}));
      break;
    }
    case EventType::kFlowStep: {
      trace_flow_id_t id;
      if (!record.ReadUint64(&id))
        return false;
      record_consumer_(
          Record(Record::Event{timestamp, process_thread, std::move(category), std::move(name),
                               std::move(arguments), EventData(EventData::FlowStep{id})}));
      break;
    }
    case EventType::kFlowEnd: {
      trace_flow_id_t id;
      if (!record.ReadUint64(&id))
        return false;
      record_consumer_(
          Record(Record::Event{timestamp, process_thread, std::move(category), std::move(name),
                               std::move(arguments), EventData(EventData::FlowEnd{id})}));
      break;
    }
    default: {
      // Ignore unknown event types for forward compatibility.
      ReportError(
          fbl::StringPrintf("Skipping event of unknown type %d", static_cast<uint32_t>(type)));
      break;
    }
  }
  return true;
}

bool TraceReader::ReadBlobRecord(Chunk& record, RecordHeader header, void** out_blob) {
  auto blob_type = BlobRecordFields::BlobType::Get<trace_blob_type_t>(header);
  auto name_ref = BlobRecordFields::NameStringRef::Get<trace_encoded_string_ref_t>(header);
  auto blob_size = BlobRecordFields::BlobSize::Get<size_t>(header);
  fbl::String name;
  if (!DecodeStringRef(record, name_ref, &name))
    return false;
  const void* blob;
  auto blob_words = BytesToWords(blob_size);
  if (!record.ReadInPlace(blob_words, &blob))
    return false;

  record_consumer_(Record(Record::Blob{blob_type, name, blob, blob_size}));
  return true;
}

bool TraceReader::ReadKernelObjectRecord(Chunk& record, RecordHeader header) {
  auto object_type = KernelObjectRecordFields::ObjectType::Get<zx_obj_type_t>(header);
  auto name_ref = KernelObjectRecordFields::NameStringRef::Get<trace_encoded_string_ref_t>(header);
  auto argument_count = KernelObjectRecordFields::ArgumentCount::Get<size_t>(header);

  zx_koid_t koid;
  fbl::String name;
  fbl::Vector<Argument> arguments;
  if (!record.ReadUint64(&koid) || !DecodeStringRef(record, name_ref, &name) ||
      !ReadArguments(record, argument_count, &arguments))
    return false;

  record_consumer_(Record(Record::KernelObject{koid, object_type, name, std::move(arguments)}));
  return true;
}

bool TraceReader::ReadContextSwitchRecord(Chunk& record, RecordHeader header) {
  auto cpu_number = ContextSwitchRecordFields::CpuNumber::Get<trace_cpu_number_t>(header);
  auto outgoing_thread_state =
      ContextSwitchRecordFields::OutgoingThreadState::Get<ThreadState>(header);
  auto outgoing_thread_priority =
      ContextSwitchRecordFields::OutgoingThreadPriority::Get<trace_thread_priority_t>(header);
  auto incoming_thread_priority =
      ContextSwitchRecordFields::IncomingThreadPriority::Get<trace_thread_priority_t>(header);
  auto outgoing_thread_ref =
      ContextSwitchRecordFields::OutgoingThreadRef::Get<trace_encoded_thread_ref_t>(header);
  auto incoming_thread_ref =
      ContextSwitchRecordFields::IncomingThreadRef::Get<trace_encoded_thread_ref_t>(header);

  trace_ticks_t timestamp;
  ProcessThread outgoing_thread;
  ProcessThread incoming_thread;
  if (!record.ReadUint64(&timestamp) ||
      !DecodeThreadRef(record, outgoing_thread_ref, &outgoing_thread) ||
      !DecodeThreadRef(record, incoming_thread_ref, &incoming_thread))
    return false;

  record_consumer_(Record(
      Record::ContextSwitch{timestamp, cpu_number, outgoing_thread_state, outgoing_thread,
                            incoming_thread, outgoing_thread_priority, incoming_thread_priority}));
  return true;
}

bool TraceReader::ReadLogRecord(Chunk& record, RecordHeader header) {
  auto log_message_length = LogRecordFields::LogMessageLength::Get<uint16_t>(header);

  if (log_message_length > LogRecordFields::kMaxMessageLength)
    return false;

  auto thread_ref = LogRecordFields::ThreadRef::Get<trace_encoded_thread_ref_t>(header);
  trace_ticks_t timestamp;
  ProcessThread process_thread;
  std::string_view log_message;
  if (!record.ReadUint64(&timestamp) || !DecodeThreadRef(record, thread_ref, &process_thread) ||
      !record.ReadString(log_message_length, &log_message))
    return false;
  record_consumer_(Record(Record::Log{timestamp, process_thread, fbl::String(log_message)}));
  return true;
}

bool TraceReader::ReadLargeRecord(trace::Chunk& record, trace::RecordHeader header) {
  auto large_type = LargeRecordFields::LargeType::Get<LargeRecordType>(header);

  switch (large_type) {
    case LargeRecordType::kBlob:
      return ReadLargeBlob(record, header);
    default:
      ReportError(
          fbl::StringPrintf("Skipping unknown large record type %d", ToUnderlyingType(large_type)));
  }
  return true;
}

bool TraceReader::ReadLargeBlob(trace::Chunk& record, trace::RecordHeader header) {
  auto format_type = LargeBlobFields::BlobFormat::Get<trace_blob_format_t>(header);

  switch (format_type) {
    case TRACE_BLOB_FORMAT_EVENT: {
      uint64_t format_header;
      if (!record.ReadUint64(&format_header))
        return false;

      using Format = BlobFormatEventFields;
      auto category_ref = Format::CategoryStringRef::Get<trace_encoded_string_ref_t>(format_header);
      auto name_ref = Format::NameStringRef::Get<trace_encoded_string_ref_t>(format_header);
      auto argument_count = Format::ArgumentCount::Get<size_t>(format_header);
      auto thread_ref = Format::ThreadRef::Get<trace_encoded_thread_ref_t>(format_header);

      fbl::String category;
      fbl::String name;
      trace_ticks_t timestamp;
      ProcessThread process_thread;
      fbl::Vector<Argument> arguments;
      uint64_t blob_size;
      const void* blob;
      if (!DecodeStringRef(record, category_ref, &category) ||
          !DecodeStringRef(record, name_ref, &name) || !record.ReadUint64(&timestamp) ||
          !DecodeThreadRef(record, thread_ref, &process_thread) ||
          !ReadArguments(record, argument_count, &arguments) || !record.ReadUint64(&blob_size) ||
          !record.ReadInPlace(trace::BytesToWords(trace::Pad(blob_size)), &blob))
        return false;

      record_consumer_(Record(Record::Large(LargeRecordData::Blob(LargeRecordData::BlobEvent{
          std::move(category),
          std::move(name),
          timestamp,
          process_thread,
          std::move(arguments),
          blob,
          blob_size,
      }))));
      break;
    }
    case TRACE_BLOB_FORMAT_ATTACHMENT: {
      uint64_t format_header;
      if (!record.ReadUint64(&format_header))
        return false;

      using Format = BlobFormatAttachmentFields;
      auto category_ref = Format::CategoryStringRef::Get<trace_encoded_string_ref_t>(format_header);
      auto name_ref = Format::NameStringRef::Get<trace_encoded_string_ref_t>(format_header);

      fbl::String category;
      fbl::String name;
      uint64_t blob_size;
      const void* blob;
      if (!DecodeStringRef(record, category_ref, &category) ||
          !DecodeStringRef(record, name_ref, &name) || !record.ReadUint64(&blob_size) ||
          !record.ReadInPlace(trace::BytesToWords(trace::Pad(blob_size)), &blob))
        return false;

      record_consumer_(Record(Record::Large(LargeRecordData::Blob(LargeRecordData::BlobAttachment{
          std::move(category),
          std::move(name),
          blob,
          blob_size,
      }))));
      break;
    }
    default:
      ReportError(fbl::StringPrintf("Skipping unknown large blob record format %d",
                                    ToUnderlyingType(format_type)));
  }
  return true;
}

bool TraceReader::ReadArguments(Chunk& record, size_t count, fbl::Vector<Argument>* out_arguments) {
  while (count-- > 0) {
    ArgumentHeader header;
    if (!record.ReadUint64(&header)) {
      ReportError("Failed to read argument header");
      return false;
    }

    auto size = ArgumentFields::ArgumentSize::Get<size_t>(header);
    Chunk arg;
    if (!size || !record.ReadChunk(size - 1, &arg)) {
      ReportError("Invalid argument size");
      return false;
    }

    auto name_ref = ArgumentFields::NameRef::Get<trace_encoded_string_ref_t>(header);
    fbl::String name;
    if (!DecodeStringRef(arg, name_ref, &name)) {
      ReportError("Failed to read argument name");
      return false;
    }

    auto type = ArgumentFields::Type::Get<ArgumentType>(header);
    switch (type) {
      case ArgumentType::kNull: {
        out_arguments->push_back(Argument{std::move(name), ArgumentValue::MakeNull()});
        break;
      }
      case ArgumentType::kBool: {
        auto value = BoolArgumentFields::Value::Get<bool>(header);
        out_arguments->push_back(Argument{std::move(name), ArgumentValue::MakeBool(value)});
        break;
      }
      case ArgumentType::kInt32: {
        auto value = Int32ArgumentFields::Value::Get<int32_t>(header);
        out_arguments->push_back(Argument{std::move(name), ArgumentValue::MakeInt32(value)});
        break;
      }
      case ArgumentType::kUint32: {
        auto value = Uint32ArgumentFields::Value::Get<uint32_t>(header);
        out_arguments->push_back(Argument{std::move(name), ArgumentValue::MakeUint32(value)});
        break;
      }
      case ArgumentType::kInt64: {
        int64_t value;
        if (!arg.ReadInt64(&value)) {
          ReportError("Failed to read int64 argument value");
          return false;
        }
        out_arguments->push_back(Argument{std::move(name), ArgumentValue::MakeInt64(value)});
        break;
      }
      case ArgumentType::kUint64: {
        uint64_t value;
        if (!arg.ReadUint64(&value)) {
          ReportError("Failed to read uint64 argument value");
          return false;
        }
        out_arguments->push_back(Argument{std::move(name), ArgumentValue::MakeUint64(value)});
        break;
      }
      case ArgumentType::kDouble: {
        double value;
        if (!arg.ReadDouble(&value)) {
          ReportError("Failed to read double argument value");
          return false;
        }
        out_arguments->push_back(Argument{std::move(name), ArgumentValue::MakeDouble(value)});
        break;
      }
      case ArgumentType::kString: {
        auto string_ref = StringArgumentFields::Index::Get<trace_encoded_string_ref_t>(header);
        fbl::String value;
        if (!DecodeStringRef(arg, string_ref, &value)) {
          ReportError("Failed to read string argument value");
          return false;
        }
        out_arguments->push_back(
            Argument{std::move(name), ArgumentValue::MakeString(std::move(value))});
        break;
      }
      case ArgumentType::kPointer: {
        uint64_t value;
        if (!arg.ReadUint64(&value)) {
          ReportError("Failed to read pointer argument value");
          return false;
        }
        out_arguments->push_back(Argument{std::move(name), ArgumentValue::MakePointer(value)});
        break;
      }
      case ArgumentType::kKoid: {
        zx_koid_t value;
        if (!arg.ReadUint64(&value)) {
          ReportError("Failed to read koid argument value");
          return false;
        }
        out_arguments->push_back(Argument{std::move(name), ArgumentValue::MakeKoid(value)});
        break;
      }
      default: {
        // Ignore unknown argument types for forward compatibility.
        ReportError(fbl::StringPrintf("Skipping argument of unknown type %d, argument name %s",
                                      static_cast<uint32_t>(type), name.c_str()));
        break;
      }
    }
  }
  return true;
}

fbl::String TraceReader::GetProviderName(ProviderId id) const {
  auto it = providers_.find(id);
  if (it != providers_.end())
    return it->name;
  return fbl::String();
}

void TraceReader::SetCurrentProvider(ProviderId id) {
  auto it = providers_.find(id);
  if (it != providers_.end()) {
    current_provider_ = &*it;
    return;
  }
  ReportError(fbl::StringPrintf("Registering non-existent provider %u\n", id));
  RegisterProvider(id, "");
}

void TraceReader::RegisterProvider(ProviderId id, fbl::String name) {
  auto provider = std::make_unique<ProviderInfo>();
  provider->id = id;
  provider->name = name;
  current_provider_ = provider.get();

  providers_.insert_or_replace(std::move(provider));
}

void TraceReader::RegisterString(trace_string_index_t index, fbl::String string) {
  ZX_DEBUG_ASSERT(index >= TRACE_ENCODED_STRING_REF_MIN_INDEX &&
                  index <= TRACE_ENCODED_STRING_REF_MAX_INDEX);

  auto entry = std::make_unique<StringTableEntry>(index, string);
  current_provider_->string_table.insert_or_replace(std::move(entry));
}

void TraceReader::RegisterThread(trace_thread_index_t index, const ProcessThread& process_thread) {
  ZX_DEBUG_ASSERT(index >= TRACE_ENCODED_THREAD_REF_MIN_INDEX &&
                  index <= TRACE_ENCODED_THREAD_REF_MAX_INDEX);

  auto entry = std::make_unique<ThreadTableEntry>(index, process_thread);
  current_provider_->thread_table.insert_or_replace(std::move(entry));
}

bool TraceReader::DecodeStringRef(Chunk& chunk, trace_encoded_string_ref_t string_ref,
                                  fbl::String* out_string) const {
  if (string_ref == TRACE_ENCODED_STRING_REF_EMPTY) {
    out_string->clear();
    return true;
  }

  if (string_ref & TRACE_ENCODED_STRING_REF_INLINE_FLAG) {
    size_t length = string_ref & TRACE_ENCODED_STRING_REF_LENGTH_MASK;
    std::string_view string_view;
    if (length > TRACE_ENCODED_STRING_REF_MAX_LENGTH || !chunk.ReadString(length, &string_view)) {
      ReportError("Could not read inline string");
      return false;
    }
    *out_string = string_view;
    return true;
  }

  auto it = current_provider_->string_table.find(string_ref);
  if (it == current_provider_->string_table.end()) {
    ReportError("String ref not in table");
    return false;
  }
  *out_string = it->string;
  return true;
}

bool TraceReader::DecodeThreadRef(Chunk& chunk, trace_encoded_thread_ref_t thread_ref,
                                  ProcessThread* out_process_thread) const {
  if (thread_ref == TRACE_ENCODED_THREAD_REF_INLINE) {
    zx_koid_t process_koid, thread_koid;
    if (!chunk.ReadUint64(&process_koid) || !chunk.ReadUint64(&thread_koid)) {
      ReportError("Could not read inline process and thread");
      return false;
    }
    *out_process_thread = ProcessThread(process_koid, thread_koid);
    return true;
  }

  auto it = current_provider_->thread_table.find(thread_ref);
  if (it == current_provider_->thread_table.end()) {
    ReportError(fbl::StringPrintf("Thread ref 0x%x not in table", thread_ref));
    return false;
  }
  *out_process_thread = it->process_thread;
  return true;
}

void TraceReader::ReportError(fbl::String error) const {
  if (error_handler_)
    error_handler_(std::move(error));
}

Chunk::Chunk() : begin_(nullptr), current_(nullptr), end_(nullptr) {}

Chunk::Chunk(const uint64_t* begin, size_t num_words)
    : begin_(begin), current_(begin), end_(begin_ + num_words) {}

bool Chunk::ReadUint64(uint64_t* out_value) {
  if (current_ < end_) {
    *out_value = *current_++;
    return true;
  }
  return false;
}

bool Chunk::ReadInt64(int64_t* out_value) {
  if (current_ < end_) {
    *out_value = *reinterpret_cast<const int64_t*>(current_++);
    return true;
  }
  return false;
}

bool Chunk::ReadDouble(double* out_value) {
  if (current_ < end_) {
    *out_value = *reinterpret_cast<const double*>(current_++);
    return true;
  }
  return false;
}

bool Chunk::ReadChunk(size_t num_words, Chunk* out_chunk) {
  if (current_ + num_words > end_)
    return false;

  *out_chunk = Chunk(current_, num_words);
  current_ += num_words;
  return true;
}

bool Chunk::ReadString(size_t length, std::string_view* out_string) {
  auto num_words = BytesToWords(length);
  if (current_ + num_words > end_)
    return false;

  *out_string = std::string_view(reinterpret_cast<const char*>(current_), length);
  current_ += num_words;
  return true;
}

bool Chunk::ReadInPlace(size_t num_words, const void** out_ptr) {
  if (current_ + num_words > end_)
    return false;
  *out_ptr = current_;
  current_ += num_words;
  return true;
}

}  // namespace trace
