input_reader.cc 2.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990
  1. // Copyright 2022 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. #include "components/web_package/input_reader.h"
  5. #include "base/strings/string_util.h"
  6. namespace web_package {
  7. absl::optional<uint8_t> InputReader::ReadByte() {
  8. if (buf_.empty())
  9. return absl::nullopt;
  10. uint8_t byte = buf_[0];
  11. Advance(1);
  12. return byte;
  13. }
  14. absl::optional<base::span<const uint8_t>> InputReader::ReadBytes(size_t n) {
  15. if (buf_.size() < n)
  16. return absl::nullopt;
  17. auto result = buf_.subspan(0, n);
  18. Advance(n);
  19. return result;
  20. }
  21. absl::optional<base::StringPiece> InputReader::ReadString(size_t n) {
  22. auto bytes = ReadBytes(n);
  23. if (!bytes)
  24. return absl::nullopt;
  25. base::StringPiece str(reinterpret_cast<const char*>(bytes->data()),
  26. bytes->size());
  27. if (!base::IsStringUTF8(str))
  28. return absl::nullopt;
  29. return str;
  30. }
  31. absl::optional<uint64_t> InputReader::ReadCBORHeader(CBORType expected_type) {
  32. auto pair = ReadTypeAndArgument();
  33. if (!pair || pair->first != expected_type)
  34. return absl::nullopt;
  35. return pair->second;
  36. }
  37. // https://datatracker.ietf.org/doc/html/rfc8949.html#section-3
  38. absl::optional<std::pair<CBORType, uint64_t>>
  39. InputReader::ReadTypeAndArgument() {
  40. absl::optional<uint8_t> first_byte = ReadByte();
  41. if (!first_byte)
  42. return absl::nullopt;
  43. CBORType type = static_cast<CBORType>((*first_byte & 0xE0) / 0x20);
  44. uint8_t b = *first_byte & 0x1F;
  45. if (b <= 23)
  46. return std::make_pair(type, b);
  47. if (b == 24) {
  48. auto content = ReadByte();
  49. if (!content || *content < 24)
  50. return absl::nullopt;
  51. return std::make_pair(type, *content);
  52. }
  53. if (b == 25) {
  54. uint16_t content;
  55. if (!ReadBigEndian(&content) || content >> 8 == 0)
  56. return absl::nullopt;
  57. return std::make_pair(type, content);
  58. }
  59. if (b == 26) {
  60. uint32_t content;
  61. if (!ReadBigEndian(&content) || content >> 16 == 0)
  62. return absl::nullopt;
  63. return std::make_pair(type, content);
  64. }
  65. if (b == 27) {
  66. uint64_t content;
  67. if (!ReadBigEndian(&content) || content >> 32 == 0)
  68. return absl::nullopt;
  69. return std::make_pair(type, content);
  70. }
  71. return absl::nullopt;
  72. }
  73. void InputReader::Advance(size_t n) {
  74. DCHECK_LE(n, buf_.size());
  75. buf_ = buf_.subspan(n);
  76. current_offset_ += n;
  77. }
  78. } // namespace web_package