blob: 0d83ff6da5ce31bb96c392a0ec147d3a9efcdece [file] [log] [blame]
// Copyright 2016 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.
#include "net/third_party/http2/hpack/varint/hpack_varint_decoder.h"
#include "net/third_party/http2/platform/api/http2_string_utils.h"
namespace http2 {
DecodeStatus HpackVarintDecoder::Start(uint8_t prefix_value,
uint8_t prefix_length,
DecodeBuffer* db) {
DCHECK_LE(3u, prefix_length);
DCHECK_LE(prefix_length, 7u);
// |prefix_mask| defines the sequence of low-order bits of the first byte
// that encode the prefix of the value. It is also the marker in those bits
// of the first byte indicating that at least one extension byte is needed.
const uint8_t prefix_mask = (1 << prefix_length) - 1;
// Ignore the bits that aren't a part of the prefix of the varint.
value_ = prefix_value & prefix_mask;
if (value_ < prefix_mask) {
MarkDone();
return DecodeStatus::kDecodeDone;
}
offset_ = 0;
return Resume(db);
}
DecodeStatus HpackVarintDecoder::StartExtended(uint8_t prefix_length,
DecodeBuffer* db) {
DCHECK_LE(3u, prefix_length);
DCHECK_LE(prefix_length, 7u);
value_ = (1 << prefix_length) - 1;
offset_ = 0;
return Resume(db);
}
DecodeStatus HpackVarintDecoder::Resume(DecodeBuffer* db) {
CheckNotDone();
do {
if (db->Empty()) {
return DecodeStatus::kDecodeInProgress;
}
uint8_t byte = db->DecodeUInt8();
if (offset_ == MaxOffset() && byte != 0)
break;
value_ += (byte & 0x7f) << offset_;
if ((byte & 0x80) == 0) {
MarkDone();
return DecodeStatus::kDecodeDone;
}
offset_ += 7;
} while (offset_ <= MaxOffset());
DLOG(WARNING) << "Variable length int encoding is too large or too long. "
<< DebugString();
MarkDone();
return DecodeStatus::kDecodeError;
}
uint32_t HpackVarintDecoder::value() const {
CheckDone();
return value_;
}
void HpackVarintDecoder::set_value(uint32_t v) {
MarkDone();
value_ = v;
}
Http2String HpackVarintDecoder::DebugString() const {
return Http2StrCat("HpackVarintDecoder(value=", value_, ", offset=", offset_,
")");
}
DecodeStatus HpackVarintDecoder::StartForTest(uint8_t prefix_value,
uint8_t prefix_length,
DecodeBuffer* db) {
return Start(prefix_value, prefix_length, db);
}
DecodeStatus HpackVarintDecoder::StartExtendedForTest(uint8_t prefix_length,
DecodeBuffer* db) {
return StartExtended(prefix_length, db);
}
DecodeStatus HpackVarintDecoder::ResumeForTest(DecodeBuffer* db) {
return Resume(db);
}
} // namespace http2