optional_blob_encoding.cc (3236B)
1 /* 2 * Copyright (c) 2023 The WebRTC project authors. All Rights Reserved. 3 * 4 * Use of this source code is governed by a BSD-style license 5 * that can be found in the LICENSE file in the root of the source 6 * tree. An additional intellectual property rights grant can be found 7 * in the file PATENTS. All contributing project authors may 8 * be found in the AUTHORS file in the root of the source tree. 9 */ 10 11 #include "logging/rtc_event_log/encoder/optional_blob_encoding.h" 12 13 #include <cstddef> 14 #include <cstdint> 15 #include <optional> 16 #include <string> 17 #include <vector> 18 19 #include "absl/strings/string_view.h" 20 #include "rtc_base/bit_buffer.h" 21 #include "rtc_base/bitstream_reader.h" 22 #include "rtc_base/checks.h" 23 24 namespace webrtc { 25 26 std::string EncodeOptionalBlobs( 27 const std::vector<std::optional<std::string>>& blobs) { 28 if (blobs.empty()) { 29 return {}; 30 } 31 32 size_t reserve_size_bits = 1; 33 size_t num_blobs_present = 0; 34 for (const auto& blob : blobs) { 35 if (blob.has_value()) { 36 ++num_blobs_present; 37 reserve_size_bits += 38 (BitBufferWriter::kMaxLeb128Length.bytes() + blob->size()) * 8; 39 } 40 } 41 42 if (num_blobs_present == 0) { 43 return {}; 44 } 45 46 const bool all_blobs_present = num_blobs_present == blobs.size(); 47 if (!all_blobs_present) { 48 reserve_size_bits += blobs.size(); 49 } 50 51 std::vector<uint8_t> buffer((reserve_size_bits + 7) / 8); 52 BitBufferWriter writer(buffer.data(), buffer.size()); 53 54 // Write present bits if all blobs are not present. 55 writer.WriteBits(all_blobs_present, 1); 56 if (!all_blobs_present) { 57 for (const auto& blob : blobs) { 58 writer.WriteBits(blob.has_value(), 1); 59 } 60 } 61 62 // Byte align the writer. 63 writer.ConsumeBits(writer.RemainingBitCount() % 8); 64 65 // Write blobs. 66 for (const auto& blob : blobs) { 67 if (blob.has_value()) { 68 writer.WriteLeb128(blob->length()); 69 writer.WriteString(*blob); 70 } 71 } 72 73 size_t bytes_written; 74 size_t bits_written; 75 writer.GetCurrentOffset(&bytes_written, &bits_written); 76 RTC_CHECK_EQ(bits_written, 0); 77 RTC_CHECK_LE(bytes_written, buffer.size()); 78 79 return std::string(buffer.data(), buffer.data() + bytes_written); 80 } 81 82 std::vector<std::optional<std::string>> DecodeOptionalBlobs( 83 absl::string_view encoded_blobs, 84 size_t num_of_blobs) { 85 std::vector<std::optional<std::string>> res(num_of_blobs); 86 if (encoded_blobs.empty() || num_of_blobs == 0) { 87 return res; 88 } 89 90 BitstreamReader reader(encoded_blobs); 91 const bool all_blobs_present = reader.ReadBit(); 92 93 // Read present bits if all blobs are not present. 94 std::vector<uint8_t> present; 95 if (!all_blobs_present) { 96 present.resize(num_of_blobs); 97 for (size_t i = 0; i < num_of_blobs; ++i) { 98 present[i] = reader.ReadBit(); 99 } 100 } 101 102 // Byte align the reader. 103 reader.ConsumeBits(reader.RemainingBitCount() % 8); 104 105 // Read the blobs. 106 for (size_t i = 0; i < num_of_blobs; ++i) { 107 if (!all_blobs_present && !present[i]) { 108 continue; 109 } 110 res[i] = reader.ReadString(reader.ReadLeb128()); 111 } 112 113 // The result is only valid if exactly all bits was consumed during decoding. 114 if (!reader.Ok() || reader.RemainingBitCount() > 0) { 115 return {}; 116 } 117 118 return res; 119 } 120 121 } // namespace webrtc