Make writing Prioritized Element ID and Element Dependency ID optional when handling priority.

These fields are specified to be absent when priority type or dependency type is ROOT_OF_TREE.

On the decoding side, the absent fields will be parsed as 0 for default value. Those fields won't be used when later the frame is processed.

gfe-relnote: v99 only, not flag protected.
PiperOrigin-RevId: 254072432
Change-Id: I336e06b39d89ff01507e54818dafa67923e96e4c
diff --git a/quic/core/http/http_encoder.cc b/quic/core/http/http_encoder.cc
index 4505dc7..2b8be8e 100644
--- a/quic/core/http/http_encoder.cc
+++ b/quic/core/http/http_encoder.cc
@@ -3,6 +3,7 @@
 // found in the LICENSE file.
 
 #include "net/third_party/quiche/src/quic/core/http/http_encoder.h"
+
 #include "net/third_party/quiche/src/quic/core/quic_data_writer.h"
 
 namespace quic {
@@ -43,6 +44,8 @@
 static const size_t kPriorityWeightLength = 1;
 // Length of a priority frame's first byte.
 static const size_t kPriorityFirstByteLength = 1;
+// The bit that indicates Priority frame is exclusive.
+static const uint8_t kPriorityExclusiveBit = 1;
 
 }  // namespace
 
@@ -95,8 +98,12 @@
     std::unique_ptr<char[]>* output) {
   QuicByteCount payload_length =
       kPriorityFirstByteLength +
-      QuicDataWriter::GetVarInt62Len(priority.prioritized_element_id) +
-      QuicDataWriter::GetVarInt62Len(priority.element_dependency_id) +
+      (priority.prioritized_type == ROOT_OF_TREE
+           ? 0
+           : QuicDataWriter::GetVarInt62Len(priority.prioritized_element_id)) +
+      (priority.dependency_type == ROOT_OF_TREE
+           ? 0
+           : QuicDataWriter::GetVarInt62Len(priority.element_dependency_id)) +
       kPriorityWeightLength;
   QuicByteCount total_length =
       GetTotalLength(payload_length, HttpFrameType::PRIORITY);
@@ -111,16 +118,14 @@
   }
 
   // Set the first byte of the payload.
-  uint8_t bits = 0;
-  bits = SetPriorityFields(bits, priority.prioritized_type, true);
-  bits = SetPriorityFields(bits, priority.dependency_type, false);
+  uint8_t firstByte = 0;
+  firstByte = SetPriorityFields(firstByte, priority.prioritized_type, true);
+  firstByte = SetPriorityFields(firstByte, priority.dependency_type, false);
   if (priority.exclusive) {
-    bits |= 1;
+    firstByte |= kPriorityExclusiveBit;
   }
 
-  if (writer.WriteUInt8(bits) &&
-      writer.WriteVarInt62(priority.prioritized_element_id) &&
-      writer.WriteVarInt62(priority.element_dependency_id) &&
+  if (writer.WriteUInt8(firstByte) && MaybeWriteIds(priority, &writer) &&
       writer.WriteUInt8(priority.weight)) {
     return total_length;
   }
@@ -282,4 +287,27 @@
          payload_length;
 }
 
+bool HttpEncoder::MaybeWriteIds(const PriorityFrame& priority,
+                                QuicDataWriter* writer) {
+  if (priority.prioritized_type != ROOT_OF_TREE) {
+    if (!writer->WriteVarInt62(priority.prioritized_element_id)) {
+      return false;
+    }
+  } else {
+    DCHECK_EQ(0u, priority.prioritized_element_id)
+        << "Prioritized element id should be 0 when prioritized type is "
+           "ROOT_OF_TREE";
+  }
+  if (priority.dependency_type != ROOT_OF_TREE) {
+    if (!writer->WriteVarInt62(priority.element_dependency_id)) {
+      return false;
+    }
+  } else {
+    DCHECK_EQ(0u, priority.element_dependency_id)
+        << "Element dependency id should be 0 when dependency type is "
+           "ROOT_OF_TREE";
+  }
+  return true;
+}
+
 }  // namespace quic