// Copyright 2022 The Chromium Authors // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. #ifndef COMPONENTS_WEB_PACKAGE_INPUT_READER_H_ #define COMPONENTS_WEB_PACKAGE_INPUT_READER_H_ #include "base/big_endian.h" #include "base/containers/span.h" #include "base/strings/string_piece_forward.h" #include "third_party/abseil-cpp/absl/types/optional.h" namespace web_package { // https://datatracker.ietf.org/doc/html/rfc8949.html#section-3.1 enum class CBORType { // kUnsignedInt = 0, // kNegativeInt = 1, kByteString = 2, kTextString = 3, kArray = 4, kMap = 5, }; // The maximum length of the CBOR item header (type and argument). // https://datatracker.ietf.org/doc/html/rfc8949.html#section-3 // When the additional information (the low-order 5 bits of the first // byte) is 27, the argument's value is held in the following 8 bytes. constexpr uint64_t kMaxCBORItemHeaderSize = 9; // A utility class for reading various values from input buffer. class InputReader { public: explicit InputReader(base::span buf) : buf_(buf) {} InputReader(const InputReader&) = delete; InputReader& operator=(const InputReader&) = delete; uint64_t CurrentOffset() const { return current_offset_; } size_t Size() const { return buf_.size(); } absl::optional ReadByte(); template bool ReadBigEndian(T* out) { auto bytes = ReadBytes(sizeof(T)); if (!bytes) return false; base::ReadBigEndian(bytes->data(), out); return true; } absl::optional> ReadBytes(size_t n); absl::optional ReadString(size_t n); // Parses the type and argument of a CBOR item from the input head. If parsed // successfully and the type matches |expected_type|, returns the argument. // Otherwise returns nullopt. absl::optional ReadCBORHeader(CBORType expected_type); private: absl::optional> ReadTypeAndArgument(); void Advance(size_t n); base::span buf_; uint64_t current_offset_ = 0; }; } // namespace web_package #endif // COMPONENTS_WEB_PACKAGE_INPUT_READER_H_