// Copyright (c) 2023 The Chromium 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 "quiche/quic/moqt/moqt_framer.h"

#include <algorithm>
#include <cstddef>
#include <cstdint>
#include <cstdlib>
#include <optional>
#include <string>
#include <utility>
#include <variant>

#include "absl/container/fixed_array.h"
#include "absl/functional/overload.h"
#include "absl/status/status.h"
#include "absl/status/statusor.h"
#include "absl/strings/string_view.h"
#include "absl/types/span.h"
#include "quiche/quic/core/quic_time.h"
#include "quiche/quic/moqt/moqt_error.h"
#include "quiche/quic/moqt/moqt_key_value_pair.h"
#include "quiche/quic/moqt/moqt_messages.h"
#include "quiche/quic/moqt/moqt_names.h"
#include "quiche/quic/moqt/moqt_object.h"
#include "quiche/quic/moqt/moqt_priority.h"
#include "quiche/quic/moqt/moqt_types.h"
#include "quiche/common/platform/api/quiche_bug_tracker.h"
#include "quiche/common/platform/api/quiche_logging.h"
#include "quiche/common/quiche_buffer_allocator.h"
#include "quiche/common/quiche_data_writer.h"
#include "quiche/common/simple_buffer_allocator.h"
#include "quiche/common/wire_serialization.h"

namespace moqt {

namespace {

using ::quiche::QuicheBuffer;
using ::quiche::WireBytes;
using ::quiche::WireMoqVarInt;
using ::quiche::WireOptional;
using ::quiche::WireSpan;
using ::quiche::WireStringWithMoqVarIntLength;
using ::quiche::WireUint8;

class WireKeyVarIntPair {
 public:
  explicit WireKeyVarIntPair(uint64_t key, uint64_t value)
      : key_(key), value_(value) {}

  size_t GetLengthOnWire() {
    return quiche::ComputeLengthOnWire(WireMoqVarInt(key_),
                                       WireMoqVarInt(value_));
  }
  absl::Status SerializeIntoWriter(quiche::QuicheDataWriter& writer) {
    return quiche::SerializeIntoWriter(writer, WireMoqVarInt(key_),
                                       WireMoqVarInt(value_));
  }

 private:
  const uint64_t key_;
  const uint64_t value_;
};

class WireKeyStringPair {
 public:
  explicit WireKeyStringPair(uint64_t key, absl::string_view value)
      : key_(key), value_(value) {}
  size_t GetLengthOnWire() {
    return quiche::ComputeLengthOnWire(WireMoqVarInt(key_),
                                       WireStringWithMoqVarIntLength(value_));
  }
  absl::Status SerializeIntoWriter(quiche::QuicheDataWriter& writer) {
    return quiche::SerializeIntoWriter(writer, WireMoqVarInt(key_),
                                       WireStringWithMoqVarIntLength(value_));
  }

 private:
  const uint64_t key_;
  const absl::string_view value_;
};

class WireKeyValuePairList {
 public:
  explicit WireKeyValuePairList(const KeyValuePairList& list,
                                bool length_prefix = true)
      : list_(list), length_prefix_(length_prefix) {}

  size_t GetLengthOnWire() {
    size_t total =
        length_prefix_ ? WireMoqVarInt(list_.size()).GetLengthOnWire() : 0;
    uint64_t last_key = 0;
    list_.ForEach([&](uint64_t key,
                      std::variant<uint64_t, absl::string_view> value) {
      total += std::visit(
          absl::Overload{
              [&](uint64_t val) {
                return WireKeyVarIntPair(key - last_key, val).GetLengthOnWire();
              },
              [&](absl::string_view val) {
                return WireKeyStringPair(key - last_key, val).GetLengthOnWire();
              }},
          value);
      last_key = key;
      return true;
    });
    return total;
  }
  absl::Status SerializeIntoWriter(quiche::QuicheDataWriter& writer) {
    if (length_prefix_) {
      WireMoqVarInt(list_.size()).SerializeIntoWriter(writer);
    }
    uint64_t last_key = 0;
    list_.ForEach(
        [&](uint64_t key, std::variant<uint64_t, absl::string_view> value) {
          absl::Status status = std::visit(
              absl::Overload{[&](uint64_t val) {
                               return WireKeyVarIntPair(key - last_key, val)
                                   .SerializeIntoWriter(writer);
                             },
                             [&](absl::string_view val) {
                               return WireKeyStringPair(key - last_key, val)
                                   .SerializeIntoWriter(writer);
                             }},
              value);
          last_key = key;
          return quiche::IsWriterStatusOk(status);
        });
    return absl::OkStatus();
  }

 private:
  const KeyValuePairList& list_;
  const bool length_prefix_;
};

class WireTrackNamespace {
 public:
  WireTrackNamespace(const TrackNamespace& name) : namespace_(name) {}

  size_t GetLengthOnWire() {
    absl::FixedArray<absl::string_view> tuple(namespace_.tuple().begin(),
                                              namespace_.tuple().end());
    return quiche::ComputeLengthOnWire(
        WireMoqVarInt(namespace_.number_of_elements()),
        WireSpan<WireStringWithMoqVarIntLength, absl::string_view>(
            absl::MakeSpan(tuple)));
  }
  absl::Status SerializeIntoWriter(quiche::QuicheDataWriter& writer) {
    absl::FixedArray<absl::string_view> tuple(namespace_.tuple().begin(),
                                              namespace_.tuple().end());
    return quiche::SerializeIntoWriter(
        writer, WireMoqVarInt(namespace_.number_of_elements()),
        WireSpan<WireStringWithMoqVarIntLength, absl::string_view>(
            absl::MakeSpan(tuple)));
  }

 private:
  const TrackNamespace& namespace_;
};

class WireFullTrackName {
 public:
  WireFullTrackName(const FullTrackName& name) : name_(name) {}

  size_t GetLengthOnWire() {
    return quiche::ComputeLengthOnWire(
        WireTrackNamespace(name_.track_namespace()),
        WireStringWithMoqVarIntLength(name_.name()));
  }
  absl::Status SerializeIntoWriter(quiche::QuicheDataWriter& writer) {
    return quiche::SerializeIntoWriter(
        writer, WireTrackNamespace(name_.track_namespace()),
        WireStringWithMoqVarIntLength(name_.name()));
  }

 private:
  const FullTrackName& name_;
};

// Serializes data into buffer using the default allocator.  Invokes QUICHE_BUG
// on failure.
template <typename... Ts>
QuicheBuffer Serialize(Ts... data) {
  absl::StatusOr<QuicheBuffer> buffer = quiche::SerializeIntoBuffer(
      quiche::SimpleBufferAllocator::Get(), data...);
  if (!buffer.ok()) {
    QUICHE_BUG(moqt_failed_serialization)
        << "Failed to serialize MoQT frame: " << buffer.status();
    return QuicheBuffer();
  }
  return *std::move(buffer);
}

// Serializes data into buffer using the default allocator.  Invokes QUICHE_BUG
// on failure.
template <typename... Ts>
QuicheBuffer SerializeControlMessage(MoqtMessageType type, Ts... data) {
  uint64_t message_type = static_cast<uint64_t>(type);
  size_t payload_size = quiche::ComputeLengthOnWire(data...);
  size_t buffer_size = sizeof(uint16_t) + payload_size +
                       quiche::ComputeLengthOnWire(WireMoqVarInt(message_type));
  if (buffer_size == 0) {
    return QuicheBuffer();
  }

  QuicheBuffer buffer(quiche::SimpleBufferAllocator::Get(), buffer_size);
  quiche::QuicheDataWriter writer(buffer.size(), buffer.data());
  absl::Status status =
      SerializeIntoWriter(writer, WireMoqVarInt(message_type),
                          quiche::WireUint16(payload_size), data...);
  if (!status.ok() || writer.remaining() != 0) {
    QUICHE_BUG(moqt_failed_serialization)
        << "Failed to serialize MoQT frame: " << status;
    return QuicheBuffer();
  }
  return buffer;
}

[[maybe_unused]] WireUint8 WireDeliveryOrder(
    std::optional<MoqtDeliveryOrder> delivery_order) {
  if (!delivery_order.has_value()) {
    return WireUint8(0x00);
  }
  switch (*delivery_order) {
    case MoqtDeliveryOrder::kAscending:
      return WireUint8(0x01);
    case MoqtDeliveryOrder::kDescending:
      return WireUint8(0x02);
  }
  QUICHE_NOTREACHED();
  return WireUint8(0xff);
}

WireUint8 WireBoolean(bool value) { return WireUint8(value ? 0x01 : 0x00); }

uint64_t SignedVarintSerializedForm(int64_t value) {
  if (value < 0) {
    return ((-value) << 1) | 0x01;
  }
  return value << 1;
}

quiche::QuicheBuffer SerializeAuthToken(const AuthToken& token) {
  return Serialize(WireMoqVarInt(token.alias_type),
                   WireOptional<WireMoqVarInt>(token.alias),
                   WireOptional<WireMoqVarInt>(token.type),
                   WireOptional<WireBytes>(token.value));
}

quiche::QuicheBuffer SerializeSubscriptionFilter(
    const SubscriptionFilter& filter) {
  switch (filter.type()) {
    case MoqtFilterType::kNextGroupStart:
      return Serialize(WireMoqVarInt(filter.type()));
    case MoqtFilterType::kLargestObject:
      return Serialize(WireMoqVarInt(filter.type()));
    case MoqtFilterType::kAbsoluteStart:
      return Serialize(
          WireMoqVarInt(filter.type()),
          WireKeyVarIntPair(filter.start().group, filter.start().object));
    case MoqtFilterType::kAbsoluteRange:
      QUICHE_DCHECK_LE(filter.start().group, filter.end_group());
      return Serialize(
          WireMoqVarInt(filter.type()),
          WireKeyVarIntPair(filter.start().group, filter.start().object),
          WireMoqVarInt(filter.end_group() - filter.start().group));
  }
}

quiche::QuicheBuffer SerializeLocation(const Location& location) {
  return Serialize(WireKeyVarIntPair(location.group, location.object));
}

}  // namespace

KeyValuePairList SetupParameters::ToKeyValuePairList() const {
  KeyValuePairList out;
  if (max_request_id.has_value()) {
    out.insert(static_cast<uint64_t>(SetupParameter::kMaxRequestId),
               *max_request_id);
  }
  if (max_auth_token_cache_size.has_value()) {
    out.insert(static_cast<uint64_t>(SetupParameter::kMaxAuthTokenCacheSize),
               *max_auth_token_cache_size);
  }
  if (path.has_value()) {
    out.insert(static_cast<uint64_t>(SetupParameter::kPath), *path);
  }
  for (const AuthToken& token : authorization_tokens) {
    out.insert(static_cast<uint64_t>(SetupParameter::kAuthorizationToken),
               SerializeAuthToken(token).AsStringView());
  }
  if (authority.has_value()) {
    out.insert(static_cast<uint64_t>(SetupParameter::kAuthority), *authority);
  }
  if (moqt_implementation.has_value()) {
    out.insert(static_cast<uint64_t>(SetupParameter::kMoqtImplementation),
               *moqt_implementation);
  }
  if (support_object_acks.has_value()) {
    out.insert(static_cast<uint64_t>(SetupParameter::kSupportObjectAcks),
               *support_object_acks ? 1ULL : 0ULL);
  }
  return out;
}

KeyValuePairList MessageParameters::ToKeyValuePairList() const {
  KeyValuePairList list;
  if (delivery_timeout.has_value()) {
    // Value cannot be zero.
    int64_t milliseconds =
        std::max(delivery_timeout->ToMilliseconds(), int64_t{1});
    list.insert(static_cast<uint64_t>(MessageParameter::kDeliveryTimeout),
                static_cast<uint64_t>(milliseconds));
  }
  for (const AuthToken& token : authorization_tokens) {
    list.insert(static_cast<uint64_t>(MessageParameter::kAuthorizationToken),
                SerializeAuthToken(token).AsStringView());
  }
  if (expires.has_value()) {
    list.insert(static_cast<uint64_t>(MessageParameter::kExpires),
                static_cast<uint64_t>(expires->ToMilliseconds()));
  }
  if (largest_object.has_value()) {
    list.insert(static_cast<uint64_t>(MessageParameter::kLargestObject),
                SerializeLocation(*largest_object).AsStringView());
  }
  if (forward_has_value()) {
    list.insert(static_cast<uint64_t>(MessageParameter::kForward),
                forward() ? 1ULL : 0ULL);
  }
  if (subscriber_priority.has_value()) {
    list.insert(static_cast<uint64_t>(MessageParameter::kSubscriberPriority),
                *subscriber_priority);
  }
  if (subscription_filter.has_value()) {
    list.insert(
        static_cast<uint64_t>(MessageParameter::kSubscriptionFilter),
        SerializeSubscriptionFilter(*subscription_filter).AsStringView());
  }
  if (group_order.has_value()) {
    list.insert(static_cast<uint64_t>(MessageParameter::kGroupOrder),
                static_cast<uint64_t>(*group_order));
  }
  if (new_group_request.has_value()) {
    list.insert(static_cast<uint64_t>(MessageParameter::kNewGroupRequest),
                *new_group_request);
  }
  if (oack_window_size.has_value()) {
    list.insert(static_cast<uint64_t>(MessageParameter::kOackWindowSize),
                static_cast<uint64_t>(oack_window_size->ToMicroseconds()));
  }
  return list;
}

quiche::QuicheBuffer MoqtFramer::SerializeObjectHeader(
    const MoqtObject& message, MoqtDataStreamType message_type,
    std::optional<PublishedObjectMetadata>& previous_object_in_stream) {
  if (!ValidateObjectMetadata(message)) {
    QUICHE_BUG(QUICHE_BUG_serialize_object_header_01)
        << "Object metadata is invalid";
    return quiche::QuicheBuffer();
  }
  // Many fields are optional because the stream type or Fetch serialization
  // omits them.
  std::optional<uint64_t> stream_type;
  std::optional<uint64_t> track_id;  // Track alias or FETCH ID.
  std::optional<uint64_t> group_id;
  std::optional<uint64_t> subgroup_id;
  std::optional<uint64_t> object_id;
  std::optional<uint8_t> publisher_priority;
  std::optional<absl::string_view> extension_headers;
  uint64_t payload_length = message.payload_length;
  bool is_first_in_stream = !previous_object_in_stream.has_value();
  if (is_first_in_stream) {
    stream_type = message_type.value();
    track_id = message.track_alias;
  }
  if (message_type.IsFetch()) {
    MoqtFetchSerialization serialization;
    if (is_first_in_stream) {
      serialization = MoqtFetchSerialization(message);
    } else {
      serialization =
          MoqtFetchSerialization(message, *previous_object_in_stream);
    }
    if (serialization.has_group_id()) {
      group_id = message.group_id;
    }
    if (serialization.has_subgroup_id()) {
      subgroup_id = message.subgroup_id;
    }
    if (serialization.has_object_id()) {
      object_id = message.object_id;
    }
    if (serialization.has_priority()) {
      publisher_priority = message.publisher_priority;
    }
    if (serialization.has_extensions()) {
      extension_headers = message.extension_headers;
    }
    return Serialize(
        WireOptional<WireMoqVarInt>(stream_type),
        WireOptional<WireMoqVarInt>(track_id),
        WireMoqVarInt(serialization.value()),
        WireOptional<WireMoqVarInt>(group_id),
        WireOptional<WireMoqVarInt>(subgroup_id),
        WireOptional<WireMoqVarInt>(object_id),
        WireOptional<WireUint8>(publisher_priority),
        WireOptional<WireStringWithMoqVarIntLength>(extension_headers),
        WireMoqVarInt(payload_length));
  }
  // Subgroup stream.
  if (!message.subgroup_id.has_value()) {
    QUICHE_BUG(QUICHE_BUG_serialize_object_header_02)
        << "Subgroup ID is missing";
    return quiche::QuicheBuffer();
  }
  if (is_first_in_stream) {
    group_id = message.group_id;
    if (message_type.IsSubgroupPresent()) {
      subgroup_id = message.subgroup_id;
    }
    if (!message_type.HasDefaultPriority()) {
      publisher_priority = message.publisher_priority;
    }
  }
  object_id = message.object_id;
  if (!is_first_in_stream) {
    *object_id -= (previous_object_in_stream->location.object + 1);
  }
  if (message_type.AreExtensionHeadersPresent()) {
    extension_headers = message.extension_headers;
  }
  std::optional<uint64_t> object_status;
  if (payload_length == 0) {
    object_status = static_cast<uint64_t>(message.object_status);
  }
  return Serialize(
      WireOptional<WireMoqVarInt>(stream_type),
      WireOptional<WireMoqVarInt>(track_id),
      WireOptional<WireMoqVarInt>(group_id),
      WireOptional<WireMoqVarInt>(subgroup_id),
      WireOptional<WireUint8>(publisher_priority), WireMoqVarInt(*object_id),
      WireOptional<WireStringWithMoqVarIntLength>(extension_headers),
      WireMoqVarInt(message.payload_length),
      WireOptional<WireMoqVarInt>(object_status));
}

quiche::QuicheBuffer MoqtFramer::SerializeObjectDatagram(
    const MoqtObject& message, absl::string_view payload,
    MoqtPriority default_priority) {
  if (!ValidateObjectMetadata(message) || message.subgroup_id.has_value()) {
    QUICHE_BUG(QUICHE_BUG_serialize_object_datagram_01)
        << "Object metadata is invalid";
    return quiche::QuicheBuffer();
  }
  if (message.payload_length != payload.length()) {
    QUICHE_BUG(QUICHE_BUG_serialize_object_datagram_03)
        << "Payload length does not match payload";
    return quiche::QuicheBuffer();
  }
  MoqtDatagramType datagram_type(
      !payload.empty(), !message.extension_headers.empty(),
      message.object_status == MoqtObjectStatus::kEndOfGroup,
      message.publisher_priority == default_priority, message.object_id == 0);
  std::optional<uint64_t> object_id =
      datagram_type.has_object_id() ? std::optional<uint64_t>(message.object_id)
                                    : std::nullopt;
  std::optional<uint8_t> publisher_priority =
      datagram_type.has_default_priority()
          ? std::nullopt
          : std::optional<uint8_t>(message.publisher_priority);
  std::optional<absl::string_view> extensions =
      datagram_type.has_extension()
          ? std::optional<absl::string_view>(message.extension_headers)
          : std::nullopt;
  std::optional<uint64_t> object_status =
      payload.empty() ? std::optional<uint64_t>(
                            static_cast<uint64_t>(message.object_status))
                      : std::nullopt;
  std::optional<absl::string_view> raw_payload =
      payload.empty() ? std::nullopt
                      : std::optional<absl::string_view>(payload);
  return Serialize(
      WireMoqVarInt(datagram_type.value()), WireMoqVarInt(message.track_alias),
      WireMoqVarInt(message.group_id), WireOptional<WireMoqVarInt>(object_id),
      WireOptional<WireUint8>(publisher_priority),
      WireOptional<WireStringWithMoqVarIntLength>(extensions),
      WireOptional<WireMoqVarInt>(object_status),
      WireOptional<WireBytes>(raw_payload));
}

quiche::QuicheBuffer MoqtFramer::SerializeSetup(const MoqtSetup& message) {
  KeyValuePairList parameters;
  if (!FillAndValidateSetupParameters(message.parameters, parameters)) {
    return quiche::QuicheBuffer();
  }
  return SerializeControlMessage(MoqtMessageType::kSetup,
                                 WireKeyValuePairList(parameters));
}

quiche::QuicheBuffer MoqtFramer::SerializeRequestOk(
    const MoqtRequestOk& message) {
  return SerializeControlMessage(
      MoqtMessageType::kRequestOk, WireMoqVarInt(message.request_id),
      WireKeyValuePairList(message.parameters.ToKeyValuePairList()));
}

quiche::QuicheBuffer MoqtFramer::SerializeSubscribe(
    const MoqtSubscribe& message, MoqtMessageType message_type) {
  return SerializeControlMessage(
      message_type, WireMoqVarInt(message.request_id),
      WireFullTrackName(message.full_track_name),
      WireKeyValuePairList(message.parameters.ToKeyValuePairList()));
}

quiche::QuicheBuffer MoqtFramer::SerializeSubscribeOk(
    const MoqtSubscribeOk& message, MoqtMessageType message_type) {
  if (!message.extensions.Validate()) {
    QUICHE_BUG(QUICHE_BUG_serialize_subscribe_ok_01)
        << "Subscribe OK extensions are ill-formed";
    return quiche::QuicheBuffer();
  }
  return SerializeControlMessage(
      message_type, WireMoqVarInt(message.request_id),
      WireMoqVarInt(message.track_alias),
      WireKeyValuePairList(message.parameters.ToKeyValuePairList()),
      WireKeyValuePairList(message.extensions, false));
}

quiche::QuicheBuffer MoqtFramer::SerializeRequestError(
    const MoqtRequestError& message) {
  return SerializeControlMessage(
      MoqtMessageType::kRequestError, WireMoqVarInt(message.request_id),
      WireMoqVarInt(message.error_code),
      WireMoqVarInt(message.retry_interval.has_value()
                        ? message.retry_interval->ToMilliseconds() + 1
                        : 0),
      WireStringWithMoqVarIntLength(message.reason_phrase));
}

quiche::QuicheBuffer MoqtFramer::SerializePublishDone(
    const MoqtPublishDone& message) {
  return SerializeControlMessage(
      MoqtMessageType::kPublishDone, WireMoqVarInt(message.request_id),
      WireMoqVarInt(message.status_code), WireMoqVarInt(message.stream_count),
      WireStringWithMoqVarIntLength(message.error_reason));
}

quiche::QuicheBuffer MoqtFramer::SerializeRequestUpdate(
    const MoqtRequestUpdate& message) {
  return SerializeControlMessage(
      MoqtMessageType::kRequestUpdate, WireMoqVarInt(message.request_id),
      WireMoqVarInt(message.existing_request_id),
      WireKeyValuePairList(message.parameters.ToKeyValuePairList()));
}

quiche::QuicheBuffer MoqtFramer::SerializePublishNamespace(
    const MoqtPublishNamespace& message) {
  return SerializeControlMessage(
      MoqtMessageType::kPublishNamespace, WireMoqVarInt(message.request_id),
      WireTrackNamespace(message.track_namespace),
      WireKeyValuePairList(message.parameters.ToKeyValuePairList()));
}

quiche::QuicheBuffer MoqtFramer::SerializePublishNamespaceDone(
    const MoqtPublishNamespaceDone& message) {
  return SerializeControlMessage(MoqtMessageType::kPublishNamespaceDone,
                                 WireMoqVarInt(message.request_id));
}

quiche::QuicheBuffer MoqtFramer::SerializeNamespace(
    const MoqtNamespace& message) {
  return SerializeControlMessage(
      MoqtMessageType::kNamespace,
      WireTrackNamespace(message.track_namespace_suffix));
}

quiche::QuicheBuffer MoqtFramer::SerializeNamespaceDone(
    const MoqtNamespaceDone& message) {
  return SerializeControlMessage(
      MoqtMessageType::kNamespaceDone,
      WireTrackNamespace(message.track_namespace_suffix));
}

quiche::QuicheBuffer MoqtFramer::SerializePublishNamespaceCancel(
    const MoqtPublishNamespaceCancel& message) {
  return SerializeControlMessage(
      MoqtMessageType::kPublishNamespaceCancel,
      WireMoqVarInt(message.request_id), WireMoqVarInt(message.error_code),
      WireStringWithMoqVarIntLength(message.error_reason));
}

quiche::QuicheBuffer MoqtFramer::SerializeTrackStatus(
    const MoqtTrackStatus& message) {
  return SerializeSubscribe(message, MoqtMessageType::kTrackStatus);
}

quiche::QuicheBuffer MoqtFramer::SerializeGoAway(const MoqtGoAway& message) {
  return SerializeControlMessage(
      MoqtMessageType::kGoAway,
      WireStringWithMoqVarIntLength(message.new_session_uri));
}

quiche::QuicheBuffer MoqtFramer::SerializeSubscribeNamespace(
    const MoqtSubscribeNamespace& message) {
  return SerializeControlMessage(
      MoqtMessageType::kSubscribeNamespace, WireMoqVarInt(message.request_id),
      WireTrackNamespace(message.track_namespace_prefix),
      WireKeyValuePairList(message.parameters.ToKeyValuePairList()));
}

quiche::QuicheBuffer MoqtFramer::SerializeSubscribeTracks(
    const MoqtSubscribeTracks& message) {
  return SerializeControlMessage(
      MoqtMessageType::kSubscribeTracks, WireMoqVarInt(message.request_id),
      WireTrackNamespace(message.track_namespace_prefix),
      WireKeyValuePairList(message.parameters.ToKeyValuePairList()));
}

quiche::QuicheBuffer MoqtFramer::SerializeMaxRequestId(
    const MoqtMaxRequestId& message) {
  return SerializeControlMessage(MoqtMessageType::kMaxRequestId,
                                 WireMoqVarInt(message.max_request_id));
}

quiche::QuicheBuffer MoqtFramer::SerializeFetch(const MoqtFetch& message) {
  if (std::holds_alternative<StandaloneFetch>(message.fetch)) {
    const StandaloneFetch& standalone_fetch =
        std::get<StandaloneFetch>(message.fetch);
    if (standalone_fetch.end_location < standalone_fetch.start_location) {
      QUICHE_BUG(MoqtFramer_invalid_fetch) << "Invalid FETCH object range";
      return quiche::QuicheBuffer();
    }
  }
  if (std::holds_alternative<StandaloneFetch>(message.fetch)) {
    const StandaloneFetch& standalone_fetch =
        std::get<StandaloneFetch>(message.fetch);
    return SerializeControlMessage(
        MoqtMessageType::kFetch, WireMoqVarInt(message.request_id),
        WireMoqVarInt(FetchType::kStandalone),
        WireFullTrackName(standalone_fetch.full_track_name),
        WireMoqVarInt(standalone_fetch.start_location.group),
        WireMoqVarInt(standalone_fetch.start_location.object),
        WireMoqVarInt(standalone_fetch.end_location.group),
        WireMoqVarInt(standalone_fetch.end_location.object == kMaxObjectId
                          ? 0
                          : standalone_fetch.end_location.object + 1),
        WireKeyValuePairList(message.parameters.ToKeyValuePairList()));
  }
  uint64_t request_id, joining_start;
  if (std::holds_alternative<JoiningFetchRelative>(message.fetch)) {
    const JoiningFetchRelative& joining_fetch =
        std::get<JoiningFetchRelative>(message.fetch);
    request_id = joining_fetch.joining_request_id;
    joining_start = joining_fetch.joining_start;
  } else {
    const JoiningFetchAbsolute& joining_fetch =
        std::get<JoiningFetchAbsolute>(message.fetch);
    request_id = joining_fetch.joining_request_id;
    joining_start = joining_fetch.joining_start;
  }
  return SerializeControlMessage(
      MoqtMessageType::kFetch, WireMoqVarInt(message.request_id),
      WireMoqVarInt(message.fetch.index() + 1), WireMoqVarInt(request_id),
      WireMoqVarInt(joining_start),
      WireKeyValuePairList(message.parameters.ToKeyValuePairList()));
}

quiche::QuicheBuffer MoqtFramer::SerializeFetchOk(const MoqtFetchOk& message) {
  return SerializeControlMessage(
      MoqtMessageType::kFetchOk, WireMoqVarInt(message.request_id),
      WireBoolean(message.end_of_track),
      WireMoqVarInt(message.end_location.group),
      WireMoqVarInt(message.end_location.object == kMaxObjectId
                        ? 0
                        : (message.end_location.object + 1)),
      WireKeyValuePairList(message.parameters.ToKeyValuePairList()),
      WireKeyValuePairList(message.extensions, false));
}

quiche::QuicheBuffer MoqtFramer::SerializeFetchCancel(
    const MoqtFetchCancel& message) {
  return SerializeControlMessage(MoqtMessageType::kFetchCancel,
                                 WireMoqVarInt(message.request_id));
}

quiche::QuicheBuffer MoqtFramer::SerializeRequestsBlocked(
    const MoqtRequestsBlocked& message) {
  return SerializeControlMessage(MoqtMessageType::kRequestsBlocked,
                                 WireMoqVarInt(message.max_request_id));
}

quiche::QuicheBuffer MoqtFramer::SerializePublish(const MoqtPublish& message) {
  return SerializeControlMessage(
      MoqtMessageType::kPublish, WireMoqVarInt(message.request_id),
      WireFullTrackName(message.full_track_name),
      WireMoqVarInt(message.track_alias),
      WireKeyValuePairList(message.parameters.ToKeyValuePairList()),
      WireKeyValuePairList(message.extensions, false));
}

quiche::QuicheBuffer MoqtFramer::SerializeObjectAck(
    const MoqtObjectAck& message) {
  return SerializeControlMessage(
      MoqtMessageType::kObjectAck, WireMoqVarInt(message.group_id),
      WireMoqVarInt(message.object_id),
      WireMoqVarInt(SignedVarintSerializedForm(
          message.delta_from_deadline.ToMicroseconds())));
}

bool MoqtFramer::FillAndValidateSetupParameters(
    const SetupParameters& parameters, KeyValuePairList& out) {
  if (SetupParametersAllowedByMessage(parameters, perspective_,
                                      using_webtrans_) != MoqtError::kNoError) {
    QUICHE_BUG(QUICHE_BUG_invalid_setup_parameters)
        << "Invalid setup parameters for "
        << MoqtMessageTypeToString(MoqtMessageType::kSetup);
    return false;
  }
  out = parameters.ToKeyValuePairList();
  return true;
}

// static
bool MoqtFramer::ValidateObjectMetadata(const MoqtObject& object) {
  return (object.object_status == MoqtObjectStatus::kNormal ||
          object.object_status == MoqtObjectStatus::kEndOfGroup ||
          object.payload_length == 0);
}

}  // namespace moqt
