diff --git a/src/bin/ion/commands/beta/generate/templates/rust/nested_type.templ b/src/bin/ion/commands/beta/generate/templates/rust/nested_type.templ index 86dafd5..ca9b22b 100644 --- a/src/bin/ion/commands/beta/generate/templates/rust/nested_type.templ +++ b/src/bin/ion/commands/beta/generate/templates/rust/nested_type.templ @@ -1,3 +1,5 @@ +{% import "util_macros.templ" as util_macros %} + {# following macro defines an anonymous type as children class for its parent type definition #} {% macro nested_type(target_kind_name, fields, abstract_data_type, nested_anonymous_types) -%} #[derive(Debug, Clone, Default)] @@ -29,7 +31,7 @@ abstract_data_type.value = {% if fields[0].value_type | is_built_in_type == false %} {{ fields[0].value_type }}::read_from(reader)?; {% else %} - reader.read_{% if fields[0].isl_type_name == "symbol" %}symbol()?.text().unwrap(){% else %}{{ fields[0].value_type | replace(from="string", to ="str") }}()?{% endif %}{% if fields[0].value_type | lower == "string" %} .to_string() {% endif %}; + reader.read_{% if fields[0].isl_type_name == "symbol" %}symbol()?.text().unwrap(){% else %}{{ fields[0].value_type | lower | replace(from="string", to ="str") }}()?{% endif %}{% if fields[0].value_type | lower == "string" %} .to_string() {% endif %}; {% endif %} {% elif abstract_data_type is object and abstract_data_type is containing("Structure") %} reader.step_in()?; @@ -38,7 +40,11 @@ match field_name { {% for field in fields -%} {% if field.value_type | is_built_in_type == false %} - "{{ field.name }}" => { abstract_data_type.{{ field.name | snake }} = {{ field.value_type }}::read_from(reader)?; } + {% if field.value_type is containing("Vec") %} + "{{ field.name }}" => { {{ util_macros::read_as_sequence(field=field) }} } + {% else %} + "{{ field.name }}" => { abstract_data_type.{{ field.name | snake }} = {{ field.value_type }}::read_from(reader)?; } + {% endif %} {% else %} "{{ field.name }}" => { abstract_data_type.{{ field.name | snake}} = reader.read_{% if field.isl_type_name == "symbol" %}symbol()?.text().unwrap(){% else %}{{ field.value_type | lower | replace(from="string", to ="str") }}()?{% endif %}{% if field.value_type | lower== "string" %} .to_string() {% endif %}; } {% endif %} @@ -95,7 +101,7 @@ {% if field.value_type | is_built_in_type == false %} self.{{ field.name | snake }}.write_to(writer)?; {% else %} - writer.write_{% if field.isl_type_name == "symbol" %}symbol{% else %}{{ field.value_type | lower }}{% endif %}(self.value)?; + writer.write_{% if field.isl_type_name == "symbol" %}symbol{% else %}{{ field.value_type | lower }}{% endif %}(self.value.to_owned())?; {% endif %} {% endfor %} {% elif abstract_data_type is object and abstract_data_type is containing("Structure") %} @@ -103,7 +109,11 @@ {% for field in fields %} writer.set_field_name("{{ field.name }}"); {% if field.value_type | is_built_in_type == false %} - self.{{ field.name | snake }}.write_to(writer)?; + {% if field.value_type is containing("Vec") %} + {{ util_macros::write_as_sequence(field=field) }} + {% else %} + self.{{ field.name | snake }}.write_to(writer)?; + {% endif %} {% else %} {# TODO: Change the following `to_owned` to only be used when writing i64,f32,f64,bool which require owned value as input #} writer.write_{% if field.isl_type_name == "symbol" %}symbol{% else %}{{ field.value_type | lower }}{% endif %}(self.{{ field.name | snake }}.to_owned())?; diff --git a/src/bin/ion/commands/beta/generate/templates/rust/struct.templ b/src/bin/ion/commands/beta/generate/templates/rust/struct.templ index 0dcdc0d..3a5e62a 100644 --- a/src/bin/ion/commands/beta/generate/templates/rust/struct.templ +++ b/src/bin/ion/commands/beta/generate/templates/rust/struct.templ @@ -1,5 +1,7 @@ {# Includes the macros for anonymous types that will be added as child classes #} {% import "nested_type.templ" as macros %} +{% import "util_macros.templ" as util_macros %} + use {{ target_kind_name | snake }}::{{ target_kind_name }}; pub mod {{ target_kind_name | snake }} { use super::*; @@ -33,7 +35,7 @@ pub mod {{ target_kind_name | snake }} { abstract_data_type.value = {% if fields[0].value_type | is_built_in_type == false %} {{ fields[0].value_type }}::read_from(reader)?; {% else %} - reader.read_{% if fields[0].isl_type_name == "symbol" %}symbol()?.text().unwrap(){% else %}{{ fields[0].value_type | replace(from="string", to ="str") }}()?{% endif %}{% if fields[0].value_type | lower == "string" %} .to_string() {% endif %}; + reader.read_{% if fields[0].isl_type_name == "symbol" %}symbol()?.text().unwrap(){% else %}{{ fields[0].value_type | lower | replace(from="string", to ="str") }}()?{% endif %}{% if fields[0].value_type | lower == "string" %} .to_string() {% endif %}; {% endif %} {% elif abstract_data_type is object and abstract_data_type is containing("Structure") %} reader.step_in()?; @@ -42,7 +44,11 @@ pub mod {{ target_kind_name | snake }} { match field_name { {% for field in fields -%} {% if field.value_type | is_built_in_type == false %} - "{{ field.name }}" => { abstract_data_type.{{ field.name | snake }} = {{ field.value_type }}::read_from(reader)?; } + {% if field.value_type is containing("Vec") %} + "{{ field.name }}" => { {{ util_macros::read_as_sequence(field=field) }} } + {% else %} + "{{ field.name }}" => { abstract_data_type.{{ field.name | snake }} = {{ field.value_type }}::read_from(reader)?; } + {% endif %} {% else %} "{{ field.name }}" => { abstract_data_type.{{ field.name | snake}} = reader.read_{% if field.isl_type_name == "symbol" %}symbol()?.text().unwrap(){% else %}{{ field.value_type | lower | replace(from="string", to ="str") }}()?{% endif %}{% if field.value_type | lower== "string" %} .to_string() {% endif %}; } {% endif %} @@ -99,7 +105,7 @@ pub mod {{ target_kind_name | snake }} { {% if field.value_type | is_built_in_type == false %} self.{{ field.name | snake }}.write_to(writer)?; {% else %} - writer.write_{% if field.isl_type_name == "symbol" %}symbol{% else %}{{ field.value_type | lower }}{% endif %}(self.value)?; + writer.write_{% if field.isl_type_name == "symbol" %}symbol{% else %}{{ field.value_type | lower }}{% endif %}(self.value.to_owned())?; {% endif %} {% endfor %} {% elif abstract_data_type is object and abstract_data_type is containing("Structure") %} @@ -107,7 +113,11 @@ pub mod {{ target_kind_name | snake }} { {% for field in fields %} writer.set_field_name("{{ field.name }}"); {% if field.value_type | is_built_in_type == false %} - self.{{ field.name | snake }}.write_to(writer)?; + {% if field.value_type is containing("Vec") %} + {{ util_macros::write_as_sequence(field=field) }} + {% else %} + self.{{ field.name | snake }}.write_to(writer)?; + {% endif %} {% else %} {# TODO: Change the following `to_owned` to only be used when writing i64,f32,f64,bool which require owned value as input #} writer.write_{% if field.isl_type_name == "symbol" %}symbol{% else %}{{ field.value_type | lower }}{% endif %}(self.{{ field.name | snake }}.to_owned())?; diff --git a/src/bin/ion/commands/beta/generate/templates/rust/util_macros.templ b/src/bin/ion/commands/beta/generate/templates/rust/util_macros.templ new file mode 100644 index 0000000..d958be7 --- /dev/null +++ b/src/bin/ion/commands/beta/generate/templates/rust/util_macros.templ @@ -0,0 +1,47 @@ +{# following macro defines statements to read a class field as sequence #} +{% macro read_as_sequence(field) %} + {% if field.abstract_data_type["Sequence"].sequence_type == "List" %} + if reader.ion_type() != Some(IonType::List) { + return validation_error(format!( + "Expected list, found {} while reading {{ field.name | snake }}.", reader.ion_type().unwrap() + )); + } + {% elif field.abstract_data_type["Sequence"].sequence_type == "SExp" %} + if reader.ion_type() != Some(IonType::SExp) { + return validation_error(format!( + "Expected sexpression, found {} while reading {{ field.name | snake }}.", reader.ion_type().unwrap() + )); + } + {% endif %} + reader.step_in()?; + + abstract_data_type.{{ field.name | snake }} = { + let mut values = vec![]; + + while reader.next()? != StreamItem::Nothing { + {% if field.abstract_data_type["Sequence"].element_type | is_built_in_type == false %} + values.push({{ field.abstract_data_type["Sequence"].element_type }}::read_from(reader)?); + {% else %} + values.push(reader.read_{% if field.isl_type_name == "symbol" %}symbol()?.text().unwrap(){% else %}{{ field.abstract_data_type["Sequence"].element_type | lower | replace(from="string", to ="str") }}()?{% endif %}{% if field.abstract_data_type["Sequence"].element_type | lower== "string" %} .to_string() {% endif %}); + {% endif %} + } + values + }; + reader.step_out()?; +{% endmacro %} +{# following macro defines statements to write a class field as sequence #} +{% macro write_as_sequence(field) %} + {% if field.abstract_data_type["Sequence"].sequence_type == "List" %} + writer.step_in(IonType::List)?; + {% else %} + writer.step_in(IonType::SExp)?; + {% endif %} + for value in &self.{{ field.name | snake }} { + {% if field.abstract_data_type["Sequence"].element_type | is_built_in_type == false %} + value.write_to(writer)?; + {% else %} + writer.write_{% if field.isl_type_name == "symbol" %}symbol{% else %}{{ field.abstract_data_type["Sequence"].element_type | lower }}{% endif %}(value.to_owned())?; + {% endif %} + } + writer.step_out()?; +{% endmacro %} \ No newline at end of file