diff --git a/codegenerator/common/rust.py b/codegenerator/common/rust.py index 9e778c0..1047e2c 100644 --- a/codegenerator/common/rust.py +++ b/codegenerator/common/rust.py @@ -628,7 +628,7 @@ class HashMapResponse(Dictionary): """Wrapper around a simple dictionary to implement Display trait""" # name: str | None = None - lifetimes: set[str] = set() + # lifetimes: set[str] = set() @property def type_hint(self): diff --git a/codegenerator/rust_tui.py b/codegenerator/rust_tui.py index 3974d8c..aab8e49 100644 --- a/codegenerator/rust_tui.py +++ b/codegenerator/rust_tui.py @@ -231,6 +231,17 @@ class Struct(rust_sdk.Struct): return result +class StringEnum(common_rust.StringEnum): + def get_sdk_setter( + self, source_var_name: str, sdk_mod_path: str, into: bool = False + ) -> str: + return f"val.clone().into()" + + @property + def derive_container_macros(self) -> str | None: + return "#[derive(Clone, Debug, Eq, PartialEq, Deserialize, Serialize)]" + + class TypeManager(common_rust.TypeManager): """Rust SDK type manager @@ -253,6 +264,7 @@ class TypeManager(common_rust.TypeManager): request_parameter_class: type[common_rust.RequestParameter] = ( common_rust.RequestParameter ) + string_enum_class = StringEnum sdk_type_manager: SdkTypeManager | None = None diff --git a/codegenerator/templates/rust_tui/impl.rs.j2 b/codegenerator/templates/rust_tui/impl.rs.j2 index 9e1bd96..18d8383 100644 --- a/codegenerator/templates/rust_tui/impl.rs.j2 +++ b/codegenerator/templates/rust_tui/impl.rs.j2 @@ -16,7 +16,7 @@ // `openstack-codegenerator`. {% import 'rust_macros.j2' as macros with context -%} use derive_builder::Builder; -use eyre::{Result, WrapErr, Report}; +use eyre::{Result, WrapErr, Report, eyre}; use serde::{Deserialize, Serialize}; use std::fmt; use tokio::sync::mpsc::UnboundedSender; @@ -33,7 +33,7 @@ use {{ mod }}; {%- set sdk_data_type = sdk_type_manager.get_root_data_type() %} {%- if data_type.__class__.__name__ == "Struct" %} -#[derive(Builder, Debug, Default, Clone, PartialEq, Eq, Serialize, Deserialize)] +#[derive(Builder, Clone, Debug, Default, Deserialize, PartialEq, Eq, Serialize)] #[builder(setter(strip_option))] pub struct {{ class_name }}{ {%- for name, param in type_manager.parameters|dictsort if param.location != "header" %} @@ -51,6 +51,7 @@ pub struct {{ class_name }}{ Option<{{ param.type_hint }}>, {%- endif %} {%- endif %} +{%- endfor %} {%- if data_type["fields"] is defined %} {#- Structure #} @@ -62,13 +63,48 @@ pub struct {{ class_name }}{ {%- endfor %} {%- endif %} -{%- endfor %} } {%- for type, sdk_type in type_manager.get_subtypes_with_sdk() %} -{%- if type["base_type"] == "struct" %} +{%- if type["variants"] is defined %} +{#- Enum #} +{{ macros.docstring(type.description, indent=0) }} +#[derive(Clone, Debug, Deserialize, Eq, Ord, PartialEq, PartialOrd, Serialize)] +pub enum {{ type.name }} { + {%- for k in type.variants.keys()|sort %} + {{ type.variant_serde_macros(k) }} + {{ k }}, + {%- endfor %} +} + +impl TryFrom for {{ type.name }} { + type Error = Report; + + fn try_from(value: String) -> Result { + match value.as_str() { + {%- for k, vals in type.variants|dictsort %} + {%- for val in vals|sort %} + "{{val}}" => Ok(Self::{{k}}), + {%- endfor %} + {%- endfor %} + other => Err(eyre!("'{}' is not a valid {{ type.name }}", other)), + } + } +} + +impl From<{{ type.name }}> for {{ sdk_mod_path | join("::") }}::{{ sdk_type.name }} { + fn from(value: {{ type.name }}) -> Self { + match value { + {%- for k in type.variants.keys()|sort %} + {{ type.name }}::{{k}} => Self::{{k}}, + {%- endfor %} + } + } +} + +{%- elif type["base_type"] == "struct" %} /// {{ type.name }} data -#[derive(Builder, Debug, Default, Deserialize, Clone, Eq, PartialEq, Serialize)] +#[derive(Builder, Clone, Debug, Default, Deserialize, Eq, PartialEq, Serialize)] #[builder(setter(strip_option))] pub struct {{ type.name }} { {%- for _, field in type.fields | dictsort %} @@ -118,7 +154,7 @@ impl fmt::Display for {{ class_name }} { } } -impl TryFrom<&{{ class_name }}> for RequestBuilder{{ "<'_>" if sdk_type_manager.get_request_static_lifetimes(data_type) else "" }} { +impl TryFrom<&{{ class_name }}> for RequestBuilder{{ "<'_>" if sdk_type_manager.get_request_static_lifetimes(sdk_data_type) else "" }} { type Error = Report; fn try_from(value: &{{ class_name }}) -> Result { let mut ep_builder = Self::default(); @@ -182,7 +218,7 @@ impl ExecuteApiRequest for {{ class_name }} { request: request.clone(), data: ep.query_async(session).await?, })?; - {%- elif operation_type in ["action", "set"] %} + {%- elif operation_type in ["action", "create", "set"] %} app_tx.send(Action::ApiResponseData { request: request.clone(), data: ep.query_async(session).await?, diff --git a/metadata/network_metadata.yaml b/metadata/network_metadata.yaml index e0f44f4..a970564 100644 --- a/metadata/network_metadata.yaml +++ b/metadata/network_metadata.yaml @@ -3133,6 +3133,8 @@ resources: sdk_mod_name: create rust-sdk: module_name: create + rust-tui: + module_name: create delete: operation_id: security-group-rules/id:delete operation_type: delete