/*
 * 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
 *
 *   https://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

import (
	"context"
	"encoding/binary"
	stdErrors "errors"
	"fmt"

	"github.com/pkg/errors"
	"github.com/rs/zerolog"

	"github.com/apache/plc4x/plc4go/spi/codegen"
	. "github.com/apache/plc4x/plc4go/spi/codegen/fields"
	. "github.com/apache/plc4x/plc4go/spi/codegen/io"
	"github.com/apache/plc4x/plc4go/spi/utils"
)

// Code generated by code-generation. DO NOT EDIT.

// Constant values.
const AdsDataTypeTableEntry_DATATYPENAMETERMINATOR uint8 = 0x00
const AdsDataTypeTableEntry_SIMPLETYPENAMETERMINATOR uint8 = 0x00
const AdsDataTypeTableEntry_COMMENTTERMINATOR uint8 = 0x00

// AdsDataTypeTableEntry is the corresponding interface of AdsDataTypeTableEntry
// https://gitlab.com/xilix-systems-llc/go-native-ads/-/blob/master/symbols.go#L15
type AdsDataTypeTableEntry interface {
	fmt.Stringer
	utils.LengthAware
	utils.Serializable
	utils.Copyable
	// GetEntryLength returns EntryLength (property field)
	GetEntryLength() uint32
	// GetVersion returns Version (property field)
	GetVersion() uint32
	// GetHashValue returns HashValue (property field)
	GetHashValue() uint32
	// GetTypeHashValue returns TypeHashValue (property field)
	GetTypeHashValue() uint32
	// GetSize returns Size (property field)
	GetSize() uint32
	// GetOffset returns Offset (property field)
	GetOffset() uint32
	// GetDataType returns DataType (property field)
	GetDataType() uint32
	// GetFlags returns Flags (property field)
	GetFlags() uint32
	// GetArrayDimensions returns ArrayDimensions (property field)
	GetArrayDimensions() uint16
	// GetNumChildren returns NumChildren (property field)
	GetNumChildren() uint16
	// GetDataTypeName returns DataTypeName (property field)
	GetDataTypeName() string
	// GetSimpleTypeName returns SimpleTypeName (property field)
	GetSimpleTypeName() string
	// GetComment returns Comment (property field)
	GetComment() string
	// GetArrayInfo returns ArrayInfo (property field)
	GetArrayInfo() []AdsDataTypeArrayInfo
	// GetChildren returns Children (property field)
	GetChildren() []AdsDataTypeTableChildEntry
	// GetRest returns Rest (property field)
	// Gobbling up the rest, but it seems there is content in here, when looking
	// at the data in wireshark, it seems to be related to the flags field.
	// Will have to continue searching for more details on how to decode this.
	// I would assume that we'll have some "optional" fields here which depend
	// on values in the flags section.
	GetRest() []byte
	// IsAdsDataTypeTableEntry is a marker method to prevent unintentional type checks (interfaces of same signature)
	IsAdsDataTypeTableEntry()
	// CreateBuilder creates a AdsDataTypeTableEntryBuilder
	CreateAdsDataTypeTableEntryBuilder() AdsDataTypeTableEntryBuilder
}

// _AdsDataTypeTableEntry is the data-structure of this message
type _AdsDataTypeTableEntry struct {
	EntryLength     uint32
	Version         uint32
	HashValue       uint32
	TypeHashValue   uint32
	Size            uint32
	Offset          uint32
	DataType        uint32
	Flags           uint32
	ArrayDimensions uint16
	NumChildren     uint16
	DataTypeName    string
	SimpleTypeName  string
	Comment         string
	ArrayInfo       []AdsDataTypeArrayInfo
	Children        []AdsDataTypeTableChildEntry
	Rest            []byte
}

var _ AdsDataTypeTableEntry = (*_AdsDataTypeTableEntry)(nil)

// NewAdsDataTypeTableEntry factory function for _AdsDataTypeTableEntry
func NewAdsDataTypeTableEntry(entryLength uint32, version uint32, hashValue uint32, typeHashValue uint32, size uint32, offset uint32, dataType uint32, flags uint32, arrayDimensions uint16, numChildren uint16, dataTypeName string, simpleTypeName string, comment string, arrayInfo []AdsDataTypeArrayInfo, children []AdsDataTypeTableChildEntry, rest []byte) *_AdsDataTypeTableEntry {
	return &_AdsDataTypeTableEntry{EntryLength: entryLength, Version: version, HashValue: hashValue, TypeHashValue: typeHashValue, Size: size, Offset: offset, DataType: dataType, Flags: flags, ArrayDimensions: arrayDimensions, NumChildren: numChildren, DataTypeName: dataTypeName, SimpleTypeName: simpleTypeName, Comment: comment, ArrayInfo: arrayInfo, Children: children, Rest: rest}
}

///////////////////////////////////////////////////////////
///////////////////////////////////////////////////////////
/////////////////////// Builder
///////////////////////

// AdsDataTypeTableEntryBuilder is a builder for AdsDataTypeTableEntry
type AdsDataTypeTableEntryBuilder interface {
	utils.Copyable
	// WithMandatoryFields adds all mandatory fields (convenience for using multiple builder calls)
	WithMandatoryFields(entryLength uint32, version uint32, hashValue uint32, typeHashValue uint32, size uint32, offset uint32, dataType uint32, flags uint32, arrayDimensions uint16, numChildren uint16, dataTypeName string, simpleTypeName string, comment string, arrayInfo []AdsDataTypeArrayInfo, children []AdsDataTypeTableChildEntry, rest []byte) AdsDataTypeTableEntryBuilder
	// WithEntryLength adds EntryLength (property field)
	WithEntryLength(uint32) AdsDataTypeTableEntryBuilder
	// WithVersion adds Version (property field)
	WithVersion(uint32) AdsDataTypeTableEntryBuilder
	// WithHashValue adds HashValue (property field)
	WithHashValue(uint32) AdsDataTypeTableEntryBuilder
	// WithTypeHashValue adds TypeHashValue (property field)
	WithTypeHashValue(uint32) AdsDataTypeTableEntryBuilder
	// WithSize adds Size (property field)
	WithSize(uint32) AdsDataTypeTableEntryBuilder
	// WithOffset adds Offset (property field)
	WithOffset(uint32) AdsDataTypeTableEntryBuilder
	// WithDataType adds DataType (property field)
	WithDataType(uint32) AdsDataTypeTableEntryBuilder
	// WithFlags adds Flags (property field)
	WithFlags(uint32) AdsDataTypeTableEntryBuilder
	// WithArrayDimensions adds ArrayDimensions (property field)
	WithArrayDimensions(uint16) AdsDataTypeTableEntryBuilder
	// WithNumChildren adds NumChildren (property field)
	WithNumChildren(uint16) AdsDataTypeTableEntryBuilder
	// WithDataTypeName adds DataTypeName (property field)
	WithDataTypeName(string) AdsDataTypeTableEntryBuilder
	// WithSimpleTypeName adds SimpleTypeName (property field)
	WithSimpleTypeName(string) AdsDataTypeTableEntryBuilder
	// WithComment adds Comment (property field)
	WithComment(string) AdsDataTypeTableEntryBuilder
	// WithArrayInfo adds ArrayInfo (property field)
	WithArrayInfo(...AdsDataTypeArrayInfo) AdsDataTypeTableEntryBuilder
	// WithChildren adds Children (property field)
	WithChildren(...AdsDataTypeTableChildEntry) AdsDataTypeTableEntryBuilder
	// WithRest adds Rest (property field)
	WithRest(...byte) AdsDataTypeTableEntryBuilder
	// Build builds the AdsDataTypeTableEntry or returns an error if something is wrong
	Build() (AdsDataTypeTableEntry, error)
	// MustBuild does the same as Build but panics on error
	MustBuild() AdsDataTypeTableEntry
}

// NewAdsDataTypeTableEntryBuilder() creates a AdsDataTypeTableEntryBuilder
func NewAdsDataTypeTableEntryBuilder() AdsDataTypeTableEntryBuilder {
	return &_AdsDataTypeTableEntryBuilder{_AdsDataTypeTableEntry: new(_AdsDataTypeTableEntry)}
}

type _AdsDataTypeTableEntryBuilder struct {
	*_AdsDataTypeTableEntry

	collectedErr []error
}

var _ (AdsDataTypeTableEntryBuilder) = (*_AdsDataTypeTableEntryBuilder)(nil)

func (b *_AdsDataTypeTableEntryBuilder) WithMandatoryFields(entryLength uint32, version uint32, hashValue uint32, typeHashValue uint32, size uint32, offset uint32, dataType uint32, flags uint32, arrayDimensions uint16, numChildren uint16, dataTypeName string, simpleTypeName string, comment string, arrayInfo []AdsDataTypeArrayInfo, children []AdsDataTypeTableChildEntry, rest []byte) AdsDataTypeTableEntryBuilder {
	return b.WithEntryLength(entryLength).WithVersion(version).WithHashValue(hashValue).WithTypeHashValue(typeHashValue).WithSize(size).WithOffset(offset).WithDataType(dataType).WithFlags(flags).WithArrayDimensions(arrayDimensions).WithNumChildren(numChildren).WithDataTypeName(dataTypeName).WithSimpleTypeName(simpleTypeName).WithComment(comment).WithArrayInfo(arrayInfo...).WithChildren(children...).WithRest(rest...)
}

func (b *_AdsDataTypeTableEntryBuilder) WithEntryLength(entryLength uint32) AdsDataTypeTableEntryBuilder {
	b.EntryLength = entryLength
	return b
}

func (b *_AdsDataTypeTableEntryBuilder) WithVersion(version uint32) AdsDataTypeTableEntryBuilder {
	b.Version = version
	return b
}

func (b *_AdsDataTypeTableEntryBuilder) WithHashValue(hashValue uint32) AdsDataTypeTableEntryBuilder {
	b.HashValue = hashValue
	return b
}

func (b *_AdsDataTypeTableEntryBuilder) WithTypeHashValue(typeHashValue uint32) AdsDataTypeTableEntryBuilder {
	b.TypeHashValue = typeHashValue
	return b
}

func (b *_AdsDataTypeTableEntryBuilder) WithSize(size uint32) AdsDataTypeTableEntryBuilder {
	b.Size = size
	return b
}

func (b *_AdsDataTypeTableEntryBuilder) WithOffset(offset uint32) AdsDataTypeTableEntryBuilder {
	b.Offset = offset
	return b
}

func (b *_AdsDataTypeTableEntryBuilder) WithDataType(dataType uint32) AdsDataTypeTableEntryBuilder {
	b.DataType = dataType
	return b
}

func (b *_AdsDataTypeTableEntryBuilder) WithFlags(flags uint32) AdsDataTypeTableEntryBuilder {
	b.Flags = flags
	return b
}

func (b *_AdsDataTypeTableEntryBuilder) WithArrayDimensions(arrayDimensions uint16) AdsDataTypeTableEntryBuilder {
	b.ArrayDimensions = arrayDimensions
	return b
}

func (b *_AdsDataTypeTableEntryBuilder) WithNumChildren(numChildren uint16) AdsDataTypeTableEntryBuilder {
	b.NumChildren = numChildren
	return b
}

func (b *_AdsDataTypeTableEntryBuilder) WithDataTypeName(dataTypeName string) AdsDataTypeTableEntryBuilder {
	b.DataTypeName = dataTypeName
	return b
}

func (b *_AdsDataTypeTableEntryBuilder) WithSimpleTypeName(simpleTypeName string) AdsDataTypeTableEntryBuilder {
	b.SimpleTypeName = simpleTypeName
	return b
}

func (b *_AdsDataTypeTableEntryBuilder) WithComment(comment string) AdsDataTypeTableEntryBuilder {
	b.Comment = comment
	return b
}

func (b *_AdsDataTypeTableEntryBuilder) WithArrayInfo(arrayInfo ...AdsDataTypeArrayInfo) AdsDataTypeTableEntryBuilder {
	b.ArrayInfo = arrayInfo
	return b
}

func (b *_AdsDataTypeTableEntryBuilder) WithChildren(children ...AdsDataTypeTableChildEntry) AdsDataTypeTableEntryBuilder {
	b.Children = children
	return b
}

func (b *_AdsDataTypeTableEntryBuilder) WithRest(rest ...byte) AdsDataTypeTableEntryBuilder {
	b.Rest = rest
	return b
}

func (b *_AdsDataTypeTableEntryBuilder) Build() (AdsDataTypeTableEntry, error) {
	if err := stdErrors.Join(b.collectedErr...); err != nil {
		return nil, errors.Wrap(err, "error occurred during build")
	}
	return b._AdsDataTypeTableEntry.deepCopy(), nil
}

func (b *_AdsDataTypeTableEntryBuilder) MustBuild() AdsDataTypeTableEntry {
	build, err := b.Build()
	if err != nil {
		panic(err)
	}
	return build
}

func (b *_AdsDataTypeTableEntryBuilder) DeepCopy() any {
	_copy := b.CreateAdsDataTypeTableEntryBuilder().(*_AdsDataTypeTableEntryBuilder)
	if b.collectedErr != nil {
		copy(_copy.collectedErr, b.collectedErr)
	}
	return _copy
}

// CreateAdsDataTypeTableEntryBuilder creates a AdsDataTypeTableEntryBuilder
func (b *_AdsDataTypeTableEntry) CreateAdsDataTypeTableEntryBuilder() AdsDataTypeTableEntryBuilder {
	if b == nil {
		return NewAdsDataTypeTableEntryBuilder()
	}
	return &_AdsDataTypeTableEntryBuilder{_AdsDataTypeTableEntry: b.deepCopy()}
}

///////////////////////
///////////////////////
///////////////////////////////////////////////////////////
///////////////////////////////////////////////////////////

///////////////////////////////////////////////////////////
///////////////////////////////////////////////////////////
/////////////////////// Accessors for property fields.
///////////////////////

func (m *_AdsDataTypeTableEntry) GetEntryLength() uint32 {
	return m.EntryLength
}

func (m *_AdsDataTypeTableEntry) GetVersion() uint32 {
	return m.Version
}

func (m *_AdsDataTypeTableEntry) GetHashValue() uint32 {
	return m.HashValue
}

func (m *_AdsDataTypeTableEntry) GetTypeHashValue() uint32 {
	return m.TypeHashValue
}

func (m *_AdsDataTypeTableEntry) GetSize() uint32 {
	return m.Size
}

func (m *_AdsDataTypeTableEntry) GetOffset() uint32 {
	return m.Offset
}

func (m *_AdsDataTypeTableEntry) GetDataType() uint32 {
	return m.DataType
}

func (m *_AdsDataTypeTableEntry) GetFlags() uint32 {
	return m.Flags
}

func (m *_AdsDataTypeTableEntry) GetArrayDimensions() uint16 {
	return m.ArrayDimensions
}

func (m *_AdsDataTypeTableEntry) GetNumChildren() uint16 {
	return m.NumChildren
}

func (m *_AdsDataTypeTableEntry) GetDataTypeName() string {
	return m.DataTypeName
}

func (m *_AdsDataTypeTableEntry) GetSimpleTypeName() string {
	return m.SimpleTypeName
}

func (m *_AdsDataTypeTableEntry) GetComment() string {
	return m.Comment
}

func (m *_AdsDataTypeTableEntry) GetArrayInfo() []AdsDataTypeArrayInfo {
	return m.ArrayInfo
}

func (m *_AdsDataTypeTableEntry) GetChildren() []AdsDataTypeTableChildEntry {
	return m.Children
}

func (m *_AdsDataTypeTableEntry) GetRest() []byte {
	return m.Rest
}

///////////////////////
///////////////////////
///////////////////////////////////////////////////////////
///////////////////////////////////////////////////////////
///////////////////////////////////////////////////////////
///////////////////////////////////////////////////////////
/////////////////////// Accessors for const fields.
///////////////////////

func (m *_AdsDataTypeTableEntry) GetDataTypeNameTerminator() uint8 {
	return AdsDataTypeTableEntry_DATATYPENAMETERMINATOR
}

func (m *_AdsDataTypeTableEntry) GetSimpleTypeNameTerminator() uint8 {
	return AdsDataTypeTableEntry_SIMPLETYPENAMETERMINATOR
}

func (m *_AdsDataTypeTableEntry) GetCommentTerminator() uint8 {
	return AdsDataTypeTableEntry_COMMENTTERMINATOR
}

///////////////////////
///////////////////////
///////////////////////////////////////////////////////////
///////////////////////////////////////////////////////////

// Deprecated: use the interface for direct cast
func CastAdsDataTypeTableEntry(structType any) AdsDataTypeTableEntry {
	if casted, ok := structType.(AdsDataTypeTableEntry); ok {
		return casted
	}
	if casted, ok := structType.(*AdsDataTypeTableEntry); ok {
		return *casted
	}
	return nil
}

func (m *_AdsDataTypeTableEntry) GetTypeName() string {
	return "AdsDataTypeTableEntry"
}

func (m *_AdsDataTypeTableEntry) GetLengthInBits(ctx context.Context) uint16 {
	lengthInBits := uint16(0)

	// Simple field (entryLength)
	lengthInBits += 32

	// Simple field (version)
	lengthInBits += 32

	// Simple field (hashValue)
	lengthInBits += 32

	// Simple field (typeHashValue)
	lengthInBits += 32

	// Simple field (size)
	lengthInBits += 32

	// Simple field (offset)
	lengthInBits += 32

	// Simple field (dataType)
	lengthInBits += 32

	// Simple field (flags)
	lengthInBits += 32

	// Implicit Field (dataTypeNameLength)
	lengthInBits += 16

	// Implicit Field (simpleTypeNameLength)
	lengthInBits += 16

	// Implicit Field (commentLength)
	lengthInBits += 16

	// Simple field (arrayDimensions)
	lengthInBits += 16

	// Simple field (numChildren)
	lengthInBits += 16

	// Simple field (dataTypeName)
	lengthInBits += uint16(int32(uint16(len(m.GetDataTypeName()))) * int32(int32(8)))

	// Const Field (dataTypeNameTerminator)
	lengthInBits += 8

	// Simple field (simpleTypeName)
	lengthInBits += uint16(int32(uint16(len(m.GetSimpleTypeName()))) * int32(int32(8)))

	// Const Field (simpleTypeNameTerminator)
	lengthInBits += 8

	// Simple field (comment)
	lengthInBits += uint16(int32(uint16(len(m.GetComment()))) * int32(int32(8)))

	// Const Field (commentTerminator)
	lengthInBits += 8

	// Array field
	if len(m.ArrayInfo) > 0 {
		for _curItem, element := range m.ArrayInfo {
			arrayCtx := utils.CreateArrayContext(ctx, len(m.ArrayInfo), _curItem)
			lengthInBits += element.GetLengthInBits(arrayCtx)
		}
	}

	// Array field
	if len(m.Children) > 0 {
		for _curItem, element := range m.Children {
			arrayCtx := utils.CreateArrayContext(ctx, len(m.Children), _curItem)
			lengthInBits += element.GetLengthInBits(arrayCtx)
		}
	}

	// Array field
	if len(m.Rest) > 0 {
		lengthInBits += 8 * uint16(len(m.Rest))
	}

	return lengthInBits
}

func (m *_AdsDataTypeTableEntry) GetLengthInBytes(ctx context.Context) uint16 {
	return m.GetLengthInBits(ctx) / 8
}

func AdsDataTypeTableEntryParse(ctx context.Context, theBytes []byte) (AdsDataTypeTableEntry, error) {
	return AdsDataTypeTableEntryParseWithBuffer(ctx, utils.NewReadBufferByteBased(theBytes, utils.WithByteOrderForReadBufferByteBased(binary.LittleEndian)))
}

func AdsDataTypeTableEntryParseWithBufferProducer() func(ctx context.Context, readBuffer utils.ReadBuffer) (AdsDataTypeTableEntry, error) {
	return func(ctx context.Context, readBuffer utils.ReadBuffer) (AdsDataTypeTableEntry, error) {
		return AdsDataTypeTableEntryParseWithBuffer(ctx, readBuffer)
	}
}

func AdsDataTypeTableEntryParseWithBuffer(ctx context.Context, readBuffer utils.ReadBuffer) (AdsDataTypeTableEntry, error) {
	v, err := (new(_AdsDataTypeTableEntry)).parse(ctx, readBuffer)
	if err != nil {
		return nil, err
	}
	return v, nil
}

func (m *_AdsDataTypeTableEntry) parse(ctx context.Context, readBuffer utils.ReadBuffer) (__adsDataTypeTableEntry AdsDataTypeTableEntry, err error) {
	positionAware := readBuffer
	_ = positionAware
	if pullErr := readBuffer.PullContext("AdsDataTypeTableEntry"); pullErr != nil {
		return nil, errors.Wrap(pullErr, "Error pulling for AdsDataTypeTableEntry")
	}
	currentPos := positionAware.GetPos()
	_ = currentPos
	var startPos = positionAware.GetPos()
	_ = startPos

	entryLength, err := ReadSimpleField(ctx, "entryLength", ReadUnsignedInt(readBuffer, uint8(32)), codegen.WithByteOrder(binary.LittleEndian))
	if err != nil {
		return nil, errors.Wrap(err, fmt.Sprintf("Error parsing 'entryLength' field"))
	}
	m.EntryLength = entryLength

	version, err := ReadSimpleField(ctx, "version", ReadUnsignedInt(readBuffer, uint8(32)), codegen.WithByteOrder(binary.LittleEndian))
	if err != nil {
		return nil, errors.Wrap(err, fmt.Sprintf("Error parsing 'version' field"))
	}
	m.Version = version

	hashValue, err := ReadSimpleField(ctx, "hashValue", ReadUnsignedInt(readBuffer, uint8(32)), codegen.WithByteOrder(binary.LittleEndian))
	if err != nil {
		return nil, errors.Wrap(err, fmt.Sprintf("Error parsing 'hashValue' field"))
	}
	m.HashValue = hashValue

	typeHashValue, err := ReadSimpleField(ctx, "typeHashValue", ReadUnsignedInt(readBuffer, uint8(32)), codegen.WithByteOrder(binary.LittleEndian))
	if err != nil {
		return nil, errors.Wrap(err, fmt.Sprintf("Error parsing 'typeHashValue' field"))
	}
	m.TypeHashValue = typeHashValue

	size, err := ReadSimpleField(ctx, "size", ReadUnsignedInt(readBuffer, uint8(32)), codegen.WithByteOrder(binary.LittleEndian))
	if err != nil {
		return nil, errors.Wrap(err, fmt.Sprintf("Error parsing 'size' field"))
	}
	m.Size = size

	offset, err := ReadSimpleField(ctx, "offset", ReadUnsignedInt(readBuffer, uint8(32)), codegen.WithByteOrder(binary.LittleEndian))
	if err != nil {
		return nil, errors.Wrap(err, fmt.Sprintf("Error parsing 'offset' field"))
	}
	m.Offset = offset

	dataType, err := ReadSimpleField(ctx, "dataType", ReadUnsignedInt(readBuffer, uint8(32)), codegen.WithByteOrder(binary.LittleEndian))
	if err != nil {
		return nil, errors.Wrap(err, fmt.Sprintf("Error parsing 'dataType' field"))
	}
	m.DataType = dataType

	flags, err := ReadSimpleField(ctx, "flags", ReadUnsignedInt(readBuffer, uint8(32)), codegen.WithByteOrder(binary.LittleEndian))
	if err != nil {
		return nil, errors.Wrap(err, fmt.Sprintf("Error parsing 'flags' field"))
	}
	m.Flags = flags

	dataTypeNameLength, err := ReadImplicitField[uint16](ctx, "dataTypeNameLength", ReadUnsignedShort(readBuffer, uint8(16)), codegen.WithByteOrder(binary.LittleEndian))
	if err != nil {
		return nil, errors.Wrap(err, fmt.Sprintf("Error parsing 'dataTypeNameLength' field"))
	}
	_ = dataTypeNameLength

	simpleTypeNameLength, err := ReadImplicitField[uint16](ctx, "simpleTypeNameLength", ReadUnsignedShort(readBuffer, uint8(16)), codegen.WithByteOrder(binary.LittleEndian))
	if err != nil {
		return nil, errors.Wrap(err, fmt.Sprintf("Error parsing 'simpleTypeNameLength' field"))
	}
	_ = simpleTypeNameLength

	commentLength, err := ReadImplicitField[uint16](ctx, "commentLength", ReadUnsignedShort(readBuffer, uint8(16)), codegen.WithByteOrder(binary.LittleEndian))
	if err != nil {
		return nil, errors.Wrap(err, fmt.Sprintf("Error parsing 'commentLength' field"))
	}
	_ = commentLength

	arrayDimensions, err := ReadSimpleField(ctx, "arrayDimensions", ReadUnsignedShort(readBuffer, uint8(16)), codegen.WithByteOrder(binary.LittleEndian))
	if err != nil {
		return nil, errors.Wrap(err, fmt.Sprintf("Error parsing 'arrayDimensions' field"))
	}
	m.ArrayDimensions = arrayDimensions

	numChildren, err := ReadSimpleField(ctx, "numChildren", ReadUnsignedShort(readBuffer, uint8(16)), codegen.WithByteOrder(binary.LittleEndian))
	if err != nil {
		return nil, errors.Wrap(err, fmt.Sprintf("Error parsing 'numChildren' field"))
	}
	m.NumChildren = numChildren

	dataTypeName, err := ReadSimpleField(ctx, "dataTypeName", ReadString(readBuffer, uint32(int32(dataTypeNameLength)*int32(int32(8)))), codegen.WithByteOrder(binary.LittleEndian))
	if err != nil {
		return nil, errors.Wrap(err, fmt.Sprintf("Error parsing 'dataTypeName' field"))
	}
	m.DataTypeName = dataTypeName

	dataTypeNameTerminator, err := ReadConstField[uint8](ctx, "dataTypeNameTerminator", ReadUnsignedByte(readBuffer, uint8(8)), AdsDataTypeTableEntry_DATATYPENAMETERMINATOR, codegen.WithByteOrder(binary.LittleEndian))
	if err != nil {
		return nil, errors.Wrap(err, fmt.Sprintf("Error parsing 'dataTypeNameTerminator' field"))
	}
	_ = dataTypeNameTerminator

	simpleTypeName, err := ReadSimpleField(ctx, "simpleTypeName", ReadString(readBuffer, uint32(int32(simpleTypeNameLength)*int32(int32(8)))), codegen.WithByteOrder(binary.LittleEndian))
	if err != nil {
		return nil, errors.Wrap(err, fmt.Sprintf("Error parsing 'simpleTypeName' field"))
	}
	m.SimpleTypeName = simpleTypeName

	simpleTypeNameTerminator, err := ReadConstField[uint8](ctx, "simpleTypeNameTerminator", ReadUnsignedByte(readBuffer, uint8(8)), AdsDataTypeTableEntry_SIMPLETYPENAMETERMINATOR, codegen.WithByteOrder(binary.LittleEndian))
	if err != nil {
		return nil, errors.Wrap(err, fmt.Sprintf("Error parsing 'simpleTypeNameTerminator' field"))
	}
	_ = simpleTypeNameTerminator

	comment, err := ReadSimpleField(ctx, "comment", ReadString(readBuffer, uint32(int32(commentLength)*int32(int32(8)))), codegen.WithByteOrder(binary.LittleEndian))
	if err != nil {
		return nil, errors.Wrap(err, fmt.Sprintf("Error parsing 'comment' field"))
	}
	m.Comment = comment

	commentTerminator, err := ReadConstField[uint8](ctx, "commentTerminator", ReadUnsignedByte(readBuffer, uint8(8)), AdsDataTypeTableEntry_COMMENTTERMINATOR, codegen.WithByteOrder(binary.LittleEndian))
	if err != nil {
		return nil, errors.Wrap(err, fmt.Sprintf("Error parsing 'commentTerminator' field"))
	}
	_ = commentTerminator

	arrayInfo, err := ReadCountArrayField[AdsDataTypeArrayInfo](ctx, "arrayInfo", ReadComplex[AdsDataTypeArrayInfo](AdsDataTypeArrayInfoParseWithBuffer, readBuffer), uint64(arrayDimensions), codegen.WithByteOrder(binary.LittleEndian))
	if err != nil {
		return nil, errors.Wrap(err, fmt.Sprintf("Error parsing 'arrayInfo' field"))
	}
	m.ArrayInfo = arrayInfo

	children, err := ReadCountArrayField[AdsDataTypeTableChildEntry](ctx, "children", ReadComplex[AdsDataTypeTableChildEntry](AdsDataTypeTableChildEntryParseWithBuffer, readBuffer), uint64(numChildren), codegen.WithByteOrder(binary.LittleEndian))
	if err != nil {
		return nil, errors.Wrap(err, fmt.Sprintf("Error parsing 'children' field"))
	}
	m.Children = children

	rest, err := readBuffer.ReadByteArray("rest", int(int32(entryLength)-int32((positionAware.GetPos()-startPos))), codegen.WithByteOrder(binary.LittleEndian))
	if err != nil {
		return nil, errors.Wrap(err, fmt.Sprintf("Error parsing 'rest' field"))
	}
	m.Rest = rest

	if closeErr := readBuffer.CloseContext("AdsDataTypeTableEntry"); closeErr != nil {
		return nil, errors.Wrap(closeErr, "Error closing for AdsDataTypeTableEntry")
	}

	return m, nil
}

func (m *_AdsDataTypeTableEntry) Serialize() ([]byte, error) {
	wb := utils.NewWriteBufferByteBased(utils.WithInitialSizeForByteBasedBuffer(int(m.GetLengthInBytes(context.Background()))), utils.WithByteOrderForByteBasedBuffer(binary.LittleEndian))
	if err := m.SerializeWithWriteBuffer(context.Background(), wb); err != nil {
		return nil, err
	}
	return wb.GetBytes(), nil
}

func (m *_AdsDataTypeTableEntry) SerializeWithWriteBuffer(ctx context.Context, writeBuffer utils.WriteBuffer) error {
	positionAware := writeBuffer
	_ = positionAware
	log := zerolog.Ctx(ctx)
	_ = log
	if pushErr := writeBuffer.PushContext("AdsDataTypeTableEntry"); pushErr != nil {
		return errors.Wrap(pushErr, "Error pushing for AdsDataTypeTableEntry")
	}

	if err := WriteSimpleField[uint32](ctx, "entryLength", m.GetEntryLength(), WriteUnsignedInt(writeBuffer, 32), codegen.WithByteOrder(binary.LittleEndian)); err != nil {
		return errors.Wrap(err, "Error serializing 'entryLength' field")
	}

	if err := WriteSimpleField[uint32](ctx, "version", m.GetVersion(), WriteUnsignedInt(writeBuffer, 32), codegen.WithByteOrder(binary.LittleEndian)); err != nil {
		return errors.Wrap(err, "Error serializing 'version' field")
	}

	if err := WriteSimpleField[uint32](ctx, "hashValue", m.GetHashValue(), WriteUnsignedInt(writeBuffer, 32), codegen.WithByteOrder(binary.LittleEndian)); err != nil {
		return errors.Wrap(err, "Error serializing 'hashValue' field")
	}

	if err := WriteSimpleField[uint32](ctx, "typeHashValue", m.GetTypeHashValue(), WriteUnsignedInt(writeBuffer, 32), codegen.WithByteOrder(binary.LittleEndian)); err != nil {
		return errors.Wrap(err, "Error serializing 'typeHashValue' field")
	}

	if err := WriteSimpleField[uint32](ctx, "size", m.GetSize(), WriteUnsignedInt(writeBuffer, 32), codegen.WithByteOrder(binary.LittleEndian)); err != nil {
		return errors.Wrap(err, "Error serializing 'size' field")
	}

	if err := WriteSimpleField[uint32](ctx, "offset", m.GetOffset(), WriteUnsignedInt(writeBuffer, 32), codegen.WithByteOrder(binary.LittleEndian)); err != nil {
		return errors.Wrap(err, "Error serializing 'offset' field")
	}

	if err := WriteSimpleField[uint32](ctx, "dataType", m.GetDataType(), WriteUnsignedInt(writeBuffer, 32), codegen.WithByteOrder(binary.LittleEndian)); err != nil {
		return errors.Wrap(err, "Error serializing 'dataType' field")
	}

	if err := WriteSimpleField[uint32](ctx, "flags", m.GetFlags(), WriteUnsignedInt(writeBuffer, 32), codegen.WithByteOrder(binary.LittleEndian)); err != nil {
		return errors.Wrap(err, "Error serializing 'flags' field")
	}
	dataTypeNameLength := uint16(uint16(len(m.GetDataTypeName())))
	if err := WriteImplicitField(ctx, "dataTypeNameLength", dataTypeNameLength, WriteUnsignedShort(writeBuffer, 16), codegen.WithByteOrder(binary.LittleEndian)); err != nil {
		return errors.Wrap(err, "Error serializing 'dataTypeNameLength' field")
	}
	simpleTypeNameLength := uint16(uint16(len(m.GetSimpleTypeName())))
	if err := WriteImplicitField(ctx, "simpleTypeNameLength", simpleTypeNameLength, WriteUnsignedShort(writeBuffer, 16), codegen.WithByteOrder(binary.LittleEndian)); err != nil {
		return errors.Wrap(err, "Error serializing 'simpleTypeNameLength' field")
	}
	commentLength := uint16(uint16(len(m.GetComment())))
	if err := WriteImplicitField(ctx, "commentLength", commentLength, WriteUnsignedShort(writeBuffer, 16), codegen.WithByteOrder(binary.LittleEndian)); err != nil {
		return errors.Wrap(err, "Error serializing 'commentLength' field")
	}

	if err := WriteSimpleField[uint16](ctx, "arrayDimensions", m.GetArrayDimensions(), WriteUnsignedShort(writeBuffer, 16), codegen.WithByteOrder(binary.LittleEndian)); err != nil {
		return errors.Wrap(err, "Error serializing 'arrayDimensions' field")
	}

	if err := WriteSimpleField[uint16](ctx, "numChildren", m.GetNumChildren(), WriteUnsignedShort(writeBuffer, 16), codegen.WithByteOrder(binary.LittleEndian)); err != nil {
		return errors.Wrap(err, "Error serializing 'numChildren' field")
	}

	if err := WriteSimpleField[string](ctx, "dataTypeName", m.GetDataTypeName(), WriteString(writeBuffer, int32(int32(uint16(len(m.GetDataTypeName())))*int32(int32(8)))), codegen.WithByteOrder(binary.LittleEndian)); err != nil {
		return errors.Wrap(err, "Error serializing 'dataTypeName' field")
	}

	if err := WriteConstField(ctx, "dataTypeNameTerminator", AdsDataTypeTableEntry_DATATYPENAMETERMINATOR, WriteUnsignedByte(writeBuffer, 8), codegen.WithByteOrder(binary.LittleEndian)); err != nil {
		return errors.Wrap(err, "Error serializing 'dataTypeNameTerminator' field")
	}

	if err := WriteSimpleField[string](ctx, "simpleTypeName", m.GetSimpleTypeName(), WriteString(writeBuffer, int32(int32(uint16(len(m.GetSimpleTypeName())))*int32(int32(8)))), codegen.WithByteOrder(binary.LittleEndian)); err != nil {
		return errors.Wrap(err, "Error serializing 'simpleTypeName' field")
	}

	if err := WriteConstField(ctx, "simpleTypeNameTerminator", AdsDataTypeTableEntry_SIMPLETYPENAMETERMINATOR, WriteUnsignedByte(writeBuffer, 8), codegen.WithByteOrder(binary.LittleEndian)); err != nil {
		return errors.Wrap(err, "Error serializing 'simpleTypeNameTerminator' field")
	}

	if err := WriteSimpleField[string](ctx, "comment", m.GetComment(), WriteString(writeBuffer, int32(int32(uint16(len(m.GetComment())))*int32(int32(8)))), codegen.WithByteOrder(binary.LittleEndian)); err != nil {
		return errors.Wrap(err, "Error serializing 'comment' field")
	}

	if err := WriteConstField(ctx, "commentTerminator", AdsDataTypeTableEntry_COMMENTTERMINATOR, WriteUnsignedByte(writeBuffer, 8), codegen.WithByteOrder(binary.LittleEndian)); err != nil {
		return errors.Wrap(err, "Error serializing 'commentTerminator' field")
	}

	if err := WriteComplexTypeArrayField(ctx, "arrayInfo", m.GetArrayInfo(), writeBuffer, codegen.WithByteOrder(binary.LittleEndian)); err != nil {
		return errors.Wrap(err, "Error serializing 'arrayInfo' field")
	}

	if err := WriteComplexTypeArrayField(ctx, "children", m.GetChildren(), writeBuffer, codegen.WithByteOrder(binary.LittleEndian)); err != nil {
		return errors.Wrap(err, "Error serializing 'children' field")
	}

	if err := WriteByteArrayField(ctx, "rest", m.GetRest(), WriteByteArray(writeBuffer, 8), codegen.WithByteOrder(binary.LittleEndian)); err != nil {
		return errors.Wrap(err, "Error serializing 'rest' field")
	}

	if popErr := writeBuffer.PopContext("AdsDataTypeTableEntry"); popErr != nil {
		return errors.Wrap(popErr, "Error popping for AdsDataTypeTableEntry")
	}
	return nil
}

func (m *_AdsDataTypeTableEntry) IsAdsDataTypeTableEntry() {}

func (m *_AdsDataTypeTableEntry) DeepCopy() any {
	return m.deepCopy()
}

func (m *_AdsDataTypeTableEntry) deepCopy() *_AdsDataTypeTableEntry {
	if m == nil {
		return nil
	}
	_AdsDataTypeTableEntryCopy := &_AdsDataTypeTableEntry{
		m.EntryLength,
		m.Version,
		m.HashValue,
		m.TypeHashValue,
		m.Size,
		m.Offset,
		m.DataType,
		m.Flags,
		m.ArrayDimensions,
		m.NumChildren,
		m.DataTypeName,
		m.SimpleTypeName,
		m.Comment,
		utils.DeepCopySlice[AdsDataTypeArrayInfo, AdsDataTypeArrayInfo](m.ArrayInfo),
		utils.DeepCopySlice[AdsDataTypeTableChildEntry, AdsDataTypeTableChildEntry](m.Children),
		utils.DeepCopySlice[byte, byte](m.Rest),
	}
	return _AdsDataTypeTableEntryCopy
}

func (m *_AdsDataTypeTableEntry) String() string {
	if m == nil {
		return "<nil>"
	}
	wb := utils.NewWriteBufferBoxBased(
		utils.WithWriteBufferBoxBasedMergeSingleBoxes(),
		utils.WithWriteBufferBoxBasedOmitEmptyBoxes(),
		utils.WithWriteBufferBoxBasedPrintPosLengthFooter(),
	)
	if err := wb.WriteSerializable(context.Background(), m); err != nil {
		return err.Error()
	}
	return wb.GetBox().String()
}
