text: // Copyright (c) 2015 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.
  
  // This file contains data structures and utility functions used for serializing
  // and parsing alternative service header values, common to HTTP/1.1 header
  // fields and HTTP/2 and QUIC ALTSVC frames.  See specification at
  // https://httpwg.github.io/http-extensions/alt-svc.html.
  
  #ifndef QUICHE_SPDY_CORE_SPDY_ALT_SVC_WIRE_FORMAT_H_
  #define QUICHE_SPDY_CORE_SPDY_ALT_SVC_WIRE_FORMAT_H_
  
  #include <cstdint>
  #include <string>
  #include <vector>
  
  #include "absl/container/inlined_vector.h"
  #include "absl/strings/string_view.h"
  #include "quiche/common/platform/api/quiche_export.h"
  
  namespace spdy {
  
  namespace test {
  class SpdyAltSvcWireFormatPeer;
  }  // namespace test
  
  class QUICHE_EXPORT_PRIVATE SpdyAltSvcWireFormat {
   public:
    using VersionVector = absl::InlinedVector<uint32_t, 8>;
  
    struct QUICHE_EXPORT_PRIVATE AlternativeService {
      std::string protocol_id;
      std::string host;
  
      // Default is 0: invalid port.
      uint16_t port = 0;
      // Default is one day.
      uint32_t max_age_seconds = 86400;
      // Default is empty: unspecified version.
      VersionVector version;
  
      AlternativeService();
      AlternativeService(const std::string& protocol_id, const std::string& host,
                         uint16_t port, uint32_t max_age_seconds,
                         VersionVector version);
      AlternativeService(const AlternativeService& other);
      ~AlternativeService();
  
      bool operator==(const AlternativeService& other) const {
        return protocol_id == other.protocol_id && host == other.host &&
               port == other.port && version == other.version &&
               max_age_seconds == other.max_age_seconds;
      }
    };
    // An empty vector means alternative services should be cleared for given
    // origin.  Note that the wire format for this is the string "clear", not an
    // empty value (which is invalid).
    typedef std::vector<AlternativeService> AlternativeServiceVector;
  
    friend class test::SpdyAltSvcWireFormatPeer;
    static bool ParseHeaderFieldValue(absl::string_view value,
                                      AlternativeServiceVector* altsvc_vector);
    static std::string SerializeHeaderFieldValue(
        const AlternativeServiceVector& altsvc_vector);
  
   private:
    // Forward |*c| over space and tab or until |end| is reached.
    static void SkipWhiteSpace(absl::string_view::const_iterator* c,
                               absl::string_view::const_iterator end);
    // Decode percent-decoded string between |c| and |end| into |*output|.
    // Return true on success, false if input is invalid.
    static bool PercentDecode(absl::string_view::const_iterator c,
                              absl::string_view::const_iterator end,
                              std::string* output);
    // Parse the authority part of Alt-Svc between |c| and |end| into |*host| and
    // |*port|.  Return true on success, false if input is invalid.
    static bool ParseAltAuthority(absl::string_view::const_iterator c,
                                  absl::string_view::const_iterator end,
                                  std::string* host, uint16_t* port);
    // Parse a positive integer between |c| and |end| into |*value|.
    // Return true on success, false if input is not a positive integer or it
    // cannot be represented on uint16_t.
    static bool ParsePositiveInteger16(absl::string_view::const_iterator c,
                                       absl::string_view::const_iterator end,
                                       uint16_t* value);
    // Parse a positive integer between |c| and |end| into |*value|.
    // Return true on success, false if input is not a positive integer or it
    // cannot be represented on uint32_t.
    static bool ParsePositiveInteger32(absl::string_view::const_iterator c,
                                       absl::string_view::const_iterator end,
                                       uint32_t* value);
    // Parse |c| as hexadecimal digit, case insensitive.  |c| must be [0-9a-fA-F].
    // Output is between 0 and 15.
    static char HexDigitToInt(char c);
    // Parse |data| as hexadecimal number into |*value|.  |data| must only contain
    // hexadecimal digits, no "0x" prefix.
    // Return true on success, false if input is empty, not valid hexadecimal
    // number, or cannot be represented on uint32_t.
    static bool HexDecodeToUInt32(absl::string_view data, uint32_t* value);
  };
  
  }  // namespace spdy
  
  #endif  // QUICHE_SPDY_CORE_SPDY_ALT_SVC_WIRE_FORMAT_H_
  