xref: /aosp_15_r20/external/webrtc/logging/rtc_event_log/events/rtc_event_field_encoding_parser.cc (revision d9f758449e529ab9291ac668be2861e7a55c2422)
1 
2 /*
3  *  Copyright (c) 2021 The WebRTC project authors. All Rights Reserved.
4  *
5  *  Use of this source code is governed by a BSD-style license
6  *  that can be found in the LICENSE file in the root of the source
7  *  tree. An additional intellectual property rights grant can be found
8  *  in the file PATENTS.  All contributing project authors may
9  *  be found in the AUTHORS file in the root of the source tree.
10  */
11 
12 #include "logging/rtc_event_log/events/rtc_event_field_encoding_parser.h"
13 
14 #include "absl/strings/string_view.h"
15 #include "absl/types/optional.h"
16 #include "logging/rtc_event_log/encoder/var_int.h"
17 #include "logging/rtc_event_log/events/rtc_event_field_encoding.h"
18 #include "rtc_base/bitstream_reader.h"
19 #include "rtc_base/checks.h"
20 
21 namespace {
ConvertFieldType(uint64_t value)22 absl::optional<webrtc::FieldType> ConvertFieldType(uint64_t value) {
23   switch (value) {
24     case static_cast<uint64_t>(webrtc::FieldType::kFixed8):
25       return webrtc::FieldType::kFixed8;
26     case static_cast<uint64_t>(webrtc::FieldType::kFixed32):
27       return webrtc::FieldType::kFixed32;
28     case static_cast<uint64_t>(webrtc::FieldType::kFixed64):
29       return webrtc::FieldType::kFixed64;
30     case static_cast<uint64_t>(webrtc::FieldType::kVarInt):
31       return webrtc::FieldType::kVarInt;
32     case static_cast<uint64_t>(webrtc::FieldType::kString):
33       return webrtc::FieldType::kString;
34     default:
35       return absl::nullopt;
36   }
37 }
38 }  // namespace
39 
40 namespace webrtc {
41 
ReadLittleEndian(uint8_t bytes)42 uint64_t EventParser::ReadLittleEndian(uint8_t bytes) {
43   RTC_DCHECK_LE(bytes, sizeof(uint64_t));
44   RTC_DCHECK_GE(bytes, 1);
45 
46   uint64_t value = 0;
47 
48   if (bytes > pending_data_.length()) {
49     SetError();
50     return value;
51   }
52 
53   const uint8_t* p = reinterpret_cast<const uint8_t*>(pending_data_.data());
54   unsigned int shift = 0;
55   uint8_t remaining = bytes;
56   while (remaining > 0) {
57     value += (static_cast<uint64_t>(*p) << shift);
58     shift += 8;
59     ++p;
60     --remaining;
61   }
62 
63   pending_data_ = pending_data_.substr(bytes);
64   return value;
65 }
66 
ReadVarInt()67 uint64_t EventParser::ReadVarInt() {
68   uint64_t output = 0;
69   bool success;
70   std::tie(success, pending_data_) = DecodeVarInt(pending_data_, &output);
71   if (!success) {
72     SetError();
73   }
74   return output;
75 }
76 
ReadOptionalValuePositions()77 uint64_t EventParser::ReadOptionalValuePositions() {
78   RTC_DCHECK(positions_.empty());
79   size_t bits_to_read = NumEventsInBatch();
80   positions_.reserve(bits_to_read);
81   if (pending_data_.size() * 8 < bits_to_read) {
82     SetError();
83     return 0;
84   }
85 
86   BitstreamReader reader(pending_data_);
87   for (size_t i = 0; i < bits_to_read; i++) {
88     positions_.push_back(reader.ReadBit());
89   }
90   if (!reader.Ok()) {
91     SetError();
92     return 0;
93   }
94 
95   size_t num_existing_values =
96       std::count(positions_.begin(), positions_.end(), 1);
97   pending_data_ = pending_data_.substr((bits_to_read + 7) / 8);
98   return num_existing_values;
99 }
100 
ReadSingleValue(FieldType field_type)101 uint64_t EventParser::ReadSingleValue(FieldType field_type) {
102   switch (field_type) {
103     case FieldType::kFixed8:
104       return ReadLittleEndian(/*bytes=*/1);
105     case FieldType::kFixed32:
106       return ReadLittleEndian(/*bytes=*/4);
107     case FieldType::kFixed64:
108       return ReadLittleEndian(/*bytes=*/8);
109     case FieldType::kVarInt:
110       return ReadVarInt();
111     case FieldType::kString:
112       RTC_DCHECK_NOTREACHED();
113       SetError();
114       return 0;
115   }
116   RTC_DCHECK_NOTREACHED();
117   SetError();
118   return 0;
119 }
120 
ReadDeltasAndPopulateValues(FixedLengthEncodingParametersV3 params,uint64_t num_deltas,uint64_t base)121 void EventParser::ReadDeltasAndPopulateValues(
122     FixedLengthEncodingParametersV3 params,
123     uint64_t num_deltas,
124     uint64_t base) {
125   RTC_DCHECK(values_.empty());
126   values_.reserve(num_deltas + 1);
127   values_.push_back(base);
128 
129   if (pending_data_.size() * 8 < num_deltas * params.delta_bit_width()) {
130     SetError();
131     return;
132   }
133 
134   BitstreamReader reader(pending_data_);
135   const uint64_t top_bit = static_cast<uint64_t>(1)
136                            << (params.delta_bit_width() - 1);
137 
138   uint64_t value = base;
139   for (uint64_t i = 0; i < num_deltas; ++i) {
140     uint64_t delta = reader.ReadBits(params.delta_bit_width());
141     RTC_DCHECK_LE(value, webrtc_event_logging::MaxUnsignedValueOfBitWidth(
142                              params.value_bit_width()));
143     RTC_DCHECK_LE(delta, webrtc_event_logging::MaxUnsignedValueOfBitWidth(
144                              params.delta_bit_width()));
145     bool negative_delta = params.signed_deltas() && ((delta & top_bit) != 0);
146     if (negative_delta) {
147       uint64_t delta_abs = (~delta & params.delta_mask()) + 1;
148       value = (value - delta_abs) & params.value_mask();
149     } else {
150       value = (value + delta) & params.value_mask();
151     }
152     values_.push_back(value);
153   }
154 
155   if (!reader.Ok()) {
156     SetError();
157     return;
158   }
159 
160   pending_data_ =
161       pending_data_.substr((num_deltas * params.delta_bit_width() + 7) / 8);
162 }
163 
Initialize(absl::string_view s,bool batched)164 RtcEventLogParseStatus EventParser::Initialize(absl::string_view s,
165                                                bool batched) {
166   pending_data_ = s;
167   num_events_ = 1;
168 
169   if (batched) {
170     num_events_ = ReadVarInt();
171     if (!Ok()) {
172       return RtcEventLogParseStatus::Error(
173           "Failed to read number of events in batch.", __FILE__, __LINE__);
174     }
175   }
176   return RtcEventLogParseStatus::Success();
177 }
178 
ParseNumericFieldInternal(uint64_t value_bit_width,FieldType field_type)179 RtcEventLogParseStatus EventParser::ParseNumericFieldInternal(
180     uint64_t value_bit_width,
181     FieldType field_type) {
182   RTC_DCHECK(values_.empty());
183   RTC_DCHECK(positions_.empty());
184 
185   if (num_events_ == 1) {
186     // Just a single value in the batch.
187     uint64_t base = ReadSingleValue(field_type);
188     if (!Ok()) {
189       return RtcEventLogParseStatus::Error("Failed to read value", __FILE__,
190                                            __LINE__);
191     }
192     positions_.push_back(true);
193     values_.push_back(base);
194   } else {
195     // Delta compressed batch.
196     // Read delta header.
197     uint64_t header_value = ReadVarInt();
198     if (!Ok())
199       return RtcEventLogParseStatus::Error("Failed to read delta header",
200                                            __FILE__, __LINE__);
201     // NB: value_bit_width may be incorrect for the field, if this isn't the
202     // field we are looking for.
203     absl::optional<FixedLengthEncodingParametersV3> delta_header =
204         FixedLengthEncodingParametersV3::ParseDeltaHeader(header_value,
205                                                           value_bit_width);
206     if (!delta_header.has_value()) {
207       return RtcEventLogParseStatus::Error("Failed to parse delta header",
208                                            __FILE__, __LINE__);
209     }
210 
211     uint64_t num_existing_deltas = NumEventsInBatch() - 1;
212     if (delta_header->values_optional()) {
213       size_t num_nonempty_values = ReadOptionalValuePositions();
214       if (!Ok()) {
215         return RtcEventLogParseStatus::Error(
216             "Failed to read positions of optional values", __FILE__, __LINE__);
217       }
218       if (num_nonempty_values < 1 || NumEventsInBatch() < num_nonempty_values) {
219         return RtcEventLogParseStatus::Error(
220             "Expected at least one non_empty value", __FILE__, __LINE__);
221       }
222       num_existing_deltas = num_nonempty_values - 1;
223     } else {
224       // All elements in the batch have values.
225       positions_.assign(NumEventsInBatch(), 1u);
226     }
227 
228     // Read base.
229     uint64_t base = ReadSingleValue(field_type);
230     if (!Ok()) {
231       return RtcEventLogParseStatus::Error("Failed to read value", __FILE__,
232                                            __LINE__);
233     }
234 
235     if (delta_header->values_equal()) {
236       // Duplicate the base value num_existing_deltas times.
237       values_.assign(num_existing_deltas + 1, base);
238     } else {
239       // Read deltas; ceil(num_existing_deltas*delta_width/8) bits
240       ReadDeltasAndPopulateValues(delta_header.value(), num_existing_deltas,
241                                   base);
242       if (!Ok()) {
243         return RtcEventLogParseStatus::Error("Failed to decode deltas",
244                                              __FILE__, __LINE__);
245       }
246     }
247   }
248   return RtcEventLogParseStatus::Success();
249 }
250 
ParseStringFieldInternal()251 RtcEventLogParseStatus EventParser::ParseStringFieldInternal() {
252   RTC_DCHECK(strings_.empty());
253   if (num_events_ > 1) {
254     // String encoding params reserved for future use.
255     uint64_t encoding_params = ReadVarInt();
256     if (!Ok()) {
257       return RtcEventLogParseStatus::Error("Failed to read string encoding",
258                                            __FILE__, __LINE__);
259     }
260     if (encoding_params != 0) {
261       return RtcEventLogParseStatus::Error(
262           "Unrecognized string encoding parameters", __FILE__, __LINE__);
263     }
264   }
265   strings_.reserve(num_events_);
266   for (uint64_t i = 0; i < num_events_; ++i) {
267     // Just a single value in the batch.
268     uint64_t size = ReadVarInt();
269     if (!Ok()) {
270       return RtcEventLogParseStatus::Error("Failed to read string size",
271                                            __FILE__, __LINE__);
272     }
273     if (size > pending_data_.size()) {
274       return RtcEventLogParseStatus::Error("String size exceeds remaining data",
275                                            __FILE__, __LINE__);
276     }
277     strings_.push_back(pending_data_.substr(0, size));
278     pending_data_ = pending_data_.substr(size);
279   }
280   return RtcEventLogParseStatus::Success();
281 }
282 
ParseField(const FieldParameters & params)283 RtcEventLogParseStatus EventParser::ParseField(const FieldParameters& params) {
284   // Verify that the event parses fields in increasing order.
285   if (params.field_id == FieldParameters::kTimestampField) {
286     RTC_DCHECK_EQ(last_field_id_, FieldParameters::kTimestampField);
287   } else {
288     RTC_DCHECK_GT(params.field_id, last_field_id_);
289   }
290   last_field_id_ = params.field_id;
291 
292   // Initialization for positional fields that don't encode field ID and type.
293   uint64_t field_id = params.field_id;
294   FieldType field_type = params.field_type;
295 
296   // Fields are encoded in increasing field_id order.
297   // Skip unknown fields with field_id < params.field_id until we either
298   // find params.field_id or a field with higher id, in which case we know that
299   // params.field_id doesn't exist.
300   while (!pending_data_.empty()) {
301     absl::string_view field_start = pending_data_;
302     ClearTemporaries();
303 
304     // Read tag for non-positional fields.
305     if (params.field_id != FieldParameters::kTimestampField) {
306       uint64_t field_tag = ReadVarInt();
307       if (!Ok())
308         return RtcEventLogParseStatus::Error("Failed to read field tag",
309                                              __FILE__, __LINE__);
310       // Split tag into field ID and field type.
311       field_id = field_tag >> 3;
312       absl::optional<FieldType> conversion = ConvertFieldType(field_tag & 7u);
313       if (!conversion.has_value())
314         return RtcEventLogParseStatus::Error("Failed to parse field type",
315                                              __FILE__, __LINE__);
316       field_type = conversion.value();
317     }
318 
319     if (field_id > params.field_id) {
320       // We've passed all fields with ids less than or equal to what we are
321       // looking for. Reset pending_data_ to first field with id higher than
322       // params.field_id, since we didn't find the field we were looking for.
323       pending_data_ = field_start;
324       return RtcEventLogParseStatus::Success();
325     }
326 
327     if (field_type == FieldType::kString) {
328       auto status = ParseStringFieldInternal();
329       if (!status.ok()) {
330         return status;
331       }
332     } else {
333       auto status = ParseNumericFieldInternal(params.value_width, field_type);
334       if (!status.ok()) {
335         return status;
336       }
337     }
338 
339     if (field_id == params.field_id) {
340       // The field we're looking for has been found and values populated.
341       return RtcEventLogParseStatus::Success();
342     }
343   }
344 
345   // Field not found because the event ended.
346   ClearTemporaries();
347   return RtcEventLogParseStatus::Success();
348 }
349 
350 RtcEventLogParseStatusOr<rtc::ArrayView<absl::string_view>>
ParseStringField(const FieldParameters & params,bool required_field)351 EventParser::ParseStringField(const FieldParameters& params,
352                               bool required_field) {
353   using StatusOr = RtcEventLogParseStatusOr<rtc::ArrayView<absl::string_view>>;
354   RTC_DCHECK_EQ(params.field_type, FieldType::kString);
355   auto status = ParseField(params);
356   if (!status.ok())
357     return StatusOr(status);
358   rtc::ArrayView<absl::string_view> strings = GetStrings();
359   if (required_field && strings.size() != NumEventsInBatch()) {
360     return StatusOr::Error("Required string field not found", __FILE__,
361                            __LINE__);
362   }
363   return StatusOr(strings);
364 }
365 
366 RtcEventLogParseStatusOr<rtc::ArrayView<uint64_t>>
ParseNumericField(const FieldParameters & params,bool required_field)367 EventParser::ParseNumericField(const FieldParameters& params,
368                                bool required_field) {
369   using StatusOr = RtcEventLogParseStatusOr<rtc::ArrayView<uint64_t>>;
370   RTC_DCHECK_NE(params.field_type, FieldType::kString);
371   auto status = ParseField(params);
372   if (!status.ok())
373     return StatusOr(status);
374   rtc::ArrayView<uint64_t> values = GetValues();
375   if (required_field && values.size() != NumEventsInBatch()) {
376     return StatusOr::Error("Required numerical field not found", __FILE__,
377                            __LINE__);
378   }
379   return StatusOr(values);
380 }
381 
382 RtcEventLogParseStatusOr<EventParser::ValueAndPostionView>
ParseOptionalNumericField(const FieldParameters & params,bool required_field)383 EventParser::ParseOptionalNumericField(const FieldParameters& params,
384                                        bool required_field) {
385   using StatusOr = RtcEventLogParseStatusOr<ValueAndPostionView>;
386   RTC_DCHECK_NE(params.field_type, FieldType::kString);
387   auto status = ParseField(params);
388   if (!status.ok())
389     return StatusOr(status);
390   ValueAndPostionView view{GetValues(), GetPositions()};
391   if (required_field && view.positions.size() != NumEventsInBatch()) {
392     return StatusOr::Error("Required numerical field not found", __FILE__,
393                            __LINE__);
394   }
395   return StatusOr(view);
396 }
397 
398 }  // namespace webrtc
399