// -*- mode: C++ -*- // AUTOGENERATED BY glean_parser. DO NOT EDIT. {# The rendered source is autogenerated, but this Jinja2 template is not. Please file bugs! #} /* This Source Code Form is subject to the terms of the Mozilla Public * License, v. 2.0. If a copy of the MPL was not distributed with this * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ #ifndef mozilla_Glean{{ options.header_name }}_h #define mozilla_Glean{{ options.header_name }}_h {% if all_objs|has_structure %} #include "mozilla/JSONStringWriteFuncs.h" {% endif %} {% if options.standalone %} #include "mozilla/glean/bindings/MetricStandaloneTypes.h" {% else %} #include "mozilla/glean/bindings/MetricTypes.h" {% endif %} namespace mozilla::glean { {%- macro structure_to_json(struct, property_name, value) -%} {% if struct.type == "array" and property_name %} if ({{value}}.isSome()) { writer.StartArrayProperty("{{property_name}}"); {% set valuename = value|replace("->", "")|camelize ~ "Item" %} for (const auto& {{valuename}}: *{{value}}) { {{ structure_to_json(struct["items"], None, valuename)|indent(4) }} } writer.EndArray(); } {% elif struct.type == "array" and not property_name %} writer.StartArrayElement(); { {% set valuename = value|replace("->", "")|camelize ~ "Item" %} for (const auto& {{valuename}}: {{value}}) { {{ structure_to_json(struct["items"], None, valuename)|indent(4) }} } } writer.EndArray(); {% elif struct.type == "object" and property_name %} if ({{value}}.isSome()) { writer.StartObjectProperty("{{property_name}}"); {% for propname, val in struct.properties.items() %} {{ structure_to_json(val, propname, value ~ "->" ~ propname)|indent(2) }} {%- endfor %} writer.EndObject(); } {% elif struct.type == "object" and not property_name %} writer.StartObjectElement(); { {% for propname, val in struct.properties.items() %} {{ structure_to_json(val, propname, value ~ "." ~ propname)|indent(2) }} {%- endfor %} } writer.EndObject(); {% elif property_name %} if ({{value}}.isSome()) { writer.{{struct.type|jsonwriter_prefix}}Property("{{property_name}}", *({{value}})); } {% else %} writer.{{struct.type|jsonwriter_prefix}}Element({{value}}); {% endif %} {%- endmacro -%} {%- macro generate_structure(name, struct) -%} {% if struct.type == "array" %} {% if struct["items"].type not in ("array", "object") %} using {{ name }} = nsTArray<{{struct["items"].type|structure_type_name}}>; {% else %} {{ generate_structure(name ~ "Item", struct["items"]) }} using {{ name }} = nsTArray<{{ name }}Item>; {% endif %} {% elif struct.type == "object" %} {% for itemname, val in struct.properties.items() %} {% if val.type in ("array", "object") %} {{ generate_structure(name ~ itemname|Camelize, val) }} {% endif %} {% endfor %} struct {{ name }} { {% for itemname, val in struct.properties.items() %} {% if val.type not in ("array", "object") %} Maybe<{{val.type|structure_type_name}}> {{ itemname }}; {% else %} Maybe<{{name ~ itemname|Camelize}}> {{ itemname }}; {% endif %} {% endfor %} }; {% endif %} {%- endmacro -%} {%- macro generate_extra_keys(obj) -%} {% for name, suffix in obj["_generate_enums"] %} {# we always use the `extra` suffix, because we only expose the new event API #} {% set suffix = "Extra" %} {% if obj|attr(name)|length %} {{ extra_keys_with_types(obj, name, suffix)|indent(2) }} {% endif %} {% endfor %} {%- endmacro -%} {%- macro extra_keys_with_types(obj, name, suffix) -%} struct {{ obj.name|Camelize }}{{ suffix }} { {% for item, type in obj|attr(name) %} mozilla::Maybe<{{type|extra_type_name}}> {{ item|camelize }}; {% endfor %} std::tuple, nsTArray> ToFfiExtra() const { nsTArray extraKeys; nsTArray extraValues; {% for item, type in obj|attr(name) %} if ({{item|camelize}}) { extraKeys.AppendElement()->AssignASCII("{{item}}"); {% if type == "string" %} extraValues.EmplaceBack({{item|camelize}}.value()); {% elif type == "boolean" %} extraValues.AppendElement()->AssignASCII({{item|camelize}}.value() ? "true" : "false"); {% elif type == "quantity" %} extraValues.AppendElement()->AppendInt({{item|camelize}}.value()); {% else %} #error "Glean: Invalid extra key type for metric {{obj.category}}.{{obj.name}}, defined in: {{obj.defined_in['filepath']}}:{{obj.defined_in['line']}})" {% endif %} } {% endfor %} return std::make_tuple(std::move(extraKeys), std::move(extraValues)); } }; {%- endmacro -%} {# Okay, so though `enum class` means we can't pollute the namespace with the enum variants' identifiers, there's no guarantee there isn't some preprocessor #define lying in wait to collide with us. Using CamelCase helps, but isn't foolproof (X11/X.h has `#define Success 0`). So we prefix it. I chose `e` (for `enum`) for the prefix. #} {%- macro generate_label_enum(obj) -%} enum class {{ obj.name|Camelize }}Label: uint16_t { {% for label in obj.ordered_labels %} e{{ label|Camelize }} = {{loop.index0}}, {% endfor %} e__Other__, }; {%- endmacro %} {% for category_name, objs in all_objs.items() %} namespace {{ category_name|snake_case }} { {% for obj in objs.values() %} /** * generated from {{ category_name }}.{{ obj.name }} {% if obj|attr("_generate_enums") or (obj.labeled and obj.labels and obj.labels|length) or obj|attr("_generate_structure")%} */ {% if obj|attr("_generate_structure") %} {{ generate_structure(obj.name|Camelize ~ "Object", obj._generate_structure) }} {%- endif %} {% if obj|attr("_generate_enums") %} {{ generate_extra_keys(obj) }} {%- endif %} {% if obj.labeled and obj.labels and obj.labels|length %} {{ generate_label_enum(obj)|indent(2) }} {% endif %} /** {% endif %} * {{ obj.description|trim | replace('\n', '\n * ') }} */ constexpr impl::{{ obj|type_name }} {{obj.name|snake_case }}({{obj|metric_id}}); {% if not loop.last %} {% endif %} {% endfor %} } {% for obj in objs.values() %} {% if obj|attr("_generate_structure") %} {% set typename_t = category_name|snake_case ~ "::" ~ obj.name|Camelize ~ "Object" %} template <> inline void impl::ObjectMetric<{{typename_t}}, {{typename_t}}Tag>::Set(const {{typename_t}}& aObj) const { nsCString json; JSONStringRefWriteFunc writeFunc(json); JSONWriter writer(writeFunc, JSONWriter::CollectionStyle::SingleLineStyle); {{ structure_to_json(obj._generate_structure, None, "aObj")|indent(2) }} SetStr(json); } {% endif %} {% endfor %} {% endfor %} } // namespace mozilla::glean #endif // mozilla_Glean{{ options.header_name }}_h