xref: /aosp_15_r20/external/cronet/net/third_party/quiche/src/quiche/http2/hpack/varint/hpack_varint_encoder.cc (revision 6777b5387eb2ff775bb5750e3f5d96f37fb7352b)
1 // Copyright 2016 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
4 
5 #include "quiche/http2/hpack/varint/hpack_varint_encoder.h"
6 
7 #include <limits>
8 
9 #include "quiche/common/platform/api/quiche_logging.h"
10 
11 namespace http2 {
12 
13 // static
Encode(uint8_t high_bits,uint8_t prefix_length,uint64_t varint,std::string * output)14 void HpackVarintEncoder::Encode(uint8_t high_bits, uint8_t prefix_length,
15                                 uint64_t varint, std::string* output) {
16   QUICHE_DCHECK_LE(1u, prefix_length);
17   QUICHE_DCHECK_LE(prefix_length, 8u);
18 
19   // prefix_mask defines the sequence of low-order bits of the first byte
20   // that encode the prefix of the value. It is also the marker in those bits
21   // of the first byte indicating that at least one extension byte is needed.
22   const uint8_t prefix_mask = (1 << prefix_length) - 1;
23   QUICHE_DCHECK_EQ(0, high_bits & prefix_mask);
24 
25   if (varint < prefix_mask) {
26     // The integer fits into the prefix in its entirety.
27     unsigned char first_byte = high_bits | static_cast<unsigned char>(varint);
28     output->push_back(first_byte);
29     return;
30   }
31 
32   // Extension bytes are needed.
33   unsigned char first_byte = high_bits | prefix_mask;
34   output->push_back(first_byte);
35 
36   varint -= prefix_mask;
37   while (varint >= 128) {
38     // Encode the next seven bits, with continuation bit set to one.
39     output->push_back(0b10000000 | (varint % 128));
40     varint >>= 7;
41   }
42 
43   // Encode final seven bits, with continuation bit set to zero.
44   output->push_back(varint);
45 }
46 
47 }  // namespace http2
48