| <#-- |
| Licensed to the Apache Software Foundation (ASF) under one |
| or more contributor license agreements. See the NOTICE file |
| distributed with this work for additional information |
| regarding copyright ownership. The ASF licenses this file |
| to you under the Apache License, Version 2.0 (the |
| "License"); you may not use this file except in compliance |
| with the License. You may obtain a copy of the License at |
| |
| http://www.apache.org/licenses/LICENSE-2.0 |
| |
| Unless required by applicable law or agreed to in writing, |
| software distributed under the License is distributed on an |
| "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY |
| KIND, either express or implied. See the License for the |
| specific language governing permissions and limitations |
| under the License. |
| --> |
| <#-- Prevent freemarker from escaping stuff --> |
| <#outputformat "undefined"> |
| <#-- Declare the name and type of variables passed in to the template --> |
| <#-- @ftlvariable name="languageName" type="java.lang.String" --> |
| <#-- @ftlvariable name="protocolName" type="java.lang.String" --> |
| <#-- @ftlvariable name="outputFlavor" type="java.lang.String" --> |
| <#-- @ftlvariable name="helper" type="org.apache.plc4x.language.go.GoLanguageTemplateHelper" --> |
| <#-- @ftlvariable name="type" type="org.apache.plc4x.plugins.codegenerator.types.definitions.ComplexTypeDefinition" --> |
| <#-- Declare the name and type of variables declared locally inside the template --> |
| <#-- @ftlvariable name="arrayField" type="org.apache.plc4x.plugins.codegenerator.types.fields.ArrayField" --> |
| <#-- @ftlvariable name="checksumField" type="org.apache.plc4x.plugins.codegenerator.types.fields.ChecksumField" --> |
| <#-- @ftlvariable name="constField" type="org.apache.plc4x.plugins.codegenerator.types.fields.ConstField" --> |
| <#-- @ftlvariable name="discriminatorField" type="org.apache.plc4x.plugins.codegenerator.types.fields.DiscriminatorField" --> |
| <#-- @ftlvariable name="enumField" type="org.apache.plc4x.plugins.codegenerator.types.fields.EnumField" --> |
| <#-- @ftlvariable name="implicitField" type="org.apache.plc4x.plugins.codegenerator.types.fields.ImplicitField" --> |
| <#-- @ftlvariable name="manualArrayField" type="org.apache.plc4x.plugins.codegenerator.types.fields.ManualArrayField" --> |
| <#-- @ftlvariable name="manualField" type="org.apache.plc4x.plugins.codegenerator.types.fields.ManualField" --> |
| <#-- @ftlvariable name="optionalField" type="org.apache.plc4x.plugins.codegenerator.types.fields.OptionalField" --> |
| <#-- @ftlvariable name="paddingField" type="org.apache.plc4x.plugins.codegenerator.types.fields.PaddingField" --> |
| <#-- @ftlvariable name="reservedField" type="org.apache.plc4x.plugins.codegenerator.types.fields.ReservedField" --> |
| <#-- @ftlvariable name="simpleField" type="org.apache.plc4x.plugins.codegenerator.types.fields.SimpleField" --> |
| <#-- @ftlvariable name="switchField" type="org.apache.plc4x.plugins.codegenerator.types.fields.SwitchField" --> |
| <#-- @ftlvariable name="virtualField" type="org.apache.plc4x.plugins.codegenerator.types.fields.VirtualField" --> |
| <#-- @ftlvariable name="simpleTypeReference" type="org.apache.plc4x.plugins.codegenerator.types.references.SimpleTypeReference" --> |
| <#-- @ftlvariable name="complexTypeReference" type="org.apache.plc4x.plugins.codegenerator.types.references.ComplexTypeReference" --> |
| ${helper.fileName(protocolName, languageName, outputFlavor)?replace(".", "/")}/model/${type.name}.go |
| // |
| // Licensed to the Apache Software Foundation (ASF) under one |
| // or more contributor license agreements. See the NOTICE file |
| // distributed with this work for additional information |
| // regarding copyright ownership. The ASF licenses this file |
| // to you under the Apache License, Version 2.0 (the |
| // "License"); you may not use this file except in compliance |
| // with the License. You may obtain a copy of the License at |
| // |
| // http://www.apache.org/licenses/LICENSE-2.0 |
| // |
| // Unless required by applicable law or agreed to in writing, |
| // software distributed under the License is distributed on an |
| // "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY |
| // KIND, either express or implied. See the License for the |
| // specific language governing permissions and limitations |
| // under the License. |
| // |
| |
| package model |
| |
| <#macro importSectionWithContentBelow> |
| <#local sectionContent><#nested></#local> |
| import ( |
| <#if helper.getRequiredImports()?has_content> |
| <#list helper.getRequiredImports() as import> |
| ${import} |
| </#list> |
| </#if> |
| ) |
| |
| ${sectionContent} |
| </#macro> |
| |
| <#macro emitImport import>${helper.emitRequiredImport(import)}</#macro> |
| <#macro emitImportWithAlias alias import>${helper.emitRequiredImport(alias, import)}</#macro> |
| |
| <@importSectionWithContentBelow><@emitImport import="github.com/apache/plc4x/plc4go/internal/plc4go/spi/utils" /> |
| // Code generated by build-utils. DO NOT EDIT. |
| |
| <#if type.constFields?has_content> |
| |
| // Constant values. |
| <#list type.constFields as field> |
| const ${type.name}_${field.name?upper_case} ${helper.getLanguageTypeNameForField(field)} = ${field.referenceValue} |
| </#list> |
| </#if> |
| |
| // The data-structure of this message |
| type ${type.name} struct { |
| <#-- Property fields are fields that require a property in the pojo --> |
| <#if type.propertyFields?has_content> |
| <#list type.propertyFields as field> |
| ${field.name?cap_first} <#if field.loopType??>[]</#if><#if helper.needsPointerAccess(field)>*</#if>${helper.getLanguageTypeNameForField(field)} |
| </#list> |
| </#if> |
| <#if helper.isDiscriminatedParentTypeDefinition()> |
| Child I${type.name}Child |
| </#if> |
| <#-- |
| This is GO's version of inheritance |
| (Makes all properties of the following type available in this tpye) |
| --> |
| <#if type.parentType??> |
| Parent *${type.parentType.name} |
| </#if> |
| } |
| |
| // The corresponding interface |
| type I${type.name} interface { |
| <#if helper.isDiscriminatedParentTypeDefinition()> |
| <#list helper.getDiscriminatorTypes() as discriminatorName, discriminatorType> |
| <#-- If the discriminator name matches that of another field, suppress the methods generation --> |
| <#if !helper.isNonDiscriminatorField(discriminatorName)> |
| ${discriminatorName?cap_first}() ${helper.getLanguageTypeNameForTypeReference(helper.getDiscriminatorTypes()[discriminatorName])} |
| </#if> |
| </#list> |
| </#if> |
| LengthInBytes() uint16 |
| LengthInBits() uint16 |
| Serialize(writeBuffer utils.WriteBuffer) error |
| } |
| <#if helper.isDiscriminatedChildTypeDefinition()> |
| <#assign discriminatedChildType = type> |
| |
| /////////////////////////////////////////////////////////// |
| // Accessors for discriminator values. |
| /////////////////////////////////////////////////////////// |
| <#list helper.getDiscriminatorValues(discriminatedChildType) as discriminatorName, discriminatorValue> |
| <#-- If the discriminator name matches that of another field, suppress the methods generation --> |
| <#if !helper.isNonDiscriminatorField(discriminatorName)> |
| func (m *${type.name}) ${discriminatorName?cap_first}() ${helper.getLanguageTypeNameForTypeReference(helper.getDiscriminatorTypes()[discriminatorName])} { |
| return <#if discriminatorValue??><#if helper.isComplexTypeReference(helper.getDiscriminatorTypes()[discriminatorName])><#if helper.isEnumTypeReference(helper.getDiscriminatorTypes()[discriminatorName])>${helper.getLanguageTypeNameForTypeReference(helper.getDiscriminatorTypes()[discriminatorName])}_${discriminatorValue}<#else>${discriminatorValue}</#if><#else>${discriminatorValue}</#if><#else>${helper.getNullValueForTypeReference(helper.getDiscriminatorTypes()[discriminatorName])}</#if> |
| } |
| |
| </#if> |
| </#list> |
| </#if> |
| <#if helper.isDiscriminatedParentTypeDefinition()> |
| |
| type I${type.name}Parent interface { |
| SerializeParent(writeBuffer utils.WriteBuffer, child I${type.name}, serializeChildFunction func() error<#if helper.getSerializerArguments(type.parserArguments)?has_content>, <#list helper.getSerializerArguments(type.parserArguments) as parserArgument>${parserArgument.name} ${helper.getLanguageTypeNameForTypeReference(parserArgument.type)}<#sep>, </#sep></#list></#if>) error |
| GetTypeName() string |
| } |
| |
| type I${type.name}Child interface { |
| Serialize(writeBuffer utils.WriteBuffer<#if helper.getSerializerArguments(type.parserArguments)?has_content>, <#list helper.getSerializerArguments(type.parserArguments) as parserArgument>${parserArgument.name} ${helper.getLanguageTypeNameForTypeReference(parserArgument.type)}<#sep>, </#sep></#list></#if>) error |
| InitializeParent(parent *${type.name}<#if type.getPropertyFields()?has_content>, <#list type.getPropertyFields() as field>${field.name} <#if field.loopType??>[]</#if><#if helper.needsPointerAccess(field)>*</#if>${helper.getLanguageTypeNameForField(field)}<#sep>, </#sep></#list></#if>) |
| GetTypeName() string |
| I${type.name} |
| } |
| <#--list helper.getDiscriminatorTypes() as discriminatorName, discriminatorType> |
| <#- If the discriminator name matches that of another field, suppress the methods generation -> |
| <#if !helper.isNonDiscriminatorField(discriminatorName)> |
| func ${type.name}${discriminatorName?cap_first}(m I${type.name}) ${helper.getLanguageTypeNameForTypeReference(helper.getDiscriminatorTypes()[discriminatorName])} { |
| return m.${discriminatorName?cap_first}() |
| } |
| </#if> |
| </#list--> |
| <#elseif type.parentType??> |
| |
| func (m *${type.name}) InitializeParent(parent *${type.parentType.name}<#if type.parentType.getAllPropertyFields()?has_content>, <#list type.parentPropertyFields as parentField>${parentField.name} <#if parentField.loopType??>[]</#if><#if helper.needsPointerAccess(parentField)>*</#if>${helper.getLanguageTypeNameForField(parentField)}<#sep>, </#sep></#list></#if>) { |
| <#list type.parentType.getAllPropertyFields() as field> |
| m.Parent.${field.name?cap_first} = ${field.name} |
| </#list> |
| } |
| </#if> |
| |
| func New${type.name}(<#list type.getPropertyFields() as field>${field.name} <#if field.loopType??>[]</#if><#if helper.needsPointerAccess(field)>*</#if>${helper.getLanguageTypeNameForField(field)}<#sep>, </#sep></#list><#if type.parentType?has_content><#if type.getPropertyFields()?has_content && type.parentPropertyFields?has_content>, </#if><#list type.parentPropertyFields as parentField>${parentField.name} <#if parentField.loopType??>[]</#if><#if helper.needsPointerAccess(parentField)>*</#if>${helper.getLanguageTypeNameForField(parentField)}<#sep>, </#sep></#list></#if>) *<#if type.parentType?has_content>${type.parentType.name}<#else>${type.name}</#if> { |
| <#if type.parentType?has_content> |
| child := &${type.name}{ |
| <#list type.getPropertyFields() as field> |
| ${field.name?cap_first}: ${field.name}, |
| </#list> |
| Parent: New${type.parentType.name}(<#list type.parentPropertyFields as parentField>${parentField.name}<#sep>, </#list>), |
| } |
| child.Parent.Child = child |
| return child.Parent |
| <#else> |
| return &${type.name}{<#list type.getPropertyFields() as field>${field.name?cap_first}: ${field.name}<#sep>, </#sep></#list>} |
| </#if> |
| } |
| |
| func Cast${type.name}(structType interface{}) *${type.name} { |
| castFunc := func(typ interface{}) *${type.name} { |
| if casted, ok := typ.(${type.name}); ok { |
| return &casted |
| } |
| if casted, ok := typ.(*${type.name}); ok { |
| return casted |
| } |
| <#if type.parentType?has_content> |
| if casted, ok := typ.(${type.parentType.name}); ok { |
| return Cast${type.name}(casted.Child) |
| } |
| if casted, ok := typ.(*${type.parentType.name}); ok { |
| return Cast${type.name}(casted.Child) |
| } |
| </#if> |
| return nil |
| } |
| return castFunc(structType) |
| } |
| |
| func (m *${type.name}) GetTypeName() string { |
| return "${type.name}" |
| } |
| |
| func (m *${type.name}) LengthInBits() uint16 { |
| return m.LengthInBitsConditional(false) |
| } |
| |
| <#-- TODO: use serializer args instead of a fixed bool for one case --> |
| func (m *${type.name}) LengthInBitsConditional(lastItem bool) uint16 { |
| <#if helper.isDiscriminatedParentTypeDefinition()> |
| return m.Child.LengthInBits() |
| <#else> |
| <#if helper.isDiscriminatedChildTypeDefinition()> |
| lengthInBits := uint16(m.Parent.ParentLengthInBits()) |
| <#else> |
| lengthInBits := uint16(0) |
| </#if> |
| <#list type.fields as field> |
| <#switch field.typeName> |
| <#case "array"> |
| <#assign arrayField = field> |
| |
| // Array field |
| if len(m.${arrayField.name?cap_first}) > 0 { |
| <#assign simpleTypeReference = arrayField.type> |
| <#if helper.getLanguageTypeNameForTypeReference(arrayField.type) = "string"> |
| lengthInBits += uint16(${helper.toSerializationExpression(discriminatorField, simpleTypeReference.getLengthExpression(), type.parserArguments)}) * uint16(len(m.${arrayField.name?cap_first})) |
| <#elseif helper.isSimpleTypeReference(arrayField.type)> |
| lengthInBits += ${simpleTypeReference.sizeInBits} * uint16(len(m.${arrayField.name?cap_first})) |
| <#else> |
| <#if helper.isCountArrayField(arrayField)> |
| for i, element := range m.${arrayField.name?cap_first} { |
| last := i == len(m.${arrayField.name?cap_first}) -1 |
| lengthInBits += element.LengthInBitsConditional(last) |
| <#else> |
| for _, element := range m.${arrayField.name?cap_first} { |
| lengthInBits += element.LengthInBits() |
| </#if> |
| } |
| </#if> |
| } |
| <#break> |
| <#case "checksum"> |
| <#assign checksumField = field> |
| <#assign simpleTypeReference = checksumField.type> |
| |
| // Checksum Field (checksum) |
| lengthInBits += ${simpleTypeReference.sizeInBits} |
| <#break> |
| <#case "const"> |
| <#assign constField = field> |
| <#assign simpleTypeReference = constField.type> |
| |
| // Const Field (${constField.name}) |
| <#if helper.getLanguageTypeNameForTypeReference(constField.type) = "string"> |
| lengthInBits += uint16(${helper.toSerializationExpression(discriminatorField, simpleTypeReference.getLengthExpression(), type.parserArguments)}) |
| <#else> |
| lengthInBits += ${simpleTypeReference.sizeInBits} |
| </#if> |
| <#break> |
| <#case "discriminator"> |
| <#assign discriminatorField = field> |
| <#assign simpleTypeReference = discriminatorField.type> |
| // Discriminator Field (${discriminatorField.name}) |
| <#if helper.isSimpleTypeReference(simpleTypeReference)> |
| <#if helper.getLanguageTypeNameForTypeReference(discriminatorField.type) = "String"> |
| lengthInBits += uint16(${helper.toSerializationExpression(discriminatorField, simpleTypeReference.getLengthExpression(), type.parserArguments)}) |
| <#else> |
| lengthInBits += ${simpleTypeReference.sizeInBits}; |
| </#if> |
| <#elseif helper.isEnumField(discriminatorField)> |
| lengthInBits += ${helper.getEnumBaseTypeReference(discriminatorField.type).sizeInBits}; |
| <#else> |
| lengthInBits += ${discriminatorField.name}.getLengthInBits(); |
| </#if> |
| <#break> |
| <#case "enum"> |
| <#assign enumField = field> |
| |
| // Enum Field (${enumField.name}) |
| lengthInBits += ${helper.getEnumBaseTypeReference(enumField.type).sizeInBits} |
| <#break> |
| <#case "implicit"> |
| <#assign implicitField = field> |
| <#assign simpleTypeReference = implicitField.type> |
| |
| // Implicit Field (${implicitField.name}) |
| lengthInBits += ${simpleTypeReference.sizeInBits} |
| <#break> |
| <#case "manualArray"> |
| <#assign manualArrayField = field> |
| |
| // Manual Array Field (${manualArrayField.name}) |
| ${manualArrayField.name} := m.${manualArrayField.name?cap_first}<#-- TODO: ugly workaround for missing static evaluation--> |
| lengthInBits += ${helper.toParseExpression(manualArrayField, manualArrayField.lengthExpression, type.parserArguments)} * 8 |
| <#break> |
| <#case "manual"> |
| <#assign manualField = field> |
| |
| // Manual Field (${manualField.name}) |
| lengthInBits += ${helper.toParseExpression(manualField, manualField.lengthExpression, type.parserArguments)} * 8 |
| <#break> |
| <#case "optional"> |
| <#assign optionalField = field> |
| |
| // Optional Field (${optionalField.name}) |
| if m.${optionalField.name?cap_first} != nil { |
| <#if helper.isSimpleTypeReference(optionalField.type)> |
| <#assign simpleTypeReference = optionalField.type> |
| lengthInBits += ${simpleTypeReference.sizeInBits} |
| <#elseif helper.isEnumField(field)> |
| lengthInBits += ${helper.getEnumBaseTypeReference(optionalField.type).sizeInBits} |
| <#else> |
| lengthInBits += (*m.${optionalField.name?cap_first}).LengthInBits() |
| </#if> |
| } |
| <#break> |
| <#case "padding"> |
| <#assign paddingField = field> |
| <#assign simpleTypeReference = paddingField.type> |
| |
| // Padding Field (padding) |
| _timesPadding := uint8(${helper.toSerializationExpression(paddingField, paddingField.paddingCondition, type.parserArguments)}) |
| for ;_timesPadding > 0; _timesPadding-- { |
| lengthInBits += ${simpleTypeReference.sizeInBits} |
| } |
| <#break> |
| <#case "reserved"> |
| <#assign reservedField = field> |
| <#assign simpleTypeReference = reservedField.type> |
| |
| // Reserved Field (reserved) |
| lengthInBits += ${simpleTypeReference.sizeInBits} |
| <#break> |
| <#case "simple"> |
| <#assign simpleField = field> |
| |
| // Simple field (${simpleField.name}) |
| <#if helper.isSimpleTypeReference(simpleField.type)> |
| <#if helper.getLanguageTypeNameForTypeReference(simpleField.type) = "string"> |
| <#assign simpleTypeReference = simpleField.type> |
| lengthInBits += uint16(${helper.toSerializationExpression(simpleField, simpleTypeReference.getLengthExpression(), type.parserArguments)}) |
| <#else> |
| <#assign simpleTypeReference = simpleField.type> |
| lengthInBits += ${simpleTypeReference.sizeInBits}; |
| </#if> |
| <#elseif helper.isEnumField(field)> |
| lengthInBits += ${helper.getEnumBaseTypeReference(simpleField.type).sizeInBits} |
| <#else> |
| lengthInBits += m.${simpleField.name?cap_first}.LengthInBits() |
| </#if> |
| <#break> |
| <#case "switch"> |
| <#assign switchField = field> |
| |
| // Length of sub-type elements will be added by sub-type... |
| lengthInBits += m.Child.LengthInBits() |
| <#break> |
| <#case "virtual"> |
| <#assign virtualField = field> |
| |
| // A virtual field doesn't have any in- or output. |
| <#break> |
| </#switch> |
| </#list> |
| |
| return lengthInBits |
| </#if> |
| } |
| |
| <#if helper.isDiscriminatedParentTypeDefinition()> |
| func (m *${type.name}) ParentLengthInBits() uint16 { |
| lengthInBits := uint16(0) |
| <#list type.fields as field> |
| <#switch field.typeName> |
| <#case "array"> |
| <#assign arrayField = field> |
| |
| // Array field |
| if len(m.${arrayField.name?cap_first}) > 0 { |
| <#assign simpleTypeReference = arrayField.type> |
| <#if helper.getLanguageTypeNameForTypeReference(arrayField.type) = "string"> |
| lengthInBits += uint16(${helper.toSerializationExpression(discriminatorField, simpleTypeReference.getLengthExpression(), type.parserArguments)}) * uint16(len(m.${arrayField.name?cap_first})) |
| <#elseif helper.isSimpleTypeReference(arrayField.type)> |
| lengthInBits += ${simpleTypeReference.sizeInBits} * uint16(len(m.${arrayField.name?cap_first})) |
| <#else> |
| <#if helper.isCountArrayField(arrayField)> |
| for i, element := range m.${arrayField.name?cap_first} { |
| last := i >= len(m.${arrayField.name?cap_first}) -1 |
| lengthInBits += element.LengthInBitsConditional(last) |
| <#else> |
| for _, element := range m.${arrayField.name?cap_first} { |
| lengthInBits += element.LengthInBits() |
| </#if> |
| } |
| </#if> |
| } |
| <#break> |
| <#case "checksum"> |
| <#assign checksumField = field> |
| <#assign simpleTypeReference = checksumField.type> |
| |
| // Checksum Field (checksum) |
| lengthInBits += ${simpleTypeReference.sizeInBits} |
| <#break> |
| <#case "const"> |
| <#assign constField = field> |
| <#assign simpleTypeReference = constField.type> |
| |
| // Const Field (${constField.name}) |
| <#if helper.getLanguageTypeNameForTypeReference(constField.type) = "string"> |
| lengthInBits += uint16(${helper.toSerializationExpression(discriminatorField, simpleTypeReference.getLengthExpression(), type.parserArguments)}) |
| <#else> |
| lengthInBits += ${simpleTypeReference.sizeInBits} |
| </#if> |
| <#break> |
| <#case "discriminator"> |
| <#assign discriminatorField = field> |
| <#assign simpleTypeReference = discriminatorField.type> |
| // Discriminator Field (${discriminatorField.name}) |
| <#if helper.isSimpleTypeReference(simpleTypeReference)> |
| <#if helper.getLanguageTypeNameForTypeReference(discriminatorField.type) = "String"> |
| lengthInBits += uint16(${helper.toSerializationExpression(discriminatorField, simpleTypeReference.getLengthExpression(), type.parserArguments)}) |
| <#else> |
| lengthInBits += ${simpleTypeReference.sizeInBits}; |
| </#if> |
| <#elseif helper.isEnumField(discriminatorField)> |
| lengthInBits += ${helper.getEnumBaseTypeReference(discriminatorField.type).sizeInBits}; |
| <#else> |
| lengthInBits += ${discriminatorField.name}.getLengthInBits(); |
| </#if> |
| <#break> |
| <#case "enum"> |
| <#assign enumField = field> |
| |
| // Enum Field (${enumField.name}) |
| lengthInBits += ${helper.getEnumBaseTypeReference(enumField.type).sizeInBits} |
| <#break> |
| <#case "implicit"> |
| <#assign implicitField = field> |
| <#assign simpleTypeReference = implicitField.type> |
| |
| // Implicit Field (${implicitField.name}) |
| lengthInBits += ${simpleTypeReference.sizeInBits} |
| <#break> |
| <#case "manualArray"> |
| <#assign manualArrayField = field> |
| |
| // Manual Array Field (${manualArrayField.name}) |
| lengthInBits += ${helper.toParseExpression(manualArrayField, manualArrayField.lengthExpression, type.parserArguments)} * 8 |
| <#break> |
| <#case "manual"> |
| <#assign manualField = field> |
| |
| // Manual Field (${manualField.name}) |
| lengthInBits += ${helper.toParseExpression(manualField, manualField.lengthExpression, type.parserArguments)} * 8 |
| <#break> |
| <#case "optional"> |
| <#assign optionalField = field> |
| |
| // Optional Field (${optionalField.name}) |
| if m.${optionalField.name?cap_first} != nil { |
| <#if helper.isSimpleTypeReference(optionalField.type)> |
| <#assign simpleTypeReference = optionalField.type> |
| lengthInBits += ${simpleTypeReference.sizeInBits} |
| <#elseif helper.isEnumField(field)> |
| lengthInBits += ${helper.getEnumBaseTypeReference(optionalField.type).sizeInBits} |
| <#else> |
| lengthInBits += (*m.${optionalField.name?cap_first}).LengthInBits() |
| </#if> |
| } |
| <#break> |
| <#case "padding"> |
| <#assign paddingField = field> |
| <#assign simpleTypeReference = paddingField.type> |
| |
| // Padding Field (padding) |
| _timesPadding := uint8(${helper.toSerializationExpression(paddingField, paddingField.paddingCondition, type.parserArguments)}) |
| for ;_timesPadding > 0; _timesPadding-- { |
| lengthInBits += ${simpleTypeReference.sizeInBits} |
| } |
| <#break> |
| <#case "reserved"> |
| <#assign reservedField = field> |
| <#assign simpleTypeReference = reservedField.type> |
| |
| // Reserved Field (reserved) |
| lengthInBits += ${simpleTypeReference.sizeInBits} |
| <#break> |
| <#case "simple"> |
| <#assign simpleField = field> |
| |
| // Simple field (${simpleField.name}) |
| <#if helper.isSimpleTypeReference(simpleField.type)> |
| <#if helper.getLanguageTypeNameForTypeReference(simpleField.type) = "string"> |
| <#assign simpleTypeReference = simpleField.type> |
| lengthInBits += uint16(${helper.toSerializationExpression(simpleField, simpleTypeReference.getLengthExpression(), type.parserArguments)}) |
| <#else> |
| <#assign simpleTypeReference = simpleField.type> |
| lengthInBits += ${simpleTypeReference.sizeInBits}; |
| </#if> |
| <#elseif helper.isEnumField(field)> |
| lengthInBits += ${helper.getEnumBaseTypeReference(simpleField.type).sizeInBits} |
| <#else> |
| lengthInBits += m.${simpleField.name?cap_first}.LengthInBits() |
| </#if> |
| <#break> |
| <#case "virtual"> |
| <#assign virtualField = field> |
| |
| // A virtual field doesn't have any in- or output. |
| <#break> |
| </#switch> |
| </#list> |
| |
| return lengthInBits |
| } |
| </#if> |
| |
| func (m *${type.name}) LengthInBytes() uint16 { |
| return m.LengthInBits() / 8 |
| } |
| |
| func ${type.name}Parse(readBuffer utils.ReadBuffer<#if type.parserArguments?has_content>, <#list type.parserArguments as parserArgument>${parserArgument.name} <#if helper.isComplexTypeReference(parserArgument.type)>*</#if>${helper.getLanguageTypeNameForTypeReference(parserArgument.type)}<#sep>, </#sep></#list></#if>) (*<#if type.parentType?has_content>${type.parentType.name}<#else>${type.name}</#if>, error) { |
| if pullErr := readBuffer.PullContext("${type.name}"); pullErr != nil { |
| return nil, pullErr |
| } |
| <#if helper.requiresStartPosAndCurPos()> |
| var startPos = readBuffer.GetPos() |
| var curPos uint16 |
| </#if> |
| <#list type.fields as field> |
| <#switch field.typeName> |
| <#case "array"> |
| <#assign arrayField = field> |
| <#if helper.isByteBased(arrayField.type)> |
| // Byte Array field (${arrayField.name}) |
| <#assign numberOfBytesExpression> |
| <#compress> |
| <#if helper.isCountArrayField(field)> |
| numberOfBytes := int(${helper.toIntegerParseExpression(16, arrayField.loopExpression, type.parserArguments)}) |
| <#elseif helper.isLengthArrayField(field)> |
| numberOfBytes := int(${helper.toIntegerParseExpression(16, arrayField.loopExpression, type.parserArguments)}) |
| <#elseif helper.isTerminatedArrayField(field)> |
| <#-- TODO: we need to find out to implement this--> |
| numberOfBytes := int(${helper.toIntegerParseExpression(16, arrayField.loopExpression, type.parserArguments)}) |
| <#else> |
| <#-- TODO: we should throw a exception here--> |
| numberOfBytes := int(-1) |
| </#if> |
| </#compress> |
| </#assign> |
| ${numberOfBytesExpression} |
| ${arrayField.name}, _readArrayErr := readBuffer.ReadByteArray("${arrayField.name}", numberOfBytes) |
| if _readArrayErr != nil { |
| return nil, errors.Wrap(_readArrayErr, "Error parsing '${arrayField.name}' field")<@emitImport import="github.com/pkg/errors" /> |
| } |
| <#else> |
| |
| // Array field (${arrayField.name}) |
| if pullErr := readBuffer.PullContext("${arrayField.name}", utils.WithRenderAsList(true)); pullErr != nil { |
| return nil, pullErr |
| } |
| <#-- Only update curPos if the length expression uses it --> |
| <#if arrayField.loopExpression.contains("curPos")> |
| curPos = readBuffer.GetPos() - startPos |
| </#if> |
| <#-- If this is a count array, we can directly initialize an array with the given size --> |
| <#if helper.isCountArrayField(field)> |
| // Count array |
| ${arrayField.name} := make([]<#if helper.isComplexTypeReference(arrayField.type)>*</#if>${helper.getLanguageTypeNameForField(field)}, ${helper.toIntegerParseExpression(16, arrayField.loopExpression, type.parserArguments)}) |
| for curItem := uint16(0); curItem < uint16(${helper.toIntegerParseExpression(16, arrayField.loopExpression, type.parserArguments)}); curItem++ { |
| <#if (!helper.isSimpleTypeReference(arrayField.type)) && helper.requiresVariable(arrayField, "lastItem")> |
| lastItem := curItem == uint16(${helper.toParseExpression(arrayField, arrayField.loopExpression, type.parserArguments)} - 1) |
| </#if> |
| _item, _err := <#if helper.isSimpleTypeReference(arrayField.type)>${helper.getReadBufferReadMethodCall("", arrayField.type)}<#else>${arrayField.type.name}Parse(readBuffer<#if field.params?has_content>, <#list field.params as parserArgument><#if helper.isOptionalField(helper.getFieldForNameFromCurrentOrParent(parserArgument.name))>*</#if>${helper.toTypedParseExpression(helper.getArgumentType(arrayField.type, parserArgument?index), parserArgument, type.parserArguments)}<#sep>, </#sep></#list></#if>)</#if> |
| if _err != nil { |
| return nil, errors.Wrap(_err, "Error parsing '${arrayField.name}' field")<@emitImport import="github.com/pkg/errors" /> |
| } |
| ${arrayField.name}[curItem] = _item |
| } |
| <#-- In all other cases do we have to work with a list, that is later converted to an array --> |
| <#elseif helper.isLengthArrayField(field)> |
| <#-- For a length array, we read data till the read position of the buffer reaches a given position --> |
| // Length array |
| ${arrayField.name} := make([]<#if helper.isComplexTypeReference(arrayField.type)>*</#if>${helper.getLanguageTypeNameForField(field)}, 0) |
| _${arrayField.name}Length := ${helper.toIntegerParseExpression(16, arrayField.loopExpression, type.parserArguments)} |
| _${arrayField.name}EndPos := readBuffer.GetPos() + uint16(_${arrayField.name}Length) |
| for ;readBuffer.GetPos() < _${arrayField.name}EndPos; { |
| _item, _err := <#if helper.isSimpleTypeReference(arrayField.type)>${helper.getReadBufferReadMethodCall("", arrayField.type)}<#else>${arrayField.type.name}Parse(readBuffer<#if field.params?has_content>, <#list field.params as parserArgument><#if helper.isOptionalField(helper.getFieldForNameFromCurrentOrParent(parserArgument.name))>*</#if>${helper.toTypedParseExpression(helper.getArgumentType(arrayField.type, parserArgument?index), parserArgument, type.parserArguments)}<#sep>, </#sep></#list></#if>)</#if> |
| if _err != nil { |
| return nil, errors.Wrap(_err, "Error parsing '${arrayField.name}' field")<@emitImport import="github.com/pkg/errors" /> |
| } |
| ${arrayField.name} = append(${arrayField.name}, _item) |
| <#-- After parsing, update the current position, but only if it's needed --> |
| <#if arrayField.loopExpression.contains("curPos")> |
| curPos = readBuffer.GetPos() - startPos |
| </#if> |
| } |
| <#-- A terminated array keeps on reading data as long as the termination expression evaluates to false --> |
| <#elseif helper.isTerminatedArrayField(field)> |
| // Terminated array |
| ${arrayField.name} := make([]<#if helper.isComplexTypeReference(arrayField.type)>*</#if>${helper.getLanguageTypeNameForField(field)}, 0) |
| for ;!bool(${helper.toParseExpression(arrayField, arrayField.loopExpression, type.parserArguments)}); { |
| _item, _err := <#if helper.isSimpleTypeReference(arrayField.type)>${helper.getReadBufferReadMethodCall("", arrayField.type)}<#else>${arrayField.type.name}Parse(readBuffer<#if field.params?has_content>, <#list field.params as parserArgument><#if helper.isOptionalField(helper.getFieldForNameFromCurrentOrParent(parserArgument.name))>*</#if>${helper.toTypedParseExpression(helper.getArgumentType(arrayField.type, parserArgument?index), parserArgument, type.parserArguments)}<#sep>, </#sep></#list></#if>)</#if> |
| if _err != nil { |
| return nil, errors.Wrap(_err, "Error parsing '${arrayField.name}' field")<@emitImport import="github.com/pkg/errors" /> |
| } |
| ${arrayField.name} = append(${arrayField.name}, _item) |
| |
| <#-- After parsing, update the current position, but only if it's needed --> |
| <#if arrayField.loopExpression.contains("curPos")> |
| curPos = readBuffer.GetPos() - startPos |
| </#if> |
| } |
| </#if> |
| if closeErr := readBuffer.CloseContext("${arrayField.name}", utils.WithRenderAsList(true)); closeErr != nil { |
| return nil, closeErr |
| } |
| </#if> |
| <#break> |
| <#case "checksum"> |
| <#assign checksumField = field> |
| <#assign simpleTypeReference = checksumField.type> |
| |
| // Checksum Field (checksum) |
| { |
| checksumRef, _checksumRefErr := ${helper.getReadBufferReadMethodCall("checksum", simpleTypeReference)} |
| if _checksumRefErr != nil { |
| return nil, errors.Wrap(_checksumRefErr, "Error parsing 'checksum' field")<@emitImport import="github.com/pkg/errors" /> |
| } |
| checksum, _checksumErr := ${helper.toParseExpression(checksumField, checksumField.checksumExpression, type.parserArguments)} |
| if _checksumErr != nil { |
| return nil, errors.Wrap(_checksumErr, "Error parsing 'checksum' field")<@emitImport import="github.com/pkg/errors" /> |
| } |
| if checksum != checksumRef { |
| return nil, errors.Errorf("Checksum verification failed. Expected %d but got %d", (checksumRef & 0xFFFF), (checksum & 0xFFFF))<@emitImport import="github.com/pkg/errors" /> |
| } |
| } |
| <#break> |
| <#case "const"> |
| <#assign constField = field> |
| <#assign simpleTypeReference = constField.type> |
| |
| // Const Field (${constField.name}) |
| ${constField.name}, _${constField.name}Err := ${helper.getReadBufferReadMethodCall(constField.name, simpleTypeReference)} |
| if _${constField.name}Err != nil { |
| return nil, errors.Wrap(_${constField.name}Err, "Error parsing '${constField.name}' field")<@emitImport import="github.com/pkg/errors" /> |
| } |
| if ${constField.name} != ${type.name}_${constField.name?upper_case} { |
| return nil, errors.New("Expected constant value " + fmt.Sprintf("%d", ${type.name}_${constField.name?upper_case}) + " but got " + fmt.Sprintf("%d", ${constField.name}))<@emitImport import="github.com/pkg/errors" /><@emitImport import="fmt" /> |
| } |
| <#break> |
| <#case "discriminator"> |
| <#assign discriminatorField = field> |
| <#assign simpleTypeReference = discriminatorField.type> |
| |
| // Discriminator Field (${discriminatorField.name}) (Used as input to a switch field) |
| <#if helper.isEnumField(field)> |
| ${helper.getVariableName(field)}_temp, _${discriminatorField.name}Err := ${helper.getLanguageTypeNameForField(discriminatorField)}Parse(readBuffer) |
| var ${helper.getVariableName(field)} *${helper.getLanguageTypeNameForField(discriminatorField)} = &${helper.getVariableName(field)}_temp |
| <#else> |
| ${helper.getVariableName(field)}, _${discriminatorField.name}Err := ${helper.getReadBufferReadMethodCall(discriminatorField.name, simpleTypeReference)} |
| </#if> |
| if _${discriminatorField.name}Err != nil { |
| return nil, errors.Wrap(_${discriminatorField.name}Err, "Error parsing '${discriminatorField.name}' field")<@emitImport import="github.com/pkg/errors" /> |
| } |
| <#break> |
| <#case "enum"> |
| <#assign enumField = field> |
| |
| if pullErr := readBuffer.PullContext("${enumField.name}"); pullErr != nil { |
| return nil, pullErr |
| } |
| <#if enumField.fieldName?has_content> |
| // Enum field (${enumField.name}) |
| ${enumField.name}${enumField.fieldName?cap_first}, _${enumField.name}${enumField.fieldName?cap_first}Err := ${helper.getReadBufferReadMethodCall(enumField.type.name, helper.getEnumFieldSimpleTypeReference(enumField.type, enumField.fieldName))} |
| if _${enumField.name}${enumField.fieldName?cap_first}Err != nil { |
| return nil, errors.Wrap(_${enumField.name}${enumField.fieldName?cap_first}Err, "Error serializing '${enumField.name}' field")<@emitImport import="github.com/pkg/errors" /> |
| } |
| ${enumField.name}, _${enumField.name}Err := ${helper.getLanguageTypeNameForField(field)}FirstEnumForField${enumField.fieldName?cap_first}(${enumField.name}${enumField.fieldName?cap_first}) |
| if _${enumField.name}Err != nil { |
| return nil, errors.Wrap(_${enumField.name}Err, "Error serializing '${enumField.name}' field")<@emitImport import="github.com/pkg/errors" /> |
| } |
| <#else> |
| // Enum field (${enumField.name}) |
| ${enumField.name}, _${enumField.name}Err := ${helper.getLanguageTypeNameForField(field)}Parse(readBuffer) |
| if _${enumField.name}Err != nil { |
| return nil, errors.Wrap(_${enumField.name}Err, "Error parsing '${enumField.name}' field")<@emitImport import="github.com/pkg/errors" /> |
| } |
| </#if> |
| if closeErr := readBuffer.CloseContext("${enumField.name}"); closeErr != nil { |
| return nil, closeErr |
| } |
| <#break> |
| <#case "implicit"> |
| <#assign implicitField = field> |
| <#assign simpleTypeReference = implicitField.type> |
| |
| // Implicit Field (${implicitField.name}) (Used for parsing, but it's value is not stored as it's implicitly given by the objects content) |
| ${implicitField.name}, _${implicitField.name}Err := ${helper.getReadBufferReadMethodCall(implicitField.name, simpleTypeReference)} |
| _ = ${implicitField.name} |
| if _${implicitField.name}Err != nil { |
| return nil, errors.Wrap(_${implicitField.name}Err, "Error parsing '${implicitField.name}' field")<@emitImport import="github.com/pkg/errors" /> |
| } |
| <#break> |
| <#case "manualArray"> |
| <#assign manualArrayField = field> |
| if pullErr := readBuffer.PullContext("${manualArrayField.name}", utils.WithRenderAsList(true)); pullErr != nil { |
| return nil, pullErr |
| } |
| // Manual Array Field (${manualArrayField.name}) |
| <#-- Only update curPos if the length expression uses it --> |
| <#if manualArrayField.loopExpression.contains("curPos")> |
| curPos = readBuffer.GetPos() - startPos |
| </#if> |
| <#-- If this is a count array, we can directly initialize an array with the given size --> |
| <#if helper.isCountArrayField(field)> |
| // Count array |
| _${manualArrayField.name}Count := ${helper.toParseExpression(manualArrayField, manualArrayField.loopExpression, type.parserArguments)} |
| ${helper.getLanguageTypeNameForField(field)}[] ${manualArrayField.name} = new ${helper.getLanguageTypeNameForField(field)}[_${manualArrayField.name}Count] |
| for i := 0; i < _${manualArrayField.name}Count; i++ { |
| ${manualArrayField.name}[i] = (${helper.getLanguageTypeNameForField(field)}) (${helper.toParseExpression(manualArrayField, manualArrayField.parseExpression, type.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 helper.isLengthArrayField(field)> |
| // Length array |
| _${manualArrayField.name}Length := ${helper.toIntegerParseExpression(16, manualArrayField.loopExpression, type.parserArguments)} |
| _${manualArrayField.name}List := make([]${helper.getLanguageTypeNameForField(manualArrayField)}, 0) |
| ${manualArrayField.name}EndPos := readBuffer.GetPos() + _${manualArrayField.name}Length |
| for ;readBuffer.GetPos() < ${manualArrayField.name}EndPos; { |
| _${manualArrayField.name}List = append(_${manualArrayField.name}List, ((${helper.getLanguageTypeNameForField(field)}) (${helper.toParseExpression(manualArrayField, manualArrayField.parseExpression, type.parserArguments)}))) |
| <#-- After parsing, update the current position, but only if it's needed --> |
| <#if manualArrayField.loopExpression.contains("curPos")> |
| curPos = readBuffer.GetPos() - startPos |
| </#if> |
| } |
| <#-- A terminated array keeps on reading data as long as the termination expression evaluates to false --> |
| <#elseif helper.isTerminatedArrayField(field)> |
| // Terminated array |
| _${manualArrayField.name}List := make([]${helper.getLanguageTypeNameForField(manualArrayField)}, 0) |
| for ;!((bool) (${helper.toParseExpression(manualArrayField, manualArrayField.loopExpression, type.parserArguments)})); { |
| _${manualArrayField.name}List = append(_${manualArrayField.name}List, ((${helper.getLanguageTypeNameForField(field)}) (${helper.toParseExpression(manualArrayField, manualArrayField.parseExpression, type.parserArguments)}))) |
| |
| <#-- After parsing, update the current position, but only if it's needed --> |
| <#if manualArrayField.loopExpression.contains("curPos")> |
| curPos = readBuffer.GetPos() - startPos |
| </#if> |
| } |
| </#if> |
| <#-- |
| Convert the list into an array. However if the array is of a primitive |
| type we have to iterate over it's elements and explicitly cast them. |
| Otherwise a simple toArray call is fine. |
| --> |
| <#if helper.isSimpleTypeReference(field.type)> |
| ${manualArrayField.name} := make([]${helper.getLanguageTypeNameForField(field)}, len(_${manualArrayField.name}List)) |
| for i := 0; i < len(_${manualArrayField.name}List); i++ { |
| ${manualArrayField.name}[i] = ${helper.getLanguageTypeNameForField(field)}(_${manualArrayField.name}List[i]) |
| } |
| <#else> |
| ${helper.getLanguageTypeNameForField(field)}[] ${manualArrayField.name} = _${manualArrayField.name}List.toArray(new ${helper.getLanguageTypeNameForField(manualArrayField)}[0]) |
| </#if> |
| </#if> |
| if closeErr := readBuffer.CloseContext("${manualArrayField.name}", utils.WithRenderAsList(true)); closeErr != nil { |
| return nil, closeErr |
| } |
| <#break> |
| <#case "manual"> |
| <#assign manualField = field> |
| |
| // Manual Field (${manualField.name}) |
| ${manualField.name}, _${manualField.name}Err = ${helper.toParseExpression(manualField, manualField.parseExpression, type.parserArguments)} |
| if _${implicitField.name}Err != nil { |
| return nil, errors.Wrap(_${manualField.name}Err, "Error parsing '${manualField.name}' field")<@emitImport import="github.com/pkg/errors" /> |
| } |
| <#break> |
| <#case "optional"> |
| <#assign optionalField = field> |
| |
| // Optional Field (${optionalField.name}) (Can be skipped, if a given expression evaluates to false) |
| <#if optionalField.conditionExpression.contains("curPos")> |
| curPos = readBuffer.GetPos() - startPos |
| </#if> |
| var ${optionalField.name} *${helper.getLanguageTypeNameForField(field)} = nil |
| if ${helper.toBooleanParseExpression(optionalField.conditionExpression, type.parserArguments)} { |
| <#if helper.isSimpleTypeReference(optionalField.type)> |
| _val, _err := ${helper.getReadBufferReadMethodCall(optionalField.name, optionalField.type)} |
| if _err != nil { |
| return nil, errors.Wrap(_err, "Error parsing '${optionalField.name}' field")<@emitImport import="github.com/pkg/errors" /> |
| } |
| ${optionalField.name} = &_val |
| <#elseif helper.isEnumField(field)> |
| _val, _err := ${helper.getLanguageTypeNameForField(field)}Parse(readBuffer) |
| if _err != nil { |
| return nil, errors.Wrap(_err, "Error parsing '${optionalField.name}' field")<@emitImport import="github.com/pkg/errors" /> |
| } |
| ${optionalField.name} = &_val |
| <#else> |
| _val, _err := ${helper.getLanguageTypeNameForField(field)}Parse(readBuffer<#if field.params?has_content>, <#list field.params as parserArgument>${helper.toTypedParseExpression(helper.getArgumentType(optionalField.type, parserArgument?index), parserArgument, type.parserArguments)}<#sep>, </#sep></#list></#if>) |
| if _err != nil { |
| return nil, errors.Wrap(_err, "Error parsing '${optionalField.name}' field")<@emitImport import="github.com/pkg/errors" /> |
| } |
| ${optionalField.name} = _val |
| </#if> |
| } |
| <#break> |
| <#case "padding"> |
| <#assign paddingField = field> |
| <#assign simpleTypeReference = paddingField.type> |
| |
| // Padding Field (padding) |
| { |
| if pullErr := readBuffer.PullContext("padding", utils.WithRenderAsList(true)); pullErr != nil { |
| return nil, pullErr |
| } |
| _timesPadding := (${helper.toParseExpression(paddingField, paddingField.paddingCondition, type.parserArguments)}) |
| for ;(readBuffer.HasMore(${helper.getNumBits(simpleTypeReference)})) && (_timesPadding > 0);_timesPadding-- { |
| // Just read the padding data and ignore it |
| _, _err := ${helper.getReadBufferReadMethodCall("", simpleTypeReference)} |
| if _err != nil { |
| return nil, errors.Wrap(_err, "Error parsing 'padding' field")<@emitImport import="github.com/pkg/errors" /> |
| } |
| } |
| if closeErr := readBuffer.CloseContext("padding", utils.WithRenderAsList(true)); closeErr != nil { |
| return nil, closeErr |
| } |
| } |
| <#break> |
| <#case "reserved"> |
| <#assign reservedField = field> |
| <#assign simpleTypeReference = reservedField.type> |
| |
| // Reserved Field (Compartmentalized so the "reserved" variable can't leak) |
| { |
| reserved, _err := ${helper.getReadBufferReadMethodCall("reserved", simpleTypeReference)} |
| if _err != nil { |
| return nil, errors.Wrap(_err, "Error parsing 'reserved' field")<@emitImport import="github.com/pkg/errors" /> |
| } |
| if ${helper.toTypeSafeCompare(reservedField)} { |
| log.Info().Fields(map[string]interface{}{<@emitImport import="github.com/rs/zerolog/log" /> |
| "expected value": ${helper.getReservedValue(reservedField)}, |
| "got value": reserved, |
| }).Msg("Got unexpected response.") |
| } |
| } |
| <#break> |
| <#case "simple"> |
| <#assign simpleField = field> |
| |
| <#if !helper.isSimpleTypeReference(simpleField.type)> |
| if pullErr := readBuffer.PullContext("${simpleField.name}"); pullErr != nil { |
| return nil, pullErr |
| } |
| </#if> |
| |
| // Simple Field (${simpleField.name}) |
| <#assign simpleFieldLogicalName><#if helper.isSimpleTypeReference(simpleField.type) && !helper.isEnumField(field)>${simpleField.name}<#else>${simpleField.typeName}</#if></#assign> |
| ${simpleField.name}, _${simpleField.name}Err := <#if helper.isSimpleTypeReference(simpleField.type)>${helper.getReadBufferReadMethodCall(simpleFieldLogicalName, simpleField.type, null, field)}<#else>${simpleField.type.name}Parse(readBuffer<#if field.params?has_content>, <#list field.params as parserArgument><#if helper.isOptionalField(helper.getFieldForNameFromCurrentOrParent(parserArgument.name))>*<#elseif helper.needsReferenceForParserArgument(parserArgument.name, helper.getArgumentType(simpleField.type, parserArgument?index))>&</#if>${helper.toTypedParseExpression(helper.getArgumentType(simpleField.type, parserArgument?index), parserArgument, type.parserArguments)}<#sep>, </#sep></#list></#if>)</#if> |
| if _${simpleField.name}Err != nil { |
| <#if helper.isEnumField(field)> |
| return nil, errors.Wrap(_${simpleField.name}Err, "Error parsing '${simpleField.name}' field")<@emitImport import="github.com/pkg/errors" /> |
| <#else> |
| return nil, errors.Wrap(_${simpleField.name}Err, "Error parsing '${simpleField.name}' field")<@emitImport import="github.com/pkg/errors" /> |
| </#if> |
| } |
| <#if !helper.isSimpleTypeReference(simpleField.type)> |
| if closeErr := readBuffer.CloseContext("${simpleField.name}"); closeErr != nil { |
| return nil, closeErr |
| } |
| </#if> |
| <#break> |
| |
| <#case "switch"> |
| <#assign switchField = field> |
| |
| // Switch Field (Depending on the discriminator values, passes the instantiation to a sub-type) |
| var _parent *${type.name} |
| var typeSwitchError error |
| switch { |
| <#list switchField.cases as case> |
| <#--TODO: refactor the line below into multiple assigns --> |
| <#if case.discriminatorValues?has_content>case <#list case.discriminatorValues as discriminatorValue><#if helper.isComplexTypeReference(helper.getDiscriminatorTypes()[helper.toParseExpression(null, switchField.discriminatorExpressions[discriminatorValue?index], type.parserArguments)])><#if helper.isEnumTypeReference(helper.getDiscriminatorTypes()[helper.toParseExpression(null, switchField.discriminatorExpressions[discriminatorValue?index], type.parserArguments)])>*</#if></#if>${helper.toParseExpression(null, switchField.discriminatorExpressions[discriminatorValue?index], type.parserArguments)} == <#if helper.discriminatorValueNeedsStringEqualityCheck(switchField.discriminatorExpressions[discriminatorValue?index])>"${discriminatorValue}"<#elseif helper.isComplexTypeReference(helper.getDiscriminatorTypes()[helper.toParseExpression(null, switchField.discriminatorExpressions[discriminatorValue?index], type.parserArguments)])><#if helper.isEnumTypeReference(helper.getDiscriminatorTypes()[helper.toParseExpression(null, switchField.discriminatorExpressions[discriminatorValue?index], type.parserArguments)])>${helper.getLanguageTypeNameForTypeReference(helper.getDiscriminatorTypes()[helper.toParseExpression(null, switchField.discriminatorExpressions[discriminatorValue?index], type.parserArguments)])}_${discriminatorValue}<#else>${discriminatorValue}</#if><#else>${discriminatorValue}</#if><#sep> && </#sep></#list><#else><#assign defaultCaseOutput=true></#if>: // ${case.name} |
| _parent, typeSwitchError = ${case.name}Parse(readBuffer<#if case.parserArguments?has_content>, <#list case.parserArguments as parserArgument><#if helper.isOptionalField(helper.getFieldForNameFromCurrentOrParent(parserArgument.name))>*</#if>${parserArgument.name}<#sep>, </#sep></#list></#if>) |
| </#list> |
| default: |
| // TODO: return actual type |
| typeSwitchError = errors.New("Unmapped type")<@emitImport import="github.com/pkg/errors" /> |
| } |
| if typeSwitchError != nil { |
| return nil, errors.Wrap(typeSwitchError, "Error parsing sub-type for type-switch.")<@emitImport import="github.com/pkg/errors" /> |
| } |
| <#break> |
| |
| <#case "virtual"> |
| <#assign virtualField = field> |
| |
| // Virtual field (Just declare a local variable so we can access it in the parser) |
| ${virtualField.name}, _${virtualField.name}Err := ${helper.toParseExpression(virtualField, virtualField.valueExpression, type.parserArguments)} |
| if _${virtualField.name}Err != nil { |
| return nil, errors.Wrap(_${virtualField.name}Err, "Error parsing '${virtualField.name}' field")<@emitImport import="github.com/pkg/errors" /> |
| } |
| <#break> |
| </#switch> |
| </#list> |
| |
| if closeErr := readBuffer.CloseContext("${type.name}"); closeErr != nil { |
| return nil, closeErr |
| } |
| |
| <#if helper.isDiscriminatedParentTypeDefinition()> |
| // Finish initializing |
| _parent.Child.InitializeParent(_parent<#if type.propertyFields?has_content>, <#list type.propertyFields as field>${field.name}<#sep>, </#sep></#list></#if>) |
| return _parent, nil |
| <#elseif type.parentType?has_content> |
| // Create a partially initialized instance |
| _child := &${type.name}{ |
| <#list type.propertyFields as field> |
| ${field.name?cap_first}: ${field.name}, |
| </#list> |
| Parent: &${type.parentType.name}{}, |
| } |
| _child.Parent.Child = _child |
| return _child.Parent, nil |
| <#else> |
| // Create the instance |
| return New${type.name}(<#list type.propertyFields as field>${field.name}<#sep>, </#sep></#list>), nil |
| </#if> |
| } |
| |
| <#if helper.isDiscriminatedParentTypeDefinition()> |
| func (m *${type.name}) Serialize(writeBuffer utils.WriteBuffer<#if helper.getSerializerArguments(type.parserArguments)?has_content>, <#list helper.getSerializerArguments(type.parserArguments) as parserArgument>${parserArgument.name} ${helper.getLanguageTypeNameForTypeReference(parserArgument.type)}<#sep>, </#sep></#list></#if>) error { |
| return m.Child.Serialize(writeBuffer<#if helper.getSerializerArguments(type.parserArguments)?has_content>, <#list helper.getSerializerArguments(type.parserArguments) as parserArgument>${parserArgument.name}<#sep>, </#sep></#list></#if>) |
| } |
| |
| func (m *${type.name}) SerializeParent(writeBuffer utils.WriteBuffer, child I${type.name}, serializeChildFunction func() error<#if helper.getSerializerArguments(type.parserArguments)?has_content>, <#list helper.getSerializerArguments(type.parserArguments) as parserArgument>${parserArgument.name} ${helper.getLanguageTypeNameForTypeReference(parserArgument.type)}<#sep>, </#sep></#list></#if>) error { |
| <#else> |
| func (m *${type.name}) Serialize(writeBuffer utils.WriteBuffer<#if helper.getSerializerArguments(type.parserArguments)?has_content>, <#list helper.getSerializerArguments(type.parserArguments) as parserArgument>${parserArgument.name} ${helper.getLanguageTypeNameForTypeReference(parserArgument.type)}<#sep>, </#sep></#list></#if>) error { |
| </#if> |
| <#if !helper.isDiscriminatedChildTypeDefinition()> |
| if pushErr :=writeBuffer.PushContext("${type.name}"); pushErr != nil { |
| return pushErr |
| } |
| </#if> |
| <#assign arraySizeInBytesHelpers=helper.requiresHelperFunctions("ARRAY_SIZE_IN_BYTES")> |
| <#if arraySizeInBytesHelpers?has_content> |
| <#list arraySizeInBytesHelpers?keys as key> |
| <#assign typeName=arraySizeInBytesHelpers[key]> |
| ${key}ArraySizeInBytes := func(items []*${typeName}) uint32 { |
| var sizeInBytes uint32 = 0 |
| for _, v := range items { |
| sizeInBytes += uint32(v.LengthInBytes()) |
| } |
| return sizeInBytes |
| } |
| </#list> |
| </#if> |
| <#if helper.isDiscriminatedChildTypeDefinition()> |
| ser := func() error { |
| if pushErr := writeBuffer.PushContext("${type.name}"); pushErr != nil { |
| return pushErr |
| } |
| </#if> |
| <#list type.fields as field> |
| <#switch field.typeName> |
| <#case "array"> |
| <#assign arrayField = field> |
| <#assign simpleTypeReference = arrayField.type> |
| |
| // Array Field (${arrayField.name}) |
| if m.${arrayField.name?cap_first} != nil { |
| <#if helper.isByteBased(arrayField.type)> |
| // Byte Array field (${arrayField.name}) |
| _writeArrayErr := writeBuffer.WriteByteArray("${arrayField.name}", m.${arrayField.name?cap_first}) |
| if _writeArrayErr != nil { |
| return errors.Wrap(_writeArrayErr, "Error serializing '${arrayField.name}' field")<@emitImport import="github.com/pkg/errors" /> |
| } |
| <#else> |
| if pushErr := writeBuffer.PushContext("${arrayField.name}", utils.WithRenderAsList(true)); pushErr != nil { |
| return pushErr |
| } |
| <#if helper.isComplexTypeReference(arrayField.type) && (helper.needsVariable(arrayField, "curItem", true) || helper.needsVariable(arrayField, "lastItem", true))> |
| itemCount := uint16(len(m.${arrayField.name?cap_first})) |
| var curItem uint16 = 0 |
| </#if> |
| for _, _element := range m.${arrayField.name?cap_first} { |
| <#if helper.isSimpleTypeReference(arrayField.type)> |
| <#assign simpleTypeReference = arrayField.type> |
| _elementErr := ${helper.getWriteBufferWriteMethodCall("", simpleTypeReference, "_element", field)} |
| <#else> |
| <#assign complexTypeReference = arrayField.type> |
| <#if helper.needsVariable(arrayField, "lastItem", true)> |
| var lastItem bool = curItem == (itemCount - 1) |
| </#if> |
| _elementErr := _element.Serialize(writeBuffer<#if helper.getSerializerTerms(field.params)?has_content>, <#list helper.getSerializerTerms(field.params) as parserArgument>${parserArgument.name}<#sep>, </#sep></#list></#if>) |
| </#if> |
| if _elementErr != nil { |
| return errors.Wrap(_elementErr, "Error serializing '${arrayField.name}' field")<@emitImport import="github.com/pkg/errors" /> |
| } |
| <#if helper.needsVariable(arrayField, "curItem", true) || helper.needsVariable(arrayField, "lastItem", true)> |
| curItem++ |
| </#if> |
| } |
| if popErr := writeBuffer.PopContext("${arrayField.name}", utils.WithRenderAsList(true)); popErr != nil { |
| return popErr |
| } |
| </#if> |
| } |
| <#break> |
| <#case "checksum"> |
| <#assign checksumField = field> |
| <#assign simpleTypeReference = checksumField.type> |
| |
| // Checksum Field (checksum) (Calculated) |
| { |
| _checksum, _checksumErr := ${helper.toSerializationExpression(checksumField, checksumField.checksumExpression, type.parserArguments)} |
| if _checksumErr != nil { |
| return errors.Wrap(_checksumErr, "Error serializing 'checksum' field")<@emitImport import="github.com/pkg/errors" /> |
| } |
| _checksumErr = ${helper.getWriteBufferWriteMethodCall("checksum", simpleTypeReference, "(_checksum)", field)} |
| if _checksumErr != nil { |
| return errors.Wrap(_checksumErr, "Error serializing 'checksum' field")<@emitImport import="github.com/pkg/errors" /> |
| } |
| } |
| <#break> |
| <#case "const"> |
| <#assign constField = field> |
| <#assign simpleTypeReference = constField.type> |
| |
| // Const Field (${constField.name}) |
| _${constField.name}Err := ${helper.getWriteBufferWriteMethodCall(constField.name, simpleTypeReference, constField.referenceValue, field)} |
| if _${constField.name}Err != nil { |
| return errors.Wrap(_${constField.name}Err, "Error serializing '${constField.name}' field")<@emitImport import="github.com/pkg/errors" /> |
| } |
| <#break> |
| <#case "discriminator"> |
| <#assign discriminatorField = field> |
| <#assign simpleTypeReference = discriminatorField.type> |
| |
| // Discriminator Field (${discriminatorField.name}) (Used as input to a switch field) |
| ${discriminatorField.name} := ${helper.getLanguageTypeNameForField(field)}(child.${discriminatorField.name?cap_first}()) |
| <#if helper.isEnumField(field)> |
| _${discriminatorField.name}Err := ${discriminatorField.name}.Serialize(writeBuffer) |
| <#else> |
| _${discriminatorField.name}Err := ${helper.getWriteBufferWriteMethodCall(discriminatorField.name, simpleTypeReference, "(" + discriminatorField.name + ")", field)} |
| </#if> |
| |
| if _${discriminatorField.name}Err != nil { |
| return errors.Wrap(_${discriminatorField.name}Err, "Error serializing '${discriminatorField.name}' field")<@emitImport import="github.com/pkg/errors" /> |
| } |
| <#break> |
| <#case "enum"> |
| <#assign enumField = field> |
| |
| if pushErr := writeBuffer.PushContext("${enumField.name}"); pushErr != nil { |
| return pushErr |
| } |
| <#if enumField.fieldName?has_content> |
| <#assign enumValueFieldAccessor="m."+enumField.name?cap_first+"."+enumField.fieldName?cap_first+"()"> |
| // Enum field (${enumField.name}) |
| _${enumField.name}Err := ${helper.getWriteBufferWriteMethodCall(enumField.type.name, helper.getEnumFieldSimpleTypeReference(enumField.type, enumField.fieldName), enumValueFieldAccessor, enumField, "utils.WithAdditionalStringRepresentation(m.${enumField.name?cap_first}.name())")} |
| if _${enumField.name}Err != nil { |
| return errors.Wrap(_${enumField.name}Err, "Error serializing '${enumField.name}' field")<@emitImport import="github.com/pkg/errors" /> |
| } |
| <#else> |
| // Enum field (${enumField.name}) |
| ${enumField.name} := Cast${helper.getLanguageTypeNameForField(field)}(m.${enumField.name?cap_first}) |
| _${enumField.name}Err := ${enumField.name}.Serialize(writeBuffer) |
| if _${enumField.name}Err != nil { |
| return errors.Wrap(_${enumField.name}Err, "Error serializing '${enumField.name}' field")<@emitImport import="github.com/pkg/errors" /> |
| } |
| </#if> |
| if popErr := writeBuffer.PopContext("${enumField.name}"); popErr != nil { |
| return popErr |
| } |
| <#break> |
| <#case "implicit"> |
| <#assign implicitField = field> |
| <#assign simpleTypeReference = implicitField.type> |
| |
| // Implicit Field (${implicitField.name}) (Used for parsing, but it's value is not stored as it's implicitly given by the objects content) |
| ${implicitField.name} := ${helper.getLanguageTypeNameForField(field)}(${helper.toSerializationExpression(implicitField, implicitField.serializeExpression, type.parserArguments)}) |
| _${implicitField.name}Err := ${helper.getWriteBufferWriteMethodCall(implicitField.name, simpleTypeReference, "(" + implicitField.name + ")", field)} |
| if _${implicitField.name}Err != nil { |
| return errors.Wrap(_${implicitField.name}Err, "Error serializing '${implicitField.name}' field")<@emitImport import="github.com/pkg/errors" /> |
| } |
| <#break> |
| <#case "manualArray"> |
| <#assign manualArrayField = field> |
| |
| // Manual Array Field (${manualArrayField.name}) |
| if m.${manualArrayField.name?cap_first} != nil { |
| if pushErr := writeBuffer.PushContext("${manualArrayField.name}", utils.WithRenderAsList(true)); pushErr != nil { |
| return pushErr |
| } |
| for _, Element := range m.${manualArrayField.name?cap_first} { |
| <#-- TODO at the moment the implementation below is broken as element get prefixed wrong therefore we substract it with substring--> |
| ${helper.toSerializationExpression(manualArrayField, manualArrayField.serializeExpression, type.parserArguments)?replace("m.","")} |
| } |
| if popErr := writeBuffer.PopContext("${manualArrayField.name}", utils.WithRenderAsList(true)); popErr != nil { |
| return popErr |
| } |
| } |
| <#break> |
| <#case "manual"> |
| <#assign manualField = field> |
| |
| // Manual Field (${manualField.name}) |
| ${helper.toSerializationExpression(manualField, manualField.serializeExpression, type.parserArguments)} |
| <#break> |
| <#case "optional"> |
| <#assign optionalField = field> |
| |
| // Optional Field (${optionalField.name}) (Can be skipped, if the value is null) |
| var ${optionalField.name} *${helper.getLanguageTypeNameForField(field)} = nil |
| if m.${optionalField.name?cap_first} != nil { |
| <#if helper.isSimpleTypeReference(optionalField.type)> |
| <#assign simpleTypeReference = optionalField.type> |
| ${optionalField.name} = m.${optionalField.name?cap_first} |
| _${optionalField.name}Err := ${helper.getWriteBufferWriteMethodCall(optionalField.name, simpleTypeReference, "*(" + optionalField.name + ")", field)} |
| <#else> |
| <#assign complexTypeReference = optionalField.type> |
| ${optionalField.name} = m.${optionalField.name?cap_first} |
| _${optionalField.name}Err := ${optionalField.name}.Serialize(writeBuffer) |
| </#if> |
| if _${optionalField.name}Err != nil { |
| return errors.Wrap(_${optionalField.name}Err, "Error serializing '${optionalField.name}' field")<@emitImport import="github.com/pkg/errors" /> |
| } |
| } |
| <#break> |
| <#case "padding"> |
| <#assign paddingField = field> |
| <#assign simpleTypeReference = paddingField.type> |
| |
| // Padding Field (padding) |
| { |
| if pushErr := writeBuffer.PushContext("padding", utils.WithRenderAsList(true)); pushErr != nil { |
| return pushErr |
| } |
| _timesPadding := uint8(${helper.toSerializationExpression(paddingField, paddingField.paddingCondition, type.parserArguments)}) |
| for ;_timesPadding > 0; _timesPadding-- { |
| _paddingValue := ${helper.getLanguageTypeNameForField(field)}(${helper.toSerializationExpression(paddingField, paddingField.paddingValue, type.parserArguments)}) |
| _paddingErr := ${helper.getWriteBufferWriteMethodCall("", simpleTypeReference, "(_paddingValue)", field)} |
| if _paddingErr != nil { |
| return errors.Wrap(_paddingErr, "Error serializing 'padding' field")<@emitImport import="github.com/pkg/errors" /> |
| } |
| } |
| if popErr := writeBuffer.PopContext("padding", utils.WithRenderAsList(true)); popErr != nil { |
| return popErr |
| } |
| } |
| <#break> |
| <#case "reserved"> |
| <#assign reservedField = field> |
| <#assign simpleTypeReference = reservedField.type> |
| |
| // Reserved Field (reserved) |
| { |
| _err := ${helper.getWriteBufferWriteMethodCall("reserved", simpleTypeReference, helper.getReservedValue(field), field)} |
| if _err != nil { |
| return errors.Wrap(_err, "Error serializing 'reserved' field")<@emitImport import="github.com/pkg/errors" /> |
| } |
| } |
| <#break> |
| <#case "simple"> |
| <#assign simpleField = field> |
| |
| // Simple Field (${simpleField.name}) |
| <#if helper.isSimpleTypeReference(simpleField.type)> |
| <#assign simpleTypeReference = simpleField.type> |
| <#assign simpleFieldLogicalName><#if helper.isSimpleTypeReference(simpleField.type) && !helper.isEnumField(field)>${simpleField.name}<#else>${simpleField.typeName}</#if></#assign> |
| ${simpleField.name} := ${helper.getLanguageTypeNameForField(field)}(m.${simpleField.name?cap_first}) |
| <#if helper.isEnumField(field)> |
| _${simpleField.name}Err := ${helper.getWriteBufferWriteMethodCall(simpleFieldLogicalName, simpleTypeReference, "(" + simpleField.name + ")", simpleField, "utils.WithAdditionalStringRepresentation(m.${simpleField.name?cap_first}.name())")} |
| <#else> |
| _${simpleField.name}Err := ${helper.getWriteBufferWriteMethodCall(simpleFieldLogicalName, simpleTypeReference, "(" + simpleField.name + ")", simpleField)} |
| </#if> |
| <#else> |
| <#assign complexTypeReference = simpleField.type> |
| if pushErr := writeBuffer.PushContext("${simpleField.name}"); pushErr != nil { |
| return pushErr |
| } |
| _${simpleField.name}Err := m.${simpleField.name?cap_first}.Serialize(writeBuffer) |
| if popErr := writeBuffer.PopContext("${simpleField.name}"); popErr != nil { |
| return popErr |
| } |
| </#if> |
| if _${simpleField.name}Err != nil { |
| return errors.Wrap(_${simpleField.name}Err, "Error serializing '${simpleField.name}' field")<@emitImport import="github.com/pkg/errors" /> |
| } |
| <#break> |
| <#case "switch"> |
| <#assign switchField = field> |
| |
| // Switch field (Depending on the discriminator values, passes the serialization to a sub-type) |
| _typeSwitchErr := serializeChildFunction() |
| if _typeSwitchErr != nil { |
| return errors.Wrap(_typeSwitchErr, "Error serializing sub-type field")<@emitImport import="github.com/pkg/errors" /> |
| } |
| <#break> |
| <#case "virtual"> |
| <#break> |
| </#switch> |
| </#list> |
| |
| <#if helper.isDiscriminatedChildTypeDefinition()> |
| if popErr := writeBuffer.PopContext("${type.name}"); popErr != nil { |
| return popErr |
| } |
| return nil |
| } |
| return m.Parent.SerializeParent(writeBuffer, m, ser) |
| <#else> |
| if popErr := writeBuffer.PopContext("${type.name}"); popErr != nil { |
| return popErr |
| } |
| return nil |
| </#if> |
| } |
| |
| <#if !helper.getSerializerArguments(type.parserArguments)?has_content><#-- We only generate String() methods for serializer witout arguments --> |
| func (m *${type.name}) String() string { |
| if m == nil { |
| return "<nil>" |
| } |
| buffer := utils.NewBoxedWriteBufferWithOptions(true, true) |
| m.Serialize(buffer) |
| return buffer.GetBox().String() |
| } |
| </#if> |
| |
| </@importSectionWithContentBelow> |
| |
| </#outputformat> |