Use struct parser for rate control trial.

Bug: webrtc:9883
Change-Id: I9ec7988da2e4d88bedd9b71cae00452f531980d6
Reviewed-on: https://webrtc-review.googlesource.com/c/src/+/148581
Commit-Queue: Sebastian Jansson <srte@webrtc.org>
Reviewed-by: Jonas Olsson <jonasolsson@webrtc.org>
Cr-Commit-Position: refs/heads/master@{#28856}
diff --git a/rtc_base/experiments/struct_parameters_parser.h b/rtc_base/experiments/struct_parameters_parser.h
index f6728f6..b40f381 100644
--- a/rtc_base/experiments/struct_parameters_parser.h
+++ b/rtc_base/experiments/struct_parameters_parser.h
@@ -26,189 +26,83 @@
 
 namespace webrtc {
 namespace struct_parser_impl {
-inline std::string StringEncode(bool val) {
-  return rtc::ToString(val);
-}
-inline std::string StringEncode(double val) {
-  return rtc::ToString(val);
-}
-inline std::string StringEncode(int val) {
-  return rtc::ToString(val);
-}
-inline std::string StringEncode(std::string val) {
-  return val;
-}
-inline std::string StringEncode(DataRate val) {
-  return ToString(val);
-}
-inline std::string StringEncode(DataSize val) {
-  return ToString(val);
-}
-inline std::string StringEncode(TimeDelta val) {
-  return ToString(val);
-}
+struct TypedMemberParser {
+ public:
+  bool (*parse)(const absl::string_view src, void* target);
+  void (*encode)(const void* src, std::string* target);
+};
+
+struct MemberParameter {
+  const char* key;
+  void* member_ptr;
+  TypedMemberParser parser;
+};
 
 template <typename T>
-inline std::string StringEncode(absl::optional<T> val) {
-  if (val)
-    return StringEncode(*val);
-  return "";
-}
+class TypedParser {
+ public:
+  static bool Parse(absl::string_view src, void* target);
+  static void Encode(const void* src, std::string* target);
+};
+
+// Instantiated in cc file to avoid duplication during compile. Add additional
+// parsers as needed. Generally, try to use these suggested types even if the
+// context where the value is used might require a different type. For instance,
+// a size_t representing a packet size should use an int parameter as there's no
+// need to support packet sizes larger than INT32_MAX.
+extern template class TypedParser<bool>;
+extern template class TypedParser<double>;
+extern template class TypedParser<int>;
+extern template class TypedParser<absl::optional<double>>;
+extern template class TypedParser<absl::optional<int>>;
+
+extern template class TypedParser<DataRate>;
+extern template class TypedParser<DataSize>;
+extern template class TypedParser<TimeDelta>;
+extern template class TypedParser<absl::optional<DataRate>>;
+extern template class TypedParser<absl::optional<DataSize>>;
+extern template class TypedParser<absl::optional<TimeDelta>>;
 
 template <typename T>
-struct LambdaTraits : public LambdaTraits<decltype(&T::operator())> {};
-
-template <typename ClassType, typename RetType, typename SourceType>
-struct LambdaTraits<RetType* (ClassType::*)(SourceType*)const> {
-  using ret = RetType;
-  using src = SourceType;
-};
-
-void ParseConfigParams(
-    absl::string_view config_str,
-    std::map<std::string, std::function<bool(absl::string_view)>> field_map);
-
-std::string EncodeStringStringMap(std::map<std::string, std::string> mapping);
-
-template <typename StructType>
-class StructParameterParser {
- public:
-  virtual bool Parse(absl::string_view src, StructType* target) const = 0;
-  virtual bool Changed(const StructType& src, const StructType& base) const = 0;
-  virtual std::string Encode(const StructType& src) const = 0;
-  virtual ~StructParameterParser() = default;
-};
-
-template <typename StructType, typename T>
-class StructParameterImpl : public StructParameterParser<StructType> {
- public:
-  explicit StructParameterImpl(std::function<T*(StructType*)> field_getter)
-      : field_getter_(std::move(field_getter)) {}
-  bool Parse(absl::string_view src, StructType* target) const override {
-    auto parsed = ParseTypedParameter<T>(std::string(src));
-    if (parsed.has_value())
-      *field_getter_(target) = *parsed;
-    return parsed.has_value();
-  }
-  bool Changed(const StructType& src, const StructType& base) const override {
-    T base_value = *field_getter_(const_cast<StructType*>(&base));
-    T value = *field_getter_(const_cast<StructType*>(&src));
-    return value != base_value;
-  }
-  std::string Encode(const StructType& src) const override {
-    T value = *field_getter_(const_cast<StructType*>(&src));
-    return struct_parser_impl::StringEncode(value);
-  }
-
- private:
-  const std::function<T*(StructType*)> field_getter_;
-};
-
-template <typename StructType>
-struct StructParameter {
-  std::string key;
-  StructParameterParser<StructType>* parser;
-};
-
-template <typename S,
-          typename Closure,
-          typename T = typename LambdaTraits<Closure>::ret>
-void AddParameters(std::vector<StructParameter<S>>* out,
-                   std::string key,
-                   Closure getter) {
-  auto* parser = new StructParameterImpl<S, T>(getter);
-  out->push_back(StructParameter<S>{std::move(key), parser});
+void AddMembers(MemberParameter* out, const char* key, T* member) {
+  *out = MemberParameter{
+      key, member,
+      TypedMemberParser{&TypedParser<T>::Parse, &TypedParser<T>::Encode}};
 }
 
-template <typename S,
-          typename Closure,
-          typename T = typename LambdaTraits<Closure>::ret,
-          typename... Args>
-void AddParameters(std::vector<StructParameter<S>>* out,
-                   std::string key,
-                   Closure getter,
-                   Args... args) {
-  AddParameters(out, key, getter);
-  AddParameters<S>(out, args...);
+template <typename T, typename... Args>
+void AddMembers(MemberParameter* out,
+                const char* key,
+                T* member,
+                Args... args) {
+  AddMembers(out, key, member);
+  AddMembers(++out, args...);
 }
-
 }  // namespace struct_parser_impl
 
-template <typename StructType>
 class StructParametersParser {
  public:
-  ~StructParametersParser() {
-    for (auto& param : parameters_) {
-      delete param.parser;
-    }
+  template <typename T, typename... Args>
+  static std::unique_ptr<StructParametersParser> Create(const char* first_key,
+                                                        T* first_member,
+                                                        Args... args) {
+    std::vector<struct_parser_impl::MemberParameter> members(
+        sizeof...(args) / 2 + 1);
+    struct_parser_impl::AddMembers(&members.front(), std::move(first_key),
+                                   first_member, args...);
+    return absl::WrapUnique(new StructParametersParser(std::move(members)));
   }
 
-  void Parse(StructType* target, absl::string_view src) {
-    std::map<std::string, std::function<bool(absl::string_view)>> field_parsers;
-    for (const auto& param : parameters_) {
-      field_parsers.emplace(param.key, [target, param](absl::string_view src) {
-        return param.parser->Parse(src, target);
-      });
-    }
-    struct_parser_impl::ParseConfigParams(src, std::move(field_parsers));
-  }
-
-  StructType Parse(absl::string_view src) {
-    StructType res;
-    Parse(&res, src);
-    return res;
-  }
-
-  std::string EncodeChanged(const StructType& src) {
-    static StructType base;
-    std::map<std::string, std::string> pairs;
-    for (const auto& param : parameters_) {
-      if (param.parser->Changed(src, base))
-        pairs[param.key] = param.parser->Encode(src);
-    }
-    return struct_parser_impl::EncodeStringStringMap(pairs);
-  }
-
-  std::string EncodeAll(const StructType& src) {
-    std::map<std::string, std::string> pairs;
-    for (const auto& param : parameters_) {
-      pairs[param.key] = param.parser->Encode(src);
-    }
-    return struct_parser_impl::EncodeStringStringMap(pairs);
-  }
+  void Parse(absl::string_view src);
+  std::string Encode() const;
 
  private:
-  template <typename C, typename S, typename... Args>
-  friend std::unique_ptr<StructParametersParser<S>>
-  CreateStructParametersParser(std::string, C, Args...);
-
   explicit StructParametersParser(
-      std::vector<struct_parser_impl::StructParameter<StructType>> parameters)
-      : parameters_(parameters) {}
+      std::vector<struct_parser_impl::MemberParameter> members);
 
-  std::vector<struct_parser_impl::StructParameter<StructType>> parameters_;
+  std::vector<struct_parser_impl::MemberParameter> members_;
 };
 
-// Creates a struct parameters parser based on interleaved key and field
-// accessor arguments, where the field accessor converts a struct pointer to a
-// member pointer: FieldType*(StructType*). See the unit tests for example
-// usage. Note that the struct type is inferred from the field getters. Beware
-// of providing incorrect arguments to this, such as mixing the struct type or
-// incorrect return values, as this will cause very confusing compile errors.
-template <typename Closure,
-          typename S = typename struct_parser_impl::LambdaTraits<Closure>::src,
-          typename... Args>
-std::unique_ptr<StructParametersParser<S>> CreateStructParametersParser(
-    std::string first_key,
-    Closure first_getter,
-    Args... args) {
-  std::vector<struct_parser_impl::StructParameter<S>> parameters;
-  struct_parser_impl::AddParameters<S>(&parameters, std::move(first_key),
-                                       first_getter, args...);
-  // absl::make_unique can't be used since the StructParametersParser
-  // constructor is only visible to this create function.
-  return absl::WrapUnique(new StructParametersParser<S>(std::move(parameters)));
-}
 }  // namespace webrtc
 
 #endif  // RTC_BASE_EXPERIMENTS_STRUCT_PARAMETERS_PARSER_H_