No public description

PiperOrigin-RevId: 959038640
diff --git a/quiche/common/structured_headers.cc b/quiche/common/structured_headers.cc
index 2396de0..6e002f5 100644
--- a/quiche/common/structured_headers.cc
+++ b/quiche/common/structured_headers.cc
@@ -16,7 +16,6 @@
 #include "absl/algorithm/container.h"
 #include "absl/base/attributes.h"
 #include "absl/container/flat_hash_set.h"
-#include "absl/functional/overload.h"
 #include "absl/strings/ascii.h"
 #include "absl/strings/escaping.h"
 #include "absl/strings/numbers.h"
@@ -584,8 +583,6 @@
   const bool strict_;
 };
 
-}  // namespace
-
 // Serializer for (a subset of) Structured Field Values for HTTP defined in
 // [RFC8941]. Note that this serializer does not attempt to support [SH09].
 class StructuredHeaderSerializer {
@@ -599,7 +596,7 @@
   std::string Output() && { return std::move(output_).str(); }
 
   // Serializes a List ([RFC8941] 4.1.1).
-  [[nodiscard]] bool WriteList(const List& value) {
+  bool WriteList(const List& value) {
     bool first = true;
     for (const auto& member : value) {
       if (!first) output_ << ", ";
@@ -610,108 +607,105 @@
   }
 
   // Serializes an Item ([RFC8941] 4.1.3).
-  [[nodiscard]] bool WriteItem(const ParameterizedItem& value) {
+  bool WriteItem(const ParameterizedItem& value) {
     if (!WriteBareItem(value.item)) return false;
     return WriteParameters(value.params);
   }
 
   // Serializes an Item ([RFC8941] 4.1.3).
-  [[nodiscard]] bool WriteBareItem(const Item& value) {
-    return std::visit(
-        absl::Overload{
-            [&](const std::string& string) {
-              // Serializes a String ([RFC8941] 4.1.6).
-              output_ << "\"";
-              for (const char c : string) {
-                if (!absl::ascii_isprint(c)) return false;
-                if (c == '\\' || c == '\"') output_ << "\\";
-                output_ << c;
-              }
-              output_ << "\"";
-              return true;
-            },
-            [&](const Item::Token& token) {
-              // Serializes a Token ([RFC8941] 4.1.7).
-              if (!IsValidToken(token.value)) {
-                return false;
-              }
-              output_ << token.value;
-              return true;
-            },
-            [&](const Item::ByteSequence& byte_sequence) {
-              // Serializes a Byte Sequence ([RFC8941] 4.1.8).
-              output_ << ":";
-              output_ << absl::Base64Escape(byte_sequence.value);
-              output_ << ":";
-              return true;
-            },
-            [&](int64_t value) {
-              // Serializes an Integer ([RFC8941] 4.1.4).
-              if (value > kMaxInteger || value < kMinInteger) return false;
-              output_ << value;
-              return true;
-            },
-            [&](double decimal_value) {
-              // Serializes a Decimal ([RFC8941] 4.1.5).
-              if (!std::isfinite(decimal_value) ||
-                  fabs(decimal_value) >= kTooLargeDecimal)
-                return false;
+  bool WriteBareItem(const Item& value) {
+    if (value.is_string()) {
+      // Serializes a String ([RFC8941] 4.1.6).
+      output_ << "\"";
+      for (const char& c : value.GetString()) {
+        if (!absl::ascii_isprint(c)) return false;
+        if (c == '\\' || c == '\"') output_ << "\\";
+        output_ << c;
+      }
+      output_ << "\"";
+      return true;
+    }
+    if (value.is_token()) {
+      // Serializes a Token ([RFC8941] 4.1.7).
+      if (!IsValidToken(value.GetString())) {
+        return false;
+      }
+      output_ << value.GetString();
+      return true;
+    }
+    if (value.is_byte_sequence()) {
+      // Serializes a Byte Sequence ([RFC8941] 4.1.8).
+      output_ << ":";
+      output_ << absl::Base64Escape(value.GetString());
+      output_ << ":";
+      return true;
+    }
+    if (value.is_integer()) {
+      // Serializes an Integer ([RFC8941] 4.1.4).
+      if (value.GetInteger() > kMaxInteger || value.GetInteger() < kMinInteger)
+        return false;
+      output_ << value.GetInteger();
+      return true;
+    }
+    if (value.is_decimal()) {
+      // Serializes a Decimal ([RFC8941] 4.1.5).
+      double decimal_value = value.GetDecimal();
+      if (!std::isfinite(decimal_value) ||
+          fabs(decimal_value) >= kTooLargeDecimal)
+        return false;
 
-              // Handle sign separately to simplify the rest of the formatting.
-              if (decimal_value < 0) output_ << "-";
-              // Unconditionally take absolute value to ensure that -0 is
-              // serialized as "0.0", with no negative sign, as required by
-              // spec. (4.1.5, step 2).
-              decimal_value = fabs(decimal_value);
-              double remainder = fmod(decimal_value, 0.002);
-              if (remainder == 0.0005) {
-                // Value ended in exactly 0.0005, 0.0025, 0.0045, etc. Round
-                // down.
-                decimal_value -= 0.0005;
-              } else if (remainder == 0.0015) {
-                // Value ended in exactly 0.0015, 0.0035, 0,0055, etc. Round up.
-                decimal_value += 0.0005;
-              } else {
-                // Standard rounding will work in all other cases.
-                decimal_value = round(decimal_value * 1000.0) / 1000.0;
-              }
+      // Handle sign separately to simplify the rest of the formatting.
+      if (decimal_value < 0) output_ << "-";
+      // Unconditionally take absolute value to ensure that -0 is serialized as
+      // "0.0", with no negative sign, as required by spec. (4.1.5, step 2).
+      decimal_value = fabs(decimal_value);
+      double remainder = fmod(decimal_value, 0.002);
+      if (remainder == 0.0005) {
+        // Value ended in exactly 0.0005, 0.0025, 0.0045, etc. Round down.
+        decimal_value -= 0.0005;
+      } else if (remainder == 0.0015) {
+        // Value ended in exactly 0.0015, 0.0035, 0,0055, etc. Round up.
+        decimal_value += 0.0005;
+      } else {
+        // Standard rounding will work in all other cases.
+        decimal_value = round(decimal_value * 1000.0) / 1000.0;
+      }
 
-              // Use standard library functions to write the decimal, and then
-              // truncate if necessary to conform to spec.
+      // Use standard library functions to write the decimal, and then truncate
+      // if necessary to conform to spec.
 
-              // Maximum is 12 integer digits, one decimal point, three
-              // fractional digits, and a null terminator.
-              char buffer[17];
-              absl::SNPrintF(buffer, std::size(buffer), "%#.3f", decimal_value);
+      // Maximum is 12 integer digits, one decimal point, three fractional
+      // digits, and a null terminator.
+      char buffer[17];
+      absl::SNPrintF(buffer, std::size(buffer), "%#.3f", decimal_value);
 
-              // Strip any trailing 0s after the decimal point, but leave at
-              // least one digit after it in all cases. (So 1.230 becomes 1.23,
-              // but 1.000 becomes 1.0.)
-              absl::string_view formatted_number(buffer);
-              auto truncate_index = formatted_number.find_last_not_of('0');
-              if (formatted_number[truncate_index] == '.') truncate_index++;
-              output_ << formatted_number.substr(0, truncate_index + 1);
-              return true;
-            },
-            [&](bool value) {
-              // Serializes a Boolean ([RFC8941] 4.1.9).
-              output_ << (value ? "?1" : "?0");
-              return true;
-            },
-            [](std::monostate) { return false; },
-        },
-        value.value_);
+      // Strip any trailing 0s after the decimal point, but leave at least one
+      // digit after it in all cases. (So 1.230 becomes 1.23, but 1.000 becomes
+      // 1.0.)
+      absl::string_view formatted_number(buffer);
+      auto truncate_index = formatted_number.find_last_not_of('0');
+      if (formatted_number[truncate_index] == '.') truncate_index++;
+      output_ << formatted_number.substr(0, truncate_index + 1);
+      return true;
+    }
+    if (value.is_boolean()) {
+      // Serializes a Boolean ([RFC8941] 4.1.9).
+      output_ << (value.GetBoolean() ? "?1" : "?0");
+      return true;
+    }
+    return false;
   }
 
   // Serializes a Dictionary ([RFC8941] 4.1.2).
-  [[nodiscard]] bool WriteDictionary(const Dictionary& value) {
+  bool WriteDictionary(const Dictionary& value) {
     bool first = true;
     for (const auto& [dict_key, dict_value] : value) {
       if (!first) output_ << ", ";
       if (!WriteKey(dict_key)) return false;
       first = false;
       if (!dict_value.member_is_inner_list && !dict_value.member.empty() &&
-          IsBooleanTrue(dict_value.member.front().item)) {
+          dict_value.member.front().item.is_boolean() &&
+          dict_value.member.front().item.GetBoolean()) {
         if (!WriteParameters(dict_value.params)) return false;
       } else {
         output_ << "=";
@@ -722,13 +716,7 @@
   }
 
  private:
-  static bool IsBooleanTrue(const Item& item) {
-    const bool* value = item.GetIfBoolean();
-    return value && *value;
-  }
-
-  [[nodiscard]] bool WriteParameterizedMember(
-      const ParameterizedMember& value) {
+  bool WriteParameterizedMember(const ParameterizedMember& value) {
     // Serializes a parameterized member ([RFC8941] 4.1.1).
     if (value.member_is_inner_list) {
       if (!WriteInnerList(value.member)) return false;
@@ -739,8 +727,7 @@
     return WriteParameters(value.params);
   }
 
-  [[nodiscard]] bool WriteInnerList(
-      const std::vector<ParameterizedItem>& value) {
+  bool WriteInnerList(const std::vector<ParameterizedItem>& value) {
     // Serializes an inner list ([RFC8941] 4.1.1.1).
     output_ << "(";
     bool first = true;
@@ -753,19 +740,23 @@
     return true;
   }
 
-  [[nodiscard]] bool WriteParameters(const Parameters& value) {
+  bool WriteParameters(const Parameters& value) {
     // Serializes a parameter list ([RFC8941] 4.1.1.2).
-    for (const auto& [param_name, param_value] : value) {
+    for (const auto& param_name_and_value : value) {
+      const std::string& param_name = param_name_and_value.first;
+      const Item& param_value = param_name_and_value.second;
       output_ << ";";
       if (!WriteKey(param_name)) return false;
-      if (param_value.is_null() || IsBooleanTrue(param_value)) continue;
-      output_ << "=";
-      if (!WriteBareItem(param_value)) return false;
+      if (!param_value.is_null()) {
+        if (param_value.is_boolean() && param_value.GetBoolean()) continue;
+        output_ << "=";
+        if (!WriteBareItem(param_value)) return false;
+      }
     }
     return true;
   }
 
-  [[nodiscard]] bool WriteKey(const std::string& value) {
+  bool WriteKey(const std::string& value) {
     // Serializes a Key ([RFC8941] 4.1.1.3).
     if (value.empty()) return false;
     if (value.find_first_not_of(kKeyChars) != std::string::npos) return false;
@@ -777,6 +768,8 @@
   std::ostringstream output_;
 };
 
+}  // namespace
+
 absl::string_view ItemTypeToString(Item::ItemType type) {
   switch (type) {
     case Item::kNullType:
@@ -851,23 +844,17 @@
 std::string* Item::GetIfString() { return std::get_if<kStringType>(&value_); }
 
 const std::string* Item::GetIfToken() const {
-  const auto* token = std::get_if<kTokenType>(&value_);
-  return token ? &token->value : nullptr;
+  return std::get_if<kTokenType>(&value_);
 }
 
-std::string* Item::GetIfToken() {
-  auto* token = std::get_if<kTokenType>(&value_);
-  return token ? &token->value : nullptr;
-}
+std::string* Item::GetIfToken() { return std::get_if<kTokenType>(&value_); }
 
 const std::string* Item::GetIfByteSequence() const {
-  const auto* byte_sequence = std::get_if<kByteSequenceType>(&value_);
-  return byte_sequence ? &byte_sequence->value : nullptr;
+  return std::get_if<kByteSequenceType>(&value_);
 }
 
 std::string* Item::GetIfByteSequence() {
-  auto* byte_sequence = std::get_if<kByteSequenceType>(&value_);
-  return byte_sequence ? &byte_sequence->value : nullptr;
+  return std::get_if<kByteSequenceType>(&value_);
 }
 
 const bool* Item::GetIfBoolean() const {
diff --git a/quiche/common/structured_headers.h b/quiche/common/structured_headers.h
index c86c13f..a36a497 100644
--- a/quiche/common/structured_headers.h
+++ b/quiche/common/structured_headers.h
@@ -133,10 +133,6 @@
       const std::string* operator()(const int64_t&) { return nullptr; }
       const std::string* operator()(const double&) { return nullptr; }
       const std::string* operator()(const std::string& value) { return &value; }
-      const std::string* operator()(const Token& value) { return &value.value; }
-      const std::string* operator()(const ByteSequence& value) {
-        return &value.value;
-      }
       const std::string* operator()(const bool&) { return nullptr; }
     };
     const std::string* value = std::visit(Visitor(), value_);
@@ -147,21 +143,8 @@
   ItemType Type() const { return static_cast<ItemType>(value_.index()); }
 
  private:
-  friend class StructuredHeaderSerializer;
-
-  // Wrapper types to permit simplified use of `std::visit`.
-  struct Token {
-    std::string value;
-    friend bool operator==(const Token&, const Token&) = default;
-  };
-
-  struct ByteSequence {
-    std::string value;
-    friend bool operator==(const ByteSequence&, const ByteSequence&) = default;
-  };
-
-  std::variant<std::monostate, int64_t, double, std::string, Token,
-               ByteSequence, bool>
+  std::variant<std::monostate, int64_t, double, std::string, std::string,
+               std::string, bool>
       value_;
 };
 
diff --git a/quiche/common/structured_headers_test.cc b/quiche/common/structured_headers_test.cc
index 6c0fa90..2b6a575 100644
--- a/quiche/common/structured_headers_test.cc
+++ b/quiche/common/structured_headers_test.cc
@@ -795,23 +795,5 @@
   }
 }
 
-TEST(StructuredHeaderTest, GetIfToken) {
-  const Item kValue("abc", Item::kTokenType);
-  EXPECT_FALSE(kValue.GetIfByteSequence());
-  EXPECT_FALSE(kValue.GetIfString());
-  const std::string* ptr = kValue.GetIfToken();
-  ASSERT_TRUE(ptr);
-  EXPECT_EQ(*ptr, "abc");
-}
-
-TEST(StructuredHeaderTest, GetIfByteSequence) {
-  const Item kValue("def", Item::kByteSequenceType);
-  EXPECT_FALSE(kValue.GetIfString());
-  EXPECT_FALSE(kValue.GetIfToken());
-  const std::string* ptr = kValue.GetIfByteSequence();
-  ASSERT_TRUE(ptr);
-  EXPECT_EQ(*ptr, "def");
-}
-
 }  // namespace structured_headers
 }  // namespace quiche