chromium/mojo/public/tools/bindings/generators/cpp_templates/enum_macros.tmpl

{#---
  Macro for enum definition, and the declaration of associated functions.
---#}

{%- macro kythe_annotation(name) %}
{%- if enable_kythe_annotations %}
// @generated_from: {{name}}
{%- endif %}
{%- endmacro %}

{%- macro enum_forward(enum) %}
{%-   set enum_name = enum|get_name_for_kind(flatten_nested_kind=True) %}
enum class {{enum_name}} : int32_t;
{%- endmacro %}

{%- macro enum_decl(enum, export_attribute) %}
{%-   set enum_name = enum|get_name_for_kind(flatten_nested_kind=True) %}

{%- set full_enum_name = enum|get_full_mojom_name_for_kind() %}
{{ kythe_annotation(full_enum_name) }}
enum class {{enum_name}} : int32_t {
{%-   for field in enum.fields %}
  {{ kythe_annotation("%s.%s"|format(full_enum_name, field.name)) }}
  {{field.name}} = {{field.numeric_value}},
{%-   endfor %}
{%-   if enum.min_value is not none %}
  kMinValue = {{enum.min_value}},
{%-   endif %}
{%-   if enum.max_value is not none %}
  kMaxValue = {{enum.max_value}},
{%-   endif %}
{%-   if enum.default_field %}
  kDefaultValue = {{enum.default_field.numeric_value}}
{%-   endif %}
};

{{export_attribute}} std::ostream& operator<<(std::ostream& os, {{enum_name}} value);

{#-   Returns true if the given enum value exists in this version of enum. #}
inline bool IsKnownEnumValue({{enum_name}} value) {
  return {{enum|get_name_for_kind(internal=True,
                                  flatten_nested_kind=True)}}::IsKnownValue(
      static_cast<int32_t>(value));
}

{%-   if enum.extensible and enum.default_field %}
inline {{enum_name}} ToKnownEnumValue({{enum_name}} value) {
  if (IsKnownEnumValue(value)) {
    return value;
  }
  return {{enum_name}}::kDefaultValue;
}
{%-   endif %}
{%- endmacro %}

{%- macro enum_stream(enum) %}
{%-   set enum_name = enum|get_name_for_kind(flatten_nested_kind=True) %}
std::ostream& operator<<(std::ostream& os, {{enum_name}} value) {
  return os << {{enum_name}}ToString(value);
}
{%- endmacro %}

{%- macro enum_to_string(enum) %}
{%-   set enum_name = enum|get_name_for_kind(flatten_nested_kind=True) %}
NOINLINE static const char* {{enum_name}}ToStringHelper({{enum_name}} value) {
  // Defined in a helper function to ensure that Clang generates a lookup table.
{%- if enum.fields %}
  switch(value) {
{%-   for _, values in enum.fields|groupby('numeric_value') %}
    case {{enum_name}}::{{values[0].name}}:
      return "
{%-     if values|length > 1 -%}
      {{'{'}}
{%-     endif -%}
      {{values|map(attribute='name')|join(', ')}}
{%-     if values|length > 1 -%}
      {{'}'}}
{%-     endif -%}
      ";
{%-   endfor %}
    default:
      return nullptr;
  }
{%- else %}
  return nullptr;
{%- endif %}
}

std::string {{enum_name}}ToString({{enum_name}} value) {
  const char *str = {{enum_name}}ToStringHelper(value);
  if (!str) {
    return base::StringPrintf("Unknown {{enum_name}} value: %i", static_cast<int32_t>(value));
  }
  return str;
}
{%- endmacro %}

{%- macro enum_data_decl(enum) %}
{%-   set enum_name = enum|get_name_for_kind(flatten_nested_kind=True) %}
struct {{enum_name}}_Data {
 public:
  static bool constexpr kIsExtensible = {% if enum.extensible %}true{% else %}false{% endif %};

  static bool IsKnownValue(int32_t value) {
{%- if enum.fields %}
    switch (value) {
{%-   for enum_field in enum.fields|groupby('numeric_value') %}
      case {{enum_field[0]}}:
{%-   endfor %}
        return true;
    }
{%- endif %}
    return false;
  }

  static bool Validate(int32_t value,
                       mojo::internal::ValidationContext* validation_context) {
    if (kIsExtensible || IsKnownValue(value))
      return true;

    ReportValidationError(validation_context,
                          mojo::internal::VALIDATION_ERROR_UNKNOWN_ENUM_VALUE);
    return false;
  }
};
{%- endmacro %}

{%- macro enum_hash(enum) %}
{%-   set enum_name = enum|get_qualified_name_for_kind(
          flatten_nested_kind=True) %}
template <>
struct hash<{{enum_name}}>
    : public mojo::internal::EnumHashImpl<{{enum_name}}> {};
{%- endmacro %}

{%- macro enum_trace_format_traits_decl(enum, export_attributes) -%}
{%-   set enum_name = enum|get_qualified_name_for_kind(
          flatten_nested_kind=True) %}
namespace perfetto {

template <>
struct {{export_attribute}} TraceFormatTraits<{{enum_name}}> {
 static void WriteIntoTrace(perfetto::TracedValue context, {{enum_name}} value);
};

} // namespace perfetto
{%- endmacro %}

{%- macro enum_trace_format_traits(enum) -%}
{%-   set enum_name = enum|get_qualified_name_for_kind(
          flatten_nested_kind=True) %}
namespace perfetto {

// static
void TraceFormatTraits<{{enum_name}}>::WriteIntoTrace(
   perfetto::TracedValue context, {{enum_name}} value) {
  return std::move(context).WriteString({{enum_name}}ToString(value));
}

} // namespace perfetto
{%- endmacro %}endmacro