blob: 6b2a8a45f1e7e7f5b7f6e3a7374fdfb1ceff7a7c [file]
// Copyright 2022 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 "quiche/quic/core/quic_stream_priority.h"
#include <optional>
#include <string>
#include <vector>
#include "quiche/common/platform/api/quiche_bug_tracker.h"
#include "quiche/common/structured_headers.h"
namespace quic {
std::string SerializePriorityFieldValue(HttpStreamPriority priority) {
std::vector<quiche::structured_headers::DictionaryMember> members;
if (priority.urgency != HttpStreamPriority::kDefaultUrgency &&
priority.urgency >= HttpStreamPriority::kMinimumUrgency &&
priority.urgency <= HttpStreamPriority::kMaximumUrgency) {
members.emplace_back(HttpStreamPriority::kUrgencyKey,
quiche::structured_headers::Item(
static_cast<int64_t>(priority.urgency)));
}
if (priority.incremental != HttpStreamPriority::kDefaultIncremental) {
members.emplace_back(
HttpStreamPriority::kIncrementalKey,
quiche::structured_headers::Item(priority.incremental));
}
std::optional<std::string> priority_field_value =
quiche::structured_headers::SerializeDictionary(
quiche::structured_headers::Dictionary(std::move(members)));
if (!priority_field_value.has_value()) {
QUICHE_BUG(priority_field_value_serialization_failed);
return "";
}
return *std::move(priority_field_value);
}
std::optional<HttpStreamPriority> ParsePriorityFieldValue(
absl::string_view priority_field_value) {
std::optional<quiche::structured_headers::Dictionary> parsed_dictionary =
quiche::structured_headers::ParseDictionary(priority_field_value);
if (!parsed_dictionary.has_value()) {
return std::nullopt;
}
uint8_t urgency = HttpStreamPriority::kDefaultUrgency;
bool incremental = HttpStreamPriority::kDefaultIncremental;
for (const auto& [name, value] : *parsed_dictionary) {
const quiche::structured_headers::ParameterizedItem* item =
value.GetIfItem();
if (!item) {
continue;
}
if (name == HttpStreamPriority::kUrgencyKey) {
const int64_t* parsed_urgency = item->item.GetIfInteger();
// Ignore out-of-range values.
if (parsed_urgency &&
*parsed_urgency >= HttpStreamPriority::kMinimumUrgency &&
*parsed_urgency <= HttpStreamPriority::kMaximumUrgency) {
urgency = *parsed_urgency;
}
} else if (name == HttpStreamPriority::kIncrementalKey) {
if (const bool* parsed_incremental = item->item.GetIfBoolean()) {
incremental = *parsed_incremental;
}
}
}
return HttpStreamPriority{urgency, incremental};
}
} // namespace quic