blob: 8420ea76d8690bd8e557e859e7630519af64fd57 [file] [log] [blame]
<#--
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>