blob: cf49cb23119c7369809eaeac5a7f3f0546668fbc [file] [log] [blame]
Henrik Boström7978cf12024-01-11 10:41:101/*
2 * Copyright 2024 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 "api/stats/attribute.h"
12
Henrik Boström72095482024-01-19 12:53:0113#include <string>
14
Henrik Boström7978cf12024-01-11 10:41:1015#include "absl/types/variant.h"
Henrik Boström72095482024-01-19 12:53:0116#include "rtc_base/arraysize.h"
Henrik Boström7978cf12024-01-11 10:41:1017#include "rtc_base/checks.h"
Henrik Boström72095482024-01-19 12:53:0118#include "rtc_base/string_encode.h"
19#include "rtc_base/strings/string_builder.h"
Henrik Boström7978cf12024-01-11 10:41:1020
21namespace webrtc {
22
23namespace {
24
25struct VisitIsSequence {
26 // Any type of vector is a sequence.
27 template <typename T>
Henrik Boström5372bce2024-01-22 08:56:0928 bool operator()(const absl::optional<std::vector<T>>* attribute) {
Henrik Boström7978cf12024-01-11 10:41:1029 return true;
30 }
31 // Any other type is not.
32 template <typename T>
Henrik Boström5372bce2024-01-22 08:56:0933 bool operator()(const absl::optional<T>* attribute) {
Henrik Boström7978cf12024-01-11 10:41:1034 return false;
35 }
36};
37
Henrik Boström72095482024-01-19 12:53:0138// Converts the attribute to string in a JSON-compatible way.
39struct VisitToString {
40 template <typename T,
41 typename std::enable_if_t<
42 std::is_same_v<T, int32_t> || std::is_same_v<T, uint32_t> ||
43 std::is_same_v<T, bool> || std::is_same_v<T, std::string>,
44 bool> = true>
45 std::string ValueToString(const T& value) {
46 return rtc::ToString(value);
47 }
48 // Convert 64-bit integers to doubles before converting to string because JSON
49 // represents all numbers as floating points with ~15 digits of precision.
50 template <typename T,
51 typename std::enable_if_t<std::is_same_v<T, int64_t> ||
52 std::is_same_v<T, uint64_t> ||
53 std::is_same_v<T, double>,
54 bool> = true>
55 std::string ValueToString(const T& value) {
56 char buf[32];
57 const int len = std::snprintf(&buf[0], arraysize(buf), "%.16g",
58 static_cast<double>(value));
59 RTC_DCHECK_LE(len, arraysize(buf));
60 return std::string(&buf[0], len);
61 }
62
63 // Vector attributes.
64 template <typename T>
Henrik Boström5372bce2024-01-22 08:56:0965 std::string operator()(const absl::optional<std::vector<T>>* attribute) {
Henrik Boström72095482024-01-19 12:53:0166 rtc::StringBuilder sb;
67 sb << "[";
68 const char* separator = "";
69 constexpr bool element_is_string = std::is_same<T, std::string>::value;
70 for (const T& element : attribute->value()) {
71 sb << separator;
72 if (element_is_string) {
73 sb << "\"";
74 }
75 sb << ValueToString(element);
76 if (element_is_string) {
77 sb << "\"";
78 }
79 separator = ",";
80 }
81 sb << "]";
82 return sb.Release();
83 }
84 // Map attributes.
85 template <typename T>
86 std::string operator()(
Henrik Boström5372bce2024-01-22 08:56:0987 const absl::optional<std::map<std::string, T>>* attribute) {
Henrik Boström72095482024-01-19 12:53:0188 rtc::StringBuilder sb;
89 sb << "{";
90 const char* separator = "";
91 constexpr bool element_is_string = std::is_same<T, std::string>::value;
92 for (const auto& pair : attribute->value()) {
93 sb << separator;
94 sb << "\"" << pair.first << "\":";
95 if (element_is_string) {
96 sb << "\"";
97 }
98 sb << ValueToString(pair.second);
99 if (element_is_string) {
100 sb << "\"";
101 }
102 separator = ",";
103 }
104 sb << "}";
105 return sb.Release();
106 }
107 // Simple attributes.
108 template <typename T>
Henrik Boström5372bce2024-01-22 08:56:09109 std::string operator()(const absl::optional<T>* attribute) {
Henrik Boström72095482024-01-19 12:53:01110 return ValueToString(attribute->value());
111 }
112};
113
Henrik Boström7978cf12024-01-11 10:41:10114struct VisitIsEqual {
115 template <typename T>
Henrik Boström5372bce2024-01-22 08:56:09116 bool operator()(const absl::optional<T>* attribute) {
Henrik Boströmc0ac4df2024-01-16 10:03:19117 if (!other.holds_alternative<T>()) {
118 return false;
119 }
Henrik Boström5372bce2024-01-22 08:56:09120 return *attribute == other.as_optional<T>();
Henrik Boström7978cf12024-01-11 10:41:10121 }
122
Henrik Boströmc0ac4df2024-01-16 10:03:19123 const Attribute& other;
Henrik Boström7978cf12024-01-11 10:41:10124};
125
126} // namespace
127
Henrik Boström7978cf12024-01-11 10:41:10128const char* Attribute::name() const {
Henrik Boströmc0ac4df2024-01-16 10:03:19129 return name_;
Henrik Boström7978cf12024-01-11 10:41:10130}
131
132const Attribute::StatVariant& Attribute::as_variant() const {
133 return attribute_;
134}
135
Henrik Boströmbfee9612024-01-12 08:24:06136bool Attribute::has_value() const {
137 return absl::visit([](const auto* attr) { return attr->has_value(); },
138 attribute_);
139}
140
Henrik Boström7978cf12024-01-11 10:41:10141bool Attribute::is_sequence() const {
142 return absl::visit(VisitIsSequence(), attribute_);
143}
144
145bool Attribute::is_string() const {
Henrik Boström5372bce2024-01-22 08:56:09146 return absl::holds_alternative<const absl::optional<std::string>*>(
Henrik Boström7978cf12024-01-11 10:41:10147 attribute_);
148}
149
Henrik Boström72095482024-01-19 12:53:01150std::string Attribute::ToString() const {
151 if (!has_value()) {
152 return "null";
153 }
154 return absl::visit(VisitToString(), attribute_);
Henrik Boström7978cf12024-01-11 10:41:10155}
156
Henrik Boströmc0ac4df2024-01-16 10:03:19157bool Attribute::operator==(const Attribute& other) const {
158 return absl::visit(VisitIsEqual{.other = other}, attribute_);
Henrik Boström7978cf12024-01-11 10:41:10159}
160
Henrik Boströmc0ac4df2024-01-16 10:03:19161bool Attribute::operator!=(const Attribute& other) const {
162 return !(*this == other);
163}
164
165AttributeInit::AttributeInit(const char* name,
166 const Attribute::StatVariant& variant)
167 : name(name), variant(variant) {}
168
Henrik Boström7978cf12024-01-11 10:41:10169} // namespace webrtc