Cleanup uses of QUIC version

This CL gets us closer to being able to turn ParsedQuicVersion into a class. It does not change any behavior.

No behavior change

PiperOrigin-RevId: 323895265
Change-Id: I940f8ce54e0c62efab485da1140f623a51b245d7
diff --git a/quic/core/crypto/crypto_utils.cc b/quic/core/crypto/crypto_utils.cc
index 14c13fc..033fcfd 100644
--- a/quic/core/crypto/crypto_utils.cc
+++ b/quic/core/crypto/crypto_utils.cc
@@ -143,46 +143,25 @@
                                      size_t* out_len) {
   static_assert(SupportedVersions().size() == 7u,
                 "Supported versions out of sync with initial encryption salts");
-  switch (version.handshake_protocol) {
-    case PROTOCOL_QUIC_CRYPTO:
-      switch (version.transport_version) {
-        case QUIC_VERSION_50:
-          *out_len = QUICHE_ARRAYSIZE(kQ050Salt);
-          return kQ050Salt;
-        case QUIC_VERSION_RESERVED_FOR_NEGOTIATION:
-          // It doesn't matter what salt we use for
-          // QUIC_VERSION_RESERVED_FOR_NEGOTIATION, but some tests try to use a
-          // QuicFramer with QUIC_VERSION_RESERVED_FOR_NEGOTIATION and will hit
-          // the following QUIC_BUG if there isn't a case for it. ):
-          *out_len = QUICHE_ARRAYSIZE(kDraft25InitialSalt);
-          return kDraft25InitialSalt;
-        default:
-          QUIC_BUG << "No initial obfuscation salt for version " << version;
-      }
-      break;
-    case PROTOCOL_TLS1_3:
-      switch (version.transport_version) {
-        case QUIC_VERSION_50:
-          *out_len = QUICHE_ARRAYSIZE(kT050Salt);
-          return kT050Salt;
-        case QUIC_VERSION_IETF_DRAFT_25:
-          *out_len = QUICHE_ARRAYSIZE(kDraft25InitialSalt);
-          return kDraft25InitialSalt;
-        case QUIC_VERSION_IETF_DRAFT_27:
-          // draft-27 uses the same salt as draft-25.
-          *out_len = QUICHE_ARRAYSIZE(kDraft25InitialSalt);
-          return kDraft25InitialSalt;
-        case QUIC_VERSION_IETF_DRAFT_29:
-          *out_len = QUICHE_ARRAYSIZE(kDraft29InitialSalt);
-          return kDraft29InitialSalt;
-        default:
-          QUIC_BUG << "No initial obfuscation salt for version " << version;
-      }
-      break;
-    case PROTOCOL_UNSUPPORTED:
-    default:
-      QUIC_BUG << "No initial obfuscation salt for version " << version;
+  if (version == ParsedQuicVersion::Draft29()) {
+    *out_len = QUICHE_ARRAYSIZE(kDraft29InitialSalt);
+    return kDraft29InitialSalt;
   }
+  if (version == ParsedQuicVersion::Draft27() ||
+      version == ParsedQuicVersion::Draft25() ||
+      version == ParsedQuicVersion::ReservedForNegotiation()) {
+    *out_len = QUICHE_ARRAYSIZE(kDraft25InitialSalt);
+    return kDraft25InitialSalt;
+  }
+  if (version == ParsedQuicVersion::T050()) {
+    *out_len = QUICHE_ARRAYSIZE(kT050Salt);
+    return kT050Salt;
+  }
+  if (version == ParsedQuicVersion::Q050()) {
+    *out_len = QUICHE_ARRAYSIZE(kQ050Salt);
+    return kQ050Salt;
+  }
+  QUIC_BUG << "No initial obfuscation salt for version " << version;
   *out_len = QUICHE_ARRAYSIZE(kDraft25InitialSalt);
   return kDraft25InitialSalt;
 }
@@ -224,19 +203,17 @@
              << version;
     return false;
   }
-  if (version == ParsedQuicVersion(PROTOCOL_TLS1_3, QUIC_VERSION_50)) {
+  if (version == ParsedQuicVersion::Draft29()) {
     *key = quiche::QuicheStringPiece(
-        reinterpret_cast<const char*>(kT050RetryIntegrityKey),
-        QUICHE_ARRAYSIZE(kT050RetryIntegrityKey));
+        reinterpret_cast<const char*>(kDraft29RetryIntegrityKey),
+        QUICHE_ARRAYSIZE(kDraft29RetryIntegrityKey));
     *nonce = quiche::QuicheStringPiece(
-        reinterpret_cast<const char*>(kT050RetryIntegrityNonce),
-        QUICHE_ARRAYSIZE(kT050RetryIntegrityNonce));
+        reinterpret_cast<const char*>(kDraft29RetryIntegrityNonce),
+        QUICHE_ARRAYSIZE(kDraft29RetryIntegrityNonce));
     return true;
   }
-  if (version ==
-          ParsedQuicVersion(PROTOCOL_TLS1_3, QUIC_VERSION_IETF_DRAFT_25) ||
-      version ==
-          ParsedQuicVersion(PROTOCOL_TLS1_3, QUIC_VERSION_IETF_DRAFT_27)) {
+  if (version == ParsedQuicVersion::Draft25() ||
+      version == ParsedQuicVersion::Draft27()) {
     *key = quiche::QuicheStringPiece(
         reinterpret_cast<const char*>(kDraft25RetryIntegrityKey),
         QUICHE_ARRAYSIZE(kDraft25RetryIntegrityKey));
@@ -245,13 +222,13 @@
         QUICHE_ARRAYSIZE(kDraft25RetryIntegrityNonce));
     return true;
   }
-  if (version == ParsedQuicVersion::Draft29()) {
+  if (version == ParsedQuicVersion::T050()) {
     *key = quiche::QuicheStringPiece(
-        reinterpret_cast<const char*>(kDraft29RetryIntegrityKey),
-        QUICHE_ARRAYSIZE(kDraft29RetryIntegrityKey));
+        reinterpret_cast<const char*>(kT050RetryIntegrityKey),
+        QUICHE_ARRAYSIZE(kT050RetryIntegrityKey));
     *nonce = quiche::QuicheStringPiece(
-        reinterpret_cast<const char*>(kDraft29RetryIntegrityNonce),
-        QUICHE_ARRAYSIZE(kDraft29RetryIntegrityNonce));
+        reinterpret_cast<const char*>(kT050RetryIntegrityNonce),
+        QUICHE_ARRAYSIZE(kT050RetryIntegrityNonce));
     return true;
   }
   QUIC_BUG << "Attempted to get retry integrity keys for version " << version;
diff --git a/quic/core/http/quic_spdy_session.h b/quic/core/http/quic_spdy_session.h
index 6dc65f3..cb3b986 100644
--- a/quic/core/http/quic_spdy_session.h
+++ b/quic/core/http/quic_spdy_session.h
@@ -206,8 +206,7 @@
       QuicReferenceCountedPointer<QuicAckListenerInterface> ack_listener);
 
   // Writes an HTTP/2 PRIORITY frame the to peer. Returns the size in bytes of
-  // the resulting PRIORITY frame for QUIC_VERSION_43 and above. Otherwise, does
-  // nothing and returns 0.
+  // the resulting PRIORITY frame.
   size_t WritePriority(QuicStreamId id,
                        QuicStreamId parent_stream_id,
                        int weight,
diff --git a/quic/core/quic_buffered_packet_store.cc b/quic/core/quic_buffered_packet_store.cc
index cafe871..a90cef6 100644
--- a/quic/core/quic_buffered_packet_store.cc
+++ b/quic/core/quic_buffered_packet_store.cc
@@ -57,7 +57,7 @@
 BufferedPacketList::BufferedPacketList()
     : creation_time(QuicTime::Zero()),
       ietf_quic(false),
-      version(PROTOCOL_UNSUPPORTED, QUIC_VERSION_UNSUPPORTED) {}
+      version(ParsedQuicVersion::Unsupported()) {}
 
 BufferedPacketList::BufferedPacketList(BufferedPacketList&& other) = default;
 
@@ -94,7 +94,7 @@
       << "Shouldn't buffer duplicated CHLO on connection " << connection_id;
   QUIC_BUG_IF(!is_chlo && !alpns.empty())
       << "Shouldn't have an ALPN defined for a non-CHLO packet.";
-  QUIC_BUG_IF(is_chlo && version.transport_version == QUIC_VERSION_UNSUPPORTED)
+  QUIC_BUG_IF(is_chlo && !version.IsKnown())
       << "Should have version for CHLO packet.";
 
   const bool is_first_packet =
diff --git a/quic/core/quic_buffered_packet_store_test.cc b/quic/core/quic_buffered_packet_store_test.cc
index d99f4e0..85e4e5d 100644
--- a/quic/core/quic_buffered_packet_store_test.cc
+++ b/quic/core/quic_buffered_packet_store_test.cc
@@ -55,7 +55,7 @@
         packet_time_(QuicTime::Zero() + QuicTime::Delta::FromMicroseconds(42)),
         packet_(packet_content_.data(), packet_content_.size(), packet_time_),
         invalid_version_(UnsupportedQuicVersion()),
-        valid_version_(PROTOCOL_QUIC_CRYPTO, QUIC_VERSION_46) {}
+        valid_version_(CurrentSupportedVersions().front()) {}
 
  protected:
   QuicBufferedPacketStoreVisitor visitor_;
diff --git a/quic/core/quic_connection.h b/quic/core/quic_connection.h
index ff7ecb4..afddeeb 100644
--- a/quic/core/quic_connection.h
+++ b/quic/core/quic_connection.h
@@ -1457,7 +1457,7 @@
 
   // Indicates how many consecutive times an ack has arrived which indicates
   // the peer needs to stop waiting for some packets.
-  // TODO(fayang): remove this when deprecating QUIC_VERSION_43.
+  // TODO(fayang): remove this when deprecating Q043.
   int stop_waiting_count_;
 
   // Indicates the retransmission alarm needs to be set.
diff --git a/quic/core/quic_connection_test.cc b/quic/core/quic_connection_test.cc
index f345c36..97e5a4a 100644
--- a/quic/core/quic_connection_test.cc
+++ b/quic/core/quic_connection_test.cc
@@ -9355,10 +9355,10 @@
 
 // Regression test for b/120791670
 TEST_P(QuicConnectionTest, StopProcessingGQuicPacketInIetfQuicConnection) {
-  // This test mimics a problematic scenario where an IETF QUIC connection
-  // receives a Google QUIC packet and continue processing it using Google QUIC
-  // wire format.
-  if (!VersionHasIetfInvariantHeader(version().transport_version)) {
+  // This test mimics a problematic scenario where a QUIC connection using a
+  // modern version received a Q043 packet and processed it incorrectly.
+  // We can remove this test once Q043 is deprecated.
+  if (!version().HasIetfInvariantHeader()) {
     return;
   }
   set_perspective(Perspective::IS_SERVER);
@@ -9371,8 +9371,7 @@
                                   kPeerAddress);
 
   // Let connection process a Google QUIC packet.
-  peer_framer_.set_version_for_tests(
-      ParsedQuicVersion(PROTOCOL_QUIC_CRYPTO, QUIC_VERSION_43));
+  peer_framer_.set_version_for_tests(ParsedQuicVersion::Q043());
   std::unique_ptr<QuicPacket> packet(
       ConstructDataPacket(2, !kHasStopWaiting, ENCRYPTION_INITIAL));
   char buffer[kMaxOutgoingPacketSize];
diff --git a/quic/core/quic_dispatcher.cc b/quic/core/quic_dispatcher.cc
index e98359c..cfad1ac 100644
--- a/quic/core/quic_dispatcher.cc
+++ b/quic/core/quic_dispatcher.cc
@@ -512,8 +512,7 @@
     it->second->ProcessUdpPacket(packet_info.self_address,
                                  packet_info.peer_address, packet_info.packet);
     return true;
-  } else if (packet_info.version.transport_version !=
-             QUIC_VERSION_UNSUPPORTED) {
+  } else if (packet_info.version.IsKnown()) {
     // We did not find the connection ID, check if we've replaced it.
     // This is only performed for supported versions because packets with
     // unsupported versions can flow through this function in order to send
diff --git a/quic/core/quic_dispatcher_test.cc b/quic/core/quic_dispatcher_test.cc
index bd9bb7a..a5f5f91 100644
--- a/quic/core/quic_dispatcher_test.cc
+++ b/quic/core/quic_dispatcher_test.cc
@@ -1515,7 +1515,7 @@
   EXPECT_EQ(QuicDispatcherPeer::SelectAlpn(dispatcher_.get(), {""}), "");
   EXPECT_EQ(QuicDispatcherPeer::SelectAlpn(dispatcher_.get(), {"hq"}), "hq");
   // Q033 is no longer supported but Q050 is.
-  QuicEnableVersion(ParsedQuicVersion(PROTOCOL_QUIC_CRYPTO, QUIC_VERSION_50));
+  QuicEnableVersion(ParsedQuicVersion::Q050());
   EXPECT_EQ(
       QuicDispatcherPeer::SelectAlpn(dispatcher_.get(), {"h3-Q033", "h3-Q050"}),
       "h3-Q050");
diff --git a/quic/core/quic_framer.cc b/quic/core/quic_framer.cc
index 0ad2e91..be155a9 100644
--- a/quic/core/quic_framer.cc
+++ b/quic/core/quic_framer.cc
@@ -402,7 +402,7 @@
       error_(QUIC_NO_ERROR),
       last_serialized_server_connection_id_(EmptyQuicConnectionId()),
       last_serialized_client_connection_id_(EmptyQuicConnectionId()),
-      version_(PROTOCOL_UNSUPPORTED, QUIC_VERSION_UNSUPPORTED),
+      version_(ParsedQuicVersion::Unsupported()),
       supported_versions_(supported_versions),
       decrypter_level_(ENCRYPTION_INITIAL),
       alternative_decrypter_level_(NUM_ENCRYPTION_LEVELS),
@@ -2528,7 +2528,7 @@
       header->long_packet_type = VERSION_NEGOTIATION;
     } else {
       header->version = ParseQuicVersionLabel(version_label);
-      if (header->version.transport_version != QUIC_VERSION_UNSUPPORTED) {
+      if (header->version.IsKnown()) {
         if (!(type & FLAGS_FIXED_BIT)) {
           set_detailed_error("Fixed bit is 0 in long header.");
           return false;
@@ -2818,9 +2818,9 @@
       set_detailed_error("Unable to read frame type.");
       return RaiseError(QUIC_INVALID_FRAME_DATA);
     }
-    const uint8_t special_mask = transport_version() <= QUIC_VERSION_43
-                                     ? kQuicFrameTypeBrokenMask
-                                     : kQuicFrameTypeSpecialMask;
+    const uint8_t special_mask = version_.HasIetfInvariantHeader()
+                                     ? kQuicFrameTypeSpecialMask
+                                     : kQuicFrameTypeBrokenMask;
     if (frame_type & special_mask) {
       // Stream Frame
       if (frame_type & kQuicFrameTypeStreamMask) {
@@ -2949,7 +2949,7 @@
 
       case STOP_WAITING_FRAME: {
         if (GetQuicReloadableFlag(quic_do_not_accept_stop_waiting) &&
-            version_.transport_version > QUIC_VERSION_43) {
+            version_.HasIetfInvariantHeader()) {
           QUIC_RELOADABLE_FLAG_COUNT(quic_do_not_accept_stop_waiting);
           set_detailed_error("STOP WAITING not supported in version 44+.");
           return RaiseError(QUIC_INVALID_STOP_WAITING_DATA);
@@ -6324,7 +6324,7 @@
     ParsedQuicVersion parsed_version,
     QuicVersionLabel version_label,
     uint8_t first_byte) {
-  if (parsed_version.transport_version != QUIC_VERSION_UNSUPPORTED) {
+  if (parsed_version.IsKnown()) {
     return parsed_version.HasLengthPrefixedConnectionIds();
   }
 
@@ -6493,7 +6493,7 @@
     return QUIC_INVALID_PACKET_HEADER;
   }
 
-  if (parsed_version->transport_version == QUIC_VERSION_UNSUPPORTED) {
+  if (!parsed_version->IsKnown()) {
     // Skip parsing of long packet type and retry token for unknown versions.
     return QUIC_NO_ERROR;
   }
diff --git a/quic/core/quic_packet_creator.h b/quic/core/quic_packet_creator.h
index c909cd4..8db087a 100644
--- a/quic/core/quic_packet_creator.h
+++ b/quic/core/quic_packet_creator.h
@@ -394,6 +394,8 @@
 
   QuicByteCount pending_padding_bytes() const { return pending_padding_bytes_; }
 
+  ParsedQuicVersion version() const { return framer_->version(); }
+
   QuicTransportVersion transport_version() const {
     return framer_->transport_version();
   }
diff --git a/quic/core/quic_packet_creator_test.cc b/quic/core/quic_packet_creator_test.cc
index 4361ed9..7943cee 100644
--- a/quic/core/quic_packet_creator_test.cc
+++ b/quic/core/quic_packet_creator_test.cc
@@ -715,10 +715,10 @@
 
   unsigned char* p = packet;
   size_t packet_size = QUICHE_ARRAYSIZE(packet);
-  if (VersionHasIetfQuicFrames(creator_.transport_version())) {
+  if (creator_.version().HasIetfQuicFrames()) {
     p = packet99;
     packet_size = QUICHE_ARRAYSIZE(packet99);
-  } else if (creator_.transport_version() >= QUIC_VERSION_46) {
+  } else if (creator_.version().HasIetfInvariantHeader()) {
     p = packet46;
     packet_size = QUICHE_ARRAYSIZE(packet46);
   }
diff --git a/quic/core/quic_packets.cc b/quic/core/quic_packets.cc
index 2098bfe..6ffa39a 100644
--- a/quic/core/quic_packets.cc
+++ b/quic/core/quic_packets.cc
@@ -559,7 +559,7 @@
       version_flag(false),
       use_length_prefix(false),
       version_label(0),
-      version(PROTOCOL_UNSUPPORTED, QUIC_VERSION_UNSUPPORTED),
+      version(ParsedQuicVersion::Unsupported()),
       destination_connection_id(EmptyQuicConnectionId()),
       source_connection_id(EmptyQuicConnectionId()) {}
 
diff --git a/quic/core/quic_transmission_info.h b/quic/core/quic_transmission_info.h
index b6c06a1..b28ca2f 100644
--- a/quic/core/quic_transmission_info.h
+++ b/quic/core/quic_transmission_info.h
@@ -45,8 +45,7 @@
   bool has_crypto_handshake;
   // Stores the packet number of the next retransmission of this packet.
   // Zero if the packet has not been retransmitted.
-  // TODO(fayang): rename this to first_sent_after_loss_ when deprecating
-  // QUIC_VERSION_41.
+  // TODO(fayang): rename this to first_sent_after_loss_.
   QuicPacketNumber retransmission;
   // The largest_acked in the ack frame, if the packet contains an ack.
   QuicPacketNumber largest_acked;
diff --git a/quic/core/quic_types.h b/quic/core/quic_types.h
index 3236c6e..40fd3ad 100644
--- a/quic/core/quic_types.h
+++ b/quic/core/quic_types.h
@@ -361,8 +361,8 @@
   PACKET_3BYTE_PACKET_NUMBER = 3,  // Used in versions 45+.
   PACKET_4BYTE_PACKET_NUMBER = 4,
   IETF_MAX_PACKET_NUMBER_LENGTH = 4,
-  // TODO(rch): Remove these when we remove QUIC_VERSION_43 since these values
-  // are not representable with v46 and above.
+  // TODO(b/145819870): Remove 6 and 8 when we remove Q043 since these values
+  // are not representable with later versions.
   PACKET_6BYTE_PACKET_NUMBER = 6,
   PACKET_8BYTE_PACKET_NUMBER = 8
 };
@@ -392,8 +392,9 @@
   PACKET_PUBLIC_FLAGS_0BYTE_CONNECTION_ID = 0,
   PACKET_PUBLIC_FLAGS_8BYTE_CONNECTION_ID = 1 << 3,
 
-  // QUIC_VERSION_32 and earlier use two bits for an 8 byte
-  // connection id.
+  // Deprecated version 32 and earlier used two bits to indicate an 8-byte
+  // connection ID. We send this from the client because of some broken
+  // middleboxes that are still checking this bit.
   PACKET_PUBLIC_FLAGS_8BYTE_CONNECTION_ID_OLD = 1 << 3 | 1 << 2,
 
   // Bits 4 and 5 describe the packet number length as follows:
diff --git a/quic/core/quic_version_manager_test.cc b/quic/core/quic_version_manager_test.cc
index 6096806..5f95871 100644
--- a/quic/core/quic_version_manager_test.cc
+++ b/quic/core/quic_version_manager_test.cc
@@ -29,14 +29,10 @@
   QuicVersionManager manager(AllSupportedVersions());
 
   ParsedQuicVersionVector expected_parsed_versions;
-  expected_parsed_versions.push_back(
-      ParsedQuicVersion(PROTOCOL_TLS1_3, QUIC_VERSION_50));
-  expected_parsed_versions.push_back(
-      ParsedQuicVersion(PROTOCOL_QUIC_CRYPTO, QUIC_VERSION_50));
-  expected_parsed_versions.push_back(
-      ParsedQuicVersion(PROTOCOL_QUIC_CRYPTO, QUIC_VERSION_46));
-  expected_parsed_versions.push_back(
-      ParsedQuicVersion(PROTOCOL_QUIC_CRYPTO, QUIC_VERSION_43));
+  expected_parsed_versions.push_back(ParsedQuicVersion::T050());
+  expected_parsed_versions.push_back(ParsedQuicVersion::Q050());
+  expected_parsed_versions.push_back(ParsedQuicVersion::Q046());
+  expected_parsed_versions.push_back(ParsedQuicVersion::Q043());
 
   EXPECT_EQ(expected_parsed_versions, manager.GetSupportedVersions());
 
@@ -61,9 +57,8 @@
               ElementsAre("h3-29", "h3-T050", "h3-Q050", "h3-Q046", "h3-Q043"));
 
   QuicEnableVersion(ParsedQuicVersion::Draft27());
-  expected_parsed_versions.insert(
-      expected_parsed_versions.begin() + 1,
-      ParsedQuicVersion(PROTOCOL_TLS1_3, QUIC_VERSION_IETF_DRAFT_27));
+  expected_parsed_versions.insert(expected_parsed_versions.begin() + 1,
+                                  ParsedQuicVersion::Draft27());
   EXPECT_EQ(expected_parsed_versions, manager.GetSupportedVersions());
   EXPECT_EQ(expected_parsed_versions.size() - 3,
             manager.GetSupportedVersionsWithQuicCrypto().size());
@@ -76,9 +71,8 @@
                           "h3-Q043"));
 
   QuicEnableVersion(ParsedQuicVersion::Draft25());
-  expected_parsed_versions.insert(
-      expected_parsed_versions.begin() + 2,
-      ParsedQuicVersion(PROTOCOL_TLS1_3, QUIC_VERSION_IETF_DRAFT_25));
+  expected_parsed_versions.insert(expected_parsed_versions.begin() + 2,
+                                  ParsedQuicVersion::Draft25());
   EXPECT_EQ(expected_parsed_versions, manager.GetSupportedVersions());
   EXPECT_EQ(expected_parsed_versions.size() - 4,
             manager.GetSupportedVersionsWithQuicCrypto().size());
diff --git a/quic/core/quic_versions.cc b/quic/core/quic_versions.cc
index 7e7cc7f..1ba151c 100644
--- a/quic/core/quic_versions.cc
+++ b/quic/core/quic_versions.cc
@@ -233,55 +233,29 @@
 }
 
 QuicVersionLabel CreateQuicVersionLabel(ParsedQuicVersion parsed_version) {
-  char proto = 0;
-  switch (parsed_version.handshake_protocol) {
-    case PROTOCOL_QUIC_CRYPTO:
-      proto = 'Q';
-      break;
-    case PROTOCOL_TLS1_3:
-      proto = 'T';
-      break;
-    default:
-      QUIC_BUG << "Invalid HandshakeProtocol: "
-               << parsed_version.handshake_protocol;
-      return 0;
-  }
   static_assert(SupportedVersions().size() == 7u,
                 "Supported versions out of sync");
-  switch (parsed_version.transport_version) {
-    case QUIC_VERSION_43:
-      return MakeVersionLabel(proto, '0', '4', '3');
-    case QUIC_VERSION_46:
-      return MakeVersionLabel(proto, '0', '4', '6');
-    case QUIC_VERSION_50:
-      return MakeVersionLabel(proto, '0', '5', '0');
-    case QUIC_VERSION_IETF_DRAFT_25:
-      if (parsed_version.handshake_protocol == PROTOCOL_TLS1_3) {
-        return MakeVersionLabel(0xff, 0x00, 0x00, 25);
-      }
-      QUIC_BUG << "QUIC_VERSION_IETF_DRAFT_25 requires TLS";
-      return 0;
-    case QUIC_VERSION_IETF_DRAFT_27:
-      if (parsed_version.handshake_protocol == PROTOCOL_TLS1_3) {
-        return MakeVersionLabel(0xff, 0x00, 0x00, 27);
-      }
-      QUIC_BUG << "QUIC_VERSION_IETF_DRAFT_27 requires TLS";
-      return 0;
-    case QUIC_VERSION_IETF_DRAFT_29:
-      if (parsed_version.handshake_protocol == PROTOCOL_TLS1_3) {
-        return MakeVersionLabel(0xff, 0x00, 0x00, 29);
-      }
-      QUIC_BUG << "QUIC_VERSION_IETF_DRAFT_29 requires TLS";
-      return 0;
-    case QUIC_VERSION_RESERVED_FOR_NEGOTIATION:
-      return CreateRandomVersionLabelForNegotiation();
-    default:
-      // This is a bug because we should never attempt to convert an invalid
-      // QuicTransportVersion to be written to the wire.
-      QUIC_BUG << "Unsupported QuicTransportVersion: "
-               << parsed_version.transport_version;
-      return 0;
+  if (parsed_version == ParsedQuicVersion::Draft29()) {
+    return MakeVersionLabel(0xff, 0x00, 0x00, 29);
+  } else if (parsed_version == ParsedQuicVersion::Draft27()) {
+    return MakeVersionLabel(0xff, 0x00, 0x00, 27);
+  } else if (parsed_version == ParsedQuicVersion::Draft25()) {
+    return MakeVersionLabel(0xff, 0x00, 0x00, 25);
+  } else if (parsed_version == ParsedQuicVersion::T050()) {
+    return MakeVersionLabel('T', '0', '5', '0');
+  } else if (parsed_version == ParsedQuicVersion::Q050()) {
+    return MakeVersionLabel('Q', '0', '5', '0');
+  } else if (parsed_version == ParsedQuicVersion::Q046()) {
+    return MakeVersionLabel('Q', '0', '4', '6');
+  } else if (parsed_version == ParsedQuicVersion::Q043()) {
+    return MakeVersionLabel('Q', '0', '4', '3');
+  } else if (parsed_version == ParsedQuicVersion::ReservedForNegotiation()) {
+    return CreateRandomVersionLabelForNegotiation();
   }
+  QUIC_BUG << "Unsupported version "
+           << QuicVersionToString(parsed_version.transport_version) << " "
+           << HandshakeProtocolToString(parsed_version.handshake_protocol);
+  return 0;
 }
 
 QuicVersionLabelVector CreateQuicVersionLabelVector(
@@ -406,9 +380,8 @@
     quiche::QuicheTextUtils::RemoveLeadingAndTrailingWhitespace(
         &version_string);
     ParsedQuicVersion version = ParseQuicVersionString(version_string);
-    if (version.transport_version == QUIC_VERSION_UNSUPPORTED ||
-        std::find(versions.begin(), versions.end(), version) !=
-            versions.end()) {
+    if (!version.IsKnown() || std::find(versions.begin(), versions.end(),
+                                        version) != versions.end()) {
       continue;
     }
     versions.push_back(version);
@@ -438,38 +411,31 @@
   ParsedQuicVersionVector filtered_versions;
   filtered_versions.reserve(versions.size());
   for (const ParsedQuicVersion& version : versions) {
-    if (version.transport_version == QUIC_VERSION_IETF_DRAFT_29) {
-      QUIC_BUG_IF(version.handshake_protocol != PROTOCOL_TLS1_3);
+    if (version == ParsedQuicVersion::Draft29()) {
       if (!GetQuicReloadableFlag(quic_disable_version_draft_29)) {
         filtered_versions.push_back(version);
       }
-    } else if (version.transport_version == QUIC_VERSION_IETF_DRAFT_27) {
-      QUIC_BUG_IF(version.handshake_protocol != PROTOCOL_TLS1_3);
+    } else if (version == ParsedQuicVersion::Draft27()) {
       if (!GetQuicReloadableFlag(quic_disable_version_draft_27)) {
         filtered_versions.push_back(version);
       }
-    } else if (version.transport_version == QUIC_VERSION_IETF_DRAFT_25) {
-      QUIC_BUG_IF(version.handshake_protocol != PROTOCOL_TLS1_3);
+    } else if (version == ParsedQuicVersion::Draft25()) {
       if (!GetQuicReloadableFlag(quic_disable_version_draft_25)) {
         filtered_versions.push_back(version);
       }
-    } else if (version.transport_version == QUIC_VERSION_50) {
-      if (version.handshake_protocol == PROTOCOL_QUIC_CRYPTO) {
-        if (!GetQuicReloadableFlag(quic_disable_version_q050)) {
-          filtered_versions.push_back(version);
-        }
-      } else {
-        if (!GetQuicReloadableFlag(quic_disable_version_t050)) {
-          filtered_versions.push_back(version);
-        }
+    } else if (version == ParsedQuicVersion::T050()) {
+      if (!GetQuicReloadableFlag(quic_disable_version_t050)) {
+        filtered_versions.push_back(version);
       }
-    } else if (version.transport_version == QUIC_VERSION_46) {
-      QUIC_BUG_IF(version.handshake_protocol != PROTOCOL_QUIC_CRYPTO);
+    } else if (version == ParsedQuicVersion::Q050()) {
+      if (!GetQuicReloadableFlag(quic_disable_version_q050)) {
+        filtered_versions.push_back(version);
+      }
+    } else if (version == ParsedQuicVersion::Q046()) {
       if (!GetQuicReloadableFlag(quic_disable_version_q046)) {
         filtered_versions.push_back(version);
       }
-    } else if (version.transport_version == QUIC_VERSION_43) {
-      QUIC_BUG_IF(version.handshake_protocol != PROTOCOL_QUIC_CRYPTO);
+    } else if (version == ParsedQuicVersion::Q043()) {
       if (!GetQuicReloadableFlag(quic_disable_version_q043)) {
         filtered_versions.push_back(version);
       }
@@ -690,14 +656,12 @@
 }
 
 std::string AlpnForVersion(ParsedQuicVersion parsed_version) {
-  if (parsed_version.handshake_protocol == PROTOCOL_TLS1_3) {
-    if (parsed_version.transport_version == QUIC_VERSION_IETF_DRAFT_29) {
-      return "h3-29";
-    } else if (parsed_version.transport_version == QUIC_VERSION_IETF_DRAFT_27) {
-      return "h3-27";
-    } else if (parsed_version.transport_version == QUIC_VERSION_IETF_DRAFT_25) {
-      return "h3-25";
-    }
+  if (parsed_version == ParsedQuicVersion::Draft29()) {
+    return "h3-29";
+  } else if (parsed_version == ParsedQuicVersion::Draft27()) {
+    return "h3-27";
+  } else if (parsed_version == ParsedQuicVersion::Draft25()) {
+    return "h3-25";
   }
   return "h3-" + ParsedQuicVersionToString(parsed_version);
 }
diff --git a/quic/core/quic_versions_test.cc b/quic/core/quic_versions_test.cc
index 4adb2b9..64f0706 100644
--- a/quic/core/quic_versions_test.cc
+++ b/quic/core/quic_versions_test.cc
@@ -52,8 +52,9 @@
 }
 
 TEST_F(QuicVersionsTest, QuicVersionToQuicVersionLabelUnsupported) {
-  EXPECT_QUIC_BUG(CreateQuicVersionLabel(UnsupportedQuicVersion()),
-                  "Invalid HandshakeProtocol: 0");
+  EXPECT_QUIC_BUG(
+      CreateQuicVersionLabel(UnsupportedQuicVersion()),
+      "Unsupported version QUIC_VERSION_UNSUPPORTED PROTOCOL_UNSUPPORTED");
 }
 
 TEST_F(QuicVersionsTest, KnownAndValid) {