1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148
|
/*
* Copyright (c) 2021 The WebRTC project authors. All Rights Reserved.
*
* Use of this source code is governed by a BSD-style license
* that can be found in the LICENSE file in the root of the source
* tree. An additional intellectual property rights grant can be found
* in the file PATENTS. All contributing project authors may
* be found in the AUTHORS file in the root of the source tree.
*/
#ifndef LOGGING_RTC_EVENT_LOG_EVENTS_RTC_EVENT_DEFINITION_H_
#define LOGGING_RTC_EVENT_LOG_EVENTS_RTC_EVENT_DEFINITION_H_
#include <cstdint>
#include <string>
#include <vector>
#include "absl/strings/string_view.h"
#include "api/array_view.h"
#include "api/rtc_event_log/rtc_event.h"
#include "logging/rtc_event_log/events/rtc_event_field_encoding.h"
#include "logging/rtc_event_log/events/rtc_event_field_encoding_parser.h"
#include "logging/rtc_event_log/events/rtc_event_log_parse_status.h"
namespace webrtc {
template <typename EventType, typename LoggedType, typename T>
struct RtcEventFieldDefinition {
const T EventType::*event_member;
T LoggedType::*logged_member;
FieldParameters params;
};
// Base case
template <typename EventType, typename LoggedType, typename... Ts>
class RtcEventDefinitionImpl {
public:
void EncodeImpl(EventEncoder&, ArrayView<const RtcEvent*>) const {}
RtcEventLogParseStatus ParseImpl(EventParser&, ArrayView<LoggedType>) const {
return RtcEventLogParseStatus::Success();
}
};
// Recursive case
template <typename EventType, typename LoggedType, typename T, typename... Ts>
class RtcEventDefinitionImpl<EventType, LoggedType, T, Ts...> {
public:
constexpr RtcEventDefinitionImpl(
RtcEventFieldDefinition<EventType, LoggedType, T> field,
RtcEventFieldDefinition<EventType, LoggedType, Ts>... rest)
: field_(field), rest_(rest...) {}
void EncodeImpl(EventEncoder& encoder,
ArrayView<const RtcEvent*> batch) const {
auto values = ExtractRtcEventMember(batch, field_.event_member);
encoder.EncodeField(field_.params, values);
rest_.EncodeImpl(encoder, batch);
}
RtcEventLogParseStatus ParseImpl(EventParser& parser,
ArrayView<LoggedType> output_batch) const {
RtcEventLogParseStatusOr<ArrayView<uint64_t>> result =
parser.ParseNumericField(field_.params);
if (!result.ok())
return result.status();
auto status = PopulateRtcEventMember(result.value(), field_.logged_member,
output_batch);
if (!status.ok())
return status;
return rest_.ParseImpl(parser, output_batch);
}
private:
RtcEventFieldDefinition<EventType, LoggedType, T> field_;
RtcEventDefinitionImpl<EventType, LoggedType, Ts...> rest_;
};
// The RtcEventDefinition sets up a mapping between the fields
// in an RtcEvent and the corresponding fields in the parsed struct.
// For example, an RtcFoo class containing two fields; `uint32_t bar`
// and `bool baz` (a log timestamp is always implicitly added)
// might have a definition
// RtcEventDefinition<RtcFoo, LoggedFoo, uint32_t, bool>(
// {"foo", RtcFoo::Type},
// {&RtcFoo::bar_, &LoggedFoo::bar, {"bar", 1, FieldType::kVarInt, 32}},
// {&RtcFoo::baz_, &LoggedFoo::baz, {"baz", 2, FieldType::kFixed8, 1}},
// );
// In addition to defining string names to aid debugging,
// this specifies that
// * RtcFoo::Type uniquely identifies an RtcFoo in the encoded stream
// * The `bar` field has ID 1, is encoded as a VarInt
// (when not delta compressed), and wraps around after 32 bits.
// * The `baz` field has ID 2, is encoded as an 8-bit field
// (when not delta compressed), and wraps around after 1 bit.
// Note that the numerical field and event IDs can't be changed since
// that would break compatibility with old logs.
// In most cases (including all cases where wrap around isn't
// expected), the wrap around should be equal to the bitwidth of
// the field.
template <typename EventType, typename LoggedType, typename... Ts>
class RtcEventDefinition {
public:
constexpr RtcEventDefinition(
EventParameters params,
RtcEventFieldDefinition<EventType, LoggedType, Ts>... fields)
: params_(params), fields_(fields...) {}
std::string EncodeBatch(ArrayView<const RtcEvent*> batch) const {
EventEncoder encoder(params_, batch);
fields_.EncodeImpl(encoder, batch);
return encoder.AsString();
}
RtcEventLogParseStatus ParseBatch(absl::string_view s,
bool batched,
std::vector<LoggedType>& output) const {
EventParser parser;
auto status = parser.Initialize(s, batched);
if (!status.ok())
return status;
ArrayView<LoggedType> output_batch =
ExtendLoggedBatch(output, parser.NumEventsInBatch());
constexpr FieldParameters timestamp_params{"timestamp_ms",
FieldParameters::kTimestampField,
FieldType::kVarInt, 64};
RtcEventLogParseStatusOr<ArrayView<uint64_t>> result =
parser.ParseNumericField(timestamp_params);
if (!result.ok())
return result.status();
status = PopulateRtcEventTimestamp(result.value(), &LoggedType::timestamp,
output_batch);
if (!status.ok())
return status;
return fields_.ParseImpl(parser, output_batch);
}
private:
EventParameters params_;
RtcEventDefinitionImpl<EventType, LoggedType, Ts...> fields_;
};
} // namespace webrtc
#endif // LOGGING_RTC_EVENT_LOG_EVENTS_RTC_EVENT_DEFINITION_H_
|