blob: 917378ed8f341c74d7872f75666fcb75f1f526b1 [file] [log] [blame]
// Copyright 2018 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.
#ifndef QUICHE_QUIC_CORE_QPACK_QPACK_INSTRUCTION_ENCODER_H_
#define QUICHE_QUIC_CORE_QPACK_QPACK_INSTRUCTION_ENCODER_H_
#include <cstddef>
#include <cstdint>
#include <string>
#include "net/third_party/quiche/src/http2/hpack/varint/hpack_varint_encoder.h"
#include "net/third_party/quiche/src/quic/core/qpack/qpack_constants.h"
#include "net/third_party/quiche/src/quic/platform/api/quic_export.h"
#include "net/third_party/quiche/src/quic/platform/api/quic_string_piece.h"
namespace quic {
// Generic instruction encoder class. Takes a QpackLanguage that describes a
// language, that is, a set of instruction opcodes together with a list of
// fields that follow each instruction.
class QUIC_EXPORT_PRIVATE QpackInstructionEncoder {
public:
QpackInstructionEncoder();
QpackInstructionEncoder(const QpackInstructionEncoder&) = delete;
QpackInstructionEncoder& operator=(const QpackInstructionEncoder&) = delete;
// Setters for values to be encoded.
// |name| and |value| must remain valid until the instruction is encoded.
void set_s_bit(bool s_bit) { s_bit_ = s_bit; }
void set_varint(uint64_t varint) { varint_ = varint; }
void set_varint2(uint64_t varint2) { varint2_ = varint2; }
void set_name(QuicStringPiece name) { name_ = name; }
void set_value(QuicStringPiece value) { value_ = value; }
// Start encoding an instruction. Must only be called after the previous
// instruction has been completely encoded.
void Encode(const QpackInstruction* instruction);
// Returns true iff more data remains to be encoded for the current
// instruction. Returns false if there is no current instruction, that is, if
// Encode() has never been called.
bool HasNext() const;
// Encodes the next up to |max_encoded_bytes| octets of the current
// instruction, appending to |output|. Must only be called when HasNext()
// returns true. |max_encoded_bytes| must be positive.
void Next(size_t max_encoded_bytes, std::string* output);
private:
enum class State {
// Write instruction opcode to |byte_|.
kOpcode,
// Select state based on type of current field.
kStartField,
// Write static bit to |byte_|.
kSbit,
// Start encoding an integer (|varint_| or |varint2_| or string length) with
// a prefix, using |byte_| for the high bits.
kVarintStart,
// Resume encoding an integer.
kVarintResume,
// Determine if Huffman encoding should be used for |name_| or |value_|, set
// up |name_| or |value_| and |huffman_encoded_string_| accordingly, and
// write the Huffman bit to |byte_|.
kStartString,
// Write string.
kWriteString
};
// One method for each state. Some encode up to |max_encoded_bytes| octets,
// appending to |output|. Some only change internal state.
void DoOpcode();
void DoStartField();
void DoStaticBit();
size_t DoVarintStart(size_t max_encoded_bytes, std::string* output);
size_t DoVarintResume(size_t max_encoded_bytes, std::string* output);
void DoStartString();
size_t DoWriteString(size_t max_encoded_bytes, std::string* output);
// Storage for field values to be encoded.
bool s_bit_;
uint64_t varint_;
uint64_t varint2_;
// The caller must keep the string that |name_| and |value_| point to
// valid until they are encoded.
QuicStringPiece name_;
QuicStringPiece value_;
// Storage for the Huffman encoded string literal to be written if Huffman
// encoding is used.
std::string huffman_encoded_string_;
// If Huffman encoding is used, points to a substring of
// |huffman_encoded_string_|.
// Otherwise points to a substring of |name_| or |value_|.
QuicStringPiece string_to_write_;
// Storage for a single byte that contains multiple fields, that is, multiple
// states are writing it.
uint8_t byte_;
// Encoding state.
State state_;
// Instruction currently being decoded.
const QpackInstruction* instruction_;
// Field currently being decoded.
QpackInstructionFields::const_iterator field_;
// Decoder instance for decoding integers.
http2::HpackVarintEncoder varint_encoder_;
};
} // namespace quic
#endif // QUICHE_QUIC_CORE_QPACK_QPACK_INSTRUCTION_ENCODER_H_