diff --git a/rust/templates/component_type.rs.jinja b/rust/templates/component_type.rs.jinja index cdb2aaf71..0d5a8a8d5 100644 --- a/rust/templates/component_type.rs.jinja +++ b/rust/templates/component_type.rs.jinja @@ -9,6 +9,8 @@ {% include "types/string_enum.rs.jinja" -%} {% elif type.kind == "integer_enum" -%} {% include "types/integer_enum.rs.jinja" -%} +{% elif type.kind == "struct_enum" -%} + {% include "types/struct_enum.rs.jinja" -%} {% else -%} compile_error!("{{ type.kind }} types are not supported by this codegen template"); {% endif %} diff --git a/rust/templates/types/struct.rs.jinja b/rust/templates/types/struct.rs.jinja index 6318c353d..ae57b94f4 100644 --- a/rust/templates/types/struct.rs.jinja +++ b/rust/templates/types/struct.rs.jinja @@ -12,53 +12,7 @@ use super::{ {{ doc_comment }} #[derive(Clone, Debug, Default, PartialEq, Deserialize, Serialize)] pub struct {{ type.name | to_upper_camel_case }} { - {% for field in type.fields %} - {% if field.description is defined -%} - {{ field.description | to_doc_comment(style="rust") }} - {# we currently use String for date-time params, for backwards compat -#} - {# document the format so it's not _that_ awkward -#} - {% if field.type.is_datetime() -%} - /// - /// RFC3339 date string. - {% endif -%} - {% endif -%} - - {% if field.deprecated -%} - #[deprecated] - {% endif -%} - - {% if field.name != field.name | to_snake_case -%} - #[serde(rename = "{{ field.name }}")] - {% endif -%} - - {# - we only have defaults on optional fields now, and the old codegen - was not doing anything with them, so leave them alone here as well, - at least for now - -#} - {# {% if field.default is defined and field.default is not none -%} - #[serde(default = "{{ field.name | to_snake_case }}_default")] - {% endif -%} -#} - {% if field.type.is_datetime() -%} - {% set field_ty = "String" -%} - {% else -%} - {% set field_ty = field.type.to_rust() -%} - {% endif -%} - - {% if not field.required or field.nullable -%} - {# only for patch requests, if the field is both non-required - and nullable, use JsOption -#} - {% if type.name is endingwith "Patch" and field.nullable -%} - {% set field_ty %}JsOption<{{ field_ty }}>{% endset -%} - #[serde(default, skip_serializing_if = "JsOption::is_undefined")] - {% else -%} - {% set field_ty %}Option<{{ field_ty }}>{% endset -%} - #[serde(skip_serializing_if = "Option::is_none")] - {% endif -%} - {% endif -%} - - pub {{ field.name | to_snake_case }}: {{ field_ty }}, - {% endfor %} + {% include "types/struct_fields.rs.jinja" -%} } impl {{ type.name | to_upper_camel_case }} { diff --git a/rust/templates/types/struct_enum.rs.jinja b/rust/templates/types/struct_enum.rs.jinja new file mode 100644 index 000000000..b4a56c981 --- /dev/null +++ b/rust/templates/types/struct_enum.rs.jinja @@ -0,0 +1,38 @@ +use serde::{Deserialize, Serialize}; + +use super::{ + {% for c in referenced_components -%} + {{ c | to_snake_case }}::{{ c | to_upper_camel_case }}, + {% endfor -%} +}; + +{% set type_name = type.name | to_upper_camel_case -%} +{% if type.fields | length > 0 -%} + {% set enum_type_name %}{{ type_name }}{{ type.content_field | to_upper_camel_case }}{% endset -%} + + {{ doc_comment }} + #[derive(Clone, Debug, Deserialize, Serialize)] + pub struct {{ type_name }} { + {% include "types/struct_fields.rs.jinja" %} + + #[serde(flatten)] + {% set enum_field_name = type.content_field | to_snake_case %} + {% if type.content_field != enum_field_name -%} + #[serde(rename = "{{ type.content_field }}")] + {% endif -%} + pub {{ enum_field_name }}: {{ enum_type_name }}, + } +{% else -%} + {% set enum_type_name = type_name %} +{% endif %} + +#[derive(Clone, Debug, Deserialize, Serialize)] +#[serde(tag = "{{ type.discriminator_field }}", content = "{{ type.content_field }}")] +pub enum {{ enum_type_name }} { + {% for variant in type.variants -%} + {{ variant.name | to_upper_camel_case -}} + {% if variant.schema_ref is defined -%} + ({{ variant.schema_ref | to_upper_camel_case }}) + {%- endif %}, + {% endfor -%} +} diff --git a/rust/templates/types/struct_fields.rs.jinja b/rust/templates/types/struct_fields.rs.jinja new file mode 100644 index 000000000..990c3ed05 --- /dev/null +++ b/rust/templates/types/struct_fields.rs.jinja @@ -0,0 +1,47 @@ +{% for field in type.fields %} + {% if field.description is defined -%} + {{ field.description | to_doc_comment(style="rust") }} + {# we currently use String for date-time params, for backwards compat -#} + {# document the format so it's not _that_ awkward -#} + {% if field.type.is_datetime() -%} + /// + /// RFC3339 date string. + {% endif -%} + {% endif -%} + + {% if field.deprecated -%} + #[deprecated] + {% endif -%} + + {% if field.name != field.name | to_snake_case -%} + #[serde(rename = "{{ field.name }}")] + {% endif -%} + + {# + we only have defaults on optional fields now, and the old codegen + was not doing anything with them, so leave them alone here as well, + at least for now + -#} + {# {% if field.default is defined and field.default is not none -%} + #[serde(default = "{{ field.name | to_snake_case }}_default")] + {% endif -%} -#} + {% if field.type.is_datetime() -%} + {% set field_ty = "String" -%} + {% else -%} + {% set field_ty = field.type.to_rust() -%} + {% endif -%} + + {% if not field.required or field.nullable -%} + {# only for patch requests, if the field is both non-required + and nullable, use JsOption -#} + {% if type.name is endingwith "Patch" and field.nullable -%} + {% set field_ty %}JsOption<{{ field_ty }}>{% endset -%} + #[serde(default, skip_serializing_if = "JsOption::is_undefined")] + {% else -%} + {% set field_ty %}Option<{{ field_ty }}>{% endset -%} + #[serde(skip_serializing_if = "Option::is_none")] + {% endif -%} + {% endif -%} + + pub {{ field.name | to_snake_case }}: {{ field_ty }}, +{% endfor %}