This is an automated email from the ASF dual-hosted git repository.
jfeinauer pushed a commit to branch feature/plc4rs
in repository https://gitbox.apache.org/repos/asf/plc4x.git
The following commit(s) were added to refs/heads/feature/plc4rs by this push:
new b6a4d30a07 Step forward complex types
b6a4d30a07 is described below
commit b6a4d30a078860f0a477786fd332675168d1d4cc
Author: julian <[email protected]>
AuthorDate: Sat Jun 4 17:48:50 2022 +0200
Step forward complex types
---
.../language/rust/RustLanguageTemplateHelper.java | 119 +-
.../templates/rust/complex-type-template.rs.ftlh | 1648 ++++++++++----------
.../resources/templates/rust/enum-template.rs.ftlh | 2 +-
3 files changed, 958 insertions(+), 811 deletions(-)
diff --git
a/code-generation/language-rust/src/main/java/org/apache/plc4x/language/rust/RustLanguageTemplateHelper.java
b/code-generation/language-rust/src/main/java/org/apache/plc4x/language/rust/RustLanguageTemplateHelper.java
index a55a4f5666..a865744f8f 100644
---
a/code-generation/language-rust/src/main/java/org/apache/plc4x/language/rust/RustLanguageTemplateHelper.java
+++
b/code-generation/language-rust/src/main/java/org/apache/plc4x/language/rust/RustLanguageTemplateHelper.java
@@ -21,9 +21,14 @@ package org.apache.plc4x.language.rust;
import org.apache.commons.lang3.StringUtils;
import org.apache.commons.lang3.math.NumberUtils;
import org.apache.commons.text.WordUtils;
+import
org.apache.plc4x.plugins.codegenerator.language.mspec.model.definitions.DefaultComplexTypeDefinition;
import
org.apache.plc4x.plugins.codegenerator.language.mspec.model.definitions.DefaultEnumTypeDefinition;
+import
org.apache.plc4x.plugins.codegenerator.language.mspec.model.fields.DefaultDiscriminatorField;
+import
org.apache.plc4x.plugins.codegenerator.language.mspec.model.fields.DefaultSwitchField;
import
org.apache.plc4x.plugins.codegenerator.language.mspec.model.references.DefaultEnumTypeReference;
+import
org.apache.plc4x.plugins.codegenerator.language.mspec.model.terms.DefaultBooleanLiteral;
import
org.apache.plc4x.plugins.codegenerator.language.mspec.model.terms.DefaultStringLiteral;
+import
org.apache.plc4x.plugins.codegenerator.language.mspec.model.terms.DefaultVariableLiteral;
import
org.apache.plc4x.plugins.codegenerator.protocol.freemarker.BaseFreemarkerLanguageTemplateHelper;
import
org.apache.plc4x.plugins.codegenerator.protocol.freemarker.FreemarkerException;
import org.apache.plc4x.plugins.codegenerator.protocol.freemarker.Tracer;
@@ -40,6 +45,7 @@ import java.time.LocalDateTime;
import java.time.LocalTime;
import java.util.*;
import java.util.function.Function;
+import java.util.stream.Collectors;
@SuppressWarnings({"unused", "WeakerAccess"})
public class RustLanguageTemplateHelper extends
BaseFreemarkerLanguageTemplateHelper {
@@ -80,13 +86,94 @@ public class RustLanguageTemplateHelper extends
BaseFreemarkerLanguageTemplateHe
return getLanguageTypeNameForTypeReference(((TypedField)
field).getType(), !field.isOptionalField());
}
- public List<String> generateImports(EnumTypeDefinition typeDefinition) {
+ public List<TypeDefinition> getSubtypes(TypeDefinition typeDefinition) {
+ List<TypeDefinition> subtypes = new ArrayList<>();
+ if (typeDefinition instanceof DefaultComplexTypeDefinition) {
+ for (Field field : ((DefaultComplexTypeDefinition)
typeDefinition).getAllFields()) {
+ if (field instanceof DefaultSwitchField) {
+ subtypes.addAll(((DefaultSwitchField) field).getCases());
+ }
+ }
+ }
+ return subtypes;
+ }
+
+ public String generateFieldParseCode(Field field) {
+ if (field instanceof DefaultDiscriminatorField) {
+ // Get it from the parameter
+ String type = this.getLanguageTypeNameForField(field);
+ return "let " + ((DefaultDiscriminatorField) field).getName() + "
= parser.parse_" + type + "()?;";
+ }
+ if (field instanceof DefaultSwitchField) {
+ String matchExpression = String.join(", ", ((DefaultSwitchField)
field).getDiscriminatorExpressions().stream().map(literal ->
literal.getName()).collect(Collectors.toList()));
+ StringBuilder sb = new StringBuilder();
+ sb.append(String.format("match (%s) {", matchExpression) + "\n");
+
+ int numberOfCases = ((DefaultSwitchField)
field).getDiscriminatorExpressions().size();
+
+ for (DiscriminatedComplexTypeDefinition aCase :
((DefaultSwitchField) field).getCases()) {
+ ArrayList<String> caseStatement = new ArrayList<>();
+ for (int i = 0; i < numberOfCases; i++) {
+ if (aCase.getDiscriminatorValueTerms().size() > i) {
+ Term discriminatorLiteral =
aCase.getDiscriminatorValueTerms().get(i);
+ String literal =
discriminatorLiteral.stringRepresentation();
+ if (discriminatorLiteral instanceof Literal) {
+ if (discriminatorLiteral instanceof
DefaultBooleanLiteral) {
+ literal =
Boolean.toString(((DefaultBooleanLiteral) discriminatorLiteral).getValue());
+ }
+ if (discriminatorLiteral instanceof
DefaultVariableLiteral) {
+ // Find out type of the Variable
+ TypeReference typeReference =
((DefaultSwitchField)
field).getDiscriminatorExpressions().get(i).getTypeReference();
+ if (!(typeReference instanceof
DefaultEnumTypeReference)) {
+ throw new RuntimeException("...");
+ }
+ literal = ((DefaultEnumTypeReference)
typeReference).getName() + "::" + ((DefaultVariableLiteral)
discriminatorLiteral).getName();
+ }
+ }
+ caseStatement.add(literal);
+ } else {
+ caseStatement.add("_");
+ }
+ }
+
+ sb.append("(" + String.join(", ", caseStatement) + ") => {\n");
+
+
+ // TODO handle parser arguments if the type needs it
+ String options = "None";
+
+ sb.append("Ok(" + aCase.getParentType().get().getName() + "::"
+ aCase.getName() + "(" + aCase.getName() + "::parse::<T>(reader, " + options +
")?))");
+
+ // TODO add the action here...
+ System.out.println("Hallo");
+
+ sb.append("}\n");
+ }
+
+ sb.append("}\n");
+ return sb.toString();
+ }
+ return "";
+ }
+
+ public List<String> generateImports(TypeDefinition typeDefinition) {
// Iterate all Types to see what kind of other Enums / Objects are
references
List<String> imports = new ArrayList<>();
- for (String constantName : typeDefinition.getConstantNames()) {
- TypeReference constantType =
typeDefinition.getConstantType(constantName);
- if (constantType instanceof DefaultEnumTypeReference) {
- imports.add(((DefaultEnumTypeReference)
constantType).getName());
+ if (typeDefinition instanceof EnumTypeDefinition) {
+ for (String constantName : ((EnumTypeDefinition)
typeDefinition).getConstantNames()) {
+ TypeReference constantType = ((EnumTypeDefinition)
typeDefinition).getConstantType(constantName);
+ if (constantType instanceof DefaultEnumTypeReference) {
+ imports.add(((DefaultEnumTypeReference)
constantType).getName());
+ }
+ }
+ }
+ if (typeDefinition instanceof DefaultComplexTypeDefinition) {
+ for (Field field : ((DefaultComplexTypeDefinition)
typeDefinition).getFields()) {
+ if (field instanceof DefaultSwitchField) {
+ for (DiscriminatedComplexTypeDefinition subclass :
((DefaultSwitchField) field).getCases()) {
+ imports.add(subclass.getName());
+ }
+ }
}
}
return imports;
@@ -112,6 +199,28 @@ public class RustLanguageTemplateHelper extends
BaseFreemarkerLanguageTemplateHe
return false;
}
+ public boolean needsParserArguments(TypeDefinition typeDefinition) {
+ if (typeDefinition.getParserArguments().isPresent()) {
+ return !typeDefinition.getParserArguments().get().isEmpty();
+ }
+ return false;
+ }
+
+ public boolean isSwitchField(Field field) {
+ return field instanceof DefaultSwitchField;
+ }
+
+ public boolean isAbstract(TypeDefinition typeDefinition) {
+ if (typeDefinition instanceof DefaultComplexTypeDefinition) {
+ return ((DefaultComplexTypeDefinition)
typeDefinition).isAbstract();
+ }
+ return false;
+ }
+
+ public boolean isDiscriminated(TypeDefinition typeDefinition) {
+ return typeDefinition instanceof DiscriminatedComplexTypeDefinition;
+ }
+
public String sink(Object definition) {
return "";
}
diff --git
a/code-generation/language-rust/src/main/resources/templates/rust/complex-type-template.rs.ftlh
b/code-generation/language-rust/src/main/resources/templates/rust/complex-type-template.rs.ftlh
index f2b5a53216..10725b9e55 100644
---
a/code-generation/language-rust/src/main/resources/templates/rust/complex-type-template.rs.ftlh
+++
b/code-generation/language-rust/src/main/resources/templates/rust/complex-type-template.rs.ftlh
@@ -45,829 +45,867 @@ ${helper.packageName(protocolName, languageName,
outputFlavor)?replace(".", "/")
* specific language governing permissions and limitations
* under the License.
*/
-package ${helper.packageName(protocolName, languageName, outputFlavor)};
-
-import static org.apache.plc4x.java.spi.generation.StaticHelper.*;
-import static org.apache.plc4x.java.spi.codegen.io.DataReaderFactory.*;
-import static org.apache.plc4x.java.spi.codegen.io.DataWriterFactory.*;
-import static org.apache.plc4x.java.spi.codegen.fields.FieldReaderFactory.*;
-import static org.apache.plc4x.java.spi.codegen.fields.FieldWriterFactory.*;
-
-import org.apache.plc4x.java.spi.codegen.*;
-import org.apache.plc4x.java.spi.codegen.io.*;
-import org.apache.plc4x.java.spi.codegen.fields.*;
-import org.apache.plc4x.java.api.exceptions.*;
-import org.apache.plc4x.java.spi.generation.*;
-import org.apache.plc4x.java.api.value.*;
-
-import java.time.*;
-import java.util.*;
-import java.math.BigInteger;
+// package ${helper.packageName(protocolName, languageName, outputFlavor)};
// Code generated by code-generation. DO NOT EDIT.
-
-<#-- TODO: the code below implies that parserArguments will be null if not
present... not pretty -->
-<#if type.parserArguments.isPresent()><#assign
parserArguments=type.allParserArguments.orElseThrow()></#if>
-public<#if type.isDiscriminatedParentTypeDefinition()> abstract</#if> class
${type.name}<#if type.isDiscriminatedParentTypeDefinition()></#if><#if
type.parentType.isPresent()> extends
${type.parentType.orElseThrow().name}</#if> implements Message {
-
-<#--
- If this is a discriminated child type, we need to generate methods for
accessing it's discriminator
- values, as if they were normal java properties.
--->
-<#if type.isDiscriminatedChildTypeDefinition()>
- <#assign discriminatedChildType =
type.asDiscriminatedComplexTypeDefinition().orElseThrow()>
- // Accessors for discriminator values.
- <#list discriminatedChildType.getDiscriminatorMap() as discriminatorName,
discriminatorValue>
- <#-- If the discriminator name matches that of another field, suppress
the methods generation -->
- <#if
!discriminatedChildType.isNonDiscriminatorField(discriminatorName)><#--&&
!discriminatedChildType.isParserArgument(discriminatorName)-->
- <#assign discriminatorType =
helper.getDiscriminatorTypes()[discriminatorName]>
- public ${helper.getLanguageTypeNameForTypeReference(discriminatorType)}
get${discriminatorName?cap_first}() {
- <#if discriminatorValue?? &&
!helper.isWildcard(discriminatorValue)>
- <#if discriminatorType.isEnumTypeReference()>
- return
${helper.getLanguageTypeNameForTypeReference(discriminatorType)}.${helper.toParseExpression(null,
discriminatorType, discriminatorValue, parserArguments)};
- <#else>
- return
(${helper.getLanguageTypeNameForTypeReference(discriminatorType, true)})
${helper.toParseExpression(null, discriminatorType, discriminatorValue,
parserArguments)};
- </#if>
- <#else>
- return ${helper.getNullValueForTypeReference(discriminatorType)};
- </#if>
- }
- </#if>
- </#list>
-</#if>
-<#--
- If this is a discriminated parent type, we need to generate the abstract
methods for accessing it's
- discriminator values instead.
--->
-<#if type.isDiscriminatedParentTypeDefinition()>
- <#assign discriminatedParentType = type>
- <#-- @ftlvariable name="discriminatedParentType"
type="org.apache.plc4x.plugins.codegenerator.types.definitions.ComplexTypeDefinition"
-->
- // Abstract accessors for discriminator values.
- <#list helper.discriminatorTypes as discriminatorName, discriminatorType>
- <#-- If the discriminator name matches that of another field, suppress
the methods generation -->
- <#if !type.isNonDiscriminatorField(discriminatorName)><#-- &&
!type.isParserArgument(discriminatorName)-->
- public abstract
${helper.getLanguageTypeNameForTypeReference(discriminatorType)}
get${discriminatorName?cap_first}();
- </#if>
- </#list>
-</#if>
-<#-- If the current type contains "const" fields, generate some java constants
for holing their values -->
-<#if type.constFields?has_content>
-
- // Constant values.
- <#list type.constFields as field>
- public static final
${helper.getLanguageTypeNameForTypeReference(field.type)}
${field.name?upper_case} = ${helper.toParseExpression(field, field.type,
field.referenceValue, parserArguments)};
- </#list>
-</#if>
-<#-- Property fields are fields that require a property in the pojo -->
-<#if type.propertyFields?has_content>
-
- // Properties.
- <#list type.propertyFields as field>
- protected final ${helper.getLanguageTypeNameForTypeReference(field.type,
!field.isOptionalField())} ${field.name};
- </#list>
-</#if>
-<#if parserArguments?has_content>
- <#assign filteredParserArguments=parserArguments?filter(arg ->
!type.isDiscriminatorField(arg.name) &&
!type.getPropertyFieldFromThisOrParentByName(arg.name).isPresent())>
+<#list helper.generateImports(type) as import>
+<#if type.name != import>
+<#-- File -> Struct -->
+use crate::${import}::${import};
</#if>
-<#if filteredParserArguments?has_content>
-
- // Arguments.
- <#list filteredParserArguments as parserArgument>
- protected final
${helper.getLanguageTypeNameForTypeReference(parserArgument.type)}
${parserArgument.name};
- </#list>
-</#if>
-
- <#-- getAllPropertyFields() returns not only the property fields of this
type but also of it's parents -->
- <@compress single_line=true>
- public ${type.name}(
- <#list type.getAllPropertyFields() as field>
- ${helper.getLanguageTypeNameForField(field)} ${field.name}
- <#sep>, </#sep>
- </#list>
- <#if filteredParserArguments?has_content>
- <#if type.getAllPropertyFields()?has_content>, </#if>
- <#list filteredParserArguments as parserArgument>
-
${helper.getLanguageTypeNameForTypeReference(parserArgument.type)}
${parserArgument.name}
- <#sep>, </#sep>
- </#list>
- </#if>
- ) {
- </@compress>
-
- <@compress single_line=true>
- super(
- <#if type.parentPropertyFields?has_content>
- <#list type.parentPropertyFields as field>
- ${field.name}
- <#sep>, </#sep>
- </#list>
- </#if>
- <#if type.parentType.isPresent() &&
type.parentType.orElseThrow().allParserArguments.isPresent()>
- <#assign filteredParentParserArguments =
type.parentType.orElseThrow().allParserArguments.orElseThrow()?filter(arg ->
!type.parentType.orElseThrow().asComplexTypeDefinition().orElseThrow().isDiscriminatorField(arg.name))>
- <#if filteredParentParserArguments?has_content>
- <#if type.parentPropertyFields?has_content>, </#if>
- <#list filteredParentParserArguments as parserArgument>
- ${parserArgument.name}
- <#sep>, </#sep>
- </#list>
- </#if>
- </#if>
- );
- </@compress>
-
-<#list type.propertyFields as field>
- this.${field.name} = ${field.name};
</#list>
-<#if filteredParserArguments?has_content>
- <#list filteredParserArguments as parserArgument>
- this.${parserArgument.name} = ${parserArgument.name};
- </#list>
-</#if>
- }
-
-<#list type.abstractFields as field>
- public abstract ${helper.getLanguageTypeNameForField(field)}
get${field.asNamedField().orElseThrow().name?cap_first}();
+<#if helper.needsParserArguments(type)>
+pub struct ${type.name}Options {
+<#list type.parserArguments.orElseThrow() as arg>
+ ${arg.name}:
${helper.getLanguageTypeNameForTypeReference(arg.type)}<#sep>, </#sep>
</#list>
-<#list type.propertyFields as field>
- public ${helper.getLanguageTypeNameForField(field)}
get${field.name?cap_first}() {
- return ${field.name};
- }
-
-</#list>
-<#list type.virtualFields as field>
- public ${helper.getLanguageTypeNameForField(field)}
get${field.name?cap_first}() {
- <#if helper.getLanguageTypeNameForField(field) = 'String'>
- return
${helper.getLanguageTypeNameForField(field)}.valueOf(${helper.toSerializationExpression(field,
field.type, field.valueExpression, parserArguments)});
- <#--elseif helper.getLanguageTypeNameForField(field) = 'BigInteger' &&
!helper.isBigIntegerSource(field.valueExpression)-->
- <#elseif helper.getLanguageTypeNameForField(field) = 'BigInteger'>
- Object o = ${helper.toSerializationExpression(field, field.type,
field.valueExpression, parserArguments)};
- if (o instanceof BigInteger)
- return (BigInteger) o;
- return BigInteger.valueOf(((Number)o).longValue());
- <#else>
- return (${helper.getLanguageTypeNameForField(field)})
(${helper.toSerializationExpression(field, field.type, field.valueExpression,
parserArguments)});
- </#if>
- }
-
-</#list>
-<#list type.constFields as field>
- public ${helper.getLanguageTypeNameForField(field)}
get${field.name?cap_first}() {
- return ${field.name?upper_case};
- }
-
+}
+</#if>
+<#if helper.isAbstract(type)>
+#[derive(PartialEq, Debug, Clone)]
+pub enum ${type.name} {
+<#list helper.getSubtypes(type) as subtype>
+ ${subtype.name}(${subtype.name}::${subtype.name})<#sep>,</#sep>
</#list>
+}
- <#if outputFlavor != "passive">
-<#if type.isDiscriminatedChildTypeDefinition()>
- @Override
- protected void
serialize${type.parentType.orElseThrow().name}Child(WriteBuffer writeBuffer)
throws SerializationException {
-<#else>
- <#if type.isDiscriminatedParentTypeDefinition()>
- abstract protected void serialize${type.name?cap_first}Child(WriteBuffer
writeBuffer) throws SerializationException;
-
- </#if>
- public void serialize(WriteBuffer writeBuffer) throws
SerializationException {
-</#if>
- PositionAware positionAware = writeBuffer;
- <#if helper.hasFieldOfType("unknown")>
- throw new SerializationException("Unknown field not serializable");
- <#else>
- int startPos = positionAware.getPos();
- writeBuffer.pushContext("${type.name}");
- <#list type.fields as field>
- <#switch field.typeName>
- <#case "array">
- <#assign arrayField =
field.asArrayField().orElseThrow()>
- <#assign typedField =
field.asTypedField().orElseThrow()>
- <#assign namedField =
field.asNamedField().orElseThrow()>
-
- // Array Field (${arrayField.name})
- <#if
arrayField.type.elementTypeReference.isByteBased()>
- writeByteArrayField("${namedField.name}",
${namedField.name}, writeByteArray(writeBuffer, 8));
- <#elseif
arrayField.type.elementTypeReference.isSimpleTypeReference()>
- writeSimpleTypeArrayField("${namedField.name}",
${namedField.name},
${helper.getDataWriterCall(arrayField.type.elementTypeReference,
namedField.name)});
- <#else>
- writeComplexTypeArrayField("${namedField.name}",
${namedField.name}, writeBuffer);
- </#if>
- <#break>
- <#case "checksum">
- <#assign checksumField =
field.asChecksumField().orElseThrow()>
- <#assign typedField =
field.asTypedField().orElseThrow()>
- <#assign namedField =
field.asNamedField().orElseThrow()>
-
- // Checksum Field (checksum) (Calculated)
- writeChecksumField("${namedField.name}",
(${helper.getLanguageTypeNameForField(field)})
(${helper.toParseExpression(checksumField, checksumField.type,
checksumField.checksumExpression, parserArguments)}),
${helper.getDataWriterCall(typedField.type, namedField.name)});
- <#break>
- <#case "const">
- <#assign constField =
field.asConstField().orElseThrow()>
- <#assign typedField =
field.asTypedField().orElseThrow()>
- <#assign namedField =
field.asNamedField().orElseThrow()>
-
- // Const Field (${constField.name})
- <#if
typedField.type.isEnumTypeReference()>writeConstField("${constField.name}",
${namedField.name?upper_case}.getValue(),
${helper.getDataWriterCall(helper.getEnumBaseTypeReference(typedField.type),
namedField.name)});<#else>writeConstField("${constField.name}",
${namedField.name?upper_case}, ${helper.getDataWriterCall(typedField.type,
namedField.name)});</#if>
- <#break>
- <#case "discriminator">
- <#assign discriminatorField =
field.asDiscriminatorField().orElseThrow()>
- <#assign typedField =
field.asTypedField().orElseThrow()>
- <#assign namedField =
field.asNamedField().orElseThrow()>
-
- // Discriminator Field (${discriminatorField.name})
(Used as input to a switch field)
- <#if
typedField.type.isEnumTypeReference()>writeDiscriminatorEnumField("${namedField.name}",
"${helper.getLanguageTypeNameForField(field)}",
get${discriminatorField.name?cap_first}(),
${helper.getEnumDataWriterCall(typedField.type, namedField.name,
"value")});<#else>writeDiscriminatorField("${namedField.name}",
get${discriminatorField.name?cap_first}(),
${helper.getDataWriterCall(typedField.type, namedField.name)});</#if>
- <#break>
- <#case "enum">
- <#assign enumField = field.asEnumField().orElseThrow()>
- <#assign typedField =
field.asTypedField().orElseThrow()>
- <#assign namedField =
field.asNamedField().orElseThrow()>
-
- // Enum field (${namedField.name})
- writeEnumField("${namedField.name}",
"${helper.getLanguageTypeNameForField(field)}", ${namedField.name},
${helper.getEnumDataWriterCall(typedField.type, namedField.name,
enumField.fieldName)});
- <#break>
- <#case "implicit">
- <#assign implicitField =
field.asImplicitField().orElseThrow()>
- <#assign typedField =
field.asTypedField().orElseThrow()>
- <#assign namedField =
field.asNamedField().orElseThrow()>
-
- // Implicit Field (${implicitField.name}) (Used for
parsing, but its value is not stored as it's implicitly given by the objects
content)
- <#-- Implicit field values might be used in
expressions, in order to avoid problems, we generate a temporary variable with
the given name. -->
- ${helper.getLanguageTypeNameForField(field)}
${implicitField.name} = (${helper.getLanguageTypeNameForField(field)})
(${helper.toSerializationExpression(implicitField, implicitField.type,
implicitField.serializeExpression, parserArguments)});
- writeImplicitField("${namedField.name}",
${implicitField.name}, ${helper.getDataWriterCall(typedField.type,
namedField.name)});
- <#break>
- <#case "manualArray">
- <#assign manualArrayField =
field.asManualArrayField().orElseThrow()>
- <#assign typedField =
field.asTypedField().orElseThrow()>
- <#assign namedField =
field.asNamedField().orElseThrow()>
-
- // Manual Array Field (${manualArrayField.name})
- writeManualArrayField("${namedField.name}",
${namedField.name},
(${helper.getLanguageTypeNameForTypeReference(manualArrayField.type.elementTypeReference)}
_value) -> ${helper.toParseExpression(manualArrayField,
manualArrayField.type.elementTypeReference,
manualArrayField.serializeExpression, parserArguments)}, writeBuffer);
- <#break>
- <#case "manual">
- <#assign manualField =
field.asManualField().orElseThrow()>
- <#assign typedField =
field.asTypedField().orElseThrow()>
- <#assign namedField =
field.asNamedField().orElseThrow()>
-
- // Manual Field (${manualField.name})
- writeManualField("${namedField.name}", () ->
${helper.toParseExpression(manualField, manualField.type,
manualField.serializeExpression, parserArguments)}, writeBuffer);
- <#break>
- <#case "optional">
- <#assign optionalField =
field.asOptionalField().orElseThrow()>
- <#assign typedField =
field.asTypedField().orElseThrow()>
- <#assign namedField =
field.asNamedField().orElseThrow()>
-
- // Optional Field (${optionalField.name}) (Can be
skipped, if the value is null)
- <#if optionalField.type.isEnumTypeReference()>
- writeOptionalEnumField("${optionalField.name}",
"${helper.getLanguageTypeNameForField(field)}", ${optionalField.name},
${helper.getEnumDataWriterCall(optionalField.type, optionalField.name,
"value")}<#if optionalField.conditionExpression.present>,
${helper.toSerializationExpression(optionalField, helper.boolTypeReference,
optionalField.conditionExpression.get(), parserArguments)}</#if>);
- <#elseif optionalField.type.isDataIoTypeReference()>
- writeOptionalField("${optionalField.name}",
${optionalField.name}, new DataWriterDataIoDefault(writeBuffer, (wb, val) ->
${optionalField.type.asComplexTypeReference().orElseThrow().name}.staticSerialize(wb,
val<#if
optionalField.type.asComplexTypeReference().orElseThrow().params?has_content>,
<#list
optionalField.type.asComplexTypeReference().orElseThrow().params.orElseThrow()
as param>${helper.toParseExpression(optionalField, helper.anyTypeReference,
param, p [...]
- <#else>
- writeOptionalField("${optionalField.name}",
${optionalField.name}, ${helper.getDataWriterCall(typedField.type,
optionalField.name)}<#if optionalField.conditionExpression.present>,
${helper.toSerializationExpression(optionalField, helper.boolTypeReference,
optionalField.conditionExpression.get(), parserArguments)}</#if>);
- </#if>
- <#break>
- <#case "padding">
- <#assign paddingField =
field.asPaddingField().orElseThrow()>
- <#assign typedField =
field.asTypedField().orElseThrow()>
-
- // Padding Field (padding)
- writePaddingField("padding", (int)
(${helper.toParseExpression(paddingField, helper.intTypeReference,
paddingField.paddingCondition, parserArguments)}),
(${helper.getLanguageTypeNameForField(field)})
${helper.toSerializationExpression(paddingField, paddingField.type,
paddingField.paddingValue, parserArguments)},
${helper.getDataWriterCall(typedField.type, "padding")});
- <#break>
- <#case "reserved">
- <#assign reservedField =
field.asReservedField().orElseThrow()>
- <#assign typedField =
field.asTypedField().orElseThrow()>
-
- // Reserved Field (reserved)
- writeReservedField("reserved",
${helper.getReservedValue(reservedField)},
${helper.getDataWriterCall(typedField.type, "reserved")});
- <#break>
- <#case "simple">
- <#assign simpleField =
field.asSimpleField().orElseThrow()>
- <#assign typedField =
field.asTypedField().orElseThrow()>
- <#assign namedField =
field.asNamedField().orElseThrow()>
-
- // Simple Field (${namedField.name})
- <#if typedField.type.isEnumTypeReference()>
- writeSimpleEnumField("${simpleField.name}",
"${helper.getLanguageTypeNameForField(field)}", ${simpleField.name},
${helper.getEnumDataWriterCall(simpleField.type, simpleField.name, "value")});
- <#elseif simpleField.type.isDataIoTypeReference()>
- writeSimpleField("${simpleField.name}",
${simpleField.name}, new DataWriterDataIoDefault(writeBuffer, (wb, val) ->
${simpleField.type.asComplexTypeReference().orElseThrow().name}.staticSerialize(wb,
val<#if
simpleField.type.asComplexTypeReference().orElseThrow().params?has_content>,
<#list
simpleField.type.asComplexTypeReference().orElseThrow().params.orElseThrow() as
param>${helper.toParseExpression(simpleField, helper.anyTypeReference, param,
parserArguments [...]
- <#else>
- writeSimpleField("${simpleField.name}",
${simpleField.name}, ${helper.getDataWriterCall(typedField.type,
simpleField.name)}${helper.getFieldOptions(typedField, parserArguments)});</#if>
- <#break>
- <#case "switch">
- <#assign switchField =
field.asSwitchField().orElseThrow()>
-
- // Switch field (Serialize the sub-type)
- serialize${type.name?cap_first}Child(writeBuffer);
- <#break>
- <#case "virtual">
- <#assign virtualField =
field.asVirtualField().orElseThrow()>
- <#assign typedField =
field.asTypedField().orElseThrow()>
- <#assign namedField =
field.asNamedField().orElseThrow()>
-
- // Virtual field (doesn't actually serialize anything,
just makes the value available)
- ${helper.getLanguageTypeNameForField(field)}
${namedField.name} = get${namedField.name?cap_first}();
- writeBuffer.writeVirtual("${namedField.name}",
${namedField.name});
- <#break>
- </#switch>
- </#list>
-
- writeBuffer.popContext("${type.name}");
- </#if>
- }
- </#if>
+impl Message for ${type.name} {
+ type M = ${type.name};
+ type P = <#if
helper.needsParserArguments(type)>${type.name}Options<#else>NoOption</#if>;
- @Override
- public int getLengthInBytes() {
- return (int) Math.ceil((float) getLengthInBits() / 8.0);
+ fn get_length_in_bits(&self) -> u32 {
+ todo!()
}
- @Override
- public int getLengthInBits() {
- int lengthInBits = <#if
type.parentType.isPresent()>super.getLengthInBits()<#else>0</#if>;
- ${type.name} _value = this;
-<#list type.fields as field>
-<#switch field.typeName>
- <#case "array">
- <#assign arrayField = field.asArrayField().orElseThrow()>
- <#assign arrayElementTypeReference =
arrayField.type.asArrayTypeReference().orElseThrow().getElementTypeReference()>
-
- // Array field
- if(${arrayField.name} != null) {
- <#if arrayElementTypeReference.isSimpleTypeReference()>
- <#assign simpleTypeReference =
arrayElementTypeReference.asSimpleTypeReference().orElseThrow()>
- lengthInBits += ${simpleTypeReference.sizeInBits} *
${arrayField.name}.<#if
arrayElementTypeReference.isByteBased()>length<#else>size()</#if>;
- <#elseif arrayField.isCountArrayField()>
- int i=0;
- <#assign nonSimpleTypeReference =
arrayElementTypeReference.asNonSimpleTypeReference().orElseThrow()>
- for(${nonSimpleTypeReference.name} element : ${arrayField.name}) {
- boolean last = ++i >= ${arrayField.name}.size();
- lengthInBits += element.getLengthInBits();
+ fn serialize<T: Write>(&self, writer: &mut WriteBuffer<T>) ->
Result<usize, Error> {
+ match self {
+ <#list helper.getSubtypes(type) as subtype>
+ ${type.name}::${subtype.name}(msg) => {
+ msg.serialize(writer)
}
- <#else>
- for(Message element : ${arrayField.name}) {
- lengthInBits += element.getLengthInBits();
- }
- </#if>
- }
- <#break>
- <#case "checksum">
- <#assign checksumField = field.asChecksumField().orElseThrow()>
- <#assign typedField = field.asTypedField().orElseThrow()>
- <#assign simpleTypeReference =
typedField.type.asSimpleTypeReference().orElseThrow()>
-
- // Checksum Field (checksum)
- lengthInBits += ${simpleTypeReference.sizeInBits};
- <#break>
- <#case "const">
- <#assign constField = field.asConstField().orElseThrow()>
- <#assign typedField = field.asTypedField().orElseThrow()>
-
- // Const Field (${constField.name})
- <#if typedField.type.isSimpleTypeReference()>
- <#assign simpleTypeReference =
typedField.type.asSimpleTypeReference().orElseThrow()>
- lengthInBits += ${simpleTypeReference.sizeInBits};
- <#else>
- lengthInBits +=
${helper.getEnumBaseTypeReference(typedField.type).sizeInBits};
- </#if>
- <#break>
- <#case "discriminator">
- <#assign discriminatorField =
field.asDiscriminatorField().orElseThrow()>
-
- // Discriminator Field (${discriminatorField.name})
- <#if discriminatorField.type.isSimpleTypeReference()>
- <#assign simpleTypeReference =
discriminatorField.type.asSimpleTypeReference().orElseThrow()>
- <#if simpleTypeReference.isVstringTypeReference()>
- <#assign vstringTypeReference =
simpleTypeReference.asVstringTypeReference().orElseThrow()>
- lengthInBits += ${helper.toSerializationExpression(discriminatorField,
helper.intTypeReference, vstringTypeReference.getLengthExpression(),
parserArguments)};
- <#else>
- lengthInBits += ${simpleTypeReference.sizeInBits};
- </#if>
- <#elseif helper.isEnumField(field)>
- lengthInBits +=
${helper.getEnumBaseTypeReference(discriminatorField.type).sizeInBits};
- <#else>
- lengthInBits += ${discriminatorField.name}.getLengthInBits();
- </#if>
- <#break>
- <#case "enum">
- <#assign enumField = field.asEnumField().orElseThrow()>
-
- // Enum Field (${enumField.name})
- lengthInBits +=
${helper.getEnumBaseTypeReference(enumField.type).sizeInBits};
- <#break>
- <#case "implicit">
- <#assign implicitField = field.asImplicitField().orElseThrow()>
- <#assign simpleTypeReference =
implicitField.type.asSimpleTypeReference().orElseThrow()>
-
- // Implicit Field (${implicitField.name})
- lengthInBits += ${simpleTypeReference.sizeInBits};
- <#break>
- <#case "manualArray">
- <#assign manualArrayField = field.asManualArrayField().orElseThrow()>
- <#assign arrayElementTypeReference =
manualArrayField.type.asArrayTypeReference().orElseThrow().getElementTypeReference()>
-
- // Manual Array Field (${manualArrayField.name})
- lengthInBits += ${helper.toParseExpression(manualArrayField,
helper.intTypeReference, manualArrayField.lengthExpression, parserArguments)} *
8;
- <#break>
- <#case "manual">
- <#assign manualField = field.asManualField().orElseThrow()>
-
- // Manual Field (${manualField.name})
- lengthInBits += ${helper.toParseExpression(manualField,
helper.intTypeReference, manualField.lengthExpression, parserArguments)};
- <#break>
- <#case "optional">
- <#assign optionalField = field.asOptionalField().orElseThrow()>
-
- // Optional Field (${optionalField.name})
- if(${optionalField.name} != null) {
- <#if optionalField.type.isSimpleTypeReference()>
- <#assign simpleTypeReference =
optionalField.type.asSimpleTypeReference().orElseThrow()>
- <#if simpleTypeReference.isVstringTypeReference()>
- <#assign vstringTypeReference =
simpleTypeReference.asVstringTypeReference().orElseThrow()>
- lengthInBits += ${helper.toSerializationExpression(optionalField,
helper.intTypeReference, vstringTypeReference.getLengthExpression(),
parserArguments)};
- <#else>
- lengthInBits += ${simpleTypeReference.sizeInBits};
- </#if>
- <#elseif helper.isEnumField(field)>
- lengthInBits +=
${helper.getEnumBaseTypeReference(optionalField.type).sizeInBits};
- <#elseif optionalField.type.isDataIoTypeReference()>
- lengthInBits +=
${optionalField.type.asComplexTypeReference().orElseThrow().name}.getLengthInBits(${optionalField.name}<#if
optionalField.type.asComplexTypeReference().orElseThrow().params?has_content>,
<#list
optionalField.type.asComplexTypeReference().orElseThrow().params.orElseThrow()
as param>${helper.toParseExpression(optionalField, helper.anyTypeReference,
param, parserArguments)}<#sep>, </#sep></#list></#if>);
- <#else>
- lengthInBits += ${optionalField.name}.getLengthInBits();
- </#if>
- }
- <#break>
- <#case "padding">
- <#assign paddingField = field.asPaddingField().orElseThrow()>
- <#assign simpleTypeReference =
paddingField.type.asSimpleTypeReference().orElseThrow()>
-
- // Padding Field (padding)
- <#-- We're replacing the "lastItem" with 'false' here as the item
itself can't know if it is the last -->
- int _timesPadding = (int) (${helper.toParseExpression(paddingField,
helper.intTypeReference, paddingField.paddingCondition, parserArguments)});
- while (_timesPadding-- > 0) {
- lengthInBits += ${simpleTypeReference.sizeInBits};
- }
- <#break>
- <#case "reserved">
- <#assign reservedField = field.asReservedField().orElseThrow()>
- <#assign simpleTypeReference =
reservedField.type.asSimpleTypeReference().orElseThrow()>
-
- // Reserved Field (reserved)
- lengthInBits += ${simpleTypeReference.sizeInBits};
- <#break>
- <#case "simple">
- <#assign simpleField = field.asSimpleField().orElseThrow()>
-
- // Simple field (${simpleField.name})
- <#if simpleField.type.isSimpleTypeReference()>
- <#assign simpleTypeReference =
simpleField.type.asSimpleTypeReference().orElseThrow()>
- <#if simpleTypeReference.isVstringTypeReference()>
- <#assign vstringTypeReference =
simpleTypeReference.asVstringTypeReference().orElseThrow()>
- lengthInBits += ${helper.toSerializationExpression(simpleField,
helper.intTypeReference, vstringTypeReference.getLengthExpression(),
parserArguments)};
- <#else>
- lengthInBits += ${simpleTypeReference.sizeInBits};
- </#if>
- <#elseif helper.isEnumField(field)>
- lengthInBits +=
${helper.getEnumBaseTypeReference(simpleField.type).sizeInBits};
- <#elseif simpleField.type.isDataIoTypeReference()>
- lengthInBits +=
${simpleField.type.asComplexTypeReference().orElseThrow().name}.getLengthInBits(${simpleField.name}<#if
simpleField.type.asComplexTypeReference().orElseThrow().params?has_content>,
<#list
simpleField.type.asComplexTypeReference().orElseThrow().params.orElseThrow() as
param>${helper.toParseExpression(simpleField, helper.anyTypeReference, param,
parserArguments)}<#sep>, </#sep></#list></#if>);
- <#else>
- lengthInBits += ${simpleField.name}.getLengthInBits();
- </#if>
- <#break>
- <#case "switch">
- <#assign switchField = field.asSwitchField().orElseThrow()>
-
- // Length of sub-type elements will be added by sub-type...
- <#break>
- <#case "unknown">
- <#assign unknownField = field.asUnknownField().orElseThrow()>
- <#assign simpleTypeReference =
unknownField.type.asSimpleTypeReference().orElseThrow()>
-
- // Unknown field
- lengthInBits += ${simpleTypeReference.sizeInBits};
- <#break>
- <#case "virtual">
- <#assign virtualField = field.asVirtualField().orElseThrow()>
-
- // A virtual field doesn't have any in- or output.
- <#break>
-</#switch>
-</#list>
-
- return lengthInBits;
- }
-
-<#-- The parse and serialize methods here are just proxies for forwardning the
requests to static counterparts -->
- <#if !type.isDiscriminatedChildTypeDefinition()>
- public static ${type.name} staticParse(ReadBuffer readBuffer, Object...
args) throws ParseException {
- PositionAware positionAware = readBuffer;
- <#if parserArguments?has_content>
- if((args == null) || (args.length != ${parserArguments?size})) {
- throw new PlcRuntimeException("Wrong number of arguments, expected
${parserArguments?size}, but got " + args.length);
- }
- <#list parserArguments as parserArgument>
- <#assign
languageName=helper.getLanguageTypeNameForTypeReference(parserArgument.type,
false)>
- ${languageName} ${parserArgument.name};
- if(args[${parserArgument?index}] instanceof ${languageName}) {
- ${parserArgument.name} = (${languageName})
args[${parserArgument?index}];
- <#if parserArgument.type.isSimpleTypeReference() ||
parserArgument.type.isEnumTypeReference()>
- } else if (args[${parserArgument?index}] instanceof String) {
- ${parserArgument.name} = ${languageName}.valueOf((String)
args[${parserArgument?index}]);
- </#if>
- } else {
- throw new PlcRuntimeException("Argument ${parserArgument?index}
expected to be of type ${languageName} or a string which is parseable but was "
+ args[${parserArgument?index}].getClass().getName());
+ </#list>
}
- </#list>
- </#if>
- return staticParse(readBuffer<#if parserArguments?has_content>, <#list
parserArguments as parserArgument>${parserArgument.name}<#sep>,
</#sep></#list></#if>);
}
- </#if>
-<#-- Here come the actual parse and serialize methods that actually do the
parsing and serlaizing -->
- <#assign hasParserArguments=parserArguments?has_content/>
- <#assign parserArgumentList><#if hasParserArguments><#list parserArguments
as
parserArgument>${helper.getLanguageTypeNameForTypeReference(parserArgument.type,
false)} ${parserArgument.name}<#sep>, </#sep></#list></#if></#assign>
- public static ${type.name}<#if
type.isDiscriminatedChildTypeDefinition()>Builder staticParseBuilder<#else>
staticParse</#if>(ReadBuffer readBuffer<#if hasParserArguments>,
${parserArgumentList}</#if>) throws ParseException {
- readBuffer.pullContext("${type.name}");
- PositionAware positionAware = readBuffer;
- int startPos = positionAware.getPos();
- int curPos;
+ fn parse<T: Read>(reader: &mut ReadBuffer<T>, parameter: Option<Self::P>)
-> Result<Self::M, Error> {
+ // (Re-)define the options
+ <#list type.parserArguments.orElseThrow() as arg>
+ let ${arg.name} = parameter.unwrap().${arg.name};
+ </#list>
<#list type.fields as field>
- <#switch field.typeName>
- <#case "array">
- <#assign arrayField = field.asArrayField().orElseThrow()>
- <#assign typedField = field.asTypedField().orElseThrow()>
- <#assign namedField = field.asNamedField().orElseThrow()>
- <#assign arrayElementTypeReference =
arrayField.type.asArrayTypeReference().orElseThrow().getElementTypeReference()>
-
- <#if arrayElementTypeReference.isByteBased()>
- <#if !field.isCountArrayField() &&
!field.isLengthArrayField()>
- throw new ParseException("array fields of type byte
only support 'count' and 'length' loop-types.");
- </#if>
- byte[] ${namedField.name} =
readBuffer.readByteArray("${namedField.name}",
Math.toIntExact(${helper.toParseExpression(arrayField, helper.intTypeReference,
arrayField.loopExpression,
parserArguments)})${helper.getFieldOptions(typedField, parserArguments)});
- <#else>
- <#-- If this is a count array, we can directly initialize an
array with the given size -->
- <#if field.isCountArrayField()>
-
${helper.getNonPrimitiveLanguageTypeNameForField(arrayField)}
${arrayField.name} = readCountArrayField("${arrayField.name}",
${helper.getDataReaderCall(arrayField.type)},
${helper.toParseExpression(arrayField, helper.intTypeReference,
arrayField.loopExpression,
parserArguments)}${helper.getFieldOptions(typedField, parserArguments)});
- <#-- In all other cases do we have to work with a list,
that is later converted to an array -->
- <#else>
- <#-- For a length array, we read data till the read
position of the buffer reaches a given position -->
- <#if field.isLengthArrayField()>
-
${helper.getNonPrimitiveLanguageTypeNameForField(arrayField)}
${arrayField.name} = readLengthArrayField("${arrayField.name}",
${helper.getDataReaderCall(arrayField.type)},
${helper.toParseExpression(arrayField, helper.intTypeReference,
arrayField.loopExpression,
parserArguments)}${helper.getFieldOptions(typedField, parserArguments)});
- <#-- A terminated array keeps on reading data as long
as the termination expression evaluates to false -->
- <#elseif field.isTerminatedArrayField()>
-
${helper.getNonPrimitiveLanguageTypeNameForField(arrayField)}
${arrayField.name} = readTerminatedArrayField("${arrayField.name}",
${helper.getDataReaderCall(arrayField.type)}, () -> ((boolean)
(${helper.toParseExpression(arrayField, helper.intTypeReference,
arrayField.loopExpression,
parserArguments)}))${helper.getFieldOptions(typedField, parserArguments)});
- </#if>
- </#if>
- </#if>
- <#break>
- <#case "assert">
- <#assign assertField = field.asAssertField().orElseThrow()>
- <#assign typedField = field.asTypedField().orElseThrow()>
- <#assign namedField = field.asNamedField().orElseThrow()>
-
- ${helper.getLanguageTypeNameForField(field)}
${namedField.name} = read${field.typeName?cap_first}Field("${namedField.name}",
${helper.getDataReaderCall(typedField.type)},
(${helper.getLanguageTypeNameForField(field)})
(${helper.toParseExpression(assertField, assertField.type,
assertField.conditionExpression,
parserArguments)})${helper.getFieldOptions(typedField, parserArguments)});
- <#break>
- <#case "checksum">
- <#assign checksumField = field.asChecksumField().orElseThrow()>
- <#assign typedField = field.asTypedField().orElseThrow()>
- <#assign namedField = field.asNamedField().orElseThrow()>
-
- ${helper.getLanguageTypeNameForField(field)}
${namedField.name} = read${field.typeName?cap_first}Field("${namedField.name}",
${helper.getDataReaderCall(typedField.type)},
(${helper.getLanguageTypeNameForField(field)})
(${helper.toParseExpression(checksumField, checksumField.type,
checksumField.checksumExpression,
parserArguments)})${helper.getFieldOptions(typedField, parserArguments)});
- <#break>
- <#case "const">
- <#assign constField = field.asConstField().orElseThrow()>
- <#assign typedField = field.asTypedField().orElseThrow()>
- <#assign namedField = field.asNamedField().orElseThrow()>
-
- ${helper.getLanguageTypeNameForField(field)}
${namedField.name} = read${field.typeName?cap_first}Field("${namedField.name}",
${helper.getDataReaderCall(typedField.type)},
${type.name}.${namedField.name?upper_case}${helper.getFieldOptions(typedField,
parserArguments)});
- <#break>
- <#case "discriminator">
- <#assign discriminatorField =
field.asDiscriminatorField().orElseThrow()>
- <#assign typedField = field.asTypedField().orElseThrow()>
- <#assign namedField = field.asNamedField().orElseThrow()>
-
- ${helper.getLanguageTypeNameForField(field)}
${namedField.name} = read${field.typeName?cap_first}Field("${namedField.name}",
${helper.getDataReaderCall(typedField.type)}${helper.getFieldOptions(typedField,
parserArguments)});
- <#break>
- <#case "enum">
- <#assign enumField = field.asEnumField().orElseThrow()>
- <#assign typedField = field.asTypedField().orElseThrow()>
- <#assign namedField = field.asNamedField().orElseThrow()>
-
- ${helper.getLanguageTypeNameForField(field)}
${namedField.name} = read${field.typeName?cap_first}Field("${namedField.name}",
"${enumField.type.asNonSimpleTypeReference().orElseThrow().typeDefinition.name}",
readEnum(${enumField.type.asNonSimpleTypeReference().orElseThrow().typeDefinition.name}::firstEnumForField${enumField.fieldName?cap_first},
${helper.getDataReaderCall(helper.getEnumFieldTypeReference(enumField.type,
enumField.fieldName))})${helper.getFieldOptions(typed [...]
- <#break>
- <#case "implicit">
- <#assign implicitField = field.asImplicitField().orElseThrow()>
- <#assign typedField = field.asTypedField().orElseThrow()>
- <#assign namedField = field.asNamedField().orElseThrow()>
-
- ${helper.getLanguageTypeNameForField(field)}
${namedField.name} = read${field.typeName?cap_first}Field("${namedField.name}",
${helper.getDataReaderCall(typedField.type)}${helper.getFieldOptions(typedField,
parserArguments)});
- <#break>
- <#case "manualArray">
- <#assign manualArrayField =
field.asManualArrayField().orElseThrow()>
- <#assign typedField = field.asTypedField().orElseThrow()>
- <#assign namedField = field.asNamedField().orElseThrow()>
- <#assign arrayElementTypeReference =
manualArrayField.type.asArrayTypeReference().orElseThrow().getElementTypeReference()>
-
- <#if arrayElementTypeReference.isByteBased()>
- byte[] ${namedField.name} =
readManualByteArrayField("${namedField.name}", readBuffer, (byte[] _values) ->
(boolean) (${helper.toParseExpression(manualArrayField,
helper.boolTypeReference, manualArrayField.loopExpression, parserArguments)}),
() -> (byte) (${helper.toParseExpression(manualArrayField,
manualArrayField.type, manualArrayField.parseExpression,
parserArguments)})${helper.getFieldOptions(typedField, parserArguments)});
- <#else>
-
${helper.getNonPrimitiveLanguageTypeNameForField(manualArrayField)}
${namedField.name} = readManualArrayField("${namedField.name}", readBuffer,
(${helper.getNonPrimitiveLanguageTypeNameForField(manualArrayField)} _values)
-> (boolean) (${helper.toParseExpression(manualArrayField,
helper.boolTypeReference, manualArrayField.loopExpression, parserArguments)}),
() ->
(${helper.getLanguageTypeNameForTypeReference(manualArrayField.type.elementTypeReference)})
(${helper.toPa [...]
- </#if>
- <#break>
- <#case "manual">
- <#assign manualField = field.asManualField().orElseThrow()>
- <#assign typedField = field.asTypedField().orElseThrow()>
- <#assign namedField = field.asNamedField().orElseThrow()>
-
- ${helper.getLanguageTypeNameForField(field)}
${manualField.name} = readManualField("${namedField.name}", readBuffer, () ->
(${helper.getLanguageTypeNameForField(manualField)})
(${helper.toParseExpression(manualField, manualField.type,
manualField.parseExpression,
parserArguments)})${helper.getFieldOptions(typedField, parserArguments)});
- <#break>
- <#case "optional">
- <#assign optionalField = field.asOptionalField().orElseThrow()>
- <#assign typedField = field.asTypedField().orElseThrow()>
- <#assign namedField = field.asNamedField().orElseThrow()>
-
- ${helper.getLanguageTypeNameForField(field)}
${namedField.name} = read${field.typeName?cap_first}Field("${namedField.name}",
${helper.getDataReaderCall(typedField.type)}<#if
optionalField.conditionExpression.present>,
${helper.toParseExpression(optionalField, helper.boolTypeReference,
optionalField.conditionExpression.get(),
parserArguments)}</#if>${helper.getFieldOptions(typedField, parserArguments)});
- <#break>
- <#case "padding">
- <#assign paddingField = field.asPaddingField().orElseThrow()>
- <#assign typedField = field.asTypedField().orElseThrow()>
- <#assign simpleTypeReference =
paddingField.type.asSimpleTypeReference().orElseThrow()>
-
-
read${field.typeName?cap_first}Field(${helper.getDataReaderCall(typedField.type)},
(int) (${helper.toParseExpression(paddingField, paddingField.type,
paddingField.paddingCondition,
parserArguments)})${helper.getFieldOptions(typedField, parserArguments)});
- <#break>
- <#case "reserved">
- <#assign reservedField = field.asReservedField().orElseThrow()>
- <#assign typedField = field.asTypedField().orElseThrow()>
-
- read${field.typeName?cap_first}Field("reserved",
${helper.getDataReaderCall(typedField.type)},
${helper.getReservedValue(reservedField)}${helper.getFieldOptions(typedField,
parserArguments)});
- <#break>
- <#case "simple">
- <#assign simpleField = field.asSimpleField().orElseThrow()>
- <#assign typedField = field.asTypedField().orElseThrow()>
- <#assign namedField = field.asNamedField().orElseThrow()>
-
- ${helper.getLanguageTypeNameForField(field)}
${namedField.name} = <#if
typedField.type.isEnumTypeReference()>readEnumField("${namedField.name}",
"${helper.getLanguageTypeNameForField(field)}",
${helper.getDataReaderCall(typedField.type)}${helper.getFieldOptions(typedField,
parserArguments)});<#else>read${field.typeName?cap_first}Field("${namedField.name}",
${helper.getDataReaderCall(typedField.type)}${helper.getFieldOptions(typedField,
parserArguments)});</#if>
- <#break>
- <#case "switch">
- <#assign switchField = field.asSwitchField().orElseThrow()>
-
- // Switch Field (Depending on the discriminator values, passes
the instantiation to a sub-type)
- ${type.name}Builder builder = null;
- <#list switchField.cases as case>
- <@compress single_line=true>
- <#if case.discriminatorValueTerms?has_content>
- if(
- <#list case.discriminatorValueTerms as
discriminatorValueTerm>
- <#if helper.isWildcard(discriminatorValueTerm)>
- true
- <#else>
- <#assign
discriminatorExpression=switchField.discriminatorExpressions[discriminatorValueTerm?index].asLiteral().orElseThrow().asVariableLiteral().orElseThrow()>
- <#assign
discriminatorType=helper.getDiscriminatorTypes()[discriminatorExpression.discriminatorName]>
- EvaluationHelper.equals(
- ${helper.toParseExpression(switchField,
discriminatorType, discriminatorExpression, parserArguments)},
- <#if
discriminatorType.isEnumTypeReference()>
-
${helper.getLanguageTypeNameForTypeReference(discriminatorType)}.${helper.toParseExpression(switchField,
discriminatorType, discriminatorValueTerm, parserArguments)}
- <#else>
-
(${helper.getLanguageTypeNameForTypeReference(discriminatorType, true)})
${helper.toParseExpression(switchField, discriminatorType,
discriminatorValueTerm, parserArguments)}
- </#if>
- )
- </#if>
- <#sep> && </#sep>
- </#list>
- )
- </#if>{
- </@compress>
- <@compress single_line=true>
- <#assign
hasCaseParseArguments=case.allParserArguments.isPresent() &&
case.allParserArguments.orElseThrow()?has_content>
- <#assign caseParseArguments><#if
hasCaseParseArguments><#list case.allParserArguments.orElseThrow() as
parserArgument>${parserArgument.name}<#sep>, </#sep></#list></#if></#assign>
- builder =
${case.name}.staticParseBuilder(readBuffer<#if hasCaseParseArguments>,
${tracer.dive("case parse arguments")} ${caseParseArguments}</#if>);
- </@compress>
- }<#sep> else </#sep>
- </#list>
- if (builder == null) {
- throw new ParseException("Unsupported case for
discriminated type");
- }
- <#break>
- <#case "unknown">
- <#assign unknownField = field.asUnknownField().orElseThrow()>
- <#assign typedField = field.asTypedField().orElseThrow()>
-
- read${field.typeName?cap_first}Field("unknown",
${helper.getDataReaderCall(typedField.type)}${helper.getFieldOptions(typedField,
parserArguments)});
- <#break>
- <#case "virtual">
- <#assign virtualField = field.asVirtualField().orElseThrow()>
- <#assign typedField = field.asTypedField().orElseThrow()>
- <#assign namedField = field.asNamedField().orElseThrow()>
- ${helper.getLanguageTypeNameForField(field)}
${namedField.name} = read${field.typeName?cap_first}Field("${namedField.name}",
${helper.getLanguageTypeNameForField(field)}.class,
${helper.toParseExpression(virtualField, virtualField.type,
virtualField.valueExpression,
parserArguments)}${helper.getFieldOptions(typedField, parserArguments)});
- <#break>
- <#case "validation">
- <#assign validationField =
field.asValidationField().orElseThrow()>
- // Validation
- if (!(${helper.toParseExpression(validationField,
helper.boolTypeReference, validationField.getValidationExpression(), null)})) {
- <#assign errorType="ParseValidationException">
- <#if !validationField.shouldFail()><#assign
errorType="ParseAssertException"></#if>
- throw new
${errorType}(${validationField.getDescription().orElse("\"Validation
failed\"")});
- }
- <#break>
- <#case "peek">
- <#assign peekField = field.asPeekField().orElseThrow()>
- <#assign typedField = field.asTypedField().orElseThrow()>
- <#assign namedField = field.asNamedField().orElseThrow()>
-
- ${helper.getLanguageTypeNameForField(field)}
${namedField.name} = read${field.typeName?cap_first}Field("${namedField.name}",
${helper.getDataReaderCall(typedField.type)}<#if
peekField.offsetExpression.present>, ${helper.toParseExpression(peekField,
helper.boolTypeReference, peekField.offsetExpression.get(),
parserArguments)}</#if>${helper.getFieldOptions(typedField, parserArguments)});
- <#break>
- </#switch>
+ ${helper.generateFieldParseCode(field)}
</#list>
-
- readBuffer.closeContext("${type.name}");
- // Create the instance
- <#if type.isDiscriminatedChildTypeDefinition()>
- return new ${type.name}Builder(<#list type.propertyFields as
field>${field.name}<#sep>, </#sep></#list><#if
filteredParserArguments?has_content><#if type.propertyFields?has_content>,
</#if><#list filteredParserArguments as arg>${arg.name}<#sep>,
</#sep></#list></#if>);
- <#elseif type.isDiscriminatedParentTypeDefinition()>
- return builder.build(<#list type.propertyFields as
field>${field.name}<#sep>, </#sep></#list><#if
filteredParserArguments?has_content><#if type.propertyFields?has_content>,
</#if><#list filteredParserArguments as arg>${arg.name}<#sep>,
</#sep></#list></#if>);
- <#else>
- return new ${type.name}(<#list type.propertyFields as
field>${field.name}<#sep>, </#sep></#list><#if
filteredParserArguments?has_content><#if type.propertyFields?has_content>,
</#if><#list filteredParserArguments as arg>${arg.name}<#sep>,
</#sep></#list></#if>);
- </#if>
- }
-
- <#if type.isDiscriminatedParentTypeDefinition()>
- public static interface ${type.name}Builder {
- ${type.name} build(<#list type.propertyFields as
field>${helper.getLanguageTypeNameForField(field)} ${field.name}<#sep>,
</#sep></#list><#if filteredParserArguments?has_content><#if
type.propertyFields?has_content>, </#if><#list filteredParserArguments as
arg>${helper.getLanguageTypeNameForTypeReference(arg.type)} ${arg.name}<#sep>,
</#sep></#list></#if>);
- }
-
- </#if>
- <#if type.isDiscriminatedChildTypeDefinition()>
- public static class ${type.name}Builder implements
${type.parentType.orElseThrow().name}.${type.parentType.orElseThrow().name}Builder
{
- <#if type.propertyFields?has_content>
- <#list type.propertyFields as field>
- private final ${helper.getLanguageTypeNameForField(field)}
${field.name};
- </#list>
- </#if>
- <#if filteredParserArguments?has_content>
- <#list filteredParserArguments as arg>
- private final
${helper.getLanguageTypeNameForTypeReference(arg.type)} ${arg.name};
- </#list>
- </#if>
-
- public ${type.name}Builder(<#list type.propertyFields as
field>${helper.getLanguageTypeNameForField(field)} ${field.name}<#sep>,
</#sep></#list><#if filteredParserArguments?has_content><#if
type.propertyFields?has_content>, </#if><#list filteredParserArguments as
arg>${helper.getLanguageTypeNameForTypeReference(arg.type)} ${arg.name}<#sep>,
</#sep></#list></#if>) {
- <#list type.propertyFields as field>
- this.${field.name} = ${field.name};
- </#list>
- <#if filteredParserArguments?has_content>
- <#list filteredParserArguments as arg>
- this.${arg.name} = ${arg.name};
- </#list>
- </#if>
- }
-
- public ${type.name} build(<#list
type.parentType.orElseThrow().asComplexTypeDefinition().orElseThrow().propertyFields
as field>${helper.getLanguageTypeNameForField(field)} ${field.name}<#sep>,
</#sep></#list><#if filteredParentParserArguments?has_content><#if
type.parentType.orElseThrow().asComplexTypeDefinition().orElseThrow().propertyFields?has_content>,
</#if><#list filteredParentParserArguments as
arg>${helper.getLanguageTypeNameForTypeReference(arg.type)} ${arg.name}<#sep>,
[...]
- return new ${type.name}(<#list type.allPropertyFields as
field>${field.name}<#sep>, </#sep></#list><#if
filteredParserArguments?has_content><#if type.allPropertyFields?has_content>,
</#if><#list filteredParserArguments as arg>${arg.name}<#sep>,
</#sep></#list></#if>);
- }
- }
-
- </#if>
-
- @Override
- public boolean equals(Object o) {
- if (this == o) {
- return true;
- }
- if (!(o instanceof ${type.name})) {
- return false;
- }
- ${type.name} that = (${type.name}) o;
- return
- <#if type.propertyFields?has_content>
- <#list type.propertyFields as field>
- (get${field.name?cap_first}() ==
that.get${field.name?cap_first}()) &&
- </#list>
- </#if>
- <#if type.parentType.isPresent()>
- super.equals(that) &&
- </#if>
- true;
}
+}
+<#else>
+pub struct ${type.name} {
+}
+</#if>
- @Override
- public int hashCode() {
- return Objects.hash(
- <#if type.parentType.isPresent()>
- super.hashCode()<#if type.propertyFields?has_content>,</#if>
- </#if>
- <#if type.propertyFields?has_content>
- <#list type.propertyFields as field>
- get${field.name?cap_first}()<#sep>,</#sep>
- </#list>
- </#if>
- );
- }
- @Override
- public String toString() {
- WriteBufferBoxBased writeBufferBoxBased = new
WriteBufferBoxBased(true, true);
- try {
- serialize(writeBufferBoxBased);
- } catch (SerializationException e) {
- throw new RuntimeException(e);
- }
- return "\n" + writeBufferBoxBased.getBox().toString()+ "\n";
- }
-}
+<#--<#– TODO: the code below implies that parserArguments will be
null if not present... not pretty –>-->
+<#--<#if type.parserArguments.isPresent()><#assign
parserArguments=type.allParserArguments.orElseThrow()></#if>-->
+<#--public<#if type.isDiscriminatedParentTypeDefinition()> abstract</#if>
class ${type.name}<#if type.isDiscriminatedParentTypeDefinition()></#if><#if
type.parentType.isPresent()> extends
${type.parentType.orElseThrow().name}</#if> implements Message {-->
+
+<#--<#–-->
+<#-- If this is a discriminated child type, we need to generate methods for
accessing it's discriminator-->
+<#-- values, as if they were normal java properties.-->
+<#--–>-->
+<#--<#if type.isDiscriminatedChildTypeDefinition()>-->
+<#-- <#assign discriminatedChildType =
type.asDiscriminatedComplexTypeDefinition().orElseThrow()>-->
+<#-- // Accessors for discriminator values.-->
+<#-- <#list discriminatedChildType.getDiscriminatorMap() as
discriminatorName, discriminatorValue>-->
+<#-- <#– If the discriminator name matches that of another
field, suppress the methods generation –>-->
+<#-- <#if
!discriminatedChildType.isNonDiscriminatorField(discriminatorName)><#–&&
!discriminatedChildType.isParserArgument(discriminatorName)–>-->
+<#-- <#assign discriminatorType =
helper.getDiscriminatorTypes()[discriminatorName]>-->
+<#-- public
${helper.getLanguageTypeNameForTypeReference(discriminatorType)}
get${discriminatorName?cap_first}() {-->
+<#-- <#if discriminatorValue?? &&
!helper.isWildcard(discriminatorValue)>-->
+<#-- <#if discriminatorType.isEnumTypeReference()>-->
+<#-- return
${helper.getLanguageTypeNameForTypeReference(discriminatorType)}.${helper.toParseExpression(null,
discriminatorType, discriminatorValue, parserArguments)};-->
+<#-- <#else>-->
+<#-- return
(${helper.getLanguageTypeNameForTypeReference(discriminatorType, true)})
${helper.toParseExpression(null, discriminatorType, discriminatorValue,
parserArguments)};-->
+<#-- </#if>-->
+<#-- <#else>-->
+<#-- return
${helper.getNullValueForTypeReference(discriminatorType)};-->
+<#-- </#if>-->
+<#-- }-->
+<#-- </#if>-->
+<#-- </#list>-->
+<#--</#if>-->
+<#--<#–-->
+<#-- If this is a discriminated parent type, we need to generate the
abstract methods for accessing it's-->
+<#-- discriminator values instead.-->
+<#--–>-->
+<#--<#if type.isDiscriminatedParentTypeDefinition()>-->
+<#-- <#assign discriminatedParentType = type>-->
+<#-- <#– @ftlvariable name="discriminatedParentType"
type="org.apache.plc4x.plugins.codegenerator.types.definitions.ComplexTypeDefinition"
–>-->
+<#-- // Abstract accessors for discriminator values.-->
+<#-- <#list helper.discriminatorTypes as discriminatorName,
discriminatorType>-->
+<#-- <#– If the discriminator name matches that of another
field, suppress the methods generation –>-->
+<#-- <#if !type.isNonDiscriminatorField(discriminatorName)><#–
&& !type.isParserArgument(discriminatorName)–>-->
+<#-- public abstract
${helper.getLanguageTypeNameForTypeReference(discriminatorType)}
get${discriminatorName?cap_first}();-->
+<#-- </#if>-->
+<#-- </#list>-->
+<#--</#if>-->
+<#--<#– If the current type contains "const" fields, generate some
java constants for holing their values –>-->
+<#--<#if type.constFields?has_content>-->
+
+<#-- // Constant values.-->
+<#-- <#list type.constFields as field>-->
+<#-- public static final
${helper.getLanguageTypeNameForTypeReference(field.type)}
${field.name?upper_case} = ${helper.toParseExpression(field, field.type,
field.referenceValue, parserArguments)};-->
+<#-- </#list>-->
+<#--</#if>-->
+<#--<#– Property fields are fields that require a property in the
pojo –>-->
+<#--<#if type.propertyFields?has_content>-->
+
+<#-- // Properties.-->
+<#-- <#list type.propertyFields as field>-->
+<#-- protected final
${helper.getLanguageTypeNameForTypeReference(field.type,
!field.isOptionalField())} ${field.name};-->
+<#-- </#list>-->
+<#--</#if>-->
+<#--<#if parserArguments?has_content>-->
+<#-- <#assign filteredParserArguments=parserArguments?filter(arg ->
!type.isDiscriminatorField(arg.name) &&
!type.getPropertyFieldFromThisOrParentByName(arg.name).isPresent())>-->
+<#--</#if>-->
+<#--<#if filteredParserArguments?has_content>-->
+
+<#-- // Arguments.-->
+<#-- <#list filteredParserArguments as parserArgument>-->
+<#-- protected final
${helper.getLanguageTypeNameForTypeReference(parserArgument.type)}
${parserArgument.name};-->
+<#-- </#list>-->
+<#--</#if>-->
+
+<#-- <#– getAllPropertyFields() returns not only the property
fields of this type but also of it's parents –>-->
+<#-- <@compress single_line=true>-->
+<#-- public ${type.name}(-->
+<#-- <#list type.getAllPropertyFields() as field>-->
+<#-- ${helper.getLanguageTypeNameForField(field)} ${field.name}-->
+<#-- <#sep>, </#sep>-->
+<#-- </#list>-->
+<#-- <#if filteredParserArguments?has_content>-->
+<#-- <#if type.getAllPropertyFields()?has_content>, </#if>-->
+<#-- <#list filteredParserArguments as parserArgument>-->
+<#--
${helper.getLanguageTypeNameForTypeReference(parserArgument.type)}
${parserArgument.name}-->
+<#-- <#sep>, </#sep>-->
+<#-- </#list>-->
+<#-- </#if>-->
+<#-- ) {-->
+<#-- </@compress>-->
+
+<#-- <@compress single_line=true>-->
+<#-- super(-->
+<#-- <#if type.parentPropertyFields?has_content>-->
+<#-- <#list type.parentPropertyFields as field>-->
+<#-- ${field.name}-->
+<#-- <#sep>, </#sep>-->
+<#-- </#list>-->
+<#-- </#if>-->
+<#-- <#if type.parentType.isPresent() &&
type.parentType.orElseThrow().allParserArguments.isPresent()>-->
+<#-- <#assign filteredParentParserArguments =
type.parentType.orElseThrow().allParserArguments.orElseThrow()?filter(arg ->
!type.parentType.orElseThrow().asComplexTypeDefinition().orElseThrow().isDiscriminatorField(arg.name))>-->
+<#-- <#if filteredParentParserArguments?has_content>-->
+<#-- <#if type.parentPropertyFields?has_content>, </#if>-->
+<#-- <#list filteredParentParserArguments as parserArgument>-->
+<#-- ${parserArgument.name}-->
+<#-- <#sep>, </#sep>-->
+<#-- </#list>-->
+<#-- </#if>-->
+<#-- </#if>-->
+<#-- );-->
+<#-- </@compress>-->
+
+<#--<#list type.propertyFields as field>-->
+<#-- this.${field.name} = ${field.name};-->
+<#--</#list>-->
+<#--<#if filteredParserArguments?has_content>-->
+<#-- <#list filteredParserArguments as parserArgument>-->
+<#-- this.${parserArgument.name} = ${parserArgument.name};-->
+<#-- </#list>-->
+<#--</#if>-->
+<#-- }-->
+
+<#--<#list type.abstractFields as field>-->
+<#-- public abstract ${helper.getLanguageTypeNameForField(field)}
get${field.asNamedField().orElseThrow().name?cap_first}();-->
+
+<#--</#list>-->
+<#--<#list type.propertyFields as field>-->
+<#-- public ${helper.getLanguageTypeNameForField(field)}
get${field.name?cap_first}() {-->
+<#-- return ${field.name};-->
+<#-- }-->
+
+<#--</#list>-->
+<#--<#list type.virtualFields as field>-->
+<#-- public ${helper.getLanguageTypeNameForField(field)}
get${field.name?cap_first}() {-->
+<#-- <#if helper.getLanguageTypeNameForField(field) = 'String'>-->
+<#-- return
${helper.getLanguageTypeNameForField(field)}.valueOf(${helper.toSerializationExpression(field,
field.type, field.valueExpression, parserArguments)});-->
+<#-- <#–elseif helper.getLanguageTypeNameForField(field) =
'BigInteger' && !helper.isBigIntegerSource(field.valueExpression)–>-->
+<#-- <#elseif helper.getLanguageTypeNameForField(field) =
'BigInteger'>-->
+<#-- Object o = ${helper.toSerializationExpression(field, field.type,
field.valueExpression, parserArguments)};-->
+<#-- if (o instanceof BigInteger)-->
+<#-- return (BigInteger) o;-->
+<#-- return BigInteger.valueOf(((Number)o).longValue());-->
+<#-- <#else>-->
+<#-- return (${helper.getLanguageTypeNameForField(field)})
(${helper.toSerializationExpression(field, field.type, field.valueExpression,
parserArguments)});-->
+<#-- </#if>-->
+<#-- }-->
+
+<#--</#list>-->
+<#--<#list type.constFields as field>-->
+<#-- public ${helper.getLanguageTypeNameForField(field)}
get${field.name?cap_first}() {-->
+<#-- return ${field.name?upper_case};-->
+<#-- }-->
+
+<#--</#list>-->
+
+<#-- <#if outputFlavor != "passive">-->
+<#--<#if type.isDiscriminatedChildTypeDefinition()>-->
+<#-- @Override-->
+<#-- protected void
serialize${type.parentType.orElseThrow().name}Child(WriteBuffer writeBuffer)
throws SerializationException {-->
+<#--<#else>-->
+<#-- <#if type.isDiscriminatedParentTypeDefinition()>-->
+<#-- abstract protected void
serialize${type.name?cap_first}Child(WriteBuffer writeBuffer) throws
SerializationException;-->
+
+<#-- </#if>-->
+<#-- public void serialize(WriteBuffer writeBuffer) throws
SerializationException {-->
+<#--</#if>-->
+<#-- PositionAware positionAware = writeBuffer;-->
+<#-- <#if helper.hasFieldOfType("unknown")>-->
+<#-- throw new SerializationException("Unknown field not
serializable");-->
+<#-- <#else>-->
+<#-- int startPos = positionAware.getPos();-->
+<#-- writeBuffer.pushContext("${type.name}");-->
+<#-- <#list type.fields as field>-->
+<#-- <#switch field.typeName>-->
+<#-- <#case "array">-->
+<#-- <#assign arrayField =
field.asArrayField().orElseThrow()>-->
+<#-- <#assign typedField =
field.asTypedField().orElseThrow()>-->
+<#-- <#assign namedField =
field.asNamedField().orElseThrow()>-->
+
+<#-- // Array Field (${arrayField.name})-->
+<#-- <#if
arrayField.type.elementTypeReference.isByteBased()>-->
+<#-- writeByteArrayField("${namedField.name}",
${namedField.name}, writeByteArray(writeBuffer, 8));-->
+<#-- <#elseif
arrayField.type.elementTypeReference.isSimpleTypeReference()>-->
+<#-- writeSimpleTypeArrayField("${namedField.name}",
${namedField.name},
${helper.getDataWriterCall(arrayField.type.elementTypeReference,
namedField.name)});-->
+<#-- <#else>-->
+<#-- writeComplexTypeArrayField("${namedField.name}",
${namedField.name}, writeBuffer);-->
+<#-- </#if>-->
+<#-- <#break>-->
+<#-- <#case "checksum">-->
+<#-- <#assign checksumField =
field.asChecksumField().orElseThrow()>-->
+<#-- <#assign typedField =
field.asTypedField().orElseThrow()>-->
+<#-- <#assign namedField =
field.asNamedField().orElseThrow()>-->
+
+<#-- // Checksum Field (checksum) (Calculated)-->
+<#-- writeChecksumField("${namedField.name}",
(${helper.getLanguageTypeNameForField(field)})
(${helper.toParseExpression(checksumField, checksumField.type,
checksumField.checksumExpression, parserArguments)}),
${helper.getDataWriterCall(typedField.type, namedField.name)});-->
+<#-- <#break>-->
+<#-- <#case "const">-->
+<#-- <#assign constField =
field.asConstField().orElseThrow()>-->
+<#-- <#assign typedField =
field.asTypedField().orElseThrow()>-->
+<#-- <#assign namedField =
field.asNamedField().orElseThrow()>-->
+
+<#-- // Const Field (${constField.name})-->
+<#-- <#if
typedField.type.isEnumTypeReference()>writeConstField("${constField.name}",
${namedField.name?upper_case}.getValue(),
${helper.getDataWriterCall(helper.getEnumBaseTypeReference(typedField.type),
namedField.name)});<#else>writeConstField("${constField.name}",
${namedField.name?upper_case}, ${helper.getDataWriterCall(typedField.type,
namedField.name)});</#if>-->
+<#-- <#break>-->
+<#-- <#case "discriminator">-->
+<#-- <#assign discriminatorField =
field.asDiscriminatorField().orElseThrow()>-->
+<#-- <#assign typedField =
field.asTypedField().orElseThrow()>-->
+<#-- <#assign namedField =
field.asNamedField().orElseThrow()>-->
+
+<#-- // Discriminator Field
(${discriminatorField.name}) (Used as input to a switch field)-->
+<#-- <#if
typedField.type.isEnumTypeReference()>writeDiscriminatorEnumField("${namedField.name}",
"${helper.getLanguageTypeNameForField(field)}",
get${discriminatorField.name?cap_first}(),
${helper.getEnumDataWriterCall(typedField.type, namedField.name,
"value")});<#else>writeDiscriminatorField("${namedField.name}",
get${discriminatorField.name?cap_first}(),
${helper.getDataWriterCall(typedField.type, namedField.name)});</#if>-->
+<#-- <#break>-->
+<#-- <#case "enum">-->
+<#-- <#assign enumField =
field.asEnumField().orElseThrow()>-->
+<#-- <#assign typedField =
field.asTypedField().orElseThrow()>-->
+<#-- <#assign namedField =
field.asNamedField().orElseThrow()>-->
+
+<#-- // Enum field (${namedField.name})-->
+<#-- writeEnumField("${namedField.name}",
"${helper.getLanguageTypeNameForField(field)}", ${namedField.name},
${helper.getEnumDataWriterCall(typedField.type, namedField.name,
enumField.fieldName)});-->
+<#-- <#break>-->
+<#-- <#case "implicit">-->
+<#-- <#assign implicitField =
field.asImplicitField().orElseThrow()>-->
+<#-- <#assign typedField =
field.asTypedField().orElseThrow()>-->
+<#-- <#assign namedField =
field.asNamedField().orElseThrow()>-->
+
+<#-- // Implicit Field (${implicitField.name}) (Used
for parsing, but its value is not stored as it's implicitly given by the
objects content)-->
+<#-- <#– Implicit field values might be used
in expressions, in order to avoid problems, we generate a temporary variable
with the given name. –>-->
+<#-- ${helper.getLanguageTypeNameForField(field)}
${implicitField.name} = (${helper.getLanguageTypeNameForField(field)})
(${helper.toSerializationExpression(implicitField, implicitField.type,
implicitField.serializeExpression, parserArguments)});-->
+<#-- writeImplicitField("${namedField.name}",
${implicitField.name}, ${helper.getDataWriterCall(typedField.type,
namedField.name)});-->
+<#-- <#break>-->
+<#-- <#case "manualArray">-->
+<#-- <#assign manualArrayField =
field.asManualArrayField().orElseThrow()>-->
+<#-- <#assign typedField =
field.asTypedField().orElseThrow()>-->
+<#-- <#assign namedField =
field.asNamedField().orElseThrow()>-->
+
+<#-- // Manual Array Field (${manualArrayField.name})-->
+<#-- writeManualArrayField("${namedField.name}",
${namedField.name},
(${helper.getLanguageTypeNameForTypeReference(manualArrayField.type.elementTypeReference)}
_value) -> ${helper.toParseExpression(manualArrayField,
manualArrayField.type.elementTypeReference,
manualArrayField.serializeExpression, parserArguments)}, writeBuffer);-->
+<#-- <#break>-->
+<#-- <#case "manual">-->
+<#-- <#assign manualField =
field.asManualField().orElseThrow()>-->
+<#-- <#assign typedField =
field.asTypedField().orElseThrow()>-->
+<#-- <#assign namedField =
field.asNamedField().orElseThrow()>-->
+
+<#-- // Manual Field (${manualField.name})-->
+<#-- writeManualField("${namedField.name}", () ->
${helper.toParseExpression(manualField, manualField.type,
manualField.serializeExpression, parserArguments)}, writeBuffer);-->
+<#-- <#break>-->
+<#-- <#case "optional">-->
+<#-- <#assign optionalField =
field.asOptionalField().orElseThrow()>-->
+<#-- <#assign typedField =
field.asTypedField().orElseThrow()>-->
+<#-- <#assign namedField =
field.asNamedField().orElseThrow()>-->
+
+<#-- // Optional Field (${optionalField.name}) (Can be
skipped, if the value is null)-->
+<#-- <#if optionalField.type.isEnumTypeReference()>-->
+<#--
writeOptionalEnumField("${optionalField.name}",
"${helper.getLanguageTypeNameForField(field)}", ${optionalField.name},
${helper.getEnumDataWriterCall(optionalField.type, optionalField.name,
"value")}<#if optionalField.conditionExpression.present>,
${helper.toSerializationExpression(optionalField, helper.boolTypeReference,
optionalField.conditionExpression.get(), parserArguments)}</#if>);-->
+<#-- <#elseif
optionalField.type.isDataIoTypeReference()>-->
+<#-- writeOptionalField("${optionalField.name}",
${optionalField.name}, new DataWriterDataIoDefault(writeBuffer, (wb, val) ->
${optionalField.type.asComplexTypeReference().orElseThrow().name}.staticSerialize(wb,
val<#if
optionalField.type.asComplexTypeReference().orElseThrow().params?has_content>,
<#list
optionalField.type.asComplexTypeReference().orElseThrow().params.orElseThrow()
as param>${helper.toParseExpression(optionalField, helper.anyTypeReference,
para [...]
+<#-- <#else>-->
+<#-- writeOptionalField("${optionalField.name}",
${optionalField.name}, ${helper.getDataWriterCall(typedField.type,
optionalField.name)}<#if optionalField.conditionExpression.present>,
${helper.toSerializationExpression(optionalField, helper.boolTypeReference,
optionalField.conditionExpression.get(), parserArguments)}</#if>);-->
+<#-- </#if>-->
+<#-- <#break>-->
+<#-- <#case "padding">-->
+<#-- <#assign paddingField =
field.asPaddingField().orElseThrow()>-->
+<#-- <#assign typedField =
field.asTypedField().orElseThrow()>-->
+
+<#-- // Padding Field (padding)-->
+<#-- writePaddingField("padding", (int)
(${helper.toParseExpression(paddingField, helper.intTypeReference,
paddingField.paddingCondition, parserArguments)}),
(${helper.getLanguageTypeNameForField(field)})
${helper.toSerializationExpression(paddingField, paddingField.type,
paddingField.paddingValue, parserArguments)},
${helper.getDataWriterCall(typedField.type, "padding")});-->
+<#-- <#break>-->
+<#-- <#case "reserved">-->
+<#-- <#assign reservedField =
field.asReservedField().orElseThrow()>-->
+<#-- <#assign typedField =
field.asTypedField().orElseThrow()>-->
+
+<#-- // Reserved Field (reserved)-->
+<#-- writeReservedField("reserved",
${helper.getReservedValue(reservedField)},
${helper.getDataWriterCall(typedField.type, "reserved")});-->
+<#-- <#break>-->
+<#-- <#case "simple">-->
+<#-- <#assign simpleField =
field.asSimpleField().orElseThrow()>-->
+<#-- <#assign typedField =
field.asTypedField().orElseThrow()>-->
+<#-- <#assign namedField =
field.asNamedField().orElseThrow()>-->
+
+<#-- // Simple Field (${namedField.name})-->
+<#-- <#if typedField.type.isEnumTypeReference()>-->
+<#-- writeSimpleEnumField("${simpleField.name}",
"${helper.getLanguageTypeNameForField(field)}", ${simpleField.name},
${helper.getEnumDataWriterCall(simpleField.type, simpleField.name,
"value")});-->
+<#-- <#elseif
simpleField.type.isDataIoTypeReference()>-->
+<#-- writeSimpleField("${simpleField.name}",
${simpleField.name}, new DataWriterDataIoDefault(writeBuffer, (wb, val) ->
${simpleField.type.asComplexTypeReference().orElseThrow().name}.staticSerialize(wb,
val<#if
simpleField.type.asComplexTypeReference().orElseThrow().params?has_content>,
<#list
simpleField.type.asComplexTypeReference().orElseThrow().params.orElseThrow() as
param>${helper.toParseExpression(simpleField, helper.anyTypeReference, param,
parserArgum [...]
+<#-- <#else>-->
+<#-- writeSimpleField("${simpleField.name}",
${simpleField.name}, ${helper.getDataWriterCall(typedField.type,
simpleField.name)}${helper.getFieldOptions(typedField,
parserArguments)});</#if>-->
+<#-- <#break>-->
+<#-- <#case "switch">-->
+<#-- <#assign switchField =
field.asSwitchField().orElseThrow()>-->
+
+<#-- // Switch field (Serialize the sub-type)-->
+<#--
serialize${type.name?cap_first}Child(writeBuffer);-->
+<#-- <#break>-->
+<#-- <#case "virtual">-->
+<#-- <#assign virtualField =
field.asVirtualField().orElseThrow()>-->
+<#-- <#assign typedField =
field.asTypedField().orElseThrow()>-->
+<#-- <#assign namedField =
field.asNamedField().orElseThrow()>-->
+
+<#-- // Virtual field (doesn't actually serialize
anything, just makes the value available)-->
+<#-- ${helper.getLanguageTypeNameForField(field)}
${namedField.name} = get${namedField.name?cap_first}();-->
+<#-- writeBuffer.writeVirtual("${namedField.name}",
${namedField.name});-->
+<#-- <#break>-->
+<#-- </#switch>-->
+<#-- </#list>-->
+
+<#-- writeBuffer.popContext("${type.name}");-->
+<#-- </#if>-->
+<#-- }-->
+<#-- </#if>-->
+
+<#-- @Override-->
+<#-- public int getLengthInBytes() {-->
+<#-- return (int) Math.ceil((float) getLengthInBits() / 8.0);-->
+<#-- }-->
+
+<#-- @Override-->
+<#-- public int getLengthInBits() {-->
+<#-- int lengthInBits = <#if
type.parentType.isPresent()>super.getLengthInBits()<#else>0</#if>;-->
+<#-- ${type.name} _value = this;-->
+<#--<#list type.fields as field>-->
+<#--<#switch field.typeName>-->
+<#-- <#case "array">-->
+<#-- <#assign arrayField = field.asArrayField().orElseThrow()>-->
+<#-- <#assign arrayElementTypeReference =
arrayField.type.asArrayTypeReference().orElseThrow().getElementTypeReference()>-->
+
+<#-- // Array field-->
+<#-- if(${arrayField.name} != null) {-->
+<#-- <#if arrayElementTypeReference.isSimpleTypeReference()>-->
+<#-- <#assign simpleTypeReference =
arrayElementTypeReference.asSimpleTypeReference().orElseThrow()>-->
+<#-- lengthInBits += ${simpleTypeReference.sizeInBits} *
${arrayField.name}.<#if
arrayElementTypeReference.isByteBased()>length<#else>size()</#if>;-->
+<#-- <#elseif arrayField.isCountArrayField()>-->
+<#-- int i=0;-->
+<#-- <#assign nonSimpleTypeReference =
arrayElementTypeReference.asNonSimpleTypeReference().orElseThrow()>-->
+<#-- for(${nonSimpleTypeReference.name} element :
${arrayField.name}) {-->
+<#-- boolean last = ++i >= ${arrayField.name}.size();-->
+<#-- lengthInBits += element.getLengthInBits();-->
+<#-- }-->
+<#-- <#else>-->
+<#-- for(Message element : ${arrayField.name}) {-->
+<#-- lengthInBits += element.getLengthInBits();-->
+<#-- }-->
+<#-- </#if>-->
+<#-- }-->
+<#-- <#break>-->
+<#-- <#case "checksum">-->
+<#-- <#assign checksumField = field.asChecksumField().orElseThrow()>-->
+<#-- <#assign typedField = field.asTypedField().orElseThrow()>-->
+<#-- <#assign simpleTypeReference =
typedField.type.asSimpleTypeReference().orElseThrow()>-->
+
+<#-- // Checksum Field (checksum)-->
+<#-- lengthInBits += ${simpleTypeReference.sizeInBits};-->
+<#-- <#break>-->
+<#-- <#case "const">-->
+<#-- <#assign constField = field.asConstField().orElseThrow()>-->
+<#-- <#assign typedField = field.asTypedField().orElseThrow()>-->
+
+<#-- // Const Field (${constField.name})-->
+<#-- <#if typedField.type.isSimpleTypeReference()>-->
+<#-- <#assign simpleTypeReference =
typedField.type.asSimpleTypeReference().orElseThrow()>-->
+<#-- lengthInBits += ${simpleTypeReference.sizeInBits};-->
+<#-- <#else>-->
+<#-- lengthInBits +=
${helper.getEnumBaseTypeReference(typedField.type).sizeInBits};-->
+<#-- </#if>-->
+<#-- <#break>-->
+<#-- <#case "discriminator">-->
+<#-- <#assign discriminatorField =
field.asDiscriminatorField().orElseThrow()>-->
+
+<#-- // Discriminator Field (${discriminatorField.name})-->
+<#-- <#if discriminatorField.type.isSimpleTypeReference()>-->
+<#-- <#assign simpleTypeReference =
discriminatorField.type.asSimpleTypeReference().orElseThrow()>-->
+<#-- <#if simpleTypeReference.isVstringTypeReference()>-->
+<#-- <#assign vstringTypeReference =
simpleTypeReference.asVstringTypeReference().orElseThrow()>-->
+<#-- lengthInBits +=
${helper.toSerializationExpression(discriminatorField, helper.intTypeReference,
vstringTypeReference.getLengthExpression(), parserArguments)};-->
+<#-- <#else>-->
+<#-- lengthInBits += ${simpleTypeReference.sizeInBits};-->
+<#-- </#if>-->
+<#-- <#elseif helper.isEnumField(field)>-->
+<#-- lengthInBits +=
${helper.getEnumBaseTypeReference(discriminatorField.type).sizeInBits};-->
+<#-- <#else>-->
+<#-- lengthInBits +=
${discriminatorField.name}.getLengthInBits();-->
+<#-- </#if>-->
+<#-- <#break>-->
+<#-- <#case "enum">-->
+<#-- <#assign enumField = field.asEnumField().orElseThrow()>-->
+
+<#-- // Enum Field (${enumField.name})-->
+<#-- lengthInBits +=
${helper.getEnumBaseTypeReference(enumField.type).sizeInBits};-->
+<#-- <#break>-->
+<#-- <#case "implicit">-->
+<#-- <#assign implicitField = field.asImplicitField().orElseThrow()>-->
+<#-- <#assign simpleTypeReference =
implicitField.type.asSimpleTypeReference().orElseThrow()>-->
+
+<#-- // Implicit Field (${implicitField.name})-->
+<#-- lengthInBits += ${simpleTypeReference.sizeInBits};-->
+<#-- <#break>-->
+<#-- <#case "manualArray">-->
+<#-- <#assign manualArrayField =
field.asManualArrayField().orElseThrow()>-->
+<#-- <#assign arrayElementTypeReference =
manualArrayField.type.asArrayTypeReference().orElseThrow().getElementTypeReference()>-->
+
+<#-- // Manual Array Field (${manualArrayField.name})-->
+<#-- lengthInBits += ${helper.toParseExpression(manualArrayField,
helper.intTypeReference, manualArrayField.lengthExpression, parserArguments)} *
8;-->
+<#-- <#break>-->
+<#-- <#case "manual">-->
+<#-- <#assign manualField = field.asManualField().orElseThrow()>-->
+
+<#-- // Manual Field (${manualField.name})-->
+<#-- lengthInBits += ${helper.toParseExpression(manualField,
helper.intTypeReference, manualField.lengthExpression, parserArguments)};-->
+<#-- <#break>-->
+<#-- <#case "optional">-->
+<#-- <#assign optionalField = field.asOptionalField().orElseThrow()>-->
+
+<#-- // Optional Field (${optionalField.name})-->
+<#-- if(${optionalField.name} != null) {-->
+<#-- <#if optionalField.type.isSimpleTypeReference()>-->
+<#-- <#assign simpleTypeReference =
optionalField.type.asSimpleTypeReference().orElseThrow()>-->
+<#-- <#if simpleTypeReference.isVstringTypeReference()>-->
+<#-- <#assign vstringTypeReference =
simpleTypeReference.asVstringTypeReference().orElseThrow()>-->
+<#-- lengthInBits +=
${helper.toSerializationExpression(optionalField, helper.intTypeReference,
vstringTypeReference.getLengthExpression(), parserArguments)};-->
+<#-- <#else>-->
+<#-- lengthInBits += ${simpleTypeReference.sizeInBits};-->
+<#-- </#if>-->
+<#-- <#elseif helper.isEnumField(field)>-->
+<#-- lengthInBits +=
${helper.getEnumBaseTypeReference(optionalField.type).sizeInBits};-->
+<#-- <#elseif optionalField.type.isDataIoTypeReference()>-->
+<#-- lengthInBits +=
${optionalField.type.asComplexTypeReference().orElseThrow().name}.getLengthInBits(${optionalField.name}<#if
optionalField.type.asComplexTypeReference().orElseThrow().params?has_content>,
<#list
optionalField.type.asComplexTypeReference().orElseThrow().params.orElseThrow()
as param>${helper.toParseExpression(optionalField, helper.anyTypeReference,
param, parserArguments)}<#sep>, </#sep></#list></#if>);-->
+<#-- <#else>-->
+<#-- lengthInBits += ${optionalField.name}.getLengthInBits();-->
+<#-- </#if>-->
+<#-- }-->
+<#-- <#break>-->
+<#-- <#case "padding">-->
+<#-- <#assign paddingField = field.asPaddingField().orElseThrow()>-->
+<#-- <#assign simpleTypeReference =
paddingField.type.asSimpleTypeReference().orElseThrow()>-->
+
+<#-- // Padding Field (padding)-->
+<#-- <#– We're replacing the "lastItem" with 'false' here as
the item itself can't know if it is the last –>-->
+<#-- int _timesPadding = (int)
(${helper.toParseExpression(paddingField, helper.intTypeReference,
paddingField.paddingCondition, parserArguments)});-->
+<#-- while (_timesPadding-- > 0) {-->
+<#-- lengthInBits += ${simpleTypeReference.sizeInBits};-->
+<#-- }-->
+<#-- <#break>-->
+<#-- <#case "reserved">-->
+<#-- <#assign reservedField = field.asReservedField().orElseThrow()>-->
+<#-- <#assign simpleTypeReference =
reservedField.type.asSimpleTypeReference().orElseThrow()>-->
+
+<#-- // Reserved Field (reserved)-->
+<#-- lengthInBits += ${simpleTypeReference.sizeInBits};-->
+<#-- <#break>-->
+<#-- <#case "simple">-->
+<#-- <#assign simpleField = field.asSimpleField().orElseThrow()>-->
+
+<#-- // Simple field (${simpleField.name})-->
+<#-- <#if simpleField.type.isSimpleTypeReference()>-->
+<#-- <#assign simpleTypeReference =
simpleField.type.asSimpleTypeReference().orElseThrow()>-->
+<#-- <#if simpleTypeReference.isVstringTypeReference()>-->
+<#-- <#assign vstringTypeReference =
simpleTypeReference.asVstringTypeReference().orElseThrow()>-->
+<#-- lengthInBits += ${helper.toSerializationExpression(simpleField,
helper.intTypeReference, vstringTypeReference.getLengthExpression(),
parserArguments)};-->
+<#-- <#else>-->
+<#-- lengthInBits += ${simpleTypeReference.sizeInBits};-->
+<#-- </#if>-->
+<#-- <#elseif helper.isEnumField(field)>-->
+<#-- lengthInBits +=
${helper.getEnumBaseTypeReference(simpleField.type).sizeInBits};-->
+<#-- <#elseif simpleField.type.isDataIoTypeReference()>-->
+<#-- lengthInBits +=
${simpleField.type.asComplexTypeReference().orElseThrow().name}.getLengthInBits(${simpleField.name}<#if
simpleField.type.asComplexTypeReference().orElseThrow().params?has_content>,
<#list
simpleField.type.asComplexTypeReference().orElseThrow().params.orElseThrow() as
param>${helper.toParseExpression(simpleField, helper.anyTypeReference, param,
parserArguments)}<#sep>, </#sep></#list></#if>);-->
+<#-- <#else>-->
+<#-- lengthInBits += ${simpleField.name}.getLengthInBits();-->
+<#-- </#if>-->
+<#-- <#break>-->
+<#-- <#case "switch">-->
+<#-- <#assign switchField = field.asSwitchField().orElseThrow()>-->
+
+<#-- // Length of sub-type elements will be added by sub-type...-->
+<#-- <#break>-->
+<#-- <#case "unknown">-->
+<#-- <#assign unknownField = field.asUnknownField().orElseThrow()>-->
+<#-- <#assign simpleTypeReference =
unknownField.type.asSimpleTypeReference().orElseThrow()>-->
+
+<#-- // Unknown field-->
+<#-- lengthInBits += ${simpleTypeReference.sizeInBits};-->
+<#-- <#break>-->
+<#-- <#case "virtual">-->
+<#-- <#assign virtualField = field.asVirtualField().orElseThrow()>-->
+
+<#-- // A virtual field doesn't have any in- or output.-->
+<#-- <#break>-->
+<#--</#switch>-->
+<#--</#list>-->
+
+<#-- return lengthInBits;-->
+<#-- }-->
+
+<#--<#– The parse and serialize methods here are just proxies for
forwardning the requests to static counterparts –>-->
+<#-- <#if !type.isDiscriminatedChildTypeDefinition()>-->
+<#-- public static ${type.name} staticParse(ReadBuffer readBuffer,
Object... args) throws ParseException {-->
+<#-- PositionAware positionAware = readBuffer;-->
+<#-- <#if parserArguments?has_content>-->
+<#-- if((args == null) || (args.length != ${parserArguments?size})) {-->
+<#-- throw new PlcRuntimeException("Wrong number of arguments,
expected ${parserArguments?size}, but got " + args.length);-->
+<#-- }-->
+<#-- <#list parserArguments as parserArgument>-->
+<#-- <#assign
languageName=helper.getLanguageTypeNameForTypeReference(parserArgument.type,
false)>-->
+<#-- ${languageName} ${parserArgument.name};-->
+<#-- if(args[${parserArgument?index}] instanceof ${languageName}) {-->
+<#-- ${parserArgument.name} = (${languageName})
args[${parserArgument?index}];-->
+<#-- <#if parserArgument.type.isSimpleTypeReference() ||
parserArgument.type.isEnumTypeReference()>-->
+<#-- } else if (args[${parserArgument?index}] instanceof String) {-->
+<#-- ${parserArgument.name} = ${languageName}.valueOf((String)
args[${parserArgument?index}]);-->
+<#-- </#if>-->
+<#-- } else {-->
+<#-- throw new PlcRuntimeException("Argument
${parserArgument?index} expected to be of type ${languageName} or a string
which is parseable but was " +
args[${parserArgument?index}].getClass().getName());-->
+<#-- }-->
+<#-- </#list>-->
+<#-- </#if>-->
+<#-- return staticParse(readBuffer<#if parserArguments?has_content>,
<#list parserArguments as parserArgument>${parserArgument.name}<#sep>,
</#sep></#list></#if>);-->
+<#-- }-->
+
+<#-- </#if>-->
+<#--<#– Here come the actual parse and serialize methods that
actually do the parsing and serlaizing –>-->
+<#-- <#assign hasParserArguments=parserArguments?has_content/>-->
+<#-- <#assign parserArgumentList><#if hasParserArguments><#list
parserArguments as
parserArgument>${helper.getLanguageTypeNameForTypeReference(parserArgument.type,
false)} ${parserArgument.name}<#sep>, </#sep></#list></#if></#assign>-->
+<#-- public static ${type.name}<#if
type.isDiscriminatedChildTypeDefinition()>Builder staticParseBuilder<#else>
staticParse</#if>(ReadBuffer readBuffer<#if hasParserArguments>,
${parserArgumentList}</#if>) throws ParseException {-->
+<#-- readBuffer.pullContext("${type.name}");-->
+<#-- PositionAware positionAware = readBuffer;-->
+<#-- int startPos = positionAware.getPos();-->
+<#-- int curPos;-->
+<#-- <#list type.fields as field>-->
+<#-- <#switch field.typeName>-->
+<#-- <#case "array">-->
+<#-- <#assign arrayField =
field.asArrayField().orElseThrow()>-->
+<#-- <#assign typedField =
field.asTypedField().orElseThrow()>-->
+<#-- <#assign namedField =
field.asNamedField().orElseThrow()>-->
+<#-- <#assign arrayElementTypeReference =
arrayField.type.asArrayTypeReference().orElseThrow().getElementTypeReference()>-->
+
+<#-- <#if arrayElementTypeReference.isByteBased()>-->
+<#-- <#if !field.isCountArrayField() &&
!field.isLengthArrayField()>-->
+<#-- throw new ParseException("array fields of type
byte only support 'count' and 'length' loop-types.");-->
+<#-- </#if>-->
+<#-- byte[] ${namedField.name} =
readBuffer.readByteArray("${namedField.name}",
Math.toIntExact(${helper.toParseExpression(arrayField, helper.intTypeReference,
arrayField.loopExpression,
parserArguments)})${helper.getFieldOptions(typedField, parserArguments)});-->
+<#-- <#else>-->
+<#-- <#– If this is a count array, we can directly
initialize an array with the given size –>-->
+<#-- <#if field.isCountArrayField()>-->
+<#--
${helper.getNonPrimitiveLanguageTypeNameForField(arrayField)}
${arrayField.name} = readCountArrayField("${arrayField.name}",
${helper.getDataReaderCall(arrayField.type)},
${helper.toParseExpression(arrayField, helper.intTypeReference,
arrayField.loopExpression,
parserArguments)}${helper.getFieldOptions(typedField, parserArguments)});-->
+<#-- <#– In all other cases do we have to work
with a list, that is later converted to an array –>-->
+<#-- <#else>-->
+<#-- <#– For a length array, we read data till the
read position of the buffer reaches a given position –>-->
+<#-- <#if field.isLengthArrayField()>-->
+<#--
${helper.getNonPrimitiveLanguageTypeNameForField(arrayField)}
${arrayField.name} = readLengthArrayField("${arrayField.name}",
${helper.getDataReaderCall(arrayField.type)},
${helper.toParseExpression(arrayField, helper.intTypeReference,
arrayField.loopExpression,
parserArguments)}${helper.getFieldOptions(typedField, parserArguments)});-->
+<#-- <#– A terminated array keeps on reading
data as long as the termination expression evaluates to false –>-->
+<#-- <#elseif field.isTerminatedArrayField()>-->
+<#--
${helper.getNonPrimitiveLanguageTypeNameForField(arrayField)}
${arrayField.name} = readTerminatedArrayField("${arrayField.name}",
${helper.getDataReaderCall(arrayField.type)}, () -> ((boolean)
(${helper.toParseExpression(arrayField, helper.intTypeReference,
arrayField.loopExpression,
parserArguments)}))${helper.getFieldOptions(typedField, parserArguments)});-->
+<#-- </#if>-->
+<#-- </#if>-->
+<#-- </#if>-->
+<#-- <#break>-->
+<#-- <#case "assert">-->
+<#-- <#assign assertField =
field.asAssertField().orElseThrow()>-->
+<#-- <#assign typedField =
field.asTypedField().orElseThrow()>-->
+<#-- <#assign namedField =
field.asNamedField().orElseThrow()>-->
+
+<#-- ${helper.getLanguageTypeNameForField(field)}
${namedField.name} = read${field.typeName?cap_first}Field("${namedField.name}",
${helper.getDataReaderCall(typedField.type)},
(${helper.getLanguageTypeNameForField(field)})
(${helper.toParseExpression(assertField, assertField.type,
assertField.conditionExpression,
parserArguments)})${helper.getFieldOptions(typedField, parserArguments)});-->
+<#-- <#break>-->
+<#-- <#case "checksum">-->
+<#-- <#assign checksumField =
field.asChecksumField().orElseThrow()>-->
+<#-- <#assign typedField =
field.asTypedField().orElseThrow()>-->
+<#-- <#assign namedField =
field.asNamedField().orElseThrow()>-->
+
+<#-- ${helper.getLanguageTypeNameForField(field)}
${namedField.name} = read${field.typeName?cap_first}Field("${namedField.name}",
${helper.getDataReaderCall(typedField.type)},
(${helper.getLanguageTypeNameForField(field)})
(${helper.toParseExpression(checksumField, checksumField.type,
checksumField.checksumExpression,
parserArguments)})${helper.getFieldOptions(typedField, parserArguments)});-->
+<#-- <#break>-->
+<#-- <#case "const">-->
+<#-- <#assign constField =
field.asConstField().orElseThrow()>-->
+<#-- <#assign typedField =
field.asTypedField().orElseThrow()>-->
+<#-- <#assign namedField =
field.asNamedField().orElseThrow()>-->
+
+<#-- ${helper.getLanguageTypeNameForField(field)}
${namedField.name} = read${field.typeName?cap_first}Field("${namedField.name}",
${helper.getDataReaderCall(typedField.type)},
${type.name}.${namedField.name?upper_case}${helper.getFieldOptions(typedField,
parserArguments)});-->
+<#-- <#break>-->
+<#-- <#case "discriminator">-->
+<#-- <#assign discriminatorField =
field.asDiscriminatorField().orElseThrow()>-->
+<#-- <#assign typedField =
field.asTypedField().orElseThrow()>-->
+<#-- <#assign namedField =
field.asNamedField().orElseThrow()>-->
+
+<#-- ${helper.getLanguageTypeNameForField(field)}
${namedField.name} = read${field.typeName?cap_first}Field("${namedField.name}",
${helper.getDataReaderCall(typedField.type)}${helper.getFieldOptions(typedField,
parserArguments)});-->
+<#-- <#break>-->
+<#-- <#case "enum">-->
+<#-- <#assign enumField = field.asEnumField().orElseThrow()>-->
+<#-- <#assign typedField =
field.asTypedField().orElseThrow()>-->
+<#-- <#assign namedField =
field.asNamedField().orElseThrow()>-->
+
+<#-- ${helper.getLanguageTypeNameForField(field)}
${namedField.name} = read${field.typeName?cap_first}Field("${namedField.name}",
"${enumField.type.asNonSimpleTypeReference().orElseThrow().typeDefinition.name}",
readEnum(${enumField.type.asNonSimpleTypeReference().orElseThrow().typeDefinition.name}::firstEnumForField${enumField.fieldName?cap_first},
${helper.getDataReaderCall(helper.getEnumFieldTypeReference(enumField.type,
enumField.fieldName))})${helper.getFieldOptions(t [...]
+<#-- <#break>-->
+<#-- <#case "implicit">-->
+<#-- <#assign implicitField =
field.asImplicitField().orElseThrow()>-->
+<#-- <#assign typedField =
field.asTypedField().orElseThrow()>-->
+<#-- <#assign namedField =
field.asNamedField().orElseThrow()>-->
+
+<#-- ${helper.getLanguageTypeNameForField(field)}
${namedField.name} = read${field.typeName?cap_first}Field("${namedField.name}",
${helper.getDataReaderCall(typedField.type)}${helper.getFieldOptions(typedField,
parserArguments)});-->
+<#-- <#break>-->
+<#-- <#case "manualArray">-->
+<#-- <#assign manualArrayField =
field.asManualArrayField().orElseThrow()>-->
+<#-- <#assign typedField =
field.asTypedField().orElseThrow()>-->
+<#-- <#assign namedField =
field.asNamedField().orElseThrow()>-->
+<#-- <#assign arrayElementTypeReference =
manualArrayField.type.asArrayTypeReference().orElseThrow().getElementTypeReference()>-->
+
+<#-- <#if arrayElementTypeReference.isByteBased()>-->
+<#-- byte[] ${namedField.name} =
readManualByteArrayField("${namedField.name}", readBuffer, (byte[] _values) ->
(boolean) (${helper.toParseExpression(manualArrayField,
helper.boolTypeReference, manualArrayField.loopExpression, parserArguments)}),
() -> (byte) (${helper.toParseExpression(manualArrayField,
manualArrayField.type, manualArrayField.parseExpression,
parserArguments)})${helper.getFieldOptions(typedField, parserArguments)});-->
+<#-- <#else>-->
+<#--
${helper.getNonPrimitiveLanguageTypeNameForField(manualArrayField)}
${namedField.name} = readManualArrayField("${namedField.name}", readBuffer,
(${helper.getNonPrimitiveLanguageTypeNameForField(manualArrayField)} _values)
-> (boolean) (${helper.toParseExpression(manualArrayField,
helper.boolTypeReference, manualArrayField.loopExpression, parserArguments)}),
() ->
(${helper.getLanguageTypeNameForTypeReference(manualArrayField.type.elementTypeReference)})
(${helper. [...]
+<#-- </#if>-->
+<#-- <#break>-->
+<#-- <#case "manual">-->
+<#-- <#assign manualField =
field.asManualField().orElseThrow()>-->
+<#-- <#assign typedField =
field.asTypedField().orElseThrow()>-->
+<#-- <#assign namedField =
field.asNamedField().orElseThrow()>-->
+
+<#-- ${helper.getLanguageTypeNameForField(field)}
${manualField.name} = readManualField("${namedField.name}", readBuffer, () ->
(${helper.getLanguageTypeNameForField(manualField)})
(${helper.toParseExpression(manualField, manualField.type,
manualField.parseExpression,
parserArguments)})${helper.getFieldOptions(typedField, parserArguments)});-->
+<#-- <#break>-->
+<#-- <#case "optional">-->
+<#-- <#assign optionalField =
field.asOptionalField().orElseThrow()>-->
+<#-- <#assign typedField =
field.asTypedField().orElseThrow()>-->
+<#-- <#assign namedField =
field.asNamedField().orElseThrow()>-->
+
+<#-- ${helper.getLanguageTypeNameForField(field)}
${namedField.name} = read${field.typeName?cap_first}Field("${namedField.name}",
${helper.getDataReaderCall(typedField.type)}<#if
optionalField.conditionExpression.present>,
${helper.toParseExpression(optionalField, helper.boolTypeReference,
optionalField.conditionExpression.get(),
parserArguments)}</#if>${helper.getFieldOptions(typedField,
parserArguments)});-->
+<#-- <#break>-->
+<#-- <#case "padding">-->
+<#-- <#assign paddingField =
field.asPaddingField().orElseThrow()>-->
+<#-- <#assign typedField =
field.asTypedField().orElseThrow()>-->
+<#-- <#assign simpleTypeReference =
paddingField.type.asSimpleTypeReference().orElseThrow()>-->
+
+<#--
read${field.typeName?cap_first}Field(${helper.getDataReaderCall(typedField.type)},
(int) (${helper.toParseExpression(paddingField, paddingField.type,
paddingField.paddingCondition,
parserArguments)})${helper.getFieldOptions(typedField, parserArguments)});-->
+<#-- <#break>-->
+<#-- <#case "reserved">-->
+<#-- <#assign reservedField =
field.asReservedField().orElseThrow()>-->
+<#-- <#assign typedField =
field.asTypedField().orElseThrow()>-->
+
+<#-- read${field.typeName?cap_first}Field("reserved",
${helper.getDataReaderCall(typedField.type)},
${helper.getReservedValue(reservedField)}${helper.getFieldOptions(typedField,
parserArguments)});-->
+<#-- <#break>-->
+<#-- <#case "simple">-->
+<#-- <#assign simpleField =
field.asSimpleField().orElseThrow()>-->
+<#-- <#assign typedField =
field.asTypedField().orElseThrow()>-->
+<#-- <#assign namedField =
field.asNamedField().orElseThrow()>-->
+
+<#-- ${helper.getLanguageTypeNameForField(field)}
${namedField.name} = <#if
typedField.type.isEnumTypeReference()>readEnumField("${namedField.name}",
"${helper.getLanguageTypeNameForField(field)}",
${helper.getDataReaderCall(typedField.type)}${helper.getFieldOptions(typedField,
parserArguments)});<#else>read${field.typeName?cap_first}Field("${namedField.name}",
${helper.getDataReaderCall(typedField.type)}${helper.getFieldOptions(typedField,
parserArguments)});</#if>-->
+<#-- <#break>-->
+<#-- <#case "switch">-->
+<#-- <#assign switchField =
field.asSwitchField().orElseThrow()>-->
+
+<#-- // Switch Field (Depending on the discriminator values,
passes the instantiation to a sub-type)-->
+<#-- ${type.name}Builder builder = null;-->
+<#-- <#list switchField.cases as case>-->
+<#-- <@compress single_line=true>-->
+<#-- <#if case.discriminatorValueTerms?has_content>-->
+<#-- if(-->
+<#-- <#list case.discriminatorValueTerms as
discriminatorValueTerm>-->
+<#-- <#if
helper.isWildcard(discriminatorValueTerm)>-->
+<#-- true-->
+<#-- <#else>-->
+<#-- <#assign
discriminatorExpression=switchField.discriminatorExpressions[discriminatorValueTerm?index].asLiteral().orElseThrow().asVariableLiteral().orElseThrow()>-->
+<#-- <#assign
discriminatorType=helper.getDiscriminatorTypes()[discriminatorExpression.discriminatorName]>-->
+<#-- EvaluationHelper.equals(-->
+<#--
${helper.toParseExpression(switchField, discriminatorType,
discriminatorExpression, parserArguments)},-->
+<#-- <#if
discriminatorType.isEnumTypeReference()>-->
+<#--
${helper.getLanguageTypeNameForTypeReference(discriminatorType)}.${helper.toParseExpression(switchField,
discriminatorType, discriminatorValueTerm, parserArguments)}-->
+<#-- <#else>-->
+<#--
(${helper.getLanguageTypeNameForTypeReference(discriminatorType, true)})
${helper.toParseExpression(switchField, discriminatorType,
discriminatorValueTerm, parserArguments)}-->
+<#-- </#if>-->
+<#-- )-->
+<#-- </#if>-->
+<#-- <#sep> && </#sep>-->
+<#-- </#list>-->
+<#-- )-->
+<#-- </#if>{-->
+<#-- </@compress>-->
+<#-- <@compress single_line=true>-->
+<#-- <#assign
hasCaseParseArguments=case.allParserArguments.isPresent() &&
case.allParserArguments.orElseThrow()?has_content>-->
+<#-- <#assign caseParseArguments><#if
hasCaseParseArguments><#list case.allParserArguments.orElseThrow() as
parserArgument>${parserArgument.name}<#sep>, </#sep></#list></#if></#assign>-->
+<#-- builder =
${case.name}.staticParseBuilder(readBuffer<#if hasCaseParseArguments>,
${tracer.dive("case parse arguments")} ${caseParseArguments}</#if>);-->
+<#-- </@compress>-->
+<#-- }<#sep> else </#sep>-->
+<#-- </#list>-->
+<#-- if (builder == null) {-->
+<#-- throw new ParseException("Unsupported case for
discriminated type");-->
+<#-- }-->
+<#-- <#break>-->
+<#-- <#case "unknown">-->
+<#-- <#assign unknownField =
field.asUnknownField().orElseThrow()>-->
+<#-- <#assign typedField =
field.asTypedField().orElseThrow()>-->
+
+<#-- read${field.typeName?cap_first}Field("unknown",
${helper.getDataReaderCall(typedField.type)}${helper.getFieldOptions(typedField,
parserArguments)});-->
+<#-- <#break>-->
+<#-- <#case "virtual">-->
+<#-- <#assign virtualField =
field.asVirtualField().orElseThrow()>-->
+<#-- <#assign typedField =
field.asTypedField().orElseThrow()>-->
+<#-- <#assign namedField =
field.asNamedField().orElseThrow()>-->
+<#-- ${helper.getLanguageTypeNameForField(field)}
${namedField.name} = read${field.typeName?cap_first}Field("${namedField.name}",
${helper.getLanguageTypeNameForField(field)}.class,
${helper.toParseExpression(virtualField, virtualField.type,
virtualField.valueExpression,
parserArguments)}${helper.getFieldOptions(typedField, parserArguments)});-->
+<#-- <#break>-->
+<#-- <#case "validation">-->
+<#-- <#assign validationField =
field.asValidationField().orElseThrow()>-->
+<#-- // Validation-->
+<#-- if (!(${helper.toParseExpression(validationField,
helper.boolTypeReference, validationField.getValidationExpression(), null)}))
{-->
+<#-- <#assign errorType="ParseValidationException">-->
+<#-- <#if !validationField.shouldFail()><#assign
errorType="ParseAssertException"></#if>-->
+<#-- throw new
${errorType}(${validationField.getDescription().orElse("\"Validation
failed\"")});-->
+<#-- }-->
+<#-- <#break>-->
+<#-- <#case "peek">-->
+<#-- <#assign peekField = field.asPeekField().orElseThrow()>-->
+<#-- <#assign typedField =
field.asTypedField().orElseThrow()>-->
+<#-- <#assign namedField =
field.asNamedField().orElseThrow()>-->
+
+<#-- ${helper.getLanguageTypeNameForField(field)}
${namedField.name} = read${field.typeName?cap_first}Field("${namedField.name}",
${helper.getDataReaderCall(typedField.type)}<#if
peekField.offsetExpression.present>, ${helper.toParseExpression(peekField,
helper.boolTypeReference, peekField.offsetExpression.get(),
parserArguments)}</#if>${helper.getFieldOptions(typedField,
parserArguments)});-->
+<#-- <#break>-->
+<#-- </#switch>-->
+<#-- </#list>-->
+
+<#-- readBuffer.closeContext("${type.name}");-->
+<#-- // Create the instance-->
+<#-- <#if type.isDiscriminatedChildTypeDefinition()>-->
+<#-- return new ${type.name}Builder(<#list type.propertyFields as
field>${field.name}<#sep>, </#sep></#list><#if
filteredParserArguments?has_content><#if type.propertyFields?has_content>,
</#if><#list filteredParserArguments as arg>${arg.name}<#sep>,
</#sep></#list></#if>);-->
+<#-- <#elseif type.isDiscriminatedParentTypeDefinition()>-->
+<#-- return builder.build(<#list type.propertyFields as
field>${field.name}<#sep>, </#sep></#list><#if
filteredParserArguments?has_content><#if type.propertyFields?has_content>,
</#if><#list filteredParserArguments as arg>${arg.name}<#sep>,
</#sep></#list></#if>);-->
+<#-- <#else>-->
+<#-- return new ${type.name}(<#list type.propertyFields as
field>${field.name}<#sep>, </#sep></#list><#if
filteredParserArguments?has_content><#if type.propertyFields?has_content>,
</#if><#list filteredParserArguments as arg>${arg.name}<#sep>,
</#sep></#list></#if>);-->
+<#-- </#if>-->
+<#-- }-->
+
+<#-- <#if type.isDiscriminatedParentTypeDefinition()>-->
+<#-- public static interface ${type.name}Builder {-->
+<#-- ${type.name} build(<#list type.propertyFields as
field>${helper.getLanguageTypeNameForField(field)} ${field.name}<#sep>,
</#sep></#list><#if filteredParserArguments?has_content><#if
type.propertyFields?has_content>, </#if><#list filteredParserArguments as
arg>${helper.getLanguageTypeNameForTypeReference(arg.type)} ${arg.name}<#sep>,
</#sep></#list></#if>);-->
+<#-- }-->
+
+<#-- </#if>-->
+<#-- <#if type.isDiscriminatedChildTypeDefinition()>-->
+<#-- public static class ${type.name}Builder implements
${type.parentType.orElseThrow().name}.${type.parentType.orElseThrow().name}Builder
{-->
+<#-- <#if type.propertyFields?has_content>-->
+<#-- <#list type.propertyFields as field>-->
+<#-- private final ${helper.getLanguageTypeNameForField(field)}
${field.name};-->
+<#-- </#list>-->
+<#-- </#if>-->
+<#-- <#if filteredParserArguments?has_content>-->
+<#-- <#list filteredParserArguments as arg>-->
+<#-- private final
${helper.getLanguageTypeNameForTypeReference(arg.type)} ${arg.name};-->
+<#-- </#list>-->
+<#-- </#if>-->
+
+<#-- public ${type.name}Builder(<#list type.propertyFields as
field>${helper.getLanguageTypeNameForField(field)} ${field.name}<#sep>,
</#sep></#list><#if filteredParserArguments?has_content><#if
type.propertyFields?has_content>, </#if><#list filteredParserArguments as
arg>${helper.getLanguageTypeNameForTypeReference(arg.type)} ${arg.name}<#sep>,
</#sep></#list></#if>) {-->
+<#-- <#list type.propertyFields as field>-->
+<#-- this.${field.name} = ${field.name};-->
+<#-- </#list>-->
+<#-- <#if filteredParserArguments?has_content>-->
+<#-- <#list filteredParserArguments as arg>-->
+<#-- this.${arg.name} = ${arg.name};-->
+<#-- </#list>-->
+<#-- </#if>-->
+<#-- }-->
+
+<#-- public ${type.name} build(<#list
type.parentType.orElseThrow().asComplexTypeDefinition().orElseThrow().propertyFields
as field>${helper.getLanguageTypeNameForField(field)} ${field.name}<#sep>,
</#sep></#list><#if filteredParentParserArguments?has_content><#if
type.parentType.orElseThrow().asComplexTypeDefinition().orElseThrow().propertyFields?has_content>,
</#if><#list filteredParentParserArguments as
arg>${helper.getLanguageTypeNameForTypeReference(arg.type)} ${arg.name}<#se
[...]
+<#-- return new ${type.name}(<#list type.allPropertyFields as
field>${field.name}<#sep>, </#sep></#list><#if
filteredParserArguments?has_content><#if type.allPropertyFields?has_content>,
</#if><#list filteredParserArguments as arg>${arg.name}<#sep>,
</#sep></#list></#if>);-->
+<#-- }-->
+<#-- }-->
+
+<#-- </#if>-->
+
+<#-- @Override-->
+<#-- public boolean equals(Object o) {-->
+<#-- if (this == o) {-->
+<#-- return true;-->
+<#-- }-->
+<#-- if (!(o instanceof ${type.name})) {-->
+<#-- return false;-->
+<#-- }-->
+<#-- ${type.name} that = (${type.name}) o;-->
+<#-- return-->
+<#-- <#if type.propertyFields?has_content>-->
+<#-- <#list type.propertyFields as field>-->
+<#-- (get${field.name?cap_first}() ==
that.get${field.name?cap_first}()) &&-->
+<#-- </#list>-->
+<#-- </#if>-->
+<#-- <#if type.parentType.isPresent()>-->
+<#-- super.equals(that) &&-->
+<#-- </#if>-->
+<#-- true;-->
+<#-- }-->
+
+<#-- @Override-->
+<#-- public int hashCode() {-->
+<#-- return Objects.hash(-->
+<#-- <#if type.parentType.isPresent()>-->
+<#-- super.hashCode()<#if type.propertyFields?has_content>,</#if>-->
+<#-- </#if>-->
+<#-- <#if type.propertyFields?has_content>-->
+<#-- <#list type.propertyFields as field>-->
+<#-- get${field.name?cap_first}()<#sep>,</#sep>-->
+<#-- </#list>-->
+<#-- </#if>-->
+<#-- );-->
+<#-- }-->
+
+<#-- @Override-->
+<#-- public String toString() {-->
+<#-- WriteBufferBoxBased writeBufferBoxBased = new
WriteBufferBoxBased(true, true);-->
+<#-- try {-->
+<#-- serialize(writeBufferBoxBased);-->
+<#-- } catch (SerializationException e) {-->
+<#-- throw new RuntimeException(e);-->
+<#-- }-->
+<#-- return "\n" + writeBufferBoxBased.getBox().toString()+ "\n";-->
+<#-- }-->
+<#--}-->
</#outputformat>
\ No newline at end of file
diff --git
a/code-generation/language-rust/src/main/resources/templates/rust/enum-template.rs.ftlh
b/code-generation/language-rust/src/main/resources/templates/rust/enum-template.rs.ftlh
index 6a478a7ae4..2f58c5914c 100644
---
a/code-generation/language-rust/src/main/resources/templates/rust/enum-template.rs.ftlh
+++
b/code-generation/language-rust/src/main/resources/templates/rust/enum-template.rs.ftlh
@@ -126,7 +126,7 @@ impl Message for ${type.name} {
<#if !type.parserArguments.isEmpty()>
pub struct ${type.name}Arguments {
<#list type.parserArguments.orElseThrow() as arg>
- ${helper.sink(arg)}${arg.name}:
${helper.getNullsafeLanguageTypeNameForTypeReference(arg,
type.enumValues)}<#sep>, </#sep>
+ ${arg.name}: ${helper.getNullsafeLanguageTypeNameForTypeReference(arg,
type.enumValues)}<#sep>, </#sep>
</#list>
}