You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@plc4x.apache.org by hu...@apache.org on 2023/05/17 04:15:32 UTC

[plc4x] 02/03: feat(plc4py): migrated the python helper to be based on the go helper

This is an automated email from the ASF dual-hosted git repository.

hutcheb pushed a commit to branch develop
in repository https://gitbox.apache.org/repos/asf/plc4x.git

commit 3cbd8f52e09763f277940777b512370c63b06ef5
Author: Ben Hutcheson <be...@gmail.com>
AuthorDate: Wed May 17 06:09:51 2023 +0200

    feat(plc4py): migrated the python helper to be based on the go helper
---
 .../python/PythonLanguageTemplateHelper.java       | 2028 ++++++++++++--------
 .../python/complex-type-template.python.ftlh       |   51 +-
 .../templates/python/enum-template.python.ftlh     |    4 +-
 .../plc4py/protocols/modbus/readwrite/DataItem.py  |  346 ++--
 .../protocols/modbus/readwrite/DriverType.py       |    4 +-
 .../plc4py/protocols/modbus/readwrite/ModbusADU.py |   16 +-
 .../protocols/modbus/readwrite/ModbusAsciiADU.py   |   37 +-
 .../protocols/modbus/readwrite/ModbusConstants.py  |   16 +-
 .../protocols/modbus/readwrite/ModbusDataType.py   |    6 +-
 .../ModbusDeviceInformationConformityLevel.py      |    4 +-
 .../readwrite/ModbusDeviceInformationLevel.py      |    4 +-
 .../ModbusDeviceInformationMoreFollows.py          |    4 +-
 .../readwrite/ModbusDeviceInformationObject.py     |   20 +-
 .../protocols/modbus/readwrite/ModbusErrorCode.py  |    4 +-
 .../plc4py/protocols/modbus/readwrite/ModbusPDU.py |  172 +-
 .../modbus/readwrite/ModbusPDUDiagnosticRequest.py |   17 +-
 .../readwrite/ModbusPDUDiagnosticResponse.py       |   17 +-
 .../protocols/modbus/readwrite/ModbusPDUError.py   |   22 +-
 .../ModbusPDUGetComEventCounterRequest.py          |   11 +-
 .../ModbusPDUGetComEventCounterResponse.py         |   17 +-
 .../readwrite/ModbusPDUGetComEventLogRequest.py    |   11 +-
 .../readwrite/ModbusPDUGetComEventLogResponse.py   |   32 +-
 .../ModbusPDUMaskWriteHoldingRegisterRequest.py    |   23 +-
 .../ModbusPDUMaskWriteHoldingRegisterResponse.py   |   23 +-
 .../modbus/readwrite/ModbusPDUReadCoilsRequest.py  |   21 +-
 .../modbus/readwrite/ModbusPDUReadCoilsResponse.py |   19 +-
 .../ModbusPDUReadDeviceIdentificationRequest.py    |   34 +-
 .../ModbusPDUReadDeviceIdentificationResponse.py   |   76 +-
 .../ModbusPDUReadDiscreteInputsRequest.py          |   21 +-
 .../ModbusPDUReadDiscreteInputsResponse.py         |   19 +-
 .../ModbusPDUReadExceptionStatusRequest.py         |   11 +-
 .../ModbusPDUReadExceptionStatusResponse.py        |   13 +-
 .../readwrite/ModbusPDUReadFifoQueueRequest.py     |   17 +-
 .../readwrite/ModbusPDUReadFifoQueueResponse.py    |   31 +-
 .../readwrite/ModbusPDUReadFileRecordRequest.py    |   19 +-
 .../ModbusPDUReadFileRecordRequestItem.py          |   24 +-
 .../readwrite/ModbusPDUReadFileRecordResponse.py   |   19 +-
 .../ModbusPDUReadFileRecordResponseItem.py         |   23 +-
 .../ModbusPDUReadHoldingRegistersRequest.py        |   21 +-
 .../ModbusPDUReadHoldingRegistersResponse.py       |   19 +-
 .../ModbusPDUReadInputRegistersRequest.py          |   21 +-
 .../ModbusPDUReadInputRegistersResponse.py         |   19 +-
 ...sPDUReadWriteMultipleHoldingRegistersRequest.py |   39 +-
 ...PDUReadWriteMultipleHoldingRegistersResponse.py |   19 +-
 .../readwrite/ModbusPDUReportServerIdRequest.py    |   11 +-
 .../readwrite/ModbusPDUReportServerIdResponse.py   |   19 +-
 .../readwrite/ModbusPDUWriteFileRecordRequest.py   |   19 +-
 .../ModbusPDUWriteFileRecordRequestItem.py         |   33 +-
 .../readwrite/ModbusPDUWriteFileRecordResponse.py  |   19 +-
 .../ModbusPDUWriteFileRecordResponseItem.py        |   30 +-
 .../ModbusPDUWriteMultipleCoilsRequest.py          |   29 +-
 .../ModbusPDUWriteMultipleCoilsResponse.py         |   21 +-
 ...odbusPDUWriteMultipleHoldingRegistersRequest.py |   29 +-
 ...dbusPDUWriteMultipleHoldingRegistersResponse.py |   21 +-
 .../readwrite/ModbusPDUWriteSingleCoilRequest.py   |   17 +-
 .../readwrite/ModbusPDUWriteSingleCoilResponse.py  |   17 +-
 .../ModbusPDUWriteSingleRegisterRequest.py         |   17 +-
 .../ModbusPDUWriteSingleRegisterResponse.py        |   17 +-
 .../protocols/modbus/readwrite/ModbusRtuADU.py     |   37 +-
 .../protocols/modbus/readwrite/ModbusTcpADU.py     |   52 +-
 .../protocols/simulated/readwrite/DataItem.py      |  174 +-
 .../plc4py/protocols/simulated/readwrite/Dummy.py  |   17 +-
 .../simulated/readwrite/SimulatedDataTypeSizes.py  |    6 +-
 .../plc4py/plc4py/spi/generation/WriteBuffer.py    |  143 +-
 sandbox/plc4py/plc4py/spi/generation/__init__.py   |    1 -
 sandbox/plc4py/plc4py/spi/values/Common.py         |    3 +-
 sandbox/plc4py/setup.py                            |    2 +-
 .../tests/unit/plc4py/spi/test_write_buffer.py     |  102 +-
 68 files changed, 2276 insertions(+), 1934 deletions(-)

diff --git a/code-generation/language-python/src/main/java/org/apache/plc4x/language/python/PythonLanguageTemplateHelper.java b/code-generation/language-python/src/main/java/org/apache/plc4x/language/python/PythonLanguageTemplateHelper.java
index c5ae583d3d..56e1534400 100644
--- a/code-generation/language-python/src/main/java/org/apache/plc4x/language/python/PythonLanguageTemplateHelper.java
+++ b/code-generation/language-python/src/main/java/org/apache/plc4x/language/python/PythonLanguageTemplateHelper.java
@@ -20,41 +20,55 @@ package org.apache.plc4x.language.python;
 
 import org.apache.commons.lang3.StringUtils;
 import org.apache.commons.lang3.math.NumberUtils;
-import org.apache.commons.text.WordUtils;
+import org.apache.commons.text.CaseUtils;
+import org.apache.plc4x.plugins.codegenerator.language.mspec.model.definitions.DefaultArgument;
+import org.apache.plc4x.plugins.codegenerator.language.mspec.model.references.*;
 import org.apache.plc4x.plugins.codegenerator.language.mspec.model.terms.DefaultStringLiteral;
 import org.apache.plc4x.plugins.codegenerator.protocol.freemarker.BaseFreemarkerLanguageTemplateHelper;
 import org.apache.plc4x.plugins.codegenerator.protocol.freemarker.FreemarkerException;
 import org.apache.plc4x.plugins.codegenerator.protocol.freemarker.Tracer;
 import org.apache.plc4x.plugins.codegenerator.types.definitions.*;
+import org.apache.plc4x.plugins.codegenerator.types.enums.EnumValue;
 import org.apache.plc4x.plugins.codegenerator.types.fields.*;
 import org.apache.plc4x.plugins.codegenerator.types.references.*;
 import org.apache.plc4x.plugins.codegenerator.types.terms.*;
-
-import java.math.BigDecimal;
-import java.math.BigInteger;
-import java.time.LocalDate;
-import java.time.LocalDateTime;
-import java.time.LocalTime;
-import java.util.*;
-import java.util.function.Function;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 
+import java.util.*;
+
 @SuppressWarnings({"unused", "WeakerAccess"})
 public class PythonLanguageTemplateHelper extends BaseFreemarkerLanguageTemplateHelper {
 
-    private static final Logger LOGGER = LoggerFactory.getLogger(PythonLanguageTemplateHelper.class);
+    private static final Logger LOGGER = LoggerFactory.getLogger(BaseFreemarkerLanguageTemplateHelper.class);
 
-    private final Map<String, String> options;
+    // TODO: we could condense it to one import set as these can be emitted per template and are not hardcoded anymore
 
-    public SortedSet<String> requiredImports = new TreeSet<>();
+    public final SortedSet<String> requiredImports = new TreeSet<>();
 
-    public SortedSet<String> requiredImportsForDataIo = new TreeSet<>();
+    public final SortedSet<String> requiredImportsForDataIo = new TreeSet<>();
 
-    public PythonLanguageTemplateHelper(TypeDefinition thisType, String protocolName, String flavorName, Map<String, TypeDefinition> types,
-                                      Map<String, String> options) {
+    public PythonLanguageTemplateHelper(TypeDefinition thisType, String protocolName, String flavorName, Map<String, TypeDefinition> types) {
         super(thisType, protocolName, flavorName, types);
-        this.options = options;
+    }
+
+    public String fileName(String protocolName, String languageName, String languageFlavorName) {
+        return String.join("", protocolName.split("\\-")) + "." +
+            String.join("", languageFlavorName.split("\\-"));
+    }
+
+    public String getSanitizedPackageName() {
+        String sanitizedName = getProtocolName().replaceAll("-", "");
+        sanitizedName = sanitizedName.replaceAll("\\.", "/");
+        sanitizedName = sanitizedName.toLowerCase();
+        return sanitizedName;
+    }
+
+    // TODO: check if protocol name can be enforced to only contain valid chars
+    public String getSanitizedProtocolName() {
+        String sanitizedName = getProtocolName().replaceAll("-", "");
+        sanitizedName = CaseUtils.toCamelCase(sanitizedName, false, '.');
+        return sanitizedName;
     }
 
     public String packageName() {
@@ -62,46 +76,51 @@ public class PythonLanguageTemplateHelper extends BaseFreemarkerLanguageTemplate
     }
 
     public String packageName(String protocolName, String languageName, String languageFlavorName) {
-        return Optional.ofNullable(options.get("package")).orElseGet(() ->
-                String.join("", protocolName.split("-")) + "." +
-                String.join("", languageFlavorName.split("-")));
-    }
-
-    public String packageName(String languageFlavorName) {
-        return String.join("", languageFlavorName.split("\\-"));
+        return String.join("", protocolName.split("-")) + "." +
+                String.join("", languageFlavorName.split("-"));
     }
 
     @Override
     public String getLanguageTypeNameForField(Field field) {
+        boolean optional = field instanceof OptionalField;
         // If the referenced type is a DataIo type, the value is of type PlcValue.
-        if (field.isPropertyField()) {
-            PropertyField propertyField = field.asPropertyField().orElseThrow(IllegalStateException::new);
-            if (propertyField.getType().isComplexTypeReference()) {
-                ComplexTypeReference complexTypeReference = propertyField.getType().asComplexTypeReference().orElseThrow(IllegalStateException::new);
-                final TypeDefinition typeDefinition = getTypeDefinitions().get(complexTypeReference.getName());
+        if (field instanceof PropertyField) {
+            PropertyField propertyField = (PropertyField) field;
+            if (propertyField.getType() instanceof ComplexTypeReference) {
+                ComplexTypeReference complexTypeReference = (ComplexTypeReference) propertyField.getType();
+                final TypeDefinition typeDefinition = complexTypeReference.getTypeDefinition();
                 if (typeDefinition instanceof DataIoTypeDefinition) {
-                    emitRequiredImport(complexTypeReference.getName());
                     return "PlcValue";
                 }
             }
         }
-        return getLanguageTypeNameForTypeReference(((TypedField) field).getType(), !field.isOptionalField());
-    }
-
-    public String getNonPrimitiveLanguageTypeNameForField(TypedField field) {
-        return getLanguageTypeNameForTypeReference(field.getType(), false);
+        TypedField typedField = field.asTypedField().orElseThrow();
+        String encoding = null;
+        Optional<Term> encodingAttribute = field.getAttribute("encoding");
+        if(encodingAttribute.isPresent()) {
+            encoding = encodingAttribute.get().toString();
+        }
+        return getLanguageTypeNameForTypeReference(typedField.getType(), encoding);
     }
 
-    public String getLanguageTypeNameForSpecType(TypeReference typeReference) {
-        return getLanguageTypeNameForTypeReference(typeReference, true);
+    public boolean isComplex(Field field) {
+        return field instanceof PropertyField && ((PropertyField) field).getType() instanceof NonSimpleTypeReference;
     }
 
     @Override
     public String getLanguageTypeNameForTypeReference(TypeReference typeReference) {
-        return getLanguageTypeNameForTypeReference(typeReference, false);
+        return getLanguageTypeNameForTypeReference(typeReference, null);
+    }
+
+    public String getNonPrimitiveLanguageTypeNameForField(TypedField field) {
+        return getLanguageTypeNameForTypeReference(field.getType(), false);
+    }
+
+    public String getLanguageTypeNameForTypeReference(TypeReference typeReference, boolean allowPrimitives) {
+        return getLanguageTypeNameForTypeReference(typeReference, null);
     }
 
-    public String getLanguageTypeNameForTypeReference(TypeReference typeReference, boolean allowPrimitive) {
+    public String getLanguageTypeNameForTypeReference(TypeReference typeReference, String encoding) {
         if (typeReference == null) {
             // TODO: shouldn't this be an error case
             return "";
@@ -116,6 +135,9 @@ public class PythonLanguageTemplateHelper extends BaseFreemarkerLanguageTemplate
             emitRequiredImport("from plc4py.protocols." + protocolName + "." + flavorName.replace("-", "") + "." + typeReference.asNonSimpleTypeReference().orElseThrow().getName() + " import " + typeReference.asNonSimpleTypeReference().orElseThrow().getName());
             return typeReference.asNonSimpleTypeReference().orElseThrow().getName();
         }
+        if (typeReference instanceof ByteOrderTypeReference) {
+            return "binary.byteOrder";
+        }
         SimpleTypeReference simpleTypeReference = typeReference.asSimpleTypeReference().orElseThrow();
         switch (simpleTypeReference.getBaseType()) {
             case BIT:
@@ -190,200 +212,19 @@ public class PythonLanguageTemplateHelper extends BaseFreemarkerLanguageTemplate
         }
     }
 
-    public String getPlcValueTypeForTypeReference(TypeReference typeReference) {
-        if (!(typeReference instanceof SimpleTypeReference)) {
-            return "PlcStruct";
-        }
-        SimpleTypeReference simpleTypeReference = (SimpleTypeReference) typeReference;
-        switch (simpleTypeReference.getBaseType()) {
-            case BIT:
-                return "PlcBOOL";
-            case BYTE:
-                return "PlcSINT";
-            case UINT:
-                IntegerTypeReference unsignedIntegerTypeReference = (IntegerTypeReference) simpleTypeReference;
-                if (unsignedIntegerTypeReference.getSizeInBits() <= 4) {
-                    return "PlcUSINT";
-                }
-                if (unsignedIntegerTypeReference.getSizeInBits() <= 8) {
-                    return "PlcUINT";
-                }
-                if (unsignedIntegerTypeReference.getSizeInBits() <= 16) {
-                    return "PlcUDINT";
-                }
-                if (unsignedIntegerTypeReference.getSizeInBits() <= 32) {
-                    return "PlcULINT";
-                }
-            case INT:
-                IntegerTypeReference integerTypeReference = (IntegerTypeReference) simpleTypeReference;
-                if (integerTypeReference.getSizeInBits() <= 8) {
-                    return "PlcSINT";
-                }
-                if (integerTypeReference.getSizeInBits() <= 16) {
-                    return "PlcINT";
-                }
-                if (integerTypeReference.getSizeInBits() <= 32) {
-                    return "PlcDINT";
-                }
-                if (integerTypeReference.getSizeInBits() <= 64) {
-                    return "PlcLINT";
-                }
-
-            case FLOAT:
-            case UFLOAT:
-                FloatTypeReference floatTypeReference = (FloatTypeReference) simpleTypeReference;
-                int sizeInBits = floatTypeReference.getSizeInBits();
-                if (sizeInBits <= 32) {
-                    return "PlcREAL";
-                }
-                if (sizeInBits <= 64) {
-                    return "PlcLREAL";
-                }
-            case STRING:
-            case VSTRING:
-                return "PlcSTRING";
-            case TIME:
-            case DATE:
-            case DATETIME:
-                return "PlcTIME";
-        }
-        throw new RuntimeException("Unsupported simple type");
-    }
-
-    @Override
-    public String getNullValueForTypeReference(TypeReference typeReference) {
-        if (typeReference instanceof SimpleTypeReference) {
-            SimpleTypeReference simpleTypeReference = (SimpleTypeReference) typeReference;
-            switch (simpleTypeReference.getBaseType()) {
-                case BIT:
-                    return "False";
-                case BYTE:
-                    return "0";
-                case UINT:
-                    IntegerTypeReference unsignedIntegerTypeReference = (IntegerTypeReference) simpleTypeReference;
-                    if (unsignedIntegerTypeReference.getSizeInBits() <= 16) {
-                        return "0";
-                    }
-                    if (unsignedIntegerTypeReference.getSizeInBits() <= 32) {
-                        return "0l";
-                    }
-                    return "None";
-                case INT:
-                    IntegerTypeReference integerTypeReference = (IntegerTypeReference) simpleTypeReference;
-                    if (integerTypeReference.getSizeInBits() <= 32) {
-                        return "0";
-                    }
-                    if (integerTypeReference.getSizeInBits() <= 64) {
-                        return "0l";
-                    }
-                    return "None";
-                case FLOAT:
-                    FloatTypeReference floatTypeReference = (FloatTypeReference) simpleTypeReference;
-                    int sizeInBits = floatTypeReference.getSizeInBits();
-                    if (sizeInBits <= 32) {
-                        return "0.0f";
-                    }
-                    if (sizeInBits <= 64) {
-                        return "0.0";
-                    }
-                    return "None";
-                case STRING:
-                case VSTRING:
-                    return "None";
-            }
-            throw new FreemarkerException("Unmapped base-type" + simpleTypeReference.getBaseType());
-        } else {
-            return "None";
-        }
-    }
-
-    public int getNumBits(SimpleTypeReference simpleTypeReference) {
-        switch (simpleTypeReference.getBaseType()) {
-            case BIT:
-                return 1;
-            case BYTE:
-                return 8;
-            case UINT:
-            case INT:
-                IntegerTypeReference integerTypeReference = (IntegerTypeReference) simpleTypeReference;
-                return integerTypeReference.getSizeInBits();
-            case FLOAT:
-                FloatTypeReference floatTypeReference = (FloatTypeReference) simpleTypeReference;
-                return floatTypeReference.getSizeInBits();
-            case STRING:
-                StringTypeReference stringTypeReference = (StringTypeReference) simpleTypeReference;
-                return stringTypeReference.getSizeInBits();
-            case VSTRING:
-                throw new IllegalArgumentException("getSizeInBits doesn't work for 'vstring' fields");
-            default:
-                return 0;
+    public String getFieldOptions(TypedField field, List<Argument> parserArguments) {
+        StringBuilder sb = new StringBuilder();
+        final Optional<Term> encodingOptional = field.getEncoding();
+        if (encodingOptional.isPresent()) {
+            final String encoding = toParseExpression(field, field.getType(), encodingOptional.get(), parserArguments);
+            sb.append(", WithOption.WithEncoding(").append(encoding).append(")");
         }
-    }
-
-    @Deprecated
-    @Override
-    public String getReadBufferReadMethodCall(SimpleTypeReference simpleTypeReference, String valueString, TypedField field) {
-        return getReadBufferReadMethodCall("", simpleTypeReference, valueString, field);
-    }
-
-    @Deprecated
-    public String getReadBufferReadMethodCall(String logicalName, SimpleTypeReference simpleTypeReference, String valueString, TypedField field) {
-        switch (simpleTypeReference.getBaseType()) {
-            case BIT:
-                String bitType = "Bit";
-                return "read_buffer.read" + bitType + "(\"" + logicalName + "\")";
-            case BYTE:
-                String byteType = "Byte";
-                return "read_buffer.read" + byteType + "(\"" + logicalName + "\")";
-            case UINT:
-                String unsignedIntegerType;
-                IntegerTypeReference unsignedIntegerTypeReference = (IntegerTypeReference) simpleTypeReference;
-                if (unsignedIntegerTypeReference.getSizeInBits() <= 4) {
-                    unsignedIntegerType = "UnsignedByte";
-                } else if (unsignedIntegerTypeReference.getSizeInBits() <= 8) {
-                    unsignedIntegerType = "UnsignedShort";
-                } else if (unsignedIntegerTypeReference.getSizeInBits() <= 16) {
-                    unsignedIntegerType = "UnsignedInt";
-                } else if (unsignedIntegerTypeReference.getSizeInBits() <= 32) {
-                    unsignedIntegerType = "UnsignedLong";
-                } else {
-                    unsignedIntegerType = "UnsignedBigInteger";
-                }
-                return "read_buffer.read" + unsignedIntegerType + "(\"" + logicalName + "\", " + simpleTypeReference.getSizeInBits() + ")";
-            case INT:
-                String integerType;
-                if (simpleTypeReference.getSizeInBits() <= 8) {
-                    integerType = "SignedByte";
-                } else if (simpleTypeReference.getSizeInBits() <= 16) {
-                    integerType = "Short";
-                } else if (simpleTypeReference.getSizeInBits() <= 32) {
-                    integerType = "Int";
-                } else if (simpleTypeReference.getSizeInBits() <= 64) {
-                    integerType = "Long";
-                } else {
-                    integerType = "BigInteger";
-                }
-                return "read_buffer.read" + integerType + "(\"" + logicalName + "\", " + simpleTypeReference.getSizeInBits() + ")";
-            case FLOAT:
-                String floatType = (simpleTypeReference.getSizeInBits() <= 32) ? "Float" : "Double";
-                return "read_buffer.read" + floatType + "(\"" + logicalName + "\", " + simpleTypeReference.getSizeInBits() + ")";
-            case STRING:
-            case VSTRING:
-                String stringType = "String";
-                final Term encodingTerm = field.getEncoding().orElse(new DefaultStringLiteral("UTF-8"));
-                if (!(encodingTerm instanceof StringLiteral)) {
-                    throw new RuntimeException("Encoding must be a quoted string value");
-                }
-                String encoding = ((StringLiteral) encodingTerm).getValue();
-                String length = Integer.toString(simpleTypeReference.getSizeInBits());
-                if (simpleTypeReference.getBaseType() == SimpleTypeReference.SimpleBaseType.VSTRING) {
-                    VstringTypeReference vstringTypeReference = (VstringTypeReference) simpleTypeReference;
-                    length = toParseExpression(field, INT_TYPE_REFERENCE, vstringTypeReference.getLengthExpression(), null);
-                }
-                return "read_buffer.read" + stringType + "(\"" + logicalName + "\", " + length + ", \"" +
-                    encoding + "\")";
+        final Optional<Term> byteOrderOptional = field.getByteOrder();
+        if (byteOrderOptional.isPresent()) {
+            final String byteOrder = toParseExpression(field, field.getType(), byteOrderOptional.get(), parserArguments);
+            sb.append(", WithOption.WithByteOrder(").append(byteOrder).append(")");
         }
-        return "# TODO: migrate me " + "";
+        return sb.toString();
     }
 
     public String getDataReaderCall(TypeReference typeReference) {
@@ -502,488 +343,767 @@ public class PythonLanguageTemplateHelper extends BaseFreemarkerLanguageTemplate
         final int sizeInBits = simpleTypeReference.getSizeInBits();
         switch (simpleTypeReference.getBaseType()) {
             case BIT:
-                return "write_boolean(write_buffer)";
+                return "write_boolean";
             case BYTE:
-                return "write_byte(write_buffer, " + sizeInBits + ")";
+                return "write_byte";
             case UINT:
-                if (sizeInBits <= 4) return "write_unsigned_byte(write_buffer, " + sizeInBits + ")";
-                if (sizeInBits <= 8) return "write_unsigned_short(write_buffer, " + sizeInBits + ")";
-                if (sizeInBits <= 16) return "write_unsigned_int(write_buffer, " + sizeInBits + ")";
-                if (sizeInBits <= 32) return "write_unsigned_long(write_buffer, " + sizeInBits + ")";
-                return "write_unsigned_big_integer(write_buffer, " + sizeInBits + ")";
+                if (sizeInBits <= 8) return "write_unsigned_byte";
+                if (sizeInBits <= 16) return "write_unsigned_short";
+                if (sizeInBits <= 32) return "write_unsigned_int";
+                return "write_unsigned_long";
             case INT:
-                if (sizeInBits <= 8) return "write_signed_byte(write_buffer, " + sizeInBits + ")";
-                if (sizeInBits <= 16) return "write_signed_short(write_buffer, " + sizeInBits + ")";
-                if (sizeInBits <= 32) return "write_signed_int(write_buffer, " + sizeInBits + ")";
-                if (sizeInBits <= 64) return "write_signed_long(write_buffer, " + sizeInBits + ")";
-                return "write_signed_big_integer(write_buffer, " + sizeInBits + ")";
+                if (sizeInBits <= 8) return "write_signed_byte";
+                if (sizeInBits <= 16) return "write_signed_short";
+                if (sizeInBits <= 32) return "write_signed_int";
+                return "write_signed_long";
             case FLOAT:
-                if (sizeInBits <= 32) return "write_float(write_buffer, " + sizeInBits + ")";
-                if (sizeInBits <= 64) return "write_double(write_buffer, " + sizeInBits + ")";
-                return "write_big_decimal(write_buffer, " + sizeInBits + ")";
+                if (sizeInBits <= 32) return "write_float";
+                return "write_double";
             case STRING:
-                return "write_string(write_buffer, " + sizeInBits + ")";
+                return "write_string";
             case VSTRING:
                 VstringTypeReference vstringTypeReference = (VstringTypeReference) simpleTypeReference;
-                return "write_string(write_buffer, " + toParseExpression(null, INT_TYPE_REFERENCE, vstringTypeReference.getLengthExpression(), null) + ")";
+                return "write_string";
             case TIME:
-                return "write_time(write_buffer)";
+                return "write_time";
             case DATE:
-                return "write_date(write_buffer)";
+                return "write_date";
             case DATETIME:
-                return "write_date_time(write_buffer)";
+                return "write_date_time";
             default:
-                throw new UnsupportedOperationException("Unsupported type " + simpleTypeReference.getBaseType());
+                return "";
         }
     }
 
-    @Deprecated
-    @Override
-    public String getWriteBufferWriteMethodCall(SimpleTypeReference simpleTypeReference, String fieldName, TypedField field) {
-        return getWriteBufferWriteMethodCall("", simpleTypeReference, fieldName, field);
-    }
-
-    @Deprecated
-    public String getWriteBufferWriteMethodCall(String logicalName, SimpleTypeReference simpleTypeReference, String fieldName, TypedField field, String... writerArgs) {
-        String writerArgsString = "";
-        if (writerArgs.length > 0) {
-            writerArgsString += ", " + StringUtils.join(writerArgs, ", ");
+    public String getPlcValueTypeForTypeReference(TypeReference typeReference) {
+        if (typeReference == null) {
+            // TODO: shouldn't this be an error case
+            return "";
+        }
+        if (typeReference.isNonSimpleTypeReference()) {
+            return ((NonSimpleTypeReference) typeReference).getName();
         }
+        SimpleTypeReference simpleTypeReference = (SimpleTypeReference) typeReference;
         switch (simpleTypeReference.getBaseType()) {
             case BIT:
-                return "writeBuffer.writeBit(\"" + logicalName + "\", bool( " + fieldName + "" + writerArgsString + "))";
+                return "PlcBOOL";
             case BYTE:
-                ByteTypeReference byteTypeReference = (ByteTypeReference) simpleTypeReference;
-                return "writeBuffer.writeByte(\"" + logicalName + "\", (" + fieldName + ").byteValue()" + writerArgsString + ")";
+                return "PlcSINT";
             case UINT:
                 IntegerTypeReference unsignedIntegerTypeReference = (IntegerTypeReference) simpleTypeReference;
                 if (unsignedIntegerTypeReference.getSizeInBits() <= 4) {
-                    return "writeBuffer.writeUnsignedByte(\"" + logicalName + "\", " + unsignedIntegerTypeReference.getSizeInBits() + ", " + fieldName + ".byteValue()" + writerArgsString + ")";
+                    return "PlcUSINT";
                 }
                 if (unsignedIntegerTypeReference.getSizeInBits() <= 8) {
-                    return "writeBuffer.writeUnsignedShort(\"" + logicalName + "\", " + unsignedIntegerTypeReference.getSizeInBits() + ", " + fieldName + ".shortValue()" + writerArgsString + ")";
+                    return "PlcUINT";
                 }
                 if (unsignedIntegerTypeReference.getSizeInBits() <= 16) {
-                    return "writeBuffer.writeUnsignedInt(\"" + logicalName + "\", " + unsignedIntegerTypeReference.getSizeInBits() + ", " + fieldName + ".intValue()" + writerArgsString + ")";
+                    return "PlcUDINT";
                 }
                 if (unsignedIntegerTypeReference.getSizeInBits() <= 32) {
-                    return "writeBuffer.writeUnsignedLong(\"" + logicalName + "\", " + unsignedIntegerTypeReference.getSizeInBits() + ", " + fieldName + ".longValue()" + writerArgsString + ")";
+                    return "PlcULINT";
                 }
-                return "writeBuffer.writeUnsignedBigInteger(\"" + logicalName + "\", " + unsignedIntegerTypeReference.getSizeInBits() + ", " + fieldName + "" + writerArgsString + ")";
             case INT:
                 IntegerTypeReference integerTypeReference = (IntegerTypeReference) simpleTypeReference;
                 if (integerTypeReference.getSizeInBits() <= 8) {
-                    return "writeBuffer.writeSignedByte(\"" + logicalName + "\", " + integerTypeReference.getSizeInBits() + ", " + fieldName + ".byteValue()" + writerArgsString + ")";
+                    return "PlcSINT";
                 }
                 if (integerTypeReference.getSizeInBits() <= 16) {
-                    return "writeBuffer.writeShort(\"" + logicalName + "\", " + integerTypeReference.getSizeInBits() + ", " + fieldName + ".shortValue()" + writerArgsString + ")";
+                    return "PlcINT";
                 }
                 if (integerTypeReference.getSizeInBits() <= 32) {
-                    return "writeBuffer.writeInt(\"" + logicalName + "\", " + integerTypeReference.getSizeInBits() + ", " + fieldName + ".intValue()" + writerArgsString + ")";
+                    return "PlcDINT";
                 }
                 if (integerTypeReference.getSizeInBits() <= 64) {
-                    return "writeBuffer.writeLong(\"" + logicalName + "\", " + integerTypeReference.getSizeInBits() + ", " + fieldName + ".longValue()" + writerArgsString + ")";
+                    return "PlcLINT";
                 }
-                return "writeBuffer.writeBigInteger(\"" + logicalName + "\", " + integerTypeReference.getSizeInBits() + ", " + fieldName + "" + writerArgsString + ")";
+
             case FLOAT:
             case UFLOAT:
                 FloatTypeReference floatTypeReference = (FloatTypeReference) simpleTypeReference;
-                if (floatTypeReference.getSizeInBits() <= 32) {
-                    return "writeBuffer.writeFloat(\"" + logicalName + "\", " + floatTypeReference.getSizeInBits() + "," + fieldName + "" + writerArgsString + ")";
-                } else if (floatTypeReference.getSizeInBits() <= 64) {
-                    return "writeBuffer.writeDouble(\"" + logicalName + "\", " + floatTypeReference.getSizeInBits() + "," + fieldName + "" + writerArgsString + ")";
-                } else {
-                    throw new RuntimeException("Unsupported float type");
+                int sizeInBits = floatTypeReference.getSizeInBits();
+                if (sizeInBits <= 32) {
+                    return "PlcREAL";
+                }
+                if (sizeInBits <= 64) {
+                    return "PlcLREAL";
                 }
             case STRING:
             case VSTRING:
-                final Term encodingTerm = field.getEncoding().orElse(new DefaultStringLiteral("UTF-8"));
-                if (!(encodingTerm instanceof StringLiteral)) {
-                    throw new RuntimeException("Encoding must be a quoted string value");
-                }
-                String encoding = ((StringLiteral) encodingTerm).getValue();
-                String length = Integer.toString(simpleTypeReference.getSizeInBits());
-                if (simpleTypeReference.getBaseType() == SimpleTypeReference.SimpleBaseType.VSTRING) {
-                    VstringTypeReference vstringTypeReference = (VstringTypeReference) simpleTypeReference;
-                    length = toSerializationExpression(field, INT_TYPE_REFERENCE, vstringTypeReference.getLengthExpression(), thisType.getParserArguments().orElse(Collections.emptyList()));
-                }
-                return "writeBuffer.writeString(\"" + logicalName + "\", " + length + ", \"" +
-                    encoding + "\", (String) " + fieldName + "" + writerArgsString + ")";
+                return "PlcSTRING";
+            case TIME:
+            case DATE:
+            case DATETIME:
+                return "PlcTIME";
+            default:
+                return "";
         }
-        throw new FreemarkerException("Unmapped basetype" + simpleTypeReference.getBaseType());
     }
 
-    public String getReservedValue(ReservedField reservedField) {
-        final String languageTypeName = getLanguageTypeNameForTypeReference(reservedField.getType(), true);
-        return languageTypeName + "(" + reservedField.getReferenceValue() + ")";
-    }
-
-    /**
-     * @param field           this generally only is needed in order to access field attributes such as encoding etc.
-     * @param resultType      the type the resulting expression should have
-     * @param term            the term representing the expression
-     * @param parserArguments any parser arguments, which could be referenced in expressions (Needed for getting the type)
-     * @return Java code which does the things defined in 'term'
-     */
-    public String toParseExpression(Field field, TypeReference resultType, Term term, List<Argument> parserArguments) {
-        Tracer tracer = Tracer.start("toParseExpression");
-        return tracer + toExpression(field, resultType, term, variableLiteral -> tracer.dive("variableExpressionGenerator") + toVariableParseExpression(field, resultType, variableLiteral, parserArguments));
-    }
+    @Override
+    public String getNullValueForTypeReference(TypeReference typeReference) {
+        if (typeReference instanceof SimpleTypeReference) {
+            SimpleTypeReference simpleTypeReference = (SimpleTypeReference) typeReference;
+            switch (simpleTypeReference.getBaseType()) {
+                case BIT:
+                    return "False";
+                case BYTE:
+                case UINT:
+                case INT:
+                    return "0";
+                case FLOAT:
+                    return "0.0";
+                case STRING:
+                case VSTRING:
+                    return "\"\"";
+            }
+        } else if (typeReference.isEnumTypeReference()) {
+            return "0";
+        }
+        return "None";
+    }
 
-    /**
-     * @param field               this generally only is needed in order to access field attributes such as encoding etc.
-     * @param resultType          the type the resulting expression should have
-     * @param term                the term representing the expression
-     * @param serializerArguments any serializer arguments, which could be referenced in expressions (Needed for getting the type)
-     * @return Java code which does the things defined in 'term'
-     */
-    public String toSerializationExpression(Field field, TypeReference resultType, Term term, List<Argument> serializerArguments) {
-        Tracer tracer = Tracer.start("toSerializationExpression");
-        return tracer + toExpression(field, resultType, term, variableLiteral -> tracer.dive("variableExpressionGenerator") + toVariableSerializationExpression(field, resultType, variableLiteral, serializerArguments));
+    public int getNumBits(SimpleTypeReference simpleTypeReference) {
+        switch (simpleTypeReference.getBaseType()) {
+            case BIT:
+                return 1;
+            case BYTE:
+                return 8;
+            case UINT:
+            case INT:
+                IntegerTypeReference integerTypeReference = (IntegerTypeReference) simpleTypeReference;
+                return integerTypeReference.getSizeInBits();
+            case FLOAT:
+                FloatTypeReference floatTypeReference = (FloatTypeReference) simpleTypeReference;
+                return floatTypeReference.getSizeInBits();
+            case STRING:
+            case VSTRING:
+                StringTypeReference stringTypeReference = (StringTypeReference) simpleTypeReference;
+                return stringTypeReference.getSizeInBits();
+            default:
+                return 0;
+        }
     }
 
-    private String toExpression(Field field, TypeReference resultType, Term term, Function<VariableLiteral, String> variableExpressionGenerator) {
-        Tracer tracer = Tracer.start("toExpression");
-        if (term == null) {
-            return tracer + "";
+    public boolean needsPointerAccess(PropertyField field) {
+        boolean isAnTypeOfOptional = "optional".equals(field.getTypeName());
+        return isAnTypeOfOptional && needPointerAccess(field.getType());
+    }
+
+    public boolean needPointerAccess(TypeReference typeReference) {
+        boolean isNotAnComplexTypeReference = !typeReference.isComplexTypeReference();
+        boolean arrayTypeIsNotAnComplexTypeReference = !(typeReference.isArrayTypeReference() && typeReference.asArrayTypeReference().orElseThrow().getElementTypeReference().isComplexTypeReference());
+        return isNotAnComplexTypeReference && arrayTypeIsNotAnComplexTypeReference;
+    }
+
+    public String getSpecialReadBufferReadMethodCall(String logicalName, SimpleTypeReference simpleTypeReference, TypedField field) {
+        return getReadBufferReadMethodCall(logicalName, simpleTypeReference, null, field);
+    }
+
+    public String getReadBufferReadMethodCall(String logicalName, SimpleTypeReference simpleTypeReference, TypedField field) {
+        return getReadBufferReadMethodCall(logicalName, simpleTypeReference, null, field);
+    }
+
+    @Override
+    public String getReadBufferReadMethodCall(SimpleTypeReference simpleTypeReference, String valueString, TypedField field) {
+        return getReadBufferReadMethodCall("", simpleTypeReference, valueString, field);
+    }
+
+    public String getReadBufferReadMethodCall(String logicalName, SimpleTypeReference simpleTypeReference, String valueString, TypedField field) {
+        switch (simpleTypeReference.getBaseType()) {
+            case BIT:
+                String bitType = "Bit";
+                return "read_buffer.read" + bitType + "(\"" + logicalName + "\")";
+            case BYTE:
+                String byteType = "Byte";
+                return "read_buffer.read" + byteType + "(\"" + logicalName + "\")";
+            case UINT:
+                String unsignedIntegerType;
+                IntegerTypeReference unsignedIntegerTypeReference = (IntegerTypeReference) simpleTypeReference;
+                if (unsignedIntegerTypeReference.getSizeInBits() <= 4) {
+                    unsignedIntegerType = "UnsignedByte";
+                } else if (unsignedIntegerTypeReference.getSizeInBits() <= 8) {
+                    unsignedIntegerType = "UnsignedShort";
+                } else if (unsignedIntegerTypeReference.getSizeInBits() <= 16) {
+                    unsignedIntegerType = "UnsignedInt";
+                } else if (unsignedIntegerTypeReference.getSizeInBits() <= 32) {
+                    unsignedIntegerType = "UnsignedLong";
+                } else {
+                    unsignedIntegerType = "UnsignedBigInteger";
+                }
+                return "read_buffer.read" + unsignedIntegerType + "(\"" + logicalName + "\", " + simpleTypeReference.getSizeInBits() + ")";
+            case INT:
+                String integerType;
+                if (simpleTypeReference.getSizeInBits() <= 8) {
+                    integerType = "SignedByte";
+                } else if (simpleTypeReference.getSizeInBits() <= 16) {
+                    integerType = "Short";
+                } else if (simpleTypeReference.getSizeInBits() <= 32) {
+                    integerType = "Int";
+                } else if (simpleTypeReference.getSizeInBits() <= 64) {
+                    integerType = "Long";
+                } else {
+                    integerType = "BigInteger";
+                }
+                return "read_buffer.read" + integerType + "(\"" + logicalName + "\", " + simpleTypeReference.getSizeInBits() + ")";
+            case FLOAT:
+                String floatType = (simpleTypeReference.getSizeInBits() <= 32) ? "Float" : "Double";
+                return "read_buffer.read" + floatType + "(\"" + logicalName + "\", " + simpleTypeReference.getSizeInBits() + ")";
+            case STRING:
+            case VSTRING:
+                String stringType = "String";
+                final Term encodingTerm = field.getEncoding().orElse(new DefaultStringLiteral("UTF-8"));
+                if (!(encodingTerm instanceof StringLiteral)) {
+                    throw new RuntimeException("Encoding must be a quoted string value");
+                }
+                String encoding = ((StringLiteral) encodingTerm).getValue();
+                String length = Integer.toString(simpleTypeReference.getSizeInBits());
+                if (simpleTypeReference.getBaseType() == SimpleTypeReference.SimpleBaseType.VSTRING) {
+                    VstringTypeReference vstringTypeReference = (VstringTypeReference) simpleTypeReference;
+                    length = toParseExpression(field, INT_TYPE_REFERENCE, vstringTypeReference.getLengthExpression(), null);
+                }
+                return "read_buffer.read" + stringType + "(\"" + logicalName + "\", " + length + ", \"" +
+                    encoding + "\")";
+            default:
+                return "";
         }
-        if (term instanceof Literal) {
-            return toLiteralTermExpression(field, resultType, (Literal) term, variableExpressionGenerator, tracer);
-        } else if (term instanceof UnaryTerm) {
-            return toUnaryTermExpression(field, resultType, (UnaryTerm) term, variableExpressionGenerator, tracer);
-        } else if (term instanceof BinaryTerm) {
-            return toBinaryTermExpression(field, resultType, (BinaryTerm) term, variableExpressionGenerator, tracer);
-        } else if (term instanceof TernaryTerm) {
-            return toTernaryTermExpression(field, resultType, (TernaryTerm) term, variableExpressionGenerator, tracer);
-        } else {
-            throw new RuntimeException("Unsupported Term type " + term.getClass().getName() + ". Actual type " + resultType);
+    }
+
+    @Override
+    public String getWriteBufferWriteMethodCall(SimpleTypeReference simpleTypeReference, String fieldName, TypedField field) {
+        // Fallback if somewhere the method gets called without a name
+        String logicalName = fieldName.replaceAll("[\"()*]", "").replaceFirst("_", "");
+        return getWriteBufferWriteMethodCall(logicalName, simpleTypeReference, fieldName, field);
+    }
+
+    public String getWriteBufferWriteMethodCall(String logicalName, SimpleTypeReference simpleTypeReference, Term valueTerm, TypedField field, String... writerArgs) {
+        if (valueTerm instanceof BooleanLiteral) {
+            return getWriteBufferWriteMethodCall(logicalName, simpleTypeReference, Boolean.toString(((BooleanLiteral) valueTerm).getValue()), field, writerArgs);
         }
+        if (valueTerm instanceof NumericLiteral) {
+            return getWriteBufferWriteMethodCall(logicalName, simpleTypeReference, ((NumericLiteral) valueTerm).getNumber().toString(), field, writerArgs);
+        }
+        if (valueTerm instanceof HexadecimalLiteral) {
+            return getWriteBufferWriteMethodCall(logicalName, simpleTypeReference, ((HexadecimalLiteral) valueTerm).getHexString(), field, writerArgs);
+        }
+        if (valueTerm instanceof StringLiteral) {
+            return getWriteBufferWriteMethodCall(logicalName, simpleTypeReference, "\"" + ((StringLiteral) valueTerm).getValue() + "\"", field, writerArgs);
+        }
+        throw new RuntimeException("Outputting " + valueTerm.toString() + " not implemented yet. Please continue defining other types in the PythonLanguageHelper.getWriteBufferWriteMethodCall.");
     }
 
-    private String toLiteralTermExpression(Field field, TypeReference resultType, Literal literal, Function<VariableLiteral, String> variableExpressionGenerator, Tracer tracer) {
-        tracer = tracer.dive("literal term instanceOf");
-        if (literal instanceof NullLiteral) {
-            tracer = tracer.dive("null literal instanceOf");
-            return tracer + "null";
-        } else if (literal instanceof BooleanLiteral) {
-            tracer = tracer.dive("boolean literal instanceOf");
-            String bool = Boolean.toString(((BooleanLiteral) literal).getValue());
-            return tracer + bool.substring(0,1).toUpperCase() + bool.substring(1);
-        } else if (literal instanceof NumericLiteral) {
-            tracer = tracer.dive("numeric literal instanceOf");
-            final String numberString = ((NumericLiteral) literal).getNumber().toString();
-            if (resultType.isIntegerTypeReference()) {
-                final IntegerTypeReference integerTypeReference = resultType.asIntegerTypeReference().orElseThrow(RuntimeException::new);
-                if (integerTypeReference.getBaseType() == SimpleTypeReference.SimpleBaseType.UINT && integerTypeReference.getSizeInBits() >= 32) {
-                    tracer = tracer.dive("uint >= 32bit");
-                    return tracer + numberString + "L";
-                } else if (integerTypeReference.getBaseType() == SimpleTypeReference.SimpleBaseType.INT && integerTypeReference.getSizeInBits() > 32) {
-                    tracer = tracer.dive("int > 32bit");
-                    return tracer + numberString + "L";
+    public String getWriteBufferWriteMethodCall(String logicalName, SimpleTypeReference simpleTypeReference, String fieldName, TypedField field, String... writerArgs) {
+        String writerArgsString = "";
+        if (writerArgs.length > 0) {
+            writerArgsString += ", " + StringUtils.join(writerArgs, ", ");
+        }
+        switch (simpleTypeReference.getBaseType()) {
+            case BIT:
+                return "writeBuffer.WriteBit(\"" + logicalName + "\", " + fieldName + writerArgsString + ")";
+            case BYTE:
+                return "writeBuffer.WriteByte(\"" + logicalName + "\", " + fieldName + writerArgsString + ")";
+            case UINT:
+                IntegerTypeReference unsignedIntegerTypeReference = (IntegerTypeReference) simpleTypeReference;
+                if (unsignedIntegerTypeReference.getSizeInBits() <= 8) {
+                    return "writeBuffer.WriteUint8(\"" + logicalName + "\", " + unsignedIntegerTypeReference.getSizeInBits() + ", " + fieldName + writerArgsString + ")";
+                }
+                if (unsignedIntegerTypeReference.getSizeInBits() <= 16) {
+                    return "writeBuffer.WriteUint16(\"" + logicalName + "\", " + unsignedIntegerTypeReference.getSizeInBits() + ", " + fieldName + writerArgsString + ")";
+                }
+                if (unsignedIntegerTypeReference.getSizeInBits() <= 32) {
+                    return "writeBuffer.WriteUint32(\"" + logicalName + "\", " + unsignedIntegerTypeReference.getSizeInBits() + ", " + fieldName + writerArgsString + ")";
                 }
-            } else if (resultType.isFloatTypeReference()) {
-                final FloatTypeReference floatTypeReference = resultType.asFloatTypeReference().orElseThrow(RuntimeException::new);
+                if (unsignedIntegerTypeReference.getSizeInBits() <= 64) {
+                    return "writeBuffer.WriteUint64(\"" + logicalName + "\", " + unsignedIntegerTypeReference.getSizeInBits() + ", " + fieldName + writerArgsString + ")";
+                }
+                return "writeBuffer.WriteBigInt(\"" + logicalName + "\", " + unsignedIntegerTypeReference.getSizeInBits() + ", " + fieldName + writerArgsString + ")";
+            case INT:
+                IntegerTypeReference integerTypeReference = (IntegerTypeReference) simpleTypeReference;
+                if (integerTypeReference.getSizeInBits() <= 8) {
+                    return "writeBuffer.WriteInt8(\"" + logicalName + "\", " + integerTypeReference.getSizeInBits() + ", " + fieldName + writerArgsString + ")";
+                }
+                if (integerTypeReference.getSizeInBits() <= 16) {
+                    return "writeBuffer.WriteInt16(\"" + logicalName + "\", " + integerTypeReference.getSizeInBits() + ", " + fieldName + writerArgsString + ")";
+                }
+                if (integerTypeReference.getSizeInBits() <= 32) {
+                    return "writeBuffer.WriteInt32(\"" + logicalName + "\", " + integerTypeReference.getSizeInBits() + ", " + fieldName + writerArgsString + ")";
+                }
+                if (integerTypeReference.getSizeInBits() <= 64) {
+                    return "writeBuffer.WriteInt64(\"" + logicalName + "\", " + integerTypeReference.getSizeInBits() + ", " + fieldName + writerArgsString + ")";
+                }
+                return "writeBuffer.WriteBigInt(\"" + logicalName + "\", " + integerTypeReference.getSizeInBits() + ", " + fieldName + writerArgsString + ")";
+            case FLOAT:
+            case UFLOAT:
+                FloatTypeReference floatTypeReference = (FloatTypeReference) simpleTypeReference;
                 if (floatTypeReference.getSizeInBits() <= 32) {
-                    tracer = tracer.dive("float < 32bit");
-                    return tracer + numberString + "F";
+                    return "writeBuffer.WriteFloat32(\"" + logicalName + "\", " + floatTypeReference.getSizeInBits() + ", " + fieldName + writerArgsString + ")";
                 }
-            }
-            return tracer + numberString;
-        } else if (literal instanceof HexadecimalLiteral) {
-            tracer = tracer.dive("hexadecimal literal instanceOf");
-            final String hexString = ((HexadecimalLiteral) literal).getHexString();
-            if (resultType.isIntegerTypeReference()) {
-                final IntegerTypeReference integerTypeReference = resultType.asIntegerTypeReference().orElseThrow(RuntimeException::new);
-                if (integerTypeReference.getBaseType() == SimpleTypeReference.SimpleBaseType.UINT && integerTypeReference.getSizeInBits() >= 32) {
-                    tracer = tracer.dive("uint >= 32bit");
-                    return tracer + hexString + "L";
-                } else if (integerTypeReference.getBaseType() == SimpleTypeReference.SimpleBaseType.INT && integerTypeReference.getSizeInBits() > 32) {
-                    tracer = tracer.dive("int > 32bit");
-                    return tracer + hexString + "L";
+                if (floatTypeReference.getSizeInBits() <= 64) {
+                    return "writeBuffer.WriteFloat64(\"" + logicalName + "\", " + floatTypeReference.getSizeInBits() + ", " + fieldName + writerArgsString + ")";
                 }
+                return "writeBuffer.WriteBigFloat(\"" + logicalName + "\", " + floatTypeReference.getSizeInBits() + ", " + fieldName + writerArgsString + ")";
+            case STRING: {
+                StringTypeReference stringTypeReference = (StringTypeReference) simpleTypeReference;
+                final Term encodingTerm = field.getEncoding().orElse(new DefaultStringLiteral("UTF-8"));
+                String encoding = encodingTerm.asLiteral()
+                    .orElseThrow(() -> new RuntimeException("Encoding must be a literal"))
+                    .asStringLiteral()
+                    .orElseThrow(() -> new RuntimeException("Encoding must be a quoted string value")).getValue();
+                String length = Integer.toString(simpleTypeReference.getSizeInBits());
+                return "writeBuffer.WriteString(\"" + logicalName + "\", uint32(" + length + "), \"" +
+                    encoding + "\", " + fieldName + writerArgsString + ")";
             }
-            return tracer + hexString;
-        } else if (literal instanceof StringLiteral) {
-            tracer = tracer.dive("string literal instanceOf");
-            return tracer + "\"" + ((StringLiteral) literal).getValue() + "\"";
-        } else if (literal instanceof VariableLiteral) {
-            tracer = tracer.dive("variable literal instanceOf");
-            VariableLiteral variableLiteral = (VariableLiteral) literal;
-            if ("curPos".equals(((VariableLiteral) literal).getName())) {
-                return "(positionAware.getPos() - startPos)";
-            }
-            // If this literal references an Enum type, then we have to output it differently.
-            if (getTypeDefinitions().get(variableLiteral.getName()) instanceof EnumTypeDefinition) {
-                tracer = tracer.dive("enum definition instanceOf");
-                VariableLiteral enumDefinitionChild = variableLiteral.getChild()
-                    .orElseThrow(() -> new RuntimeException("enum definitions should have childs"));
-                return tracer + variableLiteral.getName() + "." + enumDefinitionChild.getName() +
-                    enumDefinitionChild.getChild().map(child -> "." + toVariableExpressionRest(field, resultType, child)).orElse("");
-            } else {
-                return tracer + variableExpressionGenerator.apply(variableLiteral);
+            case VSTRING: {
+                VstringTypeReference vstringTypeReference = (VstringTypeReference) simpleTypeReference;
+                final Term encodingTerm = field.getEncoding().orElse(new DefaultStringLiteral("UTF-8"));
+                String encoding = encodingTerm.asLiteral()
+                    .orElseThrow(() -> new RuntimeException("Encoding must be a literal"))
+                    .asStringLiteral()
+                    .orElseThrow(() -> new RuntimeException("Encoding must be a quoted string value")).getValue();
+                String lengthExpression = toExpression(field, null, vstringTypeReference.getLengthExpression(), null, Collections.singletonList(new DefaultArgument("stringLength", new DefaultIntegerTypeReference(SimpleTypeReference.SimpleBaseType.INT, 32))), true, false);
+                String length = Integer.toString(simpleTypeReference.getSizeInBits());
+                return "writeBuffer.WriteString(\"" + logicalName + "\", uint32(" + lengthExpression + "), \"" +
+                    encoding + "\", " + fieldName + writerArgsString + ")";
             }
+            case DATE:
+            case TIME:
+            case DATETIME:
+                return "writeBuffer.WriteUint32(\"" + logicalName + "\", uint32(" + fieldName + ")" + writerArgsString + ")";
+            default:
+                throw new FreemarkerException("Unsupported base type " + simpleTypeReference.getBaseType());
+        }
+    }
+
+    public String getReservedValue(ReservedField reservedField) {
+        final String languageTypeName = getLanguageTypeNameForTypeReference(reservedField.getType());
+        switch (languageTypeName) {
+            case "*big.Int":
+                emitRequiredImport("math/big");
+                return "big.NewInt(" + reservedField.getReferenceValue() + ")";
+            case "*big.Float":
+                emitRequiredImport("math/big");
+                return "*big.Float(" + reservedField.getReferenceValue() + ")";
+            default:
+                return languageTypeName + "(" + reservedField.getReferenceValue() + ")";
+        }
+    }
+
+    public String toTypeSafeCompare(ReservedField reservedField) {
+        final String languageTypeName = getLanguageTypeNameForTypeReference(reservedField.getType());
+        switch (languageTypeName) {
+            case "*big.Int":
+            case "*big.Float":
+                emitRequiredImport("math/big");
+                return "reserved.Cmp(" + getReservedValue(reservedField) + ") != 0";
+            default:
+                return "reserved != " + getReservedValue(reservedField);
+        }
+    }
+
+    public String toParseExpression(Field field, TypeReference resultType, Term term, List<Argument> parserArguments) {
+        Tracer tracer = Tracer.start("toParseExpression");
+        return tracer + toTypedParseExpression(field, resultType, term, parserArguments);
+    }
+
+    public String toParseExpression(Field field, TypeReference resultType, Term term, List<Argument> parserArguments, boolean suppressPointerAccess) {
+        Tracer tracer = Tracer.start("toParseExpression");
+        return tracer + toTypedParseExpression(field, resultType, term, parserArguments, suppressPointerAccess);
+    }
+
+    public String toSerializationExpression(Field field, TypeReference resultType, Term term, List<Argument> serializerArguments) {
+        Tracer tracer = Tracer.start("toSerializationExpression");
+        return tracer + toTypedSerializationExpression(field, resultType, term, serializerArguments);
+    }
+
+    public String toBooleanParseExpression(Field field, Term term, List<Argument> parserArguments) {
+        Tracer tracer = Tracer.start("toBooleanParseExpression");
+        return tracer + toTypedParseExpression(field, new DefaultBooleanTypeReference(), term, parserArguments);
+    }
+
+    public String toBooleanSerializationExpression(Field field, Term term, List<Argument> serializerArguments) {
+        Tracer tracer = Tracer.start("toBooleanSerializationExpression");
+        return tracer + toTypedSerializationExpression(field, new DefaultBooleanTypeReference(), term, serializerArguments);
+    }
+
+    public String toIntegerParseExpression(Field field, int sizeInBits, Term term, List<Argument> parserArguments) {
+        Tracer tracer = Tracer.start("toIntegerParseExpression");
+        return tracer + toTypedParseExpression(field, new DefaultIntegerTypeReference(SimpleTypeReference.SimpleBaseType.UINT, sizeInBits), term, parserArguments);
+    }
+
+    public String toIntegerSerializationExpression(Field field, int sizeInBits, Term term, List<Argument> serializerArguments) {
+        Tracer tracer = Tracer.start("toIntegerSerializationExpression");
+        return tracer + toTypedSerializationExpression(field, new DefaultIntegerTypeReference(SimpleTypeReference.SimpleBaseType.UINT, sizeInBits), term, serializerArguments);
+    }
+
+    public String toTypedParseExpression(Field field, TypeReference fieldType, Term term, List<Argument> parserArguments) {
+        Tracer tracer = Tracer.start("toTypedParseExpression");
+        return tracer + toExpression(field, fieldType, term, parserArguments, null, false, fieldType != null && fieldType.isComplexTypeReference());
+    }
+
+    public String toTypedParseExpression(Field field, TypeReference fieldType, Term term, List<Argument> parserArguments, boolean suppressPointerAccess) {
+        Tracer tracer = Tracer.start("toTypedParseExpression");
+        return tracer + toExpression(field, fieldType, term, parserArguments, null, false, suppressPointerAccess);
+    }
+
+    public String toTypedSerializationExpression(Field field, TypeReference fieldType, Term term, List<Argument> serializerArguments) {
+        Tracer tracer = Tracer.start("toTypedSerializationExpression");
+        return tracer + toExpression(field, fieldType, term, null, serializerArguments, true, false);
+    }
+
+    String getCastExpressionForTypeReference(TypeReference typeReference) {
+        Tracer tracer = Tracer.start("castExpression");
+        if (typeReference instanceof SimpleTypeReference) {
+            return tracer.dive("simpleTypeRef") + getLanguageTypeNameForTypeReference(typeReference);
+        } else if (typeReference instanceof ByteOrderTypeReference) {
+            return tracer.dive( "byteOrderTypeRef") + "binary.ByteOrder";
+        } else if (typeReference != null) {
+            return tracer.dive("anyTypeRef") + "Cast" + getLanguageTypeNameForTypeReference(typeReference);
         } else {
-            throw new RuntimeException("Unsupported Literal type " + literal.getClass().getName());
+            return tracer.dive("noTypeRef") + "";
         }
     }
 
-    private String toUnaryTermExpression(Field field, TypeReference resultType, UnaryTerm unaryTerm, Function<VariableLiteral, String> variableExpressionGenerator, Tracer tracer) {
-        tracer = tracer.dive("unary term instanceOf");
-        Term a = unaryTerm.getA();
-        switch (unaryTerm.getOperation()) {
-            case "!":
-                tracer = tracer.dive("case !");
-                if ((resultType != getAnyTypeReference()) && !resultType.isBooleanTypeReference()) {
-                    throw new IllegalArgumentException("'!(...)' expression requires boolean type. Actual type " + resultType);
+    private String toExpression(Field field, TypeReference fieldType, Term term, List<Argument> parserArguments, List<Argument> serializerArguments, boolean serialize, boolean suppressPointerAccess) {
+        Tracer tracer = Tracer.start("toExpression(suppressPointerAccess=" + suppressPointerAccess + ")");
+        if (term == null) {
+            return "";
+        }
+        if (term instanceof Literal) {
+            return toLiteralTermExpression(field, fieldType, term, parserArguments, serializerArguments, serialize, suppressPointerAccess, tracer);
+        } else if (term instanceof UnaryTerm) {
+            return toUnaryTermExpression(field, fieldType, (UnaryTerm) term, parserArguments, serializerArguments, serialize, tracer);
+        } else if (term instanceof BinaryTerm) {
+            return toBinaryTermExpression(field, fieldType, (BinaryTerm) term, parserArguments, serializerArguments, serialize, tracer);
+        } else if (term instanceof TernaryTerm) {
+            return toTernaryTermExpression(field, fieldType, (TernaryTerm) term, parserArguments, serializerArguments, serialize, tracer);
+        } else {
+            throw new RuntimeException("Unsupported Term type " + term.getClass().getName());
+        }
+    }
+
+    private String toTernaryTermExpression(Field field, TypeReference fieldType, TernaryTerm ternaryTerm, List<Argument> parserArguments, List<Argument> serializerArguments, boolean serialize, Tracer tracer) {
+        tracer = tracer.dive("ternary term instanceOf");
+        if ("if".equals(ternaryTerm.getOperation())) {
+            Term a = ternaryTerm.getA();
+            Term b = ternaryTerm.getB();
+            Term c = ternaryTerm.getC();
+            String castExpressionForTypeReference = getCastExpressionForTypeReference(fieldType);
+            String inlineIf = "utils.InlineIf(" + toExpression(field, new DefaultBooleanTypeReference(), a, parserArguments, serializerArguments, serialize, false) + ", " +
+                "func() any {return " + castExpressionForTypeReference + "(" + toExpression(field, fieldType, b, parserArguments, serializerArguments, serialize, false) + ")}, " +
+                "func() any {return " + castExpressionForTypeReference + "(" + toExpression(field, fieldType, c, parserArguments, serializerArguments, serialize, false) + ")})";
+            if (fieldType != null) {
+                if (fieldType instanceof ByteOrderTypeReference) {
+                    return tracer.dive("byteordertypereference") + "(" + inlineIf + ").(binary.ByteOrder)";
                 }
-                return tracer + "!(" + toExpression(field, resultType, a, variableExpressionGenerator) + ")";
-            case "-":
-                tracer = tracer.dive("case -");
-                if ((resultType != getAnyTypeReference()) && !resultType.isIntegerTypeReference() && !resultType.isFloatTypeReference()) {
-                    throw new IllegalArgumentException("'-(...)' expression requires integer or floating-point type. Actual type " + resultType);
+                if (fieldType.isNonSimpleTypeReference()) {
+                    return tracer.dive("nonsimpletypereference") + castExpressionForTypeReference + "(" + inlineIf + ")";
                 }
-                return tracer + "-(" + toExpression(field, resultType, a, variableExpressionGenerator) + ")";
-            case "()":
-                tracer = tracer.dive("case ()");
-                return tracer + "(" + toExpression(field, resultType, a, variableExpressionGenerator) + ")";
-            default:
-                throw new RuntimeException("Unsupported unary operation type " + unaryTerm.getOperation() + ". Actual type " + resultType);
+                return tracer + inlineIf + ".(" + castExpressionForTypeReference + ")";
+            }
+            return tracer + inlineIf;
+        } else {
+            throw new RuntimeException("Unsupported ternary operation type " + ternaryTerm.getOperation());
         }
     }
 
-    private String toBinaryTermExpression(Field field, TypeReference resultType, BinaryTerm binaryTerm, Function<VariableLiteral, String> variableExpressionGenerator, Tracer tracer) {
+    private String toBinaryTermExpression(Field field, TypeReference fieldType, BinaryTerm binaryTerm, List<Argument> parserArguments, List<Argument> serializerArguments, boolean serialize, Tracer tracer) {
         tracer = tracer.dive("binary term instanceOf");
         Term a = binaryTerm.getA();
         Term b = binaryTerm.getB();
         String operation = binaryTerm.getOperation();
+        String castExpressionForTypeReference = getCastExpressionForTypeReference(fieldType);
         switch (operation) {
-            case "^": {
-                tracer = tracer.dive(operation);
-                if ((resultType != getAnyTypeReference()) && !resultType.isIntegerTypeReference() && !resultType.isFloatTypeReference()) {
-                    throw new IllegalArgumentException("'A^B' expression requires numeric result type. Actual type " + resultType);
-                }
-                return tracer + "Math.pow((" + toExpression(field, resultType, a, variableExpressionGenerator) + "), (" + toExpression(field, resultType, b, variableExpressionGenerator) + "))";
-            }
-            case "*":
-            case "/":
-            case "%":
-            case "+":
-            case "-": {
-                tracer = tracer.dive(operation);
-                if ((resultType != getAnyTypeReference()) && !resultType.isIntegerTypeReference() && !resultType.isFloatTypeReference()) {
-                    throw new IllegalArgumentException("'A" + operation + "B' expression requires numeric result type. Actual type " + resultType);
-                }
-                return tracer + "(" + toExpression(field, resultType, a, variableExpressionGenerator) + ") " + operation + " (" + toExpression(field, resultType, b, variableExpressionGenerator) + ")";
-            }
-            case ">>":
-            case "<<": {
-                tracer = tracer.dive(operation);
-                return tracer + "(" + toExpression(field, resultType, a, variableExpressionGenerator) + ") " + operation + " (" + toExpression(field, INT_TYPE_REFERENCE, b, variableExpressionGenerator) + ")";
-            }
-            case ">=":
-            case "<=":
-            case ">":
-            case "<":
+            case "^":
+                tracer = tracer.dive("^");
+                emitRequiredImport("math");
+                return tracer + "Math.pow(" +
+                    castExpressionForTypeReference + "(" + toExpression(field, fieldType, a, parserArguments, serializerArguments, serialize, false) + "), " +
+                    castExpressionForTypeReference + "(" + toExpression(field, fieldType, b, parserArguments, serializerArguments, serialize, false) + "))";
+            // If we start casting for comparisons, equals or non equals, really messy things happen.
             case "==":
             case "!=":
-                if ((resultType != getAnyTypeReference()) && !resultType.isBooleanTypeReference()) {
-                    throw new IllegalArgumentException("'A" + operation + "B' expression requires boolean result type. Actual type " + resultType);
-                }
-                // TODO: Try to infer the types of the arguments in this case
-                return tracer + "(" + toExpression(field, ANY_TYPE_REFERENCE, a, variableExpressionGenerator) + ") " + operation + " (" + toExpression(field, ANY_TYPE_REFERENCE, b, variableExpressionGenerator) + ")";
-            case "&&":
-            case "||":
-                if ((resultType != getAnyTypeReference()) && !resultType.isBooleanTypeReference()) {
-                    throw new IllegalArgumentException("'A" + operation + "B' expression requires boolean result type. Actual type " + resultType);
-                }
-                return tracer + "(" + toExpression(field, resultType, a, variableExpressionGenerator) + ") " + operation + " (" + toExpression(field, resultType, b, variableExpressionGenerator) + ")";
-            case "&":
+            case ">":
+            case "<":
+            case ">=":
+            case "<=":
+                tracer = tracer.dive("compare");
+                // For every access of optional elements we need pointer access ...
+                // Except for doing a nil or not-nil check :-(
+                // So in case of such a check, we need to suppress the pointer-access.
+                boolean suppressPointerAccessOverride = (operation.equals("==") || operation.equals("!=")) && ((a instanceof NullLiteral) || (b instanceof NullLiteral));
+                String aExpression = toExpression(field, null, a, parserArguments, serializerArguments, serialize, suppressPointerAccessOverride);
+                String bExpression = toExpression(field, null, b, parserArguments, serializerArguments, serialize, suppressPointerAccessOverride);
+                return tracer + "bool((" + aExpression + ") " + operation + " (" + bExpression + "))";
+            case ">>":
+            case "<<":
             case "|":
-                if ((resultType != getAnyTypeReference()) && !resultType.isIntegerTypeReference() && !resultType.isByteTypeReference()) {
-                    throw new IllegalArgumentException("'A" + operation + "B' expression requires byte or integer result type. Actual type " + resultType);
-                }
-                return tracer + "(" + toExpression(field, resultType, a, variableExpressionGenerator) + ") " + operation + " (" + toExpression(field, resultType, b, variableExpressionGenerator) + ")";
+            case "&":
+                tracer = tracer.dive("bitwise");
+                // We don't want casts here
+                return tracer +
+                    toExpression(field, fieldType, a, parserArguments, serializerArguments, serialize, false) +
+                    operation + " " +
+                    toExpression(field, fieldType, b, parserArguments, serializerArguments, serialize, false);
             default:
-                throw new IllegalArgumentException("Unsupported ternary operation type " + operation);
+                tracer = tracer.dive("default");
+                if (fieldType instanceof StringTypeReference) {
+                    tracer = tracer.dive("string type reference");
+                    return tracer + toExpression(field, fieldType, a, parserArguments, serializerArguments, serialize, false) +
+                        operation + " " +
+                        toExpression(field, fieldType, b, parserArguments, serializerArguments, serialize, false);
+                }
+                return tracer +
+                    castExpressionForTypeReference + "(" + toExpression(field, fieldType, a, parserArguments, serializerArguments, serialize, false) + ") " +
+                    operation + " " +
+                    castExpressionForTypeReference + "(" + toExpression(field, fieldType, b, parserArguments, serializerArguments, serialize, false) + ")";
         }
     }
 
-    private String toTernaryTermExpression(Field field, TypeReference resultType, TernaryTerm ternaryTerm, Function<VariableLiteral, String> variableExpressionGenerator, Tracer tracer) {
-        tracer = tracer.dive("ternary term instanceOf");
-        if ("if".equals(ternaryTerm.getOperation())) {
-            Term a = ternaryTerm.getA();
-            Term b = ternaryTerm.getB();
-            Term c = ternaryTerm.getC();
-            return tracer +
-                "(" +
-                "(" + toExpression(field, BOOL_TYPE_REFERENCE, a, variableExpressionGenerator) + ") ? " +
-                toExpression(field, resultType, b, variableExpressionGenerator) + " : " +
-                toExpression(field, resultType, c, variableExpressionGenerator) + "" +
-                ")";
-        } else {
-            throw new IllegalArgumentException("Unsupported ternary operation type " + ternaryTerm.getOperation() + ". Actual type " + resultType);
+    private String toUnaryTermExpression(Field field, TypeReference fieldType, UnaryTerm unaryTerm, List<Argument> parserArguments, List<Argument> serializerArguments, boolean serialize, Tracer tracer) {
+        tracer = tracer.dive("unary term instanceOf");
+        Term a = unaryTerm.getA();
+        switch (unaryTerm.getOperation()) {
+            case "!":
+                tracer = tracer.dive("case !");
+                return tracer + "!(" + toExpression(field, fieldType, a, parserArguments, serializerArguments, serialize, false) + ")";
+            case "-":
+                tracer = tracer.dive("case -");
+                return tracer + "-(" + toExpression(field, fieldType, a, parserArguments, serializerArguments, serialize, false) + ")";
+            case "()":
+                tracer = tracer.dive("case ()");
+                return tracer + "(" + toExpression(field, fieldType, a, parserArguments, serializerArguments, serialize, false) + ")";
+            default:
+                throw new RuntimeException("Unsupported unary operation type " + unaryTerm.getOperation());
         }
     }
 
-    public String toVariableEnumAccessExpression(VariableLiteral variableLiteral) {
-        return variableLiteral.getName();
-    }
-
-    private String toVariableParseExpression(Field field, TypeReference resultType, VariableLiteral variableLiteral, List<Argument> parserArguments) {
-        Tracer tracer = Tracer.start("toVariableParseExpression");
-        // CAST expressions are special as we need to add a ".class" to the second parameter in Java.
-        if ("CAST".equals(variableLiteral.getName())) {
-            return toCastVariableParseExpression(field, resultType, variableLiteral, parserArguments, tracer);
-        }
-        // Special handling for ByteOrder enums (Built in enums)
-        else if ("BIG_ENDIAN".equals(variableLiteral.getName())) {
-            return "ByteOrder.BIG_ENDIAN";
-        } else if ("LITTLE_ENDIAN".equals(variableLiteral.getName())) {
-            return "ByteOrder.LITTLE_ENDIAN";
-        }
-        // If we're referencing an implicit field, we need to handle that differently.
-        else if (isVariableLiteralImplicitField(variableLiteral)) { // If we are accessing implicit fields, we need to rely on a local variable instead.
-            return toImplicitVariableParseExpression(field, resultType, variableLiteral, tracer);
-        }
-        // Call a static function in the drivers StaticHelper
-        else if ("STATIC_CALL".equals(variableLiteral.getName())) {
-            return toStaticCallParseExpression(field, resultType, variableLiteral, parserArguments, tracer);
-        }
-        // Call a built-in global static function
-        else if (variableLiteral.getName().equals(variableLiteral.getName().toUpperCase())) { // All uppercase names are not fields, but utility methods.
-            return toFunctionCallParseExpression(field, resultType, variableLiteral, parserArguments, tracer);
-        }
-        // The synthetic checksumRawData is a local field and should not be accessed as bean property.
-        boolean isParserArg = "read_buffer".equals(variableLiteral.getName());
-        boolean isTypeArg = "_type".equals(variableLiteral.getName());
-        if (!isParserArg && !isTypeArg && parserArguments != null) {
-            for (Argument serializerArgument : parserArguments) {
-                if (serializerArgument.getName().equals(variableLiteral.getName())) {
-                    isParserArg = true;
-                    break;
-                }
+    private String toLiteralTermExpression(Field field, TypeReference fieldType, Term term, List<Argument> parserArguments, List<Argument> serializerArguments, boolean serialize, boolean suppressPointerAccess, Tracer tracer) {
+        tracer = tracer.dive("literal term instanceOf");
+        if (term instanceof NullLiteral) {
+            tracer = tracer.dive("null literal instanceOf");
+            return tracer + "None";
+        } else if (term instanceof BooleanLiteral) {
+            tracer = tracer.dive("boolean literal instanceOf");
+            return tracer + getCastExpressionForTypeReference(fieldType) + "(" + ((BooleanLiteral) term).getValue() + ")";
+        } else if (term instanceof NumericLiteral) {
+            tracer = tracer.dive("numeric literal instanceOf");
+            if (getCastExpressionForTypeReference(fieldType).equals("string")) {
+                tracer = tracer.dive("type reference string");
+                return tracer + "(" + ((NumericLiteral) term).getNumber().toString() + ")";
+            } else {
+                return tracer + getCastExpressionForTypeReference(fieldType) + "(" + ((NumericLiteral) term).getNumber().toString() + ")";
             }
-        }
-        if (isParserArg) {
-            tracer = tracer.dive("parser arg");
-            return tracer + variableLiteral.getName() + variableLiteral.getChild().map(child -> "." + toVariableExpressionRest(field, resultType, child)).orElse("");
-        } else if (isTypeArg) {
-            tracer = tracer.dive("type arg");
-            String part = variableLiteral.getChild().map(VariableLiteral::getName).orElse("");
-            switch (part) {
-                case "name":
-                    return tracer + "\"" + field.getTypeName() + "\"";
-                case "length":
-                    return tracer + "\"" + ((SimpleTypeReference) field).getSizeInBits() + "\"";
-                case "encoding":
-                    String encoding = ((StringLiteral) field.getEncoding().orElse(new DefaultStringLiteral("UTF-8"))).getValue();
-                    return tracer + "\"" + encoding + "\"";
-                default:
-                    return tracer + "";
+        } else if (term instanceof HexadecimalLiteral) {
+            tracer = tracer.dive("hexadecimal literal instanceOf");
+            return tracer + ((HexadecimalLiteral) term).getHexString();
+        } else if (term instanceof StringLiteral) {
+            tracer = tracer.dive("string literal instanceOf");
+            return tracer + "\"" + ((StringLiteral) term).getValue() + "\"";
+        } else if (term instanceof VariableLiteral) {
+            tracer = tracer.dive("variable literal instanceOf");
+            VariableLiteral variableLiteral = (VariableLiteral) term;
+            if ("curPos".equals(((VariableLiteral) term).getName())) {
+                return "(positionAware.GetPos() - startPos)";
+            } else if ("BIG_ENDIAN".equals(((VariableLiteral) term).getName()) && (fieldType instanceof ByteOrderTypeReference)) {
+                return "binary.BigEndian";
+            } else if ("LITTLE_ENDIAN".equals(((VariableLiteral) term).getName()) && (fieldType instanceof ByteOrderTypeReference)) {
+                return "binary.LittleEndian";
             }
+            return tracer + toVariableExpression(field, fieldType, (VariableLiteral) term, parserArguments, serializerArguments, serialize, suppressPointerAccess);
         } else {
-            String indexAddon = "";
-            if (variableLiteral.getIndex().isPresent()) {
-                indexAddon = ".get(" + variableLiteral.getIndex().orElseThrow() + ")";
-            }
-            return tracer + variableLiteral.getName() + indexAddon + variableLiteral.getChild().map(child -> "." + toVariableExpressionRest(field, resultType, child)).orElse("");
+            throw new RuntimeException("Unsupported Literal type " + term.getClass().getName());
         }
     }
 
-    private String toCastVariableParseExpression(Field field, TypeReference resultType, VariableLiteral variableLiteral, List<Argument> parserArguments, Tracer tracer) {
-        tracer = tracer.dive("CAST");
-        List<Term> arguments = variableLiteral.getArgs().orElseThrow(() -> new RuntimeException("A Cast expression needs arguments"));
-        if (arguments.size() != 2) {
-            throw new RuntimeException("A CAST expression expects exactly two arguments.");
-        }
-        VariableLiteral firstArgument = arguments.get(0).asLiteral()
-            .orElseThrow(() -> new RuntimeException("First argument should be a literal"))
-            .asVariableLiteral()
-            .orElseThrow(() -> new RuntimeException("First argument should be a Variable literal"));
-        StringLiteral typeArgument = arguments.get(1).asLiteral().orElseThrow(() -> new RuntimeException("Second argument should be a String literal"))
-            .asStringLiteral()
-            .orElseThrow(() -> new RuntimeException("Second argument should be a String literal"));
-        String sb = "CAST" + "(" +
-            toVariableParseExpression(field, ANY_TYPE_REFERENCE, firstArgument, parserArguments) +
-            ", " +
-            typeArgument.getValue() + ".class)";
-        return tracer + sb + variableLiteral.getChild().map(child -> "." + toVariableExpressionRest(field, resultType, child)).orElse("");
+    private String toVariableExpression(Field field, TypeReference typeReference, VariableLiteral variableLiteral, List<Argument> parserArguments, List<Argument> serializerArguments, boolean serialize, boolean suppressPointerAccess) {
+        return toVariableExpression(field, typeReference, variableLiteral, parserArguments, serializerArguments, serialize, suppressPointerAccess, false);
     }
 
-    private String toImplicitVariableParseExpression(Field field, TypeReference resultType, VariableLiteral variableLiteral, Tracer tracer) {
-        tracer = tracer.dive("implicit");
-        return tracer + variableLiteral.getName();
-    }
+    private String toVariableExpression(Field field, TypeReference typeReference, VariableLiteral variableLiteral, List<Argument> parserArguments, List<Argument> serializerArguments, boolean serialize, boolean suppressPointerAccess, boolean isChild) {
+        Tracer tracer = Tracer.start("toVariableExpression(serialize=" + serialize + ")");
+        String variableLiteralName = variableLiteral.getName();
+        boolean isEnumTypeReference = typeReference != null && typeReference.isEnumTypeReference();
+        if ("lengthInBytes".equals(variableLiteralName)) {
+            return toLengthInBytesVariableExpression(typeReference, serialize, tracer);
+        } else if ("lengthInBits".equals(variableLiteralName)) {
+            return toLengthInBitsVariableExpression(typeReference, serialize, tracer);
+        } else if ("_value".equals(variableLiteralName)) {
+            return toValueVariableExpression(field, typeReference, variableLiteral, parserArguments, serializerArguments, serialize, suppressPointerAccess, tracer);
+        }
+        if ("_lastItem".equals(variableLiteralName)) {
+            return toLastItemVariableExpression(typeReference, serialize, tracer);
+        }
+        if ("length".equals(variableLiteral.getChild().map(VariableLiteral::getName).orElse(""))) {
+            return toLengthVariableExpression(field, variableLiteral, serialize, tracer);
+        }
+        // If this literal references an Enum type, then we have to output it differently.
+        else if (getTypeDefinitions().get(variableLiteralName) instanceof EnumTypeDefinition) {
+            return toEnumVariableExpression(field, typeReference, variableLiteral, parserArguments, serializerArguments, suppressPointerAccess, tracer);
+        }
+        // If we are accessing enum constants, these also need to be output differently.
+        else if (thisType.isComplexTypeDefinition()
+            && thisType.asComplexTypeDefinition()
+            .orElseThrow(IllegalAccessError::new)
+            .getPropertyFieldByName(variableLiteralName)
+            .filter(EnumField.class::isInstance)
+            .isPresent()
+            && (variableLiteral.getChild().isPresent())
+        ) {
+            return toConstantVariableExpression(field, typeReference, variableLiteral, parserArguments, serializerArguments, suppressPointerAccess, tracer);
+        }
+        // If we are accessing optional fields, (we might need to use pointer-access).
+        else if (!serialize && thisType.isComplexTypeDefinition()
+            && thisType.asComplexTypeDefinition()
+            .orElseThrow(IllegalStateException::new)
+            .getPropertyFieldByName(variableLiteralName)
+            .filter(OptionalField.class::isInstance)
+            .isPresent()
+        ) {
+            tracer = tracer.dive("non serialize optional fields");
+            return toOptionalVariableExpression(field, typeReference, variableLiteral, parserArguments, serializerArguments, suppressPointerAccess, tracer);
+        }
+        // If we are accessing optional fields, (we might need to use pointer-access).
+        else if (thisType.isComplexTypeDefinition()
+            && thisType.asComplexTypeDefinition()
+            .orElseThrow(IllegalStateException::new)
+            .getPropertyFieldByName(variableLiteralName)
+            .filter(OptionalField.class::isInstance)
+            .isPresent()
+        ) {
+            tracer = tracer.dive("optional fields");
+            OptionalField optionalField = thisType.asComplexTypeDefinition().orElseThrow().getPropertyFieldByName(variableLiteralName).orElseThrow().asOptionalField().orElseThrow();
+            return tracer + "(" + (suppressPointerAccess || optionalField.getType().isComplexTypeReference() ? "" : "*") + "self." + camelCaseToSnakeCase(variableLiteral.getName()) + ")" +
+                variableLiteral.getChild().map(child -> "." + camelCaseToSnakeCase(toVariableExpression(field, typeReference, child, parserArguments, serializerArguments, false, suppressPointerAccess, true))).orElse("");
+        }
+        // If we are accessing implicit fields, we need to rely on local variable instead.
+        //else if (isVariableLiteralImplicitField(vl)) {
+        //    tracer = tracer.dive("implicit");
+        //    return tracer + (serialize ? vl.getName() : vl.getName()) + ((vl.getChild() != null) ?
+        //        "." + capitalize(toVariableExpression(typeReference, vl.getChild(), parserArguments, serializerArguments, false, suppressPointerAccess)) : "");
+        //}
+        // If we are accessing implicit fields, we need to rely on a local variable instead.
 
-    private String toStaticCallParseExpression(Field field, TypeReference resultType, VariableLiteral variableLiteral, List<Argument> parserArguments, Tracer tracer) {
-        tracer = tracer.dive("STATIC_CALL");
-        List<Term> arguments = variableLiteral.getArgs().orElseThrow(() -> new RuntimeException("A STATIC_CALL expression needs arguments"));
-        if (arguments.size() < 1) {
-            throw new RuntimeException("A STATIC_CALL expression expects at least one argument.");
+        // CAST expressions are special as we need to add a ".class" to the second parameter in Java.
+        else if ("CAST".equals(variableLiteralName)) {
+            return toCastVariableExpression(field, typeReference, variableLiteral, parserArguments, serializerArguments, serialize, suppressPointerAccess, tracer);
+        } else if ("STATIC_CALL".equals(variableLiteralName)) {
+            return toStaticCallVariableExpression(field, typeReference, variableLiteral, parserArguments, serializerArguments, serialize, suppressPointerAccess, tracer);
+        } else if (!isEnumTypeReference && "COUNT".equals(variableLiteralName)) {
+            return toCountVariableExpression(field, typeReference, variableLiteral, parserArguments, serializerArguments, serialize, suppressPointerAccess, tracer);
+        } else if (!isEnumTypeReference && "ARRAY_SIZE_IN_BYTES".equals(variableLiteralName)) {
+            return toArraySizeInBytesVariableExpression(field, typeReference, variableLiteral, parserArguments, serializerArguments, suppressPointerAccess, tracer);
+        } else if ("CEIL".equals(variableLiteralName)) {
+            return toCeilVariableExpression(field, variableLiteral, parserArguments, serializerArguments, serialize, suppressPointerAccess, tracer);
+        } else if ("STR_LEN".equals(variableLiteralName)) {
+            return toStrLenVariableExpression(field, typeReference, variableLiteral, parserArguments, serializerArguments, serialize, suppressPointerAccess, tracer);
         }
-        // TODO: make it as static import with a emitImport so if a static call is present a "utils" package must be present in the import
-        StringBuilder sb = new StringBuilder();
-        sb.append(packageName()).append(".utils.StaticHelper.");
-        // Get the class and method name
-        String methodName = arguments.get(0).asLiteral()
-            .orElseThrow(() -> new RuntimeException("First argument should be a literal"))
-            .asStringLiteral()
-            .orElseThrow(() -> new RuntimeException("Expecting the first argument of a 'STATIC_CALL' to be a StringLiteral")).
-            getValue();
-        sb.append(methodName).append("(");
-        for (int i = 1; i < arguments.size(); i++) {
-            Term arg = arguments.get(i);
-            if (i > 1) {
-                sb.append(", ");
-            }
-            sb.append(toParseExpression(field, ANY_TYPE_REFERENCE, arg, parserArguments));
-           /*if (arg instanceof VariableLiteral) {
-                VariableLiteral variableLiteralArg = (VariableLiteral) arg;
-                // "readBuffer" is the default name of the reader argument which is always available.
-                boolean isParserArg = "readBuffer".equals(variableLiteralArg.getName());
-                boolean isTypeArg = "_type".equals(variableLiteralArg.getName());
-                if (!isParserArg && !isTypeArg && parserArguments != null) {
-                    for (Argument parserArgument : parserArguments) {
-                        if (parserArgument.getName().equals(variableLiteralArg.getName())) {
-                            isParserArg = true;
-                            break;
-                        }
+        // All uppercase names are not fields, but utility methods.
+        // TODO: It seems we also run into this, in case of using enum constants in type-switches.
+        else if (variableLiteralName.equals(variableLiteralName.toUpperCase())) {
+            tracer = tracer.dive("utility");
+            return toUppercaseVariableExpression(field, typeReference, variableLiteral, parserArguments, serializerArguments, serialize, suppressPointerAccess, tracer);
+        }
+        // If the current property references a discriminator value, we have to serialize it differently.
+        else if (thisType.isComplexTypeDefinition() && thisType.asComplexTypeDefinition()
+            .orElseThrow(IllegalStateException::new)
+            .getPropertyFieldFromThisOrParentByName(variableLiteralName)
+            .filter(DiscriminatorField.class::isInstance)
+            .isPresent()) {
+            tracer = tracer.dive("discriminator value");
+            // TODO: Should this return something?
+        }
+        // If the variable has a child element and we're able to find a type for this ... get the type.
+        else if ((variableLiteral.getChild().isPresent()) && ((ComplexTypeDefinition) thisType).getTypeReferenceForProperty(variableLiteralName).isPresent()) {
+            tracer = tracer.dive("child element");
+            final Optional<NonSimpleTypeReference> typeReferenceForProperty = ((ComplexTypeDefinition) thisType).getTypeReferenceForProperty(variableLiteralName)
+                .flatMap(TypeReferenceConversions::asNonSimpleTypeReference);
+            if (typeReferenceForProperty.isPresent()) {
+                tracer = tracer.dive("complex");
+                final NonSimpleTypeReference nonSimpleTypeReference = typeReferenceForProperty.get();
+                TypeDefinition typeDefinition = nonSimpleTypeReference.getTypeDefinition();
+                if (typeDefinition instanceof ComplexTypeDefinition) {
+                    tracer = tracer.dive("complex");
+                    ComplexTypeDefinition complexTypeDefinition = (ComplexTypeDefinition) typeDefinition;
+                    String childProperty = variableLiteral.getChild()
+                        .orElseThrow(() -> new RuntimeException("complex needs a child"))
+                        .getName();
+                    final Optional<Field> matchingDiscriminatorField = complexTypeDefinition.getFields().stream()
+                        .filter(curField -> (curField instanceof DiscriminatorField) && ((DiscriminatorField) curField).getName().equals(childProperty))
+                        .findFirst();
+                    if (matchingDiscriminatorField.isPresent()) {
+                        return tracer + "Cast" + getLanguageTypeNameForTypeReference(nonSimpleTypeReference) + "(" + variableLiteralName + ").get_" + camelCaseToSnakeCase(childProperty) + "()";
                     }
-                }
-                if (isParserArg) {
-                    sb.append(variableLiteralArg.getName()).append(variableLiteralArg.getChild().map(child -> "." + toVariableExpressionRest(child)).orElse(""));
-                } else if (isTypeArg) {// We have to manually evaluate the type information at code-generation time.
-                    String part = variableLiteralArg.getChild().map(VariableLiteral::getName).orElse("");
-                    switch (part) {
-                        case "name":
-                            sb.append("\"").append(field.getTypeName()).append("\"");
-                            break;
-                        case "length":
-                            sb.append("\"").append(((SimpleTypeReference) field).getSizeInBits()).append("\"");
-                            break;
-                        case "encoding":
-                            String encoding = ((StringLiteral) field.getEncoding().orElse(new DefaultStringLiteral("UTF-8"))).getValue();
-                            sb.append("\"").append(encoding).append("\"");
-                            break;
+                    // TODO: is this really meant to fall through?
+                    tracer = tracer.dive("we fell through the complex complex");
+                } else if (typeDefinition instanceof EnumTypeDefinition) {
+                    tracer = tracer.dive("enum");
+                    String variableAccess = variableLiteralName;
+                    if (isChild) {
+                        variableAccess = "" + camelCaseToSnakeCase(variableLiteralName);
                     }
-                } else {
-                    sb.append(toVariableParseExpression(field, variableLiteralArg, null));
+                    return tracer + (serialize ? "self." + camelCaseToSnakeCase(variableLiteralName) + "" : variableAccess) +
+                        "." + camelCaseToSnakeCase(variableLiteral.getChild().orElseThrow(() -> new RuntimeException("enum needs a child")).getName()) + "()";
                 }
-            } else if (arg instanceof StringLiteral) {
-                sb.append(((StringLiteral) arg).getValue());
-            }*/
+            }
+            // TODO: is this really meant to fall through?
+            tracer = tracer.dive("we fell through the child complete");
+        } else if (isVariableLiteralImplicitField(variableLiteral)) {
+            tracer = tracer.dive("implicit");
+            if (serialize) {
+                tracer = tracer.dive("serialize");
+                final ImplicitField referencedImplicitField = getReferencedImplicitField(variableLiteral);
+                return tracer + toSerializationExpression(referencedImplicitField, referencedImplicitField.getType(), getReferencedImplicitField(variableLiteral).getSerializeExpression(), serializerArguments);
+            } else {
+                return tracer + variableLiteralName;
+                //return toParseExpression(getReferencedImplicitField(vl), getReferencedImplicitField(vl).getSerializeExpression(), serializerArguments);
+            }
         }
-        sb.append(")");
+
+        // This is a special case for DataIo string types, which need to access the stringLength
+        if ((serializerArguments != null) && serializerArguments.stream()
+            .anyMatch(argument -> argument.getName().equals(variableLiteralName)) && "stringLength".equals(variableLiteralName)) {
+            tracer = tracer.dive("serialization argument");
+            return tracer + variableLiteralName +
+                variableLiteral.getChild()
+                    .map(child -> "." + camelCaseToSnakeCase(toVariableExpression(field, typeReference, child, parserArguments, serializerArguments, false, suppressPointerAccess, true)))
+                    .orElse("");
+        } else if ((serializerArguments != null) && serializerArguments.stream()
+            .anyMatch(argument -> argument.getName().equals(variableLiteralName))) {
+            tracer = tracer.dive("serialization argument");
+            return tracer + "self." + camelCaseToSnakeCase(variableLiteralName) +
+                variableLiteral.getChild()
+                    .map(child -> "." + camelCaseToSnakeCase(toVariableExpression(field, typeReference, child, parserArguments, serializerArguments, false, suppressPointerAccess, true)))
+                    .orElse("");
+        }
+        if ((parserArguments != null) && parserArguments.stream()
+            .anyMatch(argument -> argument.getName().equals(variableLiteralName))) {
+            tracer = tracer.dive("parser argument");
+            return tracer + variableLiteralName +
+                variableLiteral.getChild()
+                    .map(child -> "." + camelCaseToSnakeCase(toVariableExpression(field, typeReference, child, parserArguments, serializerArguments, false, suppressPointerAccess, true)))
+                    .orElse("");
+        }
+        String indexCall = "";
         if (variableLiteral.getIndex().isPresent()) {
-            // TODO: If this is a byte typed field, this needs to be an array accessor instead.
-            sb.append(".get(").append(variableLiteral.getIndex().orElseThrow()).append(")");
+            tracer = tracer.dive("indexCall");
+            // We have a index call
+            indexCall = "[" + variableLiteral.getIndex().orElseThrow() + "]";
         }
-        return tracer + sb.toString();
+        tracer = tracer.dive("else");
+        Tracer tracer2 = tracer;
+        String variableAccess = variableLiteralName;
+        if (isChild) {
+            variableAccess = "get_" + camelCaseToSnakeCase(variableAccess) + "()";
+        }
+        return tracer + (serialize ? "self." + camelCaseToSnakeCase(variableLiteralName) + "" : variableAccess) + indexCall +
+            variableLiteral.getChild()
+                .map(child -> "." + camelCaseToSnakeCase(toVariableExpression(field, typeReference, child, parserArguments, serializerArguments, false, suppressPointerAccess, true)))
+                .orElse("");
     }
 
-    private String toFunctionCallParseExpression(Field field, TypeReference resultType, VariableLiteral variableLiteral, List<Argument> parserArguments, Tracer tracer) {
-        tracer = tracer.dive("FunctionCall");
-        StringBuilder sb = new StringBuilder(variableLiteral.getName());
+    private String toUppercaseVariableExpression(Field field, TypeReference typeReference, VariableLiteral variableLiteral, List<Argument> parserArguments, List<Argument> serializerArguments, boolean serialize, boolean suppressPointerAccess, Tracer tracer) {
+        tracer = tracer.dive("toUppercaseVariableExpression");
+        StringBuilder sb = new StringBuilder("get_" + camelCaseToSnakeCase(variableLiteral.getName()) + "()");
         if (variableLiteral.getArgs().isPresent()) {
             sb.append("(");
             boolean firstArg = true;
@@ -991,195 +1111,242 @@ public class PythonLanguageTemplateHelper extends BaseFreemarkerLanguageTemplate
                 if (!firstArg) {
                     sb.append(", ");
                 }
-                // TODO: Try to infer the type of the argument ...
-                sb.append(toParseExpression(field, ANY_TYPE_REFERENCE, arg, parserArguments));
+                sb.append(toExpression(field, typeReference, arg, parserArguments, serializerArguments, serialize, suppressPointerAccess));
                 firstArg = false;
             }
             sb.append(")");
         }
         if (variableLiteral.getIndex().isPresent()) {
-            // TODO: If this is a byte typed field, this needs to be an array accessor instead.
-            sb.append(".get(").append(variableLiteral.getIndex().orElseThrow()).append(")");
+            sb.append("[").append(variableLiteral.getIndex().orElseThrow()).append("]");
         }
-        return tracer + sb.toString() + variableLiteral.getChild().map(child -> "." + toVariableExpressionRest(field, resultType, child)).orElse("");
+        return tracer + sb.toString() + variableLiteral.getChild()
+            .map(child -> "." + toVariableExpression(field, typeReference, child, parserArguments, serializerArguments, false, suppressPointerAccess, true))
+            .orElse("");
     }
 
-    private String toVariableSerializationExpression(Field field, TypeReference resultType, VariableLiteral variableLiteral, List<Argument> serialzerArguments) {
-        Tracer tracer = Tracer.start("variable serialization expression");
-        if ("STATIC_CALL".equals(variableLiteral.getName())) {
-            return toStaticCallSerializationExpression(field, resultType, variableLiteral, serialzerArguments, tracer);
-        }
-        // All uppercase names are not fields, but utility methods.
-        else if (variableLiteral.getName().equals(variableLiteral.getName().toUpperCase())) {
-            return toGlobalFunctionCallSerializationExpression(field, resultType, variableLiteral, serialzerArguments, tracer);
-        } else if (isVariableLiteralImplicitField(variableLiteral)) { // If we are accessing implicit fields, we need to rely on a local variable instead.
-            tracer = tracer.dive("implicit field");
-            final ImplicitField referencedImplicitField = getReferencedImplicitField(variableLiteral);
-            return tracer + toSerializationExpression(referencedImplicitField, referencedImplicitField.getType(), getReferencedImplicitField(variableLiteral).getSerializeExpression(), serialzerArguments);
-        } else if (isVariableLiteralVirtualField(variableLiteral)) {
-            tracer = tracer.dive("virtual field");
-            return tracer + toVariableExpressionRest(field, resultType, variableLiteral);
-        }
-        // The synthetic checksumRawData is a local field and should not be accessed as bean property.
-        boolean isSerializerArg = "write_buffer".equals(variableLiteral.getName()) || "checksum_raw_data".equals(variableLiteral.getName()) || "_value".equals(variableLiteral.getName()) || "element".equals(variableLiteral.getName()) || "size".equals(variableLiteral.getName());
-        boolean isTypeArg = "_type".equals(variableLiteral.getName());
-        if (!isSerializerArg && !isTypeArg && serialzerArguments != null) {
-            for (Argument serializerArgument : serialzerArguments) {
-                if (serializerArgument.getName().equals(variableLiteral.getName())) {
+    private String toCeilVariableExpression(Field field, VariableLiteral variableLiteral, List<Argument> parserArguments, List<Argument> serializerArguments, boolean serialize, boolean suppressPointerAccess, Tracer tracer) {
+        tracer = tracer.dive("ceil");
+        Term va = variableLiteral.getArgs().orElseThrow(() -> new RuntimeException("CEIL needs at least one arg"))
+            .stream().findFirst().orElseThrow(IllegalStateException::new);
+        // The Ceil function expects 64 bit floating point values.
+        TypeReference tr = new DefaultFloatTypeReference(SimpleTypeReference.SimpleBaseType.FLOAT, 64);
+        emitRequiredImport("math");
+        return tracer + "math.Ceil(" + toExpression(field, tr, va, parserArguments, serializerArguments, serialize, suppressPointerAccess) + ")";
+    }
+
+    private String toArraySizeInBytesVariableExpression(Field field, TypeReference typeReference, VariableLiteral variableLiteral, List<Argument> parserArguments, List<Argument> serializerArguments, boolean suppressPointerAccess, Tracer tracer) {
+        tracer = tracer.dive("array size in bytes");
+        VariableLiteral va = variableLiteral.getArgs()
+            .orElseThrow(() -> new RuntimeException("ARRAY_SIZE_IN_BYTES needs at least one arg"))
+            .stream().findFirst().orElseThrow(IllegalStateException::new)
+            .asLiteral()
+            .orElseThrow(() -> new RuntimeException("ARRAY_SIZE_IN_BYTES needs a literal"))
+            .asVariableLiteral()
+            .orElseThrow(() -> new RuntimeException("ARRAY_SIZE_IN_BYTES needs a variable literal"));
+        // "io" and "m" are always available in every parser.
+        boolean isSerializerArg = "readBuffer".equals(va.getName()) || "writeBuffer".equals(va.getName()) || "m".equals(va.getName()) || "element".equals(va.getName());
+        if (!isSerializerArg && serializerArguments != null) {
+            for (Argument serializerArgument : serializerArguments) {
+                if (serializerArgument.getName().equals(va.getName())) {
                     isSerializerArg = true;
                     break;
                 }
             }
         }
+        StringBuilder sb = new StringBuilder();
         if (isSerializerArg) {
-            tracer = tracer.dive("serializer arg");
-            return tracer + variableLiteral.getName() + variableLiteral.getChild().map(child -> "." + toVariableExpressionRest(field, resultType, child)).orElse("");
-        } else if (isTypeArg) {
-            tracer = tracer.dive("type arg");
-            String part = variableLiteral.getChild().map(VariableLiteral::getName).orElse("");
-            switch (part) {
-                case "name":
-                    return tracer + "\"" + field.getTypeName() + "\"";
-                case "length":
-                    return tracer + "\"" + ((SimpleTypeReference) field).getSizeInBits() + "\"";
-                case "encoding":
-                    String encoding = ((StringLiteral) field.getEncoding().orElse(new DefaultStringLiteral("UTF-8"))).getValue();
-                    return tracer + "\"" + encoding + "\"";
-                default:
-                    return tracer + "";
-            }
+            sb.append(va.getName()).append(va.getChild().map(child -> "." + toVariableExpression(field, typeReference, child, parserArguments, serializerArguments, true, suppressPointerAccess, true)).orElse(""));
         } else {
-            return tracer + toVariableExpressionRest(field, resultType, variableLiteral);
+            sb.append(toVariableExpression(field, typeReference, va, parserArguments, serializerArguments, true, suppressPointerAccess));
         }
+        return tracer + getCastExpressionForTypeReference(typeReference) + "(" + va.getName() + "ArraySizeInBytes(" + sb + "))";
     }
 
-    private String toGlobalFunctionCallSerializationExpression(Field field, TypeReference resultType, VariableLiteral variableLiteral, List<Argument> serialzerArguments, Tracer tracer) {
-        tracer = tracer.dive("GLOBAL_FUNCTION_CALL");
-        StringBuilder sb = new StringBuilder(variableLiteral.getName());
-        if (variableLiteral.getArgs().isPresent()) {
-            sb.append("(");
-            boolean firstArg = true;
-            for (Term arg : variableLiteral.getArgs().get()) {
-                if (!firstArg) {
-                    sb.append(", ");
-                }
-                sb.append(toSerializationExpression(field, ANY_TYPE_REFERENCE, arg, serialzerArguments));
-                firstArg = false;
-                /*if (arg instanceof VariableLiteral) {
-                    VariableLiteral va = (VariableLiteral) arg;
-                    boolean isSerializerArg = "readBuffer".equals(va.getName()) || "writeBuffer".equals(va.getName());
-                    boolean isTypeArg = "_type".equals(va.getName());
-                    if (!isSerializerArg && !isTypeArg && serialzerArguments != null) {
-                        for (Argument serializerArgument : serialzerArguments) {
-                            if (serializerArgument.getName().equals(va.getName())) {
-                                isSerializerArg = true;
-                                break;
-                            }
-                        }
-                    }
-                    if (isSerializerArg) {
-                        sb.append(va.getName()).append(va.getChild().map(child -> "." + toVariableExpressionRest(child)).orElse(""));
-                    } else if (isTypeArg) {
-                        String part = va.getChild().map(VariableLiteral::getName).orElse("");
-                        switch (part) {
-                            case "name":
-                                sb.append("\"").append(field.getTypeName()).append("\"");
-                                break;
-                            case "length":
-                                sb.append("\"").append(((SimpleTypeReference) field).getSizeInBits()).append("\"");
-                                break;
-                            case "encoding":
-                                String encoding = ((StringLiteral) field.getEncoding().orElse(new DefaultStringLiteral("UTF-8"))).getValue();
-                                sb.append("\"").append(encoding).append("\"");
-                                break;
-                        }
-                    } else {
-                        sb.append(toVariableSerializationExpression(field, va, serialzerArguments));
-                    }
-                } else if (arg instanceof StringLiteral) {
-                    sb.append(((StringLiteral) arg).getValue());
-                }*/
-            }
-            sb.append(")");
-        }
-        return tracer + sb.toString();
+    private String toCountVariableExpression(Field field, TypeReference typeReference, VariableLiteral variableLiteral, List<Argument> parserArguments, List<Argument> serializerArguments, boolean serialize, boolean suppressPointerAccess, Tracer tracer) {
+        tracer = tracer.dive("count");
+        VariableLiteral countLiteral = variableLiteral.getArgs()
+            .orElseThrow(() -> new RuntimeException("Count needs at least one arg"))
+            .get(0)
+            .asLiteral()
+            .orElseThrow(() -> new RuntimeException("Count needs a literal"))
+            .asVariableLiteral()
+            .orElseThrow(() -> new RuntimeException("Count needs a variable literal"));
+        return tracer + (typeReference instanceof SimpleTypeReference ? getCastExpressionForTypeReference(typeReference) : "") + "(len(" +
+            toVariableExpression(field, typeReference, countLiteral, parserArguments, serializerArguments, serialize, suppressPointerAccess) +
+            "))";
+    }
+
+    private String toStrLenVariableExpression(Field field, TypeReference typeReference, VariableLiteral variableLiteral, List<Argument> parserArguments, List<Argument> serializerArguments, boolean serialize, boolean suppressPointerAccess, Tracer tracer) {
+        tracer = tracer.dive("str-len");
+        VariableLiteral countLiteral = variableLiteral.getArgs()
+            .orElseThrow(() -> new RuntimeException("Str-len needs at least one arg"))
+            .get(0)
+            .asLiteral()
+            .orElseThrow(() -> new RuntimeException("Str-len needs a literal"))
+            .asVariableLiteral()
+            .orElseThrow(() -> new RuntimeException("Str-len needs a variable literal"));
+        return tracer + (typeReference instanceof SimpleTypeReference ? getCastExpressionForTypeReference(typeReference) : "") + "(len(" +
+            toVariableExpression(field, typeReference, countLiteral, parserArguments, serializerArguments, serialize, suppressPointerAccess) +
+            "))";
     }
 
-    private String toStaticCallSerializationExpression(Field field, TypeReference resultType, VariableLiteral variableLiteral, List<Argument> serialzerArguments, Tracer tracer) {
+    private String toStaticCallVariableExpression(Field field, TypeReference typeReference, VariableLiteral variableLiteral, List<Argument> parserArguments, List<Argument> serializerArguments, boolean serialize, boolean suppressPointerAccess, Tracer tracer) {
         tracer = tracer.dive("STATIC_CALL");
         StringBuilder sb = new StringBuilder();
         List<Term> arguments = variableLiteral.getArgs().orElseThrow(() -> new RuntimeException("A STATIC_CALL expression needs arguments"));
         if (arguments.size() < 1) {
             throw new RuntimeException("A STATIC_CALL expression expects at least one argument.");
         }
-        // TODO: make it as static import with a emitImport so if a static call is present a "utils" package must be present in the import
-        sb.append(packageName()).append(".utils.StaticHelper.");
         // Get the class and method name
-        String methodName = arguments.get(0).asLiteral()
+        String staticCall = arguments.get(0).asLiteral()
             .orElseThrow(() -> new RuntimeException("First argument should be a literal"))
             .asStringLiteral()
             .orElseThrow(() -> new RuntimeException("Expecting the first argument of a 'STATIC_CALL' to be a StringLiteral")).
             getValue();
-        //methodName = methodName.substring(1, methodName.length() - 1);
-        sb.append(methodName).append("(");
+        sb.append(camelCaseToSnakeCase(staticCall)).append("(");
         for (int i = 1; i < arguments.size(); i++) {
             Term arg = arguments.get(i);
             if (i > 1) {
                 sb.append(", ");
             }
-            sb.append(toSerializationExpression(field, ANY_TYPE_REFERENCE, arg, serialzerArguments));
-            /*if (arg instanceof VariableLiteral) {
+            if (arg instanceof UnaryTerm) {
+                arg = ((UnaryTerm) arg).getA();
+            }
+            if (arg instanceof VariableLiteral) {
+                tracer = tracer.dive("VariableLiteral nr." + i);
                 VariableLiteral va = (VariableLiteral) arg;
-                // "readBuffer" and "_value" are always available in every parser.
-                boolean isSerializerArg = "readBuffer".equals(va.getName()) || "writeBuffer".equals(va.getName()) || "_value".equals(va.getName()) || "element".equals(va.getName());
+                // "io" is the default name of the reader argument which is always available.
+                boolean isParserArg = "readBuffer".equals(va.getName()) || "writeBuffer".equals(va.getName()) || ((thisType instanceof DataIoTypeDefinition) && "_value".equals(va.getName()));
                 boolean isTypeArg = "_type".equals(va.getName());
-                if (!isSerializerArg && !isTypeArg && serialzerArguments != null) {
-                    for (Argument serializerArgument : serialzerArguments) {
-                        if (serializerArgument.getName().equals(va.getName())) {
-                            isSerializerArg = true;
+                if (!isParserArg && !isTypeArg && parserArguments != null) {
+                    for (Argument parserArgument : parserArguments) {
+                        if (parserArgument.getName().equals(va.getName())) {
+                            isParserArg = true;
                             break;
                         }
                     }
                 }
-                if (isSerializerArg) {
-                    sb.append(va.getName()).append(va.getChild().map(child -> "." + toVariableExpressionRest(child)).orElse(""));
-                } else if (isTypeArg) {
+                if (isParserArg) {
+                    tracer = tracer.dive("isParserArg");
+                    if (va.getName().equals("_value")) {
+                        tracer = tracer.dive("is _value");
+                        sb.append(va.getName().substring(1)).append(va.getChild().map(child -> "." + toVariableExpression(field, typeReference, child, parserArguments, serializerArguments, false, suppressPointerAccess, true)).orElse(""));
+                    } else {
+                        sb.append(va.getName()).append((va.getChild().isPresent()) ?
+                            ".get_" + camelCaseToSnakeCase(toVariableExpression(field, typeReference, va.getChild().orElseThrow(IllegalStateException::new), parserArguments, serializerArguments, false, suppressPointerAccess)) + "()" : "");
+                    }
+                }
+                // We have to manually evaluate the type information at code-generation time.
+                else if (isTypeArg) {
                     String part = va.getChild().map(VariableLiteral::getName).orElse("");
                     switch (part) {
                         case "name":
-                            sb.append("\"").append(field.getTypeName()).append("\"");
+//                                sb.append("\"").append(field.getTypeName()).append("\"");
                             break;
                         case "length":
-                            sb.append("\"").append(((SimpleTypeReference) field).getSizeInBits()).append("\"");
+                            sb.append("\"").append(((SimpleTypeReference) typeReference).getSizeInBits()).append("\"");
                             break;
                         case "encoding":
-                            String encoding = ((StringLiteral) field.getEncoding().orElse(new DefaultStringLiteral("UTF-8"))).getValue();
+                            final Term encodingTerm = field.getEncoding().orElse(new DefaultStringLiteral("UTF-8"));
+                            if (!(encodingTerm instanceof StringLiteral)) {
+                                throw new RuntimeException("Encoding must be a quoted string value");
+                            }
+                            String encoding = ((StringLiteral) encodingTerm).getValue();
                             sb.append("\"").append(encoding).append("\"");
                             break;
                     }
                 } else {
-                    sb.append(toVariableSerializationExpression(field, va, serialzerArguments));
+                    sb.append(toVariableExpression(field, typeReference, va, parserArguments, serializerArguments, serialize, suppressPointerAccess));
                 }
             } else if (arg instanceof StringLiteral) {
+                tracer = tracer.dive("StringLiteral");
                 sb.append(((StringLiteral) arg).getValue());
-            }*/
+            } else if (arg instanceof BooleanLiteral) {
+                tracer = tracer.dive("BooleanLiteral");
+                sb.append(((BooleanLiteral) arg).getValue());
+            } else if (arg instanceof NumericLiteral) {
+                tracer = tracer.dive("NumericLiteral");
+                sb.append(((NumericLiteral) arg).getNumber());
+            } else if (arg instanceof BinaryTerm) {
+                tracer = tracer.dive("BinaryTerm");
+                sb.append(toBinaryTermExpression(field, typeReference, (BinaryTerm) arg, parserArguments, serializerArguments, serialize, tracer));
+            } else {
+                throw new RuntimeException(arg.getClass().getName());
+            }
         }
         sb.append(")");
         return tracer + sb.toString();
     }
 
-    private String toVariableExpressionRest(Field field, TypeReference resultType, VariableLiteral variableLiteral) {
-        Tracer tracer = Tracer.start("variable expression rest");
-        // length is kind of a keyword in mspec, so we shouldn't be naming variables length. if we ask for the length of a object we can just return length().
-        // This way we can get the length of a string when serializing
-        String variableLiteralName = variableLiteral.getName();
-        if (variableLiteralName.equals("length")) {
-            tracer = tracer.dive("length");
-            return tracer + variableLiteralName + "()" + ((variableLiteral.getIndex().isPresent() ? ".get(" + variableLiteral.getIndex().orElseThrow() + ")" : "") +
-                variableLiteral.getChild().map(child -> "." + toVariableExpressionRest(field, resultType, child)).orElse(""));
+    private String toCastVariableExpression(Field field, TypeReference typeReference, VariableLiteral variableLiteral, List<Argument> parserArguments, List<Argument> serializerArguments, boolean serialize, boolean suppressPointerAccess, Tracer tracer) {
+        tracer = tracer.dive("CAST");
+        List<Term> arguments = variableLiteral.getArgs().orElseThrow(() -> new RuntimeException("A Cast expression needs arguments"));
+        if (arguments.size() != 2) {
+            throw new RuntimeException("A CAST expression expects exactly two arguments.");
+        }
+        VariableLiteral firstArgument = arguments.get(0).asLiteral()
+            .orElseThrow(() -> new RuntimeException("First argument should be a literal"))
+            .asVariableLiteral()
+            .orElseThrow(() -> new RuntimeException("First argument should be a Variable literal"));
+        StringLiteral typeLiteral = arguments.get(1).asLiteral()
+            .orElseThrow(() -> new RuntimeException("Second argument should be a String literal"))
+            .asStringLiteral()
+            .orElseThrow(() -> new RuntimeException("Second argument should be a String literal"));
+        final TypeDefinition typeDefinition = getTypeDefinitions().get(typeLiteral.getValue());
+        StringBuilder sb = new StringBuilder();
+        if (typeDefinition.isComplexTypeDefinition()) {
+            sb.append("Cast");
         }
-        return tracer + "self." + camelCaseToSnakeCase(variableLiteralName) + "()" + ((variableLiteral.getIndex().isPresent() ? ".get(" + variableLiteral.getIndex().orElseThrow() + ")" : "") +
-            variableLiteral.getChild().map(child -> "." + toVariableExpressionRest(field, resultType, child)).orElse(""));
+        sb.append(typeLiteral.getValue());
+        sb.append("(").append(toVariableExpression(field, typeReference, firstArgument, parserArguments, serializerArguments, serialize, suppressPointerAccess)).append(")");
+        return tracer + sb.toString() + variableLiteral.getChild().map(child -> "." + camelCaseToSnakeCase(toVariableExpression(field, typeReference, child, parserArguments, serializerArguments, false, suppressPointerAccess, true))).orElse("");
+    }
+
+    private String toOptionalVariableExpression(Field field, TypeReference typeReference, VariableLiteral variableLiteral, List<Argument> parserArguments, List<Argument> serializerArguments, boolean suppressPointerAccess, Tracer tracer) {
+        tracer = tracer.dive("optional fields");
+        return tracer + "(" + (suppressPointerAccess || (typeReference != null && typeReference.isComplexTypeReference()) ? "" : "*") + variableLiteral.getName() + ")" +
+            variableLiteral.getChild().map(child -> "." + camelCaseToSnakeCase(toVariableExpression(field, typeReference, child, parserArguments, serializerArguments, false, suppressPointerAccess, true))).orElse("");
+    }
+
+    private String toConstantVariableExpression(Field field, TypeReference typeReference, VariableLiteral variableLiteral, List<Argument> parserArguments, List<Argument> serializerArguments, boolean suppressPointerAccess, Tracer tracer) {
+        tracer = tracer.dive("enum constant");
+        VariableLiteral child = variableLiteral.getChild().orElseThrow(IllegalStateException::new);
+        return tracer + variableLiteral.getName() + "." + camelCaseToSnakeCase(child.getName()) + "()" +
+            child.getChild().map(childChild -> "." + toVariableExpression(field, typeReference, childChild, parserArguments, serializerArguments, false, suppressPointerAccess, true)).orElse("");
+    }
+
+    private String toEnumVariableExpression(Field field, TypeReference typeReference, VariableLiteral variableLiteral, List<Argument> parserArguments, List<Argument> serializerArguments, boolean suppressPointerAccess, Tracer tracer) {
+        tracer = tracer.dive("enum");
+        VariableLiteral child = variableLiteral.getChild().orElseThrow(() -> new RuntimeException("Enum should have a child"));
+        return tracer + variableLiteral.getName() + "_" + child.getName() +
+            child.getChild().map(childChild -> "." + toVariableExpression(field, typeReference, childChild, parserArguments, serializerArguments, false, suppressPointerAccess, true)).orElse("");
+    }
+
+    private String toLastItemVariableExpression(TypeReference typeReference, boolean serialize, Tracer tracer) {
+        tracer = tracer.dive("lastItem");
+        return tracer + "utils.GetLastItemFromContext(ctx)";
+    }
+
+    private String toLengthVariableExpression(Field field, VariableLiteral variableLiteral, boolean serialize, Tracer tracer) {
+        tracer = tracer.dive("length");
+        return tracer + (serialize ? ("len(self." + camelCaseToSnakeCase(variableLiteral.getName()) + ")") : ("(" + variableLiteral.getName() + ")"));
+    }
+
+    private String toValueVariableExpression(Field field, TypeReference typeReference, VariableLiteral variableLiteral, List<Argument> parserArguments, List<Argument> serializerArguments, boolean serialize, boolean suppressPointerAccess, Tracer tracer) {
+        final Tracer tracer2 = tracer.dive("_value");
+        return variableLiteral.getChild()
+            .map(child -> tracer2.dive("withChild") + "self." + toUppercaseVariableExpression(field, typeReference, child, parserArguments, serializerArguments, serialize, suppressPointerAccess, tracer2))
+            .orElse(tracer2 + "m");
+    }
+
+    private String toLengthInBitsVariableExpression(TypeReference typeReference, boolean serialize, Tracer tracer) {
+        tracer = tracer.dive("lengthInBits");
+        return tracer + (serialize ? getCastExpressionForTypeReference(typeReference) + "(self.get" : "get") + "length_in_bits" + (serialize ? "(ctx))" : "(ctx)");
+    }
+
+    private String toLengthInBytesVariableExpression(TypeReference typeReference, boolean serialize, Tracer tracer) {
+        tracer = tracer.dive("lengthInBytes");
+        return tracer + (serialize ? getCastExpressionForTypeReference(typeReference) + "(self.get" : "Get") + "length_in_bytes" + (serialize ? "(ctx))" : "(ctx)");
     }
 
     public String getSizeInBits(ComplexTypeDefinition complexTypeDefinition, List<Argument> parserArguments) {
@@ -1191,10 +1358,10 @@ public class PythonLanguageTemplateHelper extends BaseFreemarkerLanguageTemplate
                 final SimpleTypeReference type = (SimpleTypeReference) arrayField.getType();
                 switch (arrayField.getLoopType()) {
                     case COUNT:
-                        sb.append("(").append(toSerializationExpression(null, INT_TYPE_REFERENCE, arrayField.getLoopExpression(), parserArguments)).append(" * ").append(type.getSizeInBits()).append(") + ");
+                        sb.append("(").append(toTypedSerializationExpression(field, type, arrayField.getLoopExpression(), parserArguments)).append(" * ").append(type.getSizeInBits()).append(") + ");
                         break;
                     case LENGTH:
-                        sb.append("(").append(toSerializationExpression(null, INT_TYPE_REFERENCE, arrayField.getLoopExpression(), parserArguments)).append(" * 8) + ");
+                        sb.append("(").append(toTypedSerializationExpression(field, type, arrayField.getLoopExpression(), parserArguments)).append(" * 8) + ");
                         break;
                     case TERMINATED:
                         // No terminated.
@@ -1205,14 +1372,12 @@ public class PythonLanguageTemplateHelper extends BaseFreemarkerLanguageTemplate
                 final TypeReference type = typedField.getType();
                 if (field instanceof ManualField) {
                     ManualField manualField = (ManualField) field;
-                    sb.append("(").append(toSerializationExpression(null, INT_TYPE_REFERENCE, manualField.getLengthExpression(), parserArguments)).append(") + ");
+                    sb.append("(").append(toSerializationExpression(manualField, getIntTypeReference(), manualField.getLengthExpression(), parserArguments)).append(") + ");
                 } else if (type instanceof SimpleTypeReference) {
                     SimpleTypeReference simpleTypeReference = (SimpleTypeReference) type;
-                    if (simpleTypeReference instanceof VstringTypeReference) {
-                        sb.append(toSerializationExpression(null, INT_TYPE_REFERENCE, ((VstringTypeReference) simpleTypeReference).getLengthExpression(), parserArguments)).append(" + ");
-                    } else {
-                        sizeInBits += simpleTypeReference.getSizeInBits();
-                    }
+                    sizeInBits += simpleTypeReference.getSizeInBits();
+                } else {
+                    throw new IllegalStateException("No ComplexTypeReference supported");
                 }
             }
         }
@@ -1241,38 +1406,42 @@ public class PythonLanguageTemplateHelper extends BaseFreemarkerLanguageTemplate
         return valueString;
     }
 
-    public String getFieldOptions(TypedField field, List<Argument> parserArguments) {
-        StringBuilder sb = new StringBuilder();
-        final Optional<Term> encodingOptional = field.getEncoding();
-        if (encodingOptional.isPresent()) {
-            final String encoding = toParseExpression(field, field.getType(), encodingOptional.get(), parserArguments);
-            sb.append(", WithOption.WithEncoding(").append(encoding).append(")");
-        }
-        final Optional<Term> byteOrderOptional = field.getByteOrder();
-        if (byteOrderOptional.isPresent()) {
-            final String byteOrder = toParseExpression(field, field.getType(), byteOrderOptional.get(), parserArguments);
-            sb.append(", WithOption.WithByteOrder(").append(byteOrder).append(")");
+    public String escapeEnumValue(TypeReference typeReference, String valueString) {
+        // Currently the only case in which here complex type references are used are when referencing enum constants.
+        if (typeReference != null && typeReference.isNonSimpleTypeReference()) {
+            // C doesn't like NULL values for enums, so we have to return something else (we'll treat -1 as NULL)
+            if ("null".equals(valueString) || valueString == null) {
+                return "0";
+            }
+            if (valueString.contains(".")) {
+                String typeName = valueString.substring(0, valueString.indexOf('.'));
+                String constantName = valueString.substring(valueString.indexOf('.') + 1);
+                return typeName + "_" + constantName;
+            }
+            return valueString;
+        } else {
+            return escapeValue(typeReference, valueString);
         }
-        return sb.toString();
     }
 
-    public boolean isBigIntegerSource(Term term) {
-        boolean isBigInteger = term.asLiteral()
-            .flatMap(LiteralConversions::asVariableLiteral)
-            .flatMap(VariableLiteral::getChild)
-            .map(Term.class::cast)
-            .map(this::isBigIntegerSource)
-            .orElse(false);
-        return isBigInteger || term.asLiteral()
-            .flatMap(LiteralConversions::asVariableLiteral)
-            .map(VariableLiteral::getTypeReference)
-            .flatMap(TypeReferenceConversions::asIntegerTypeReference)
-            .map(integerTypeReference -> integerTypeReference.getSizeInBits() >= 64)
-            .orElse(false);
+    public Collection<EnumValue> getUniqueEnumValues(List<EnumValue> enumValues) {
+        Map<String, EnumValue> filteredEnumValues = new TreeMap<>();
+        for (EnumValue enumValue : enumValues) {
+            if (!filteredEnumValues.containsKey(enumValue.getValue())) {
+                filteredEnumValues.put(enumValue.getValue(), enumValue);
+            }
+        }
+        return filteredEnumValues.values();
     }
 
-    public boolean needsLongMarker(Optional<SimpleTypeReference> baseTypeReference) {
-        return baseTypeReference.isPresent() && baseTypeReference.get().isIntegerTypeReference() && baseTypeReference.get().asIntegerTypeReference().orElseThrow().getSizeInBits() >= 32;
+    public List<DiscriminatedComplexTypeDefinition> getUniqueSwitchCases(List<DiscriminatedComplexTypeDefinition> allSwitchCases) {
+        Map<String, DiscriminatedComplexTypeDefinition> switchCases = new LinkedHashMap<>();
+        for (DiscriminatedComplexTypeDefinition switchCase : allSwitchCases) {
+            if (!switchCases.containsKey(switchCase.getName())) {
+                switchCases.put(switchCase.getName(), switchCase);
+            }
+        }
+        return new ArrayList<>(switchCases.values());
     }
 
     public void emitRequiredImport(String requiredImport) {
@@ -1303,6 +1472,319 @@ public class PythonLanguageTemplateHelper extends BaseFreemarkerLanguageTemplate
         return requiredImportsForDataIo;
     }
 
+    public String getVariableName(Field field) {
+        if (!(field instanceof NamedField)) {
+            return "_";
+        }
+        NamedField namedField = (NamedField) field;
+
+        String name = null;
+        for (Field curField : ((ComplexTypeDefinition) thisType).getFields()) {
+            if (curField == field) {
+                name = namedField.getName();
+            } else if (name != null) {
+                if (curField instanceof ArrayField) {
+                    ArrayField arrayField = (ArrayField) curField;
+                    if (arrayField.getLoopExpression().contains(name)) {
+                        return name;
+                    }
+                } else if (curField instanceof ChecksumField) {
+                    ChecksumField checksumField = (ChecksumField) curField;
+                    if (checksumField.getChecksumExpression().contains(name)) {
+                        return name;
+                    }
+                } else if (curField instanceof ImplicitField) {
+                    ImplicitField implicitField = (ImplicitField) curField;
+                    if (implicitField.getSerializeExpression().contains(name)) {
+                        return name;
+                    }
+                } else if (curField instanceof ManualArrayField) {
+                    ManualArrayField manualArrayField = (ManualArrayField) curField;
+                    if (manualArrayField.getLengthExpression().contains(name)) {
+                        return name;
+                    }
+                    if (manualArrayField.getLoopExpression().contains(name)) {
+                        return name;
+                    }
+                    if (manualArrayField.getParseExpression().contains(name)) {
+                        return name;
+                    }
+                    if (manualArrayField.getSerializeExpression().contains(name)) {
+                        return name;
+                    }
+                } else if (curField instanceof ManualField) {
+                    ManualField manualField = (ManualField) curField;
+                    if (manualField.getLengthExpression().contains(name)) {
+                        return name;
+                    }
+                    if (manualField.getParseExpression().contains(name)) {
+                        return name;
+                    }
+                    if (manualField.getSerializeExpression().contains(name)) {
+                        return name;
+                    }
+                } else if (curField instanceof OptionalField) {
+                    OptionalField optionalField = (OptionalField) curField;
+                    if (optionalField.getConditionExpression().isPresent() && optionalField.getConditionExpression().orElseThrow(IllegalStateException::new).contains(name)) {
+                        return name;
+                    }
+                } else if (curField instanceof SwitchField) {
+                    SwitchField switchField = (SwitchField) curField;
+                    for (Term discriminatorExpression : switchField.getDiscriminatorExpressions()) {
+                        if (discriminatorExpression.contains(name)) {
+                            return name;
+                        }
+                    }
+                    for (DiscriminatedComplexTypeDefinition curCase : switchField.getCases()) {
+                        for (Argument parserArgument : curCase.getParserArguments().orElse(Collections.emptyList())) {
+                            if (parserArgument.getName().equals(name)) {
+                                return name;
+                            }
+                        }
+                    }
+                } else if (curField instanceof VirtualField) {
+                    VirtualField virtualField = (VirtualField) curField;
+                    if (virtualField.getValueExpression().contains(name)) {
+                        return name;
+                    }
+                }
+                List<Term> params = field.asTypedField()
+                    .map(typedField -> typedField.getType().asNonSimpleTypeReference()
+                        .map(NonSimpleTypeReference::getParams)
+                        .map(terms -> terms.orElse(Collections.emptyList()))
+                        .orElse(Collections.emptyList())
+                    )
+                    .orElse(Collections.emptyList());
+                for (Term param : params) {
+                    if (param.contains(name)) {
+                        return name;
+                    }
+                }
+            }
+        }
+
+        return "_";
+    }
+
+    public boolean needsVariable(Field field, String variableName, boolean serialization) {
+        if (!serialization) {
+            if (field instanceof ArrayField) {
+                ArrayField arrayField = (ArrayField) field;
+                if (arrayField.getLoopExpression().contains(variableName)) {
+                    return true;
+                }
+            }
+        }
+        if (field instanceof VirtualField) {
+            VirtualField virtualField = (VirtualField) field;
+            if (virtualField.getValueExpression().contains(variableName)) {
+                return true;
+            }
+        }
+        if (field instanceof PaddingField) {
+            PaddingField paddingField = (PaddingField) field;
+            if (paddingField.getPaddingCondition().contains(variableName)) {
+                return true;
+            }
+            if (paddingField.getPaddingValue().contains(variableName)) {
+                return true;
+            }
+        }
+        return field.asTypedField()
+            .map(typedField -> typedField.getType().asNonSimpleTypeReference()
+                .map(nonSimpleTypeReference -> nonSimpleTypeReference.getParams()
+                    .map(params -> params.stream()
+                        .anyMatch(param -> param.contains(variableName))
+                    )
+                    .orElse(false)
+                )
+                .orElse(false)
+            )
+            .orElse(false);
+    }
+
+    /**
+     * Right now only the ARRAY_SIZE_IN_BYTES requires helpers to be generated.
+     * Also right now only the Modbus protocol requires this and here the referenced
+     * properties are all also members of the current complex type,
+     * so we'll simplify things here for now.
+     *
+     * @param functionName name of the
+     * @return something
+     */
+    public Map<String, String> requiresHelperFunctions(String functionName) {
+        Map<String, String> result = new HashMap<>();
+        boolean usesFunction = false;
+        // As the ARRAY_SIZE_IN_BYTES only applies to ArrayFields, search for these
+        for (Field curField : ((ComplexTypeDefinition) thisType).getFields()) {
+            if (curField instanceof ArrayField) {
+                ArrayField arrayField = (ArrayField) curField;
+                if (arrayField.getLoopExpression().contains(functionName)) {
+                    usesFunction = true;
+                }
+                result.put(arrayField.getName(), getLanguageTypeNameForField(arrayField));
+            } else if (curField instanceof ImplicitField) {
+                ImplicitField implicitField = (ImplicitField) curField;
+                if (implicitField.getSerializeExpression().contains(functionName)) {
+                    usesFunction = true;
+                }
+            }
+        }
+        if (!usesFunction) {
+            return Collections.emptyMap();
+        }
+        return result;
+    }
+
+    public boolean requiresCurPos() {
+        if (thisType instanceof ComplexTypeDefinition) {
+            ComplexTypeDefinition complexTypeDefinition = (ComplexTypeDefinition) this.thisType;
+            for (Field curField : complexTypeDefinition.getFields()) {
+                if (requiresVariable(curField, "curPos")) {
+                    return true;
+                }
+            }
+        }
+        return false;
+    }
+
+    public boolean requiresStartPos() {
+        if (thisType instanceof ComplexTypeDefinition) {
+            ComplexTypeDefinition complexTypeDefinition = (ComplexTypeDefinition) this.thisType;
+            for (Field curField : complexTypeDefinition.getFields()) {
+                if (requiresVariable(curField, "startPos")) {
+                    return true;
+                }
+            }
+        }
+        return false;
+    }
+
+    public boolean requiresVariable(Field curField, String variable) {
+        if (curField.isArrayField()) {
+            ArrayField arrayField = (ArrayField) curField;
+            if (arrayField.getLoopExpression().contains(variable)) {
+                return true;
+            }
+        } else if (curField.isOptionalField()) {
+            OptionalField optionalField = (OptionalField) curField;
+            if (optionalField.getConditionExpression().isPresent() && optionalField.getConditionExpression().orElseThrow(IllegalStateException::new).contains(variable)) {
+                return true;
+            }
+        }
+        return curField.asTypedField()
+            .map(typedField -> typedField.getType().asNonSimpleTypeReference()
+                .map(nonSimpleTypeReference -> nonSimpleTypeReference.getParams()
+                    .map(params -> params.stream()
+                        .anyMatch(param -> param.contains(variable))
+                    )
+                    .orElse(false)
+                )
+                .orElse(false)
+            )
+            .orElse(false);
+    }
+
+    public Term findTerm(Term baseTerm, String name) {
+        if (baseTerm instanceof VariableLiteral) {
+            VariableLiteral variableLiteral = (VariableLiteral) baseTerm;
+            if (variableLiteral.getName().equals(name)) {
+                return variableLiteral;
+            }
+            if (variableLiteral.getChild().isPresent()) {
+                Term found = findTerm(variableLiteral.getChild().get(), name);
+                if (found != null) {
+                    return found;
+                }
+            }
+            for (Term arg : variableLiteral.getArgs().orElse(Collections.emptyList())) {
+                Term found = findTerm(arg, name);
+                if (found != null) {
+                    return found;
+                }
+            }
+        } else if (baseTerm instanceof UnaryTerm) {
+            UnaryTerm unaryTerm = (UnaryTerm) baseTerm;
+            return findTerm(unaryTerm.getA(), name);
+        } else if (baseTerm instanceof BinaryTerm) {
+            BinaryTerm binaryTerm = (BinaryTerm) baseTerm;
+            Term found = findTerm(binaryTerm.getA(), name);
+            if (found != null) {
+                return found;
+            }
+            found = findTerm(binaryTerm.getB(), name);
+            return found;
+        } else if (baseTerm instanceof TernaryTerm) {
+            TernaryTerm ternaryTerm = (TernaryTerm) baseTerm;
+            Term found = findTerm(ternaryTerm.getA(), name);
+            if (found != null) {
+                return found;
+            }
+            found = findTerm(ternaryTerm.getB(), name);
+            if (found != null) {
+                return found;
+            }
+            found = findTerm(ternaryTerm.getC(), name);
+            return found;
+        }
+        return null;
+    }
+
+    public String getEnumExpression(String expression) {
+        String enumName = expression.substring(0, expression.indexOf('.'));
+        String enumConstant = expression.substring(expression.indexOf('.') + 1);
+        return enumName + "_" + enumConstant;
+    }
+
+    public boolean needsReferenceForParserArgument(String propertyName, TypeReference argumentType) {
+        return argumentType.asComplexTypeReference()
+            .map(complexTypeReference -> {
+                // Check if this is a local field.
+                // FIXME: shouldn't this look onto the argumentType? this is nowhere used...
+                return thisType.asComplexTypeDefinition()
+                    .map(
+                        complexTypeDefinition -> complexTypeDefinition.getPropertyFieldByName(propertyName)
+                            .map(TypedField.class::cast)
+                            .map(TypedField::getType)
+                            .filter(NonSimpleTypeReference.class::isInstance)
+                            .map(NonSimpleTypeReference.class::cast)
+                            .map(NonSimpleTypeReference::getTypeDefinition)
+                            .map(typeDefinition -> !(typeDefinition instanceof EnumTypeDefinition))
+                            .orElse(false)
+                    )
+                    .orElse(false);
+            })
+            .orElse(false);
+    }
+
+    public String capitalize(String str) {
+        Tracer dummyTracer = Tracer.start("");
+        String extractedTrace = dummyTracer.extractTraces(str);
+        String cleanedString = dummyTracer.removeTraces(str);
+        return extractedTrace + StringUtils.capitalize(cleanedString);
+    }
+
+    public String getEndiannessOptions(boolean read, boolean separatorPrefix) {
+        return getEndiannessOptions(read, separatorPrefix, Collections.emptyList());
+    }
+
+    public String getEndiannessOptions(boolean read, boolean separatorPrefix, List<Argument> parserArguments) {
+        Optional<Term> byteOrder = thisType.getAttribute("byteOrder");
+        if (byteOrder.isPresent()) {
+            emitRequiredImport("encoding/binary");
+            if(read) {
+                return (separatorPrefix ? ", " : "") + "utils.WithByteOrderForReadBufferByteBased(" +
+                    toParseExpression(null, new DefaultByteOrderTypeReference(), byteOrder.orElseThrow(), parserArguments) +
+                    ")";
+            } else {
+                return (separatorPrefix ? ", " : "") + "utils.WithByteOrderForByteBasedBuffer(" +
+                    toSerializationExpression(null, new DefaultByteOrderTypeReference(), byteOrder.orElseThrow(), parserArguments) +
+                    ")";
+            }
+        }
+        return "";
+    }
+
     /**
      * Converts a camel-case string to snake-case.
      *
@@ -1337,4 +1819,4 @@ public class PythonLanguageTemplateHelper extends BaseFreemarkerLanguageTemplate
         return snakeCase.toString();
     }
 
-}
+}
\ No newline at end of file
diff --git a/code-generation/language-python/src/main/resources/templates/python/complex-type-template.python.ftlh b/code-generation/language-python/src/main/resources/templates/python/complex-type-template.python.ftlh
index 77e4617393..e6e2584b03 100644
--- a/code-generation/language-python/src/main/resources/templates/python/complex-type-template.python.ftlh
+++ b/code-generation/language-python/src/main/resources/templates/python/complex-type-template.python.ftlh
@@ -64,6 +64,7 @@ ${import}
 <#if type.parserArguments.isPresent()><#assign parserArguments=type.allParserArguments.orElseThrow()></#if>
 
 <@emitImport import="from plc4py.api.messages.PlcMessage import PlcMessage" />
+<@emitImport import="from plc4py.spi.generation.WriteBuffer import WriteBuffer" />
 @dataclass
 class ${type.name}<#if type.isDiscriminatedParentTypeDefinition()></#if>(<#if type.isDiscriminatedParentTypeDefinition()>ABC, <@emitImport import="from abc import ABC" /></#if>PlcMessage<#if type.parentType.isPresent()>,${type.parentType.orElseThrow().name}<@emitImport import="from plc4py.protocols.${protocolName}.${outputFlavor?replace('-', '')}.${type.parentType.orElseThrow().name} import ${type.parentType.orElseThrow().name}" /></#if>):
     <#if parserArguments?has_content>
@@ -198,17 +199,16 @@ class ${type.name}<#if type.isDiscriminatedParentTypeDefinition()></#if>(<#if ty
     <#if type.isDiscriminatedParentTypeDefinition()>
     <@emitImport import="from abc import abstractmethod" />
     @abstractmethod
-    def serialize_${helper.camelCaseToSnakeCase(type.name)}Child(write_buffer: WriteBuffer) -> None:
+    def serialize_${helper.camelCaseToSnakeCase(type.name)}_child(write_buffer: WriteBuffer) -> None:
         pass
 
     </#if>
     def serialize(self, write_buffer: WriteBuffer):
 </#if>
-        position_aware: PositionAware = write_buffer
         <#if helper.hasFieldOfType("unknown")>
         raise SerializationException("Unknown field not serializable")
         <#else>
-        start_pos: int = position_aware.get_pos()
+        start_pos: int = write_buffer.get_pos()
         write_buffer.push_context("${type.name}")
             <#assign reservedFieldIndex=0>
             <#list type.fields as field>
@@ -220,11 +220,11 @@ class ${type.name}<#if type.isDiscriminatedParentTypeDefinition()></#if>(<#if ty
 
         # Array Field (${arrayField.name})
                         <#if arrayField.type.elementTypeReference.isByteBased()>
-        write_byte_array_field("${namedField.name}", self.${helper.camelCaseToSnakeCase(namedField.name)}, writeByteArray(write_buffer, 8))
+        write_buffer.write_byte_array(self.${helper.camelCaseToSnakeCase(namedField.name)}, 8, logical_name="${namedField.name}")
                         <#elseif arrayField.type.elementTypeReference.isSimpleTypeReference()>
-        write_simple_type_array_field("${namedField.name}", self.${helper.camelCaseToSnakeCase(namedField.name)}, ${helper.getDataWriterCall(arrayField.type.elementTypeReference, namedField.name)})
+        write_buffer.write_simple_array(self.${helper.camelCaseToSnakeCase(namedField.name)}, ${helper.getDataWriterCall(arrayField.type.elementTypeReference, namedField.name)}, logical_name="${namedField.name}")
                         <#else>
-        write_complex_type_array_field("${namedField.name}", self.${helper.camelCaseToSnakeCase(namedField.name)}, write_buffer)
+        write_buffer.write_complex_array(self.${helper.camelCaseToSnakeCase(namedField.name)}, logical_name="${namedField.name}")
                         </#if>
                         <#break>
                     <#case "checksum">
@@ -233,7 +233,7 @@ class ${type.name}<#if type.isDiscriminatedParentTypeDefinition()></#if>(<#if ty
                         <#assign namedField = field.asNamedField().orElseThrow()>
 
         # Checksum Field (checksum) (Calculated)
-        write_checksum_field("${namedField.name}", ${helper.getLanguageTypeNameForField(field)}(${helper.toParseExpression(checksumField, checksumField.type, checksumField.checksumExpression, parserArguments)}), ${helper.getDataWriterCall(typedField.type, namedField.name)})
+        write_buffer.${helper.getDataWriterCall(typedField.type, namedField.name)}(${helper.getLanguageTypeNameForField(field)}(${helper.toParseExpression(checksumField, checksumField.type, checksumField.checksumExpression, parserArguments)}), logical_name="${namedField.name}")
                         <#break>
                     <#case "const">
                         <#assign constField = field.asConstField().orElseThrow()>
@@ -241,7 +241,7 @@ class ${type.name}<#if type.isDiscriminatedParentTypeDefinition()></#if>(<#if ty
                         <#assign namedField = field.asNamedField().orElseThrow()>
 
         # Const Field (${constField.name})
-        <#if typedField.type.isEnumTypeReference()>write_const_field("${constField.name}", self.${helper.camelCaseToSnakeCase(namedField.name)}.value, ${helper.getDataWriterCall(helper.getEnumBaseTypeReference(typedField.type), namedField.name)})<#else>write_const_field("${constField.name}", self.${helper.camelCaseToSnakeCase(namedField.name)}, ${helper.getDataWriterCall(typedField.type, namedField.name)})</#if>
+        <#if typedField.type.isEnumTypeReference()>write_buffer.${helper.getDataWriterCall(helper.getEnumBaseTypeReference(typedField.type), namedField.name)}(self.${helper.camelCaseToSnakeCase(namedField.name)}.value, logical_name="${constField.name}")<#else>write_buffer.${helper.getDataWriterCall(typedField.type, namedField.name)}(self.${helper.camelCaseToSnakeCase(namedField.name)}.value, logical_name="${constField.name}")</#if>
                         <#break>
                     <#case "discriminator">
                         <#assign discriminatorField = field.asDiscriminatorField().orElseThrow()>
@@ -250,9 +250,9 @@ class ${type.name}<#if type.isDiscriminatedParentTypeDefinition()></#if>(<#if ty
 
         # Discriminator Field (${discriminatorField.name}) (Used as input to a switch field)
                         <#if typedField.type.isEnumTypeReference()>
-        write_discriminator_enum_field("${namedField.name}", "${helper.getLanguageTypeNameForField(field)}", self.${helper.camelCaseToSnakeCase(discriminatorField.name)}(), ${helper.getEnumDataWriterCall(typedField.type, namedField.name, "value")})
+        write_buffer.${helper.getEnumDataWriterCall(typedField.type, namedField.name, "value")}(self.${helper.camelCaseToSnakeCase(discriminatorField.name)}(), logical_name="${namedField.name}")
                         <#else>
-        write_discriminator_field("${namedField.name}", self.${helper.camelCaseToSnakeCase(discriminatorField.name)}(), ${helper.getDataWriterCall(typedField.type, namedField.name)})
+        write_buffer.${helper.getDataWriterCall(typedField.type, namedField.name)}(self.${helper.camelCaseToSnakeCase(discriminatorField.name)}(), logical_name="${namedField.name}")
                         </#if>
                         <#break>
                     <#case "enum">
@@ -261,7 +261,7 @@ class ${type.name}<#if type.isDiscriminatedParentTypeDefinition()></#if>(<#if ty
                         <#assign namedField = field.asNamedField().orElseThrow()>
 
         # Enum field (${namedField.name})
-        write_enum_field("${namedField.name}", "${helper.getLanguageTypeNameForField(field)}", self.${helper.camelCaseToSnakeCase(namedField.name)}, ${helper.getEnumDataWriterCall(typedField.type, namedField.name, enumField.fieldName)})
+        write_buffer.${helper.getEnumDataWriterCall(typedField.type, namedField.name, enumField.fieldName)}(self.${helper.camelCaseToSnakeCase(namedField.name)}, logical_name="${namedField.name}")
                         <#break>
                     <#case "implicit">
                         <#assign implicitField = field.asImplicitField().orElseThrow()>
@@ -270,8 +270,8 @@ class ${type.name}<#if type.isDiscriminatedParentTypeDefinition()></#if>(<#if ty
 
         # Implicit Field (${helper.camelCaseToSnakeCase(implicitField.name)}) (Used for parsing, but its value is not stored as it's implicitly given by the objects content)
                         <#-- Implicit field values might be used in expressions, in order to avoid problems, we generate a temporary variable with the given name. -->
-        ${helper.camelCaseToSnakeCase(implicitField.name)}: ${helper.getLanguageTypeNameForField(field)} = ${helper.getLanguageTypeNameForField(field)}((${helper.toSerializationExpression(implicitField, implicitField.type, implicitField.serializeExpression, parserArguments)}))
-        write_implicit_field("${namedField.name}", ${helper.camelCaseToSnakeCase(implicitField.name)}, ${helper.getDataWriterCall(typedField.type, namedField.name)})
+        ${helper.camelCaseToSnakeCase(implicitField.name)}: ${helper.getLanguageTypeNameForField(field)} = (${helper.toSerializationExpression(implicitField, implicitField.type, implicitField.serializeExpression, parserArguments)})
+        write_buffer.${helper.getDataWriterCall(typedField.type, namedField.name)}(${helper.camelCaseToSnakeCase(implicitField.name)}, logical_name="${namedField.name}")
                         <#break>
                     <#case "manualArray">
                         <#assign manualArrayField = field.asManualArrayField().orElseThrow()>
@@ -279,7 +279,7 @@ class ${type.name}<#if type.isDiscriminatedParentTypeDefinition()></#if>(<#if ty
                         <#assign namedField = field.asNamedField().orElseThrow()>
 
         # Manual Array Field (${manualArrayField.name})
-        write_manual_array_field("${namedField.name}", self.${helper.camelCaseToSnakeCase(namedField.name)}, (${helper.getLanguageTypeNameForTypeReference(manualArrayField.type.elementTypeReference)} _value) -> ${helper.toParseExpression(manualArrayField, manualArrayField.type.elementTypeReference, manualArrayField.serializeExpression, parserArguments)}, write_buffer)
+        write_buffer.${helper.getDataWriterCall(typedField.type, namedField.name)}((${helper.getLanguageTypeNameForTypeReference(manualArrayField.type.elementTypeReference)} _value) -> ${helper.toParseExpression(manualArrayField, manualArrayField.type.elementTypeReference, manualArrayField.serializeExpression, parserArguments)}, logical_name="${namedField.name}")
                         <#break>
                     <#case "manual">
                         <#assign manualField = field.asManualField().orElseThrow()>
@@ -287,7 +287,7 @@ class ${type.name}<#if type.isDiscriminatedParentTypeDefinition()></#if>(<#if ty
                         <#assign namedField = field.asNamedField().orElseThrow()>
 
         # Manual Field (${manualField.name})
-        write_manual_field("${namedField.name}", lambda : ${helper.toParseExpression(manualField, manualField.type, manualField.serializeExpression, parserArguments)}, write_buffer)
+        write_buffer.${helper.getDataWriterCall(typedField.type, namedField.name)}(lambda : ${helper.toParseExpression(manualField, manualField.type, manualField.serializeExpression, parserArguments)}, logical_name="${namedField.name}")
                         <#break>
                     <#case "optional">
                         <#assign optionalField = field.asOptionalField().orElseThrow()>
@@ -296,11 +296,11 @@ class ${type.name}<#if type.isDiscriminatedParentTypeDefinition()></#if>(<#if ty
 
         # Optional Field (${optionalField.name}) (Can be skipped, if the value is null)
                         <#if optionalField.type.isEnumTypeReference()>
-        write_optional_enum_field("${optionalField.name}", "${helper.getLanguageTypeNameForField(field)}", self.${helper.camelCaseToSnakeCase(optionalField.name)}, ${helper.getEnumDataWriterCall(optionalField.type, optionalField.name, "value")}<#if optionalField.conditionExpression.present>, ${helper.toSerializationExpression(optionalField, helper.boolTypeReference, optionalField.conditionExpression.get(), parserArguments)}</#if>)
+        write_buffer.${helper.getEnumDataWriterCall(optionalField.type, optionalField.name, "value")}(self.${helper.camelCaseToSnakeCase(optionalField.name)}, logical_name="${optionalField.name}", condition=${helper.toSerializationExpression(optionalField, helper.boolTypeReference, optionalField.conditionExpression.get(), parserArguments)})
                         <#elseif optionalField.type.isDataIoTypeReference()>
-        write_optional_field("${optionalField.name}", self.${helper.camelCaseToSnakeCase(optionalField.name)}, DataWriterDataIoDefault(write_buffer, (wb, val) -> ${optionalField.type.asComplexTypeReference().orElseThrow().name}.staticSerialize(wb, val<#if optionalField.type.asComplexTypeReference().orElseThrow().params?has_content>, <#list optionalField.type.asComplexTypeReference().orElseThrow().params.orElseThrow() as param>${helper.toParseExpression(optionalField, helper.anyTypeRefere [...]
+        write_buffer.${helper.getDataWriterCall(typedField.type, optionalField.name)}(self.${helper.camelCaseToSnakeCase(optionalField.name)}, logical_name="${optionalField.name}", condition=${helper.toSerializationExpression(optionalField, helper.boolTypeReference, optionalField.conditionExpression.get(), parserArguments)}, <#list optionalField.type.asComplexTypeReference().orElseThrow().params.orElseThrow() as param>${helper.toParseExpression(optionalField, helper.anyTypeReference, par [...]
                         <#else>
-        write_optional_field("${optionalField.name}", self.${helper.camelCaseToSnakeCase(optionalField.name)}, ${helper.getDataWriterCall(typedField.type, optionalField.name)}<#if optionalField.conditionExpression.present>, ${helper.toSerializationExpression(optionalField, helper.boolTypeReference, optionalField.conditionExpression.get(), parserArguments)}</#if>)
+        write_buffer.${helper.getDataWriterCall(typedField.type, optionalField.name)}(self.${helper.camelCaseToSnakeCase(optionalField.name)}, logical_name="${optionalField.name}"<#if optionalField.conditionExpression.present>, condition=${helper.toSerializationExpression(optionalField, helper.boolTypeReference, optionalField.conditionExpression.get(), parserArguments)}}</#if>)
                         </#if>
                         <#break>
                     <#case "padding">
@@ -308,14 +308,14 @@ class ${type.name}<#if type.isDiscriminatedParentTypeDefinition()></#if>(<#if ty
                         <#assign typedField = field.asTypedField().orElseThrow()>
 
         # Padding Field (padding)
-        write_padding_field("padding", int(${helper.toParseExpression(paddingField, helper.intTypeReference, paddingField.paddingCondition, parserArguments)}), ${helper.getLanguageTypeNameForField(field)}(${helper.toSerializationExpression(paddingField, paddingField.type, paddingField.paddingValue, parserArguments)}, ${helper.getDataWriterCall(typedField.type, "padding")})
+        write_buffer.${helper.getDataWriterCall(typedField.type, "padding")}(int(${helper.toParseExpression(paddingField, helper.intTypeReference, paddingField.paddingCondition, parserArguments)}), logical_name="padding")
                         <#break>
                     <#case "reserved">
                         <#assign reservedField = field.asReservedField().orElseThrow()>
                         <#assign typedField = field.asTypedField().orElseThrow()>
 
         # Reserved Field (reserved)
-        write_reserved_field("reserved", self.reserved_field_${reservedFieldIndex}!=null?self.reserved_field_${reservedFieldIndex}: ${helper.getReservedValue(reservedField)}, ${helper.getDataWriterCall(typedField.type, "reserved")})<#assign reservedFieldIndex=reservedFieldIndex+1>
+        write_buffer.${helper.getDataWriterCall(typedField.type, "reserved")}(self.reserved_field_${reservedFieldIndex}!=None?self.reserved_field_${reservedFieldIndex}: ${helper.getReservedValue(reservedField)}, logical_name="reserved")<#assign reservedFieldIndex=reservedFieldIndex+1>
                         <#break>
                     <#case "simple">
                         <#assign simpleField = field.asSimpleField().orElseThrow()>
@@ -324,11 +324,11 @@ class ${type.name}<#if type.isDiscriminatedParentTypeDefinition()></#if>(<#if ty
 
         # Simple Field (${namedField.name})
                         <#if typedField.type.isEnumTypeReference()>
-        write_simple_enum_field("${simpleField.name}", "${helper.getLanguageTypeNameForField(field)}", self.${helper.camelCaseToSnakeCase(simpleField.name)}, ${helper.getEnumDataWriterCall(simpleField.type, simpleField.name, "value")})
+        write_buffer.${helper.getEnumDataWriterCall(simpleField.type, simpleField.name, "value")}(self.${helper.camelCaseToSnakeCase(simpleField.name)}, logical_name="${simpleField.name}")
                         <#elseif simpleField.type.isDataIoTypeReference()>
-        write_simple_field("${simpleField.name}", self.${helper.camelCaseToSnakeCase(simpleField.name)}, DataWriterDataIoDefault(write_buffer, (wb, val) -> ${simpleField.type.asComplexTypeReference().orElseThrow().name}.staticSerialize(wb, val<#if simpleField.type.asComplexTypeReference().orElseThrow().params?has_content>, <#list simpleField.type.asComplexTypeReference().orElseThrow().params.orElseThrow() as param>${helper.toParseExpression(simpleField, helper.anyTypeReference, param, pa [...]
+        write_buffer.${helper.getEnumDataWriterCall(simpleField.type, simpleField.name, "value")}(DataWriterDataIoDefault(write_buffer, (wb, val) -> ${simpleField.type.asComplexTypeReference().orElseThrow().name}.staticSerialize(wb, val<#if simpleField.type.asComplexTypeReference().orElseThrow().params?has_content>, <#list simpleField.type.asComplexTypeReference().orElseThrow().params.orElseThrow() as param>${helper.toParseExpression(simpleField, helper.anyTypeReference, param, parserArg [...]
                         <#else>
-        write_simple_field("${simpleField.name}", self.${helper.camelCaseToSnakeCase(simpleField.name)}, ${helper.getDataWriterCall(typedField.type, simpleField.name)}${helper.getFieldOptions(typedField, parserArguments)})</#if>
+        write_buffer.${helper.getDataWriterCall(typedField.type, simpleField.name)}(self.${helper.camelCaseToSnakeCase(simpleField.name)}, logical_name="${simpleField.name}")</#if>
                         <#break>
                     <#case "switch">
                         <#assign switchField = field.asSwitchField().orElseThrow()>
@@ -343,7 +343,6 @@ class ${type.name}<#if type.isDiscriminatedParentTypeDefinition()></#if>(<#if ty
 
         # Virtual field (doesn't actually serialize anything, just makes the value available)
         ${namedField.name}: ${helper.getLanguageTypeNameForField(field)}  = self.${helper.camelCaseToSnakeCase(namedField.name)}()
-        write_buffer.write_virtual("${namedField.name}", self.${helper.camelCaseToSnakeCase(namedField.name)})
                         <#break>
                 </#switch>
             </#list>
@@ -535,7 +534,6 @@ class ${type.name}<#if type.isDiscriminatedParentTypeDefinition()></#if>(<#if ty
 <#-- The parse and serialize methods here are just proxies for forwardning the requests to static counterparts -->
     <#if !type.isDiscriminatedChildTypeDefinition()>
     def static_parse(read_buffer: ReadBuffer , args):
-        position_aware: PositionAware = read_buffer
         <#if parserArguments?has_content>
         if (args is None) or (args.length is not ${parserArguments?size}):
             raise PlcRuntimeException("Wrong number of arguments, expected ${parserArguments?size}, but got " + args.length)
@@ -564,8 +562,7 @@ class ${type.name}<#if type.isDiscriminatedParentTypeDefinition()></#if>(<#if ty
     @staticmethod
     def <#if type.isDiscriminatedChildTypeDefinition()>static_parse_builder<#else>static_parse_context</#if>(read_buffer: ReadBuffer<#if hasParserArguments>, ${parserArgumentList}</#if>):
         read_buffer.pull_context("${type.name}")
-        position_aware: PositionAware = read_buffer
-        start_pos: int = position_aware.get_pos()
+        start_pos: int = read_buffer.get_pos()
         cur_pos: int = 0
     <#assign reservedFieldIndex=0>
     <#list type.fields as field>
diff --git a/code-generation/language-python/src/main/resources/templates/python/enum-template.python.ftlh b/code-generation/language-python/src/main/resources/templates/python/enum-template.python.ftlh
index 5b882ce5c9..e14eb49d4a 100644
--- a/code-generation/language-python/src/main/resources/templates/python/enum-template.python.ftlh
+++ b/code-generation/language-python/src/main/resources/templates/python/enum-template.python.ftlh
@@ -58,9 +58,9 @@ ${import}
 </#macro>
 <#macro emitImport import>${helper.emitRequiredImport(import)}</#macro>
 <@importSectionWithContentBelow>
-<@emitImport import="from enum import Enum" />
+<@emitImport import="from enum import IntEnum" />
 
-class ${type.name}(Enum):
+class ${type.name}(IntEnum):
     <#list type.enumValues as enumValue>
     ${enumValue.name}: <@compress single_line=true>
             <#if type.type.isPresent()>
diff --git a/sandbox/plc4py/plc4py/protocols/modbus/readwrite/DataItem.py b/sandbox/plc4py/plc4py/protocols/modbus/readwrite/DataItem.py
index a0397bf828..ddbc20e5c2 100644
--- a/sandbox/plc4py/plc4py/protocols/modbus/readwrite/DataItem.py
+++ b/sandbox/plc4py/plc4py/protocols/modbus/readwrite/DataItem.py
@@ -40,9 +40,9 @@ class DataItem:
         read_buffer: ReadBuffer, data_type: ModbusDataType, number_of_values: c_uint16
     ):
         if EvaluationHelper.equals(
-            data_type, ModbusDataType.BOOL
+            data_type, ModbusDataType.get_bool()
         ) and EvaluationHelper.equals(
-            number_of_values, 1
+            number_of_values, c_uint16(1)
         ):  # BOOL
             # Reserved Field (Compartmentalized so the "reserved" variable can't leak)
             reserved: c_uint16 = read_buffer.readUnsignedInt("", 15)
@@ -59,7 +59,7 @@ class DataItem:
             value: c_bool = read_buffer.readBit("")
 
             return PlcBOOL(value)
-        if EvaluationHelper.equals(data_type, ModbusDataType.BOOL):  # List
+        if EvaluationHelper.equals(data_type, ModbusDataType.get_bool()):  # List
             # Array field (value)
             # Count array
             if numberOfValues > Integer.MAX_VALUE:
@@ -77,9 +77,9 @@ class DataItem:
 
             return PlcList(value)
         if EvaluationHelper.equals(
-            data_type, ModbusDataType.BYTE
+            data_type, ModbusDataType.get_byte()
         ) and EvaluationHelper.equals(
-            number_of_values, 1
+            number_of_values, c_uint16(1)
         ):  # BYTE
             # Reserved Field (Compartmentalized so the "reserved" variable can't leak)
             reserved: c_uint8 = read_buffer.readUnsignedShort("", 8)
@@ -96,42 +96,42 @@ class DataItem:
             value: c_uint8 = read_buffer.readUnsignedShort("", 8)
 
             return PlcBYTE(value)
-        if EvaluationHelper.equals(data_type, ModbusDataType.BYTE):  # List
+        if EvaluationHelper.equals(data_type, ModbusDataType.get_byte()):  # List
             # Array field (value)
             # Count array
-            if (numberOfValues) * (8) > Integer.MAX_VALUE:
+            if c_int32(numberOfValues) * c_int32(c_int32(8)) > Integer.MAX_VALUE:
                 raise ParseException(
                     "Array count of "
-                    + ((numberOfValues) * (8))
+                    + (c_int32(numberOfValues) * c_int32(c_int32(8)))
                     + " exceeds the maximum allowed count of "
                     + Integer.MAX_VALUE
                 )
 
-            item_count: int = int((numberOfValues) * (8))
+            item_count: int = int(c_int32(numberOfValues) * c_int32(c_int32(8)))
             value: List[PlcValue] = []
             for cur_item in range(item_count):
                 value.append(PlcBOOL(c_bool(read_buffer.readBit(""))))
 
             return PlcList(value)
-        if EvaluationHelper.equals(data_type, ModbusDataType.WORD):  # WORD
+        if EvaluationHelper.equals(data_type, ModbusDataType.get_word()):  # WORD
             # Simple Field (value)
             value: c_uint16 = read_buffer.readUnsignedInt("", 16)
 
             return PlcWORD(value)
-        if EvaluationHelper.equals(data_type, ModbusDataType.DWORD):  # DWORD
+        if EvaluationHelper.equals(data_type, ModbusDataType.get_dword()):  # DWORD
             # Simple Field (value)
             value: c_uint32 = read_buffer.readUnsignedLong("", 32)
 
             return PlcDWORD(value)
-        if EvaluationHelper.equals(data_type, ModbusDataType.LWORD):  # LWORD
+        if EvaluationHelper.equals(data_type, ModbusDataType.get_lword()):  # LWORD
             # Simple Field (value)
             value: c_uint64 = read_buffer.readUnsignedBigInteger("", 64)
 
             return PlcLWORD(value)
         if EvaluationHelper.equals(
-            data_type, ModbusDataType.SINT
+            data_type, ModbusDataType.get_sint()
         ) and EvaluationHelper.equals(
-            number_of_values, 1
+            number_of_values, c_uint16(1)
         ):  # SINT
             # Reserved Field (Compartmentalized so the "reserved" variable can't leak)
             reserved: c_uint8 = read_buffer.readUnsignedShort("", 8)
@@ -148,7 +148,7 @@ class DataItem:
             value: c_int8 = read_buffer.readSignedByte("", 8)
 
             return PlcSINT(value)
-        if EvaluationHelper.equals(data_type, ModbusDataType.SINT):  # List
+        if EvaluationHelper.equals(data_type, ModbusDataType.get_sint()):  # List
             # Array field (value)
             # Count array
             if numberOfValues > Integer.MAX_VALUE:
@@ -166,15 +166,15 @@ class DataItem:
 
             return PlcList(value)
         if EvaluationHelper.equals(
-            data_type, ModbusDataType.INT
+            data_type, ModbusDataType.get_int()
         ) and EvaluationHelper.equals(
-            number_of_values, 1
+            number_of_values, c_uint16(1)
         ):  # INT
             # Simple Field (value)
             value: c_int16 = read_buffer.readShort("", 16)
 
             return PlcINT(value)
-        if EvaluationHelper.equals(data_type, ModbusDataType.INT):  # List
+        if EvaluationHelper.equals(data_type, ModbusDataType.get_int()):  # List
             # Array field (value)
             # Count array
             if numberOfValues > Integer.MAX_VALUE:
@@ -192,15 +192,15 @@ class DataItem:
 
             return PlcList(value)
         if EvaluationHelper.equals(
-            data_type, ModbusDataType.DINT
+            data_type, ModbusDataType.get_dint()
         ) and EvaluationHelper.equals(
-            number_of_values, 1
+            number_of_values, c_uint16(1)
         ):  # DINT
             # Simple Field (value)
             value: c_int32 = read_buffer.readInt("", 32)
 
             return PlcDINT(value)
-        if EvaluationHelper.equals(data_type, ModbusDataType.DINT):  # List
+        if EvaluationHelper.equals(data_type, ModbusDataType.get_dint()):  # List
             # Array field (value)
             # Count array
             if numberOfValues > Integer.MAX_VALUE:
@@ -218,15 +218,15 @@ class DataItem:
 
             return PlcList(value)
         if EvaluationHelper.equals(
-            data_type, ModbusDataType.LINT
+            data_type, ModbusDataType.get_lint()
         ) and EvaluationHelper.equals(
-            number_of_values, 1
+            number_of_values, c_uint16(1)
         ):  # LINT
             # Simple Field (value)
             value: c_int64 = read_buffer.readLong("", 64)
 
             return PlcLINT(value)
-        if EvaluationHelper.equals(data_type, ModbusDataType.LINT):  # List
+        if EvaluationHelper.equals(data_type, ModbusDataType.get_lint()):  # List
             # Array field (value)
             # Count array
             if numberOfValues > Integer.MAX_VALUE:
@@ -244,9 +244,9 @@ class DataItem:
 
             return PlcList(value)
         if EvaluationHelper.equals(
-            data_type, ModbusDataType.USINT
+            data_type, ModbusDataType.get_usint()
         ) and EvaluationHelper.equals(
-            number_of_values, 1
+            number_of_values, c_uint16(1)
         ):  # USINT
             # Reserved Field (Compartmentalized so the "reserved" variable can't leak)
             reserved: c_uint8 = read_buffer.readUnsignedShort("", 8)
@@ -263,7 +263,7 @@ class DataItem:
             value: c_uint8 = read_buffer.readUnsignedShort("", 8)
 
             return PlcUSINT(value)
-        if EvaluationHelper.equals(data_type, ModbusDataType.USINT):  # List
+        if EvaluationHelper.equals(data_type, ModbusDataType.get_usint()):  # List
             # Array field (value)
             # Count array
             if numberOfValues > Integer.MAX_VALUE:
@@ -281,15 +281,15 @@ class DataItem:
 
             return PlcList(value)
         if EvaluationHelper.equals(
-            data_type, ModbusDataType.UINT
+            data_type, ModbusDataType.get_uint()
         ) and EvaluationHelper.equals(
-            number_of_values, 1
+            number_of_values, c_uint16(1)
         ):  # UINT
             # Simple Field (value)
             value: c_uint16 = read_buffer.readUnsignedInt("", 16)
 
             return PlcUINT(value)
-        if EvaluationHelper.equals(data_type, ModbusDataType.UINT):  # List
+        if EvaluationHelper.equals(data_type, ModbusDataType.get_uint()):  # List
             # Array field (value)
             # Count array
             if numberOfValues > Integer.MAX_VALUE:
@@ -307,15 +307,15 @@ class DataItem:
 
             return PlcList(value)
         if EvaluationHelper.equals(
-            data_type, ModbusDataType.UDINT
+            data_type, ModbusDataType.get_udint()
         ) and EvaluationHelper.equals(
-            number_of_values, 1
+            number_of_values, c_uint16(1)
         ):  # UDINT
             # Simple Field (value)
             value: c_uint32 = read_buffer.readUnsignedLong("", 32)
 
             return PlcUDINT(value)
-        if EvaluationHelper.equals(data_type, ModbusDataType.UDINT):  # List
+        if EvaluationHelper.equals(data_type, ModbusDataType.get_udint()):  # List
             # Array field (value)
             # Count array
             if numberOfValues > Integer.MAX_VALUE:
@@ -333,15 +333,15 @@ class DataItem:
 
             return PlcList(value)
         if EvaluationHelper.equals(
-            data_type, ModbusDataType.ULINT
+            data_type, ModbusDataType.get_ulint()
         ) and EvaluationHelper.equals(
-            number_of_values, 1
+            number_of_values, c_uint16(1)
         ):  # ULINT
             # Simple Field (value)
             value: c_uint64 = read_buffer.readUnsignedBigInteger("", 64)
 
             return PlcULINT(value)
-        if EvaluationHelper.equals(data_type, ModbusDataType.ULINT):  # List
+        if EvaluationHelper.equals(data_type, ModbusDataType.get_ulint()):  # List
             # Array field (value)
             # Count array
             if numberOfValues > Integer.MAX_VALUE:
@@ -361,15 +361,15 @@ class DataItem:
 
             return PlcList(value)
         if EvaluationHelper.equals(
-            data_type, ModbusDataType.REAL
+            data_type, ModbusDataType.get_real()
         ) and EvaluationHelper.equals(
-            number_of_values, 1
+            number_of_values, c_uint16(1)
         ):  # REAL
             # Simple Field (value)
             value: c_float = read_buffer.readFloat("", 32)
 
             return PlcREAL(value)
-        if EvaluationHelper.equals(data_type, ModbusDataType.REAL):  # List
+        if EvaluationHelper.equals(data_type, ModbusDataType.get_real()):  # List
             # Array field (value)
             # Count array
             if numberOfValues > Integer.MAX_VALUE:
@@ -387,15 +387,15 @@ class DataItem:
 
             return PlcList(value)
         if EvaluationHelper.equals(
-            data_type, ModbusDataType.LREAL
+            data_type, ModbusDataType.get_lreal()
         ) and EvaluationHelper.equals(
-            number_of_values, 1
+            number_of_values, c_uint16(1)
         ):  # LREAL
             # Simple Field (value)
             value: c_double = read_buffer.readDouble("", 64)
 
             return PlcLREAL(value)
-        if EvaluationHelper.equals(data_type, ModbusDataType.LREAL):  # List
+        if EvaluationHelper.equals(data_type, ModbusDataType.get_lreal()):  # List
             # Array field (value)
             # Count array
             if numberOfValues > Integer.MAX_VALUE:
@@ -413,15 +413,15 @@ class DataItem:
 
             return PlcList(value)
         if EvaluationHelper.equals(
-            data_type, ModbusDataType.CHAR
+            data_type, ModbusDataType.get_char()
         ) and EvaluationHelper.equals(
-            number_of_values, 1
+            number_of_values, c_uint16(1)
         ):  # CHAR
             # Simple Field (value)
             value: str = read_buffer.readString("", 8, "UTF-8")
 
             return PlcCHAR(value)
-        if EvaluationHelper.equals(data_type, ModbusDataType.CHAR):  # List
+        if EvaluationHelper.equals(data_type, ModbusDataType.get_char()):  # List
             # Array field (value)
             # Count array
             if numberOfValues > Integer.MAX_VALUE:
@@ -439,15 +439,15 @@ class DataItem:
 
             return PlcList(value)
         if EvaluationHelper.equals(
-            data_type, ModbusDataType.WCHAR
+            data_type, ModbusDataType.get_wchar()
         ) and EvaluationHelper.equals(
-            number_of_values, 1
+            number_of_values, c_uint16(1)
         ):  # WCHAR
             # Simple Field (value)
             value: str = read_buffer.readString("", 16, "UTF-16")
 
             return PlcWCHAR(value)
-        if EvaluationHelper.equals(data_type, ModbusDataType.WCHAR):  # List
+        if EvaluationHelper.equals(data_type, ModbusDataType.get_wchar()):  # List
             # Array field (value)
             # Count array
             if numberOfValues > Integer.MAX_VALUE:
@@ -486,234 +486,234 @@ class DataItem:
         byteOrder: ByteOrder,
     ) -> None:
         if EvaluationHelper.equals(
-            dataType, ModbusDataType.BOOL
+            dataType, ModbusDataType.get_bool()
         ) and EvaluationHelper.equals(
-            numberOfValues, 1
+            numberOfValues, c_uint16(1)
         ):  # BOOL
             # Reserved Field
-            writeBuffer.writeUnsignedInt("", 15, c_uint16(0x0000).intValue())
+            writeBuffer.WriteUint16("cuint160x0000", 15, c_uint16(0x0000))
             # Simple Field (value)
             value: c_bool = _value.getC_bool()
-            writeBuffer.writeBit("", bool((value)))
-        if EvaluationHelper.equals(dataType, ModbusDataType.BOOL):  # List
+            writeBuffer.WriteBit("value", (value))
+        if EvaluationHelper.equals(dataType, ModbusDataType.get_bool()):  # List
             values: PlcList = _value
 
             for val in values.getList():
                 value: c_bool = val.getC_bool()
-                writeBuffer.writeBit("", bool((value)))
+                writeBuffer.WriteBit("value", (value))
 
         if EvaluationHelper.equals(
-            dataType, ModbusDataType.BYTE
+            dataType, ModbusDataType.get_byte()
         ) and EvaluationHelper.equals(
-            numberOfValues, 1
+            numberOfValues, c_uint16(1)
         ):  # BYTE
             # Reserved Field
-            writeBuffer.writeUnsignedShort("", 8, c_uint8(0x00).shortValue())
+            writeBuffer.WriteUint8("cuint80x00", 8, c_uint8(0x00))
             # Simple Field (value)
             value: c_uint8 = _value.getC_uint8()
-            writeBuffer.writeUnsignedShort("", 8, (value).shortValue())
-        if EvaluationHelper.equals(dataType, ModbusDataType.BYTE):  # List
+            writeBuffer.WriteUint8("value", 8, (value))
+        if EvaluationHelper.equals(dataType, ModbusDataType.get_byte()):  # List
             values: PlcList = _value
 
             for val in values.getList():
                 value: c_bool = val.getC_bool()
-                writeBuffer.writeBit("", bool((value)))
+                writeBuffer.WriteBit("value", (value))
 
-        if EvaluationHelper.equals(dataType, ModbusDataType.WORD):  # WORD
+        if EvaluationHelper.equals(dataType, ModbusDataType.get_word()):  # WORD
             # Simple Field (value)
             value: c_uint16 = _value.getC_uint16()
-            writeBuffer.writeUnsignedInt("", 16, (value).intValue())
-        if EvaluationHelper.equals(dataType, ModbusDataType.DWORD):  # DWORD
+            writeBuffer.WriteUint16("value", 16, (value))
+        if EvaluationHelper.equals(dataType, ModbusDataType.get_dword()):  # DWORD
             # Simple Field (value)
             value: c_uint32 = _value.getC_uint32()
-            writeBuffer.writeUnsignedLong("", 32, (value).longValue())
-        if EvaluationHelper.equals(dataType, ModbusDataType.LWORD):  # LWORD
+            writeBuffer.WriteUint32("value", 32, (value))
+        if EvaluationHelper.equals(dataType, ModbusDataType.get_lword()):  # LWORD
             # Simple Field (value)
             value: c_uint64 = _value.getC_uint64()
-            writeBuffer.writeUnsignedBigInteger("", 64, (value))
+            writeBuffer.WriteUint64("value", 64, (value))
         if EvaluationHelper.equals(
-            dataType, ModbusDataType.SINT
+            dataType, ModbusDataType.get_sint()
         ) and EvaluationHelper.equals(
-            numberOfValues, 1
+            numberOfValues, c_uint16(1)
         ):  # SINT
             # Reserved Field
-            writeBuffer.writeUnsignedShort("", 8, c_uint8(0x00).shortValue())
+            writeBuffer.WriteUint8("cuint80x00", 8, c_uint8(0x00))
             # Simple Field (value)
             value: c_int8 = _value.getC_int8()
-            writeBuffer.writeSignedByte("", 8, (value).byteValue())
-        if EvaluationHelper.equals(dataType, ModbusDataType.SINT):  # List
+            writeBuffer.WriteInt8("value", 8, (value))
+        if EvaluationHelper.equals(dataType, ModbusDataType.get_sint()):  # List
             values: PlcList = _value
 
             for val in values.getList():
                 value: c_int8 = val.getC_int8()
-                writeBuffer.writeSignedByte("", 8, (value).byteValue())
+                writeBuffer.WriteInt8("value", 8, (value))
 
         if EvaluationHelper.equals(
-            dataType, ModbusDataType.INT
+            dataType, ModbusDataType.get_int()
         ) and EvaluationHelper.equals(
-            numberOfValues, 1
+            numberOfValues, c_uint16(1)
         ):  # INT
             # Simple Field (value)
             value: c_int16 = _value.getC_int16()
-            writeBuffer.writeShort("", 16, (value).shortValue())
-        if EvaluationHelper.equals(dataType, ModbusDataType.INT):  # List
+            writeBuffer.WriteInt16("value", 16, (value))
+        if EvaluationHelper.equals(dataType, ModbusDataType.get_int()):  # List
             values: PlcList = _value
 
             for val in values.getList():
                 value: c_int16 = val.getC_int16()
-                writeBuffer.writeShort("", 16, (value).shortValue())
+                writeBuffer.WriteInt16("value", 16, (value))
 
         if EvaluationHelper.equals(
-            dataType, ModbusDataType.DINT
+            dataType, ModbusDataType.get_dint()
         ) and EvaluationHelper.equals(
-            numberOfValues, 1
+            numberOfValues, c_uint16(1)
         ):  # DINT
             # Simple Field (value)
             value: c_int32 = _value.getC_int32()
-            writeBuffer.writeInt("", 32, (value).intValue())
-        if EvaluationHelper.equals(dataType, ModbusDataType.DINT):  # List
+            writeBuffer.WriteInt32("value", 32, (value))
+        if EvaluationHelper.equals(dataType, ModbusDataType.get_dint()):  # List
             values: PlcList = _value
 
             for val in values.getList():
                 value: c_int32 = val.getC_int32()
-                writeBuffer.writeInt("", 32, (value).intValue())
+                writeBuffer.WriteInt32("value", 32, (value))
 
         if EvaluationHelper.equals(
-            dataType, ModbusDataType.LINT
+            dataType, ModbusDataType.get_lint()
         ) and EvaluationHelper.equals(
-            numberOfValues, 1
+            numberOfValues, c_uint16(1)
         ):  # LINT
             # Simple Field (value)
             value: c_int64 = _value.getC_int64()
-            writeBuffer.writeLong("", 64, (value).longValue())
-        if EvaluationHelper.equals(dataType, ModbusDataType.LINT):  # List
+            writeBuffer.WriteInt64("value", 64, (value))
+        if EvaluationHelper.equals(dataType, ModbusDataType.get_lint()):  # List
             values: PlcList = _value
 
             for val in values.getList():
                 value: c_int64 = val.getC_int64()
-                writeBuffer.writeLong("", 64, (value).longValue())
+                writeBuffer.WriteInt64("value", 64, (value))
 
         if EvaluationHelper.equals(
-            dataType, ModbusDataType.USINT
+            dataType, ModbusDataType.get_usint()
         ) and EvaluationHelper.equals(
-            numberOfValues, 1
+            numberOfValues, c_uint16(1)
         ):  # USINT
             # Reserved Field
-            writeBuffer.writeUnsignedShort("", 8, c_uint8(0x00).shortValue())
+            writeBuffer.WriteUint8("cuint80x00", 8, c_uint8(0x00))
             # Simple Field (value)
             value: c_uint8 = _value.getC_uint8()
-            writeBuffer.writeUnsignedShort("", 8, (value).shortValue())
-        if EvaluationHelper.equals(dataType, ModbusDataType.USINT):  # List
+            writeBuffer.WriteUint8("value", 8, (value))
+        if EvaluationHelper.equals(dataType, ModbusDataType.get_usint()):  # List
             values: PlcList = _value
 
             for val in values.getList():
                 value: c_uint8 = val.getC_uint8()
-                writeBuffer.writeUnsignedShort("", 8, (value).shortValue())
+                writeBuffer.WriteUint8("value", 8, (value))
 
         if EvaluationHelper.equals(
-            dataType, ModbusDataType.UINT
+            dataType, ModbusDataType.get_uint()
         ) and EvaluationHelper.equals(
-            numberOfValues, 1
+            numberOfValues, c_uint16(1)
         ):  # UINT
             # Simple Field (value)
             value: c_uint16 = _value.getC_uint16()
-            writeBuffer.writeUnsignedInt("", 16, (value).intValue())
-        if EvaluationHelper.equals(dataType, ModbusDataType.UINT):  # List
+            writeBuffer.WriteUint16("value", 16, (value))
+        if EvaluationHelper.equals(dataType, ModbusDataType.get_uint()):  # List
             values: PlcList = _value
 
             for val in values.getList():
                 value: c_uint16 = val.getC_uint16()
-                writeBuffer.writeUnsignedInt("", 16, (value).intValue())
+                writeBuffer.WriteUint16("value", 16, (value))
 
         if EvaluationHelper.equals(
-            dataType, ModbusDataType.UDINT
+            dataType, ModbusDataType.get_udint()
         ) and EvaluationHelper.equals(
-            numberOfValues, 1
+            numberOfValues, c_uint16(1)
         ):  # UDINT
             # Simple Field (value)
             value: c_uint32 = _value.getC_uint32()
-            writeBuffer.writeUnsignedLong("", 32, (value).longValue())
-        if EvaluationHelper.equals(dataType, ModbusDataType.UDINT):  # List
+            writeBuffer.WriteUint32("value", 32, (value))
+        if EvaluationHelper.equals(dataType, ModbusDataType.get_udint()):  # List
             values: PlcList = _value
 
             for val in values.getList():
                 value: c_uint32 = val.getC_uint32()
-                writeBuffer.writeUnsignedLong("", 32, (value).longValue())
+                writeBuffer.WriteUint32("value", 32, (value))
 
         if EvaluationHelper.equals(
-            dataType, ModbusDataType.ULINT
+            dataType, ModbusDataType.get_ulint()
         ) and EvaluationHelper.equals(
-            numberOfValues, 1
+            numberOfValues, c_uint16(1)
         ):  # ULINT
             # Simple Field (value)
             value: c_uint64 = _value.getC_uint64()
-            writeBuffer.writeUnsignedBigInteger("", 64, (value))
-        if EvaluationHelper.equals(dataType, ModbusDataType.ULINT):  # List
+            writeBuffer.WriteUint64("value", 64, (value))
+        if EvaluationHelper.equals(dataType, ModbusDataType.get_ulint()):  # List
             values: PlcList = _value
 
             for val in values.getList():
                 value: c_uint64 = val.getC_uint64()
-                writeBuffer.writeUnsignedBigInteger("", 64, (value))
+                writeBuffer.WriteUint64("value", 64, (value))
 
         if EvaluationHelper.equals(
-            dataType, ModbusDataType.REAL
+            dataType, ModbusDataType.get_real()
         ) and EvaluationHelper.equals(
-            numberOfValues, 1
+            numberOfValues, c_uint16(1)
         ):  # REAL
             # Simple Field (value)
             value: c_float = _value.getC_float()
-            writeBuffer.writeFloat("", 32, (value))
-        if EvaluationHelper.equals(dataType, ModbusDataType.REAL):  # List
+            writeBuffer.WriteFloat32("value", 32, (value))
+        if EvaluationHelper.equals(dataType, ModbusDataType.get_real()):  # List
             values: PlcList = _value
 
             for val in values.getList():
                 value: c_float = val.getC_float()
-                writeBuffer.writeFloat("", 32, (value))
+                writeBuffer.WriteFloat32("value", 32, (value))
 
         if EvaluationHelper.equals(
-            dataType, ModbusDataType.LREAL
+            dataType, ModbusDataType.get_lreal()
         ) and EvaluationHelper.equals(
-            numberOfValues, 1
+            numberOfValues, c_uint16(1)
         ):  # LREAL
             # Simple Field (value)
             value: c_double = _value.getC_double()
-            writeBuffer.writeDouble("", 64, (value))
-        if EvaluationHelper.equals(dataType, ModbusDataType.LREAL):  # List
+            writeBuffer.WriteFloat64("value", 64, (value))
+        if EvaluationHelper.equals(dataType, ModbusDataType.get_lreal()):  # List
             values: PlcList = _value
 
             for val in values.getList():
                 value: c_double = val.getC_double()
-                writeBuffer.writeDouble("", 64, (value))
+                writeBuffer.WriteFloat64("value", 64, (value))
 
         if EvaluationHelper.equals(
-            dataType, ModbusDataType.CHAR
+            dataType, ModbusDataType.get_char()
         ) and EvaluationHelper.equals(
-            numberOfValues, 1
+            numberOfValues, c_uint16(1)
         ):  # CHAR
             # Simple Field (value)
             value: str = _value.getStr()
-            writeBuffer.writeString("", 8, "UTF-8", (String)(value))
-        if EvaluationHelper.equals(dataType, ModbusDataType.CHAR):  # List
+            writeBuffer.WriteString("value", uint32(8), "UTF-8", (value))
+        if EvaluationHelper.equals(dataType, ModbusDataType.get_char()):  # List
             values: PlcList = _value
 
             for val in values.getList():
                 value: str = val.getStr()
-                writeBuffer.writeString("", 8, "UTF-8", (String)(value))
+                writeBuffer.WriteString("value", uint32(8), "UTF-8", (value))
 
         if EvaluationHelper.equals(
-            dataType, ModbusDataType.WCHAR
+            dataType, ModbusDataType.get_wchar()
         ) and EvaluationHelper.equals(
-            numberOfValues, 1
+            numberOfValues, c_uint16(1)
         ):  # WCHAR
             # Simple Field (value)
             value: str = _value.getStr()
-            writeBuffer.writeString("", 16, "UTF-16", (String)(value))
-        if EvaluationHelper.equals(dataType, ModbusDataType.WCHAR):  # List
+            writeBuffer.WriteString("value", uint32(16), "UTF-16", (value))
+        if EvaluationHelper.equals(dataType, ModbusDataType.get_wchar()):  # List
             values: PlcList = _value
 
             for val in values.getList():
                 value: str = val.getStr()
-                writeBuffer.writeString("", 16, "UTF-16", (String)(value))
+                writeBuffer.WriteString("value", uint32(16), "UTF-16", (value))
 
     @staticmethod
     def get_length_in_bytes(
@@ -729,160 +729,160 @@ class DataItem:
     ) -> int:
         sizeInBits: int = 0
         if EvaluationHelper.equals(
-            dataType, ModbusDataType.BOOL
+            dataType, ModbusDataType.get_bool()
         ) and EvaluationHelper.equals(
-            numberOfValues, 1
+            numberOfValues, c_uint16(1)
         ):  # BOOL
             # Reserved Field
             sizeInBits += 15
             # Simple Field (value)
             sizeInBits += 1
-        if EvaluationHelper.equals(dataType, ModbusDataType.BOOL):  # List
+        if EvaluationHelper.equals(dataType, ModbusDataType.get_bool()):  # List
             values: PlcList = _value
             sizeInBits += values.getList().size() * 1
         if EvaluationHelper.equals(
-            dataType, ModbusDataType.BYTE
+            dataType, ModbusDataType.get_byte()
         ) and EvaluationHelper.equals(
-            numberOfValues, 1
+            numberOfValues, c_uint16(1)
         ):  # BYTE
             # Reserved Field
             sizeInBits += 8
             # Simple Field (value)
             sizeInBits += 8
-        if EvaluationHelper.equals(dataType, ModbusDataType.BYTE):  # List
+        if EvaluationHelper.equals(dataType, ModbusDataType.get_byte()):  # List
             values: PlcList = _value
             sizeInBits += values.getList().size() * 1
-        if EvaluationHelper.equals(dataType, ModbusDataType.WORD):  # WORD
+        if EvaluationHelper.equals(dataType, ModbusDataType.get_word()):  # WORD
             # Simple Field (value)
             sizeInBits += 16
-        if EvaluationHelper.equals(dataType, ModbusDataType.DWORD):  # DWORD
+        if EvaluationHelper.equals(dataType, ModbusDataType.get_dword()):  # DWORD
             # Simple Field (value)
             sizeInBits += 32
-        if EvaluationHelper.equals(dataType, ModbusDataType.LWORD):  # LWORD
+        if EvaluationHelper.equals(dataType, ModbusDataType.get_lword()):  # LWORD
             # Simple Field (value)
             sizeInBits += 64
         if EvaluationHelper.equals(
-            dataType, ModbusDataType.SINT
+            dataType, ModbusDataType.get_sint()
         ) and EvaluationHelper.equals(
-            numberOfValues, 1
+            numberOfValues, c_uint16(1)
         ):  # SINT
             # Reserved Field
             sizeInBits += 8
             # Simple Field (value)
             sizeInBits += 8
-        if EvaluationHelper.equals(dataType, ModbusDataType.SINT):  # List
+        if EvaluationHelper.equals(dataType, ModbusDataType.get_sint()):  # List
             values: PlcList = _value
             sizeInBits += values.getList().size() * 8
         if EvaluationHelper.equals(
-            dataType, ModbusDataType.INT
+            dataType, ModbusDataType.get_int()
         ) and EvaluationHelper.equals(
-            numberOfValues, 1
+            numberOfValues, c_uint16(1)
         ):  # INT
             # Simple Field (value)
             sizeInBits += 16
-        if EvaluationHelper.equals(dataType, ModbusDataType.INT):  # List
+        if EvaluationHelper.equals(dataType, ModbusDataType.get_int()):  # List
             values: PlcList = _value
             sizeInBits += values.getList().size() * 16
         if EvaluationHelper.equals(
-            dataType, ModbusDataType.DINT
+            dataType, ModbusDataType.get_dint()
         ) and EvaluationHelper.equals(
-            numberOfValues, 1
+            numberOfValues, c_uint16(1)
         ):  # DINT
             # Simple Field (value)
             sizeInBits += 32
-        if EvaluationHelper.equals(dataType, ModbusDataType.DINT):  # List
+        if EvaluationHelper.equals(dataType, ModbusDataType.get_dint()):  # List
             values: PlcList = _value
             sizeInBits += values.getList().size() * 32
         if EvaluationHelper.equals(
-            dataType, ModbusDataType.LINT
+            dataType, ModbusDataType.get_lint()
         ) and EvaluationHelper.equals(
-            numberOfValues, 1
+            numberOfValues, c_uint16(1)
         ):  # LINT
             # Simple Field (value)
             sizeInBits += 64
-        if EvaluationHelper.equals(dataType, ModbusDataType.LINT):  # List
+        if EvaluationHelper.equals(dataType, ModbusDataType.get_lint()):  # List
             values: PlcList = _value
             sizeInBits += values.getList().size() * 64
         if EvaluationHelper.equals(
-            dataType, ModbusDataType.USINT
+            dataType, ModbusDataType.get_usint()
         ) and EvaluationHelper.equals(
-            numberOfValues, 1
+            numberOfValues, c_uint16(1)
         ):  # USINT
             # Reserved Field
             sizeInBits += 8
             # Simple Field (value)
             sizeInBits += 8
-        if EvaluationHelper.equals(dataType, ModbusDataType.USINT):  # List
+        if EvaluationHelper.equals(dataType, ModbusDataType.get_usint()):  # List
             values: PlcList = _value
             sizeInBits += values.getList().size() * 8
         if EvaluationHelper.equals(
-            dataType, ModbusDataType.UINT
+            dataType, ModbusDataType.get_uint()
         ) and EvaluationHelper.equals(
-            numberOfValues, 1
+            numberOfValues, c_uint16(1)
         ):  # UINT
             # Simple Field (value)
             sizeInBits += 16
-        if EvaluationHelper.equals(dataType, ModbusDataType.UINT):  # List
+        if EvaluationHelper.equals(dataType, ModbusDataType.get_uint()):  # List
             values: PlcList = _value
             sizeInBits += values.getList().size() * 16
         if EvaluationHelper.equals(
-            dataType, ModbusDataType.UDINT
+            dataType, ModbusDataType.get_udint()
         ) and EvaluationHelper.equals(
-            numberOfValues, 1
+            numberOfValues, c_uint16(1)
         ):  # UDINT
             # Simple Field (value)
             sizeInBits += 32
-        if EvaluationHelper.equals(dataType, ModbusDataType.UDINT):  # List
+        if EvaluationHelper.equals(dataType, ModbusDataType.get_udint()):  # List
             values: PlcList = _value
             sizeInBits += values.getList().size() * 32
         if EvaluationHelper.equals(
-            dataType, ModbusDataType.ULINT
+            dataType, ModbusDataType.get_ulint()
         ) and EvaluationHelper.equals(
-            numberOfValues, 1
+            numberOfValues, c_uint16(1)
         ):  # ULINT
             # Simple Field (value)
             sizeInBits += 64
-        if EvaluationHelper.equals(dataType, ModbusDataType.ULINT):  # List
+        if EvaluationHelper.equals(dataType, ModbusDataType.get_ulint()):  # List
             values: PlcList = _value
             sizeInBits += values.getList().size() * 64
         if EvaluationHelper.equals(
-            dataType, ModbusDataType.REAL
+            dataType, ModbusDataType.get_real()
         ) and EvaluationHelper.equals(
-            numberOfValues, 1
+            numberOfValues, c_uint16(1)
         ):  # REAL
             # Simple Field (value)
             sizeInBits += 32
-        if EvaluationHelper.equals(dataType, ModbusDataType.REAL):  # List
+        if EvaluationHelper.equals(dataType, ModbusDataType.get_real()):  # List
             values: PlcList = _value
             sizeInBits += values.getList().size() * 32
         if EvaluationHelper.equals(
-            dataType, ModbusDataType.LREAL
+            dataType, ModbusDataType.get_lreal()
         ) and EvaluationHelper.equals(
-            numberOfValues, 1
+            numberOfValues, c_uint16(1)
         ):  # LREAL
             # Simple Field (value)
             sizeInBits += 64
-        if EvaluationHelper.equals(dataType, ModbusDataType.LREAL):  # List
+        if EvaluationHelper.equals(dataType, ModbusDataType.get_lreal()):  # List
             values: PlcList = _value
             sizeInBits += values.getList().size() * 64
         if EvaluationHelper.equals(
-            dataType, ModbusDataType.CHAR
+            dataType, ModbusDataType.get_char()
         ) and EvaluationHelper.equals(
-            numberOfValues, 1
+            numberOfValues, c_uint16(1)
         ):  # CHAR
             # Simple Field (value)
             sizeInBits += 8
-        if EvaluationHelper.equals(dataType, ModbusDataType.CHAR):  # List
+        if EvaluationHelper.equals(dataType, ModbusDataType.get_char()):  # List
             values: PlcList = _value
             sizeInBits += values.getList().size() * 8
         if EvaluationHelper.equals(
-            dataType, ModbusDataType.WCHAR
+            dataType, ModbusDataType.get_wchar()
         ) and EvaluationHelper.equals(
-            numberOfValues, 1
+            numberOfValues, c_uint16(1)
         ):  # WCHAR
             # Simple Field (value)
             sizeInBits += 16
-        if EvaluationHelper.equals(dataType, ModbusDataType.WCHAR):  # List
+        if EvaluationHelper.equals(dataType, ModbusDataType.get_wchar()):  # List
             values: PlcList = _value
             sizeInBits += values.getList().size() * 16
         return sizeInBits
diff --git a/sandbox/plc4py/plc4py/protocols/modbus/readwrite/DriverType.py b/sandbox/plc4py/plc4py/protocols/modbus/readwrite/DriverType.py
index 821d24cd90..60dd42ebb6 100644
--- a/sandbox/plc4py/plc4py/protocols/modbus/readwrite/DriverType.py
+++ b/sandbox/plc4py/plc4py/protocols/modbus/readwrite/DriverType.py
@@ -19,10 +19,10 @@
 
 # Code generated by code-generation. DO NOT EDIT.
 from ctypes import c_uint32
-from enum import Enum
+from enum import IntEnum
 
 
-class DriverType(Enum):
+class DriverType(IntEnum):
     MODBUS_TCP: c_uint32 = 0x01
     MODBUS_RTU: c_uint32 = 0x02
     MODBUS_ASCII: c_uint32 = 0x03
diff --git a/sandbox/plc4py/plc4py/protocols/modbus/readwrite/ModbusADU.py b/sandbox/plc4py/plc4py/protocols/modbus/readwrite/ModbusADU.py
index 13cbf20db8..b8afde3aef 100644
--- a/sandbox/plc4py/plc4py/protocols/modbus/readwrite/ModbusADU.py
+++ b/sandbox/plc4py/plc4py/protocols/modbus/readwrite/ModbusADU.py
@@ -24,6 +24,7 @@ from abc import abstractmethod
 from ctypes import c_bool
 from plc4py.api.messages.PlcMessage import PlcMessage
 from plc4py.protocols.modbus.readwrite.DriverType import DriverType
+from plc4py.spi.generation.WriteBuffer import WriteBuffer
 import math
 
 
@@ -42,12 +43,11 @@ class ModbusADU(ABC, PlcMessage):
         pass
 
     @abstractmethod
-    def serialize_modbus_aduChild(write_buffer: WriteBuffer) -> None:
+    def serialize_modbus_adu_child(write_buffer: WriteBuffer) -> None:
         pass
 
     def serialize(self, write_buffer: WriteBuffer):
-        position_aware: PositionAware = write_buffer
-        start_pos: int = position_aware.get_pos()
+        start_pos: int = write_buffer.get_pos()
         write_buffer.push_context("ModbusADU")
 
         # Switch field (Serialize the sub-type)
@@ -67,7 +67,6 @@ class ModbusADU(ABC, PlcMessage):
         return length_in_bits
 
     def static_parse(read_buffer: ReadBuffer, args):
-        position_aware: PositionAware = read_buffer
         if (args is None) or (args.length is not 2):
             raise PlcRuntimeException(
                 "Wrong number of arguments, expected 2, but got " + args.length
@@ -102,17 +101,16 @@ class ModbusADU(ABC, PlcMessage):
         read_buffer: ReadBuffer, driver_type: DriverType, response: c_bool
     ):
         read_buffer.pull_context("ModbusADU")
-        position_aware: PositionAware = read_buffer
-        start_pos: int = position_aware.get_pos()
+        start_pos: int = read_buffer.get_pos()
         cur_pos: int = 0
 
         # Switch Field (Depending on the discriminator values, passes the instantiation to a sub-type)
         builder: ModbusADUBuilder = None
-        if EvaluationHelper.equals(driverType, DriverType.MODBUS_TCP):
+        if EvaluationHelper.equals(driverType, DriverType.get_modbu_s__tcp()):
             builder = ModbusTcpADU.staticParseBuilder(read_buffer, driverType, response)
-        if EvaluationHelper.equals(driverType, DriverType.MODBUS_RTU):
+        if EvaluationHelper.equals(driverType, DriverType.get_modbu_s__rtu()):
             builder = ModbusRtuADU.staticParseBuilder(read_buffer, driverType, response)
-        if EvaluationHelper.equals(driverType, DriverType.MODBUS_ASCII):
+        if EvaluationHelper.equals(driverType, DriverType.get_modbu_s__ascii()):
             builder = ModbusAsciiADU.staticParseBuilder(
                 read_buffer, driverType, response
             )
diff --git a/sandbox/plc4py/plc4py/protocols/modbus/readwrite/ModbusAsciiADU.py b/sandbox/plc4py/plc4py/protocols/modbus/readwrite/ModbusAsciiADU.py
index 46c828dd89..8a06bc3a2d 100644
--- a/sandbox/plc4py/plc4py/protocols/modbus/readwrite/ModbusAsciiADU.py
+++ b/sandbox/plc4py/plc4py/protocols/modbus/readwrite/ModbusAsciiADU.py
@@ -26,6 +26,7 @@ from plc4py.protocols.modbus.readwrite.DriverType import DriverType
 from plc4py.protocols.modbus.readwrite.ModbusADU import ModbusADU
 from plc4py.protocols.modbus.readwrite.ModbusADU import ModbusADUBuilder
 from plc4py.protocols.modbus.readwrite.ModbusPDU import ModbusPDU
+from plc4py.spi.generation.WriteBuffer import WriteBuffer
 import math
 
 
@@ -36,37 +37,26 @@ class ModbusAsciiADU(PlcMessage, ModbusADU):
     # Arguments.
     response: c_bool
     # Accessors for discriminator values.
-    driver_type: DriverType = DriverType.MODBUS_ASCII
+    driver_type: DriverType = DriverType.get_modbu_s__ascii()
 
     def __post_init__(self):
         super().__init__(self.response)
 
     def serialize_modbus_adu_child(self, write_buffer: WriteBuffer):
-        position_aware: PositionAware = write_buffer
-        start_pos: int = position_aware.get_pos()
+        start_pos: int = write_buffer.get_pos()
         write_buffer.push_context("ModbusAsciiADU")
 
         # Simple Field (address)
-        write_simple_field(
-            "address",
-            self.address,
-            write_unsigned_short(write_buffer, 8),
-            WithOption.WithByteOrder(ByteOrder.BIG_ENDIAN),
-        )
+        write_buffer.write_unsigned_byte(self.address, logical_name="address")
 
         # Simple Field (pdu)
-        write_simple_field(
-            "pdu",
-            self.pdu,
-            DataWriterComplexDefault(write_buffer),
-            WithOption.WithByteOrder(ByteOrder.BIG_ENDIAN),
+        write_buffer.DataWriterComplexDefault(write_buffer)(
+            self.pdu, logical_name="pdu"
         )
 
         # Checksum Field (checksum) (Calculated)
-        write_checksum_field(
-            "crc",
-            c_uint8(modbus.readwrite.utils.StaticHelper.asciiLrcCheck(address, pdu)),
-            write_unsigned_short(write_buffer, 8),
+        write_buffer.write_unsigned_byte(
+            c_uint8(ascii_lrc_check(address, pdu)), logical_name="crc"
         )
 
         write_buffer.pop_context("ModbusAsciiADU")
@@ -94,14 +84,13 @@ class ModbusAsciiADU(PlcMessage, ModbusADU):
         read_buffer: ReadBuffer, driver_type: DriverType, response: c_bool
     ):
         read_buffer.pull_context("ModbusAsciiADU")
-        position_aware: PositionAware = read_buffer
-        start_pos: int = position_aware.get_pos()
+        start_pos: int = read_buffer.get_pos()
         cur_pos: int = 0
 
         address: c_uint8 = read_simple_field(
             "address",
             read_unsigned_short(read_buffer, 8),
-            WithOption.WithByteOrder(ByteOrder.BIG_ENDIAN),
+            WithOption.WithByteOrder(get_bi_g__endian()),
         )
 
         pdu: ModbusPDU = read_simple_field(
@@ -109,14 +98,14 @@ class ModbusAsciiADU(PlcMessage, ModbusADU):
             DataReaderComplexDefault(
                 ModbusPDU.static_parse(read_buffer, c_bool(response)), read_buffer
             ),
-            WithOption.WithByteOrder(ByteOrder.BIG_ENDIAN),
+            WithOption.WithByteOrder(get_bi_g__endian()),
         )
 
         crc: c_uint8 = read_checksum_field(
             "crc",
             read_unsigned_short(read_buffer, 8),
-            (c_uint8)(modbus.readwrite.utils.StaticHelper.asciiLrcCheck(address, pdu)),
-            WithOption.WithByteOrder(ByteOrder.BIG_ENDIAN),
+            (c_uint8)(ascii_lrc_check(address, pdu)),
+            WithOption.WithByteOrder(get_bi_g__endian()),
         )
 
         read_buffer.close_context("ModbusAsciiADU")
diff --git a/sandbox/plc4py/plc4py/protocols/modbus/readwrite/ModbusConstants.py b/sandbox/plc4py/plc4py/protocols/modbus/readwrite/ModbusConstants.py
index 5b1dffdedb..5d35fc9fa9 100644
--- a/sandbox/plc4py/plc4py/protocols/modbus/readwrite/ModbusConstants.py
+++ b/sandbox/plc4py/plc4py/protocols/modbus/readwrite/ModbusConstants.py
@@ -21,26 +21,24 @@ from dataclasses import dataclass
 
 from ctypes import c_uint16
 from plc4py.api.messages.PlcMessage import PlcMessage
+from plc4py.spi.generation.WriteBuffer import WriteBuffer
 import math
 
 
 @dataclass
 class ModbusConstants(PlcMessage):
-    MODBUSTCPDEFAULTPORT: c_uint16 = 502
+    MODBUSTCPDEFAULTPORT: c_uint16 = c_uint16(502)
 
     def __post_init__(self):
         super().__init__()
 
     def serialize(self, write_buffer: WriteBuffer):
-        position_aware: PositionAware = write_buffer
-        start_pos: int = position_aware.get_pos()
+        start_pos: int = write_buffer.get_pos()
         write_buffer.push_context("ModbusConstants")
 
         # Const Field (modbusTcpDefaultPort)
-        write_const_field(
-            "modbusTcpDefaultPort",
-            self.modbus_tcp_default_port,
-            write_unsigned_int(write_buffer, 16),
+        write_buffer.write_unsigned_short(
+            self.modbus_tcp_default_port.value, logical_name="modbusTcpDefaultPort"
         )
 
         write_buffer.pop_context("ModbusConstants")
@@ -58,14 +56,12 @@ class ModbusConstants(PlcMessage):
         return length_in_bits
 
     def static_parse(read_buffer: ReadBuffer, args):
-        position_aware: PositionAware = read_buffer
         return staticParse(read_buffer)
 
     @staticmethod
     def static_parse_context(read_buffer: ReadBuffer):
         read_buffer.pull_context("ModbusConstants")
-        position_aware: PositionAware = read_buffer
-        start_pos: int = position_aware.get_pos()
+        start_pos: int = read_buffer.get_pos()
         cur_pos: int = 0
 
         modbus_tcp_default_port: c_uint16 = read_const_field(
diff --git a/sandbox/plc4py/plc4py/protocols/modbus/readwrite/ModbusDataType.py b/sandbox/plc4py/plc4py/protocols/modbus/readwrite/ModbusDataType.py
index a0bb9a839e..f3faf92283 100644
--- a/sandbox/plc4py/plc4py/protocols/modbus/readwrite/ModbusDataType.py
+++ b/sandbox/plc4py/plc4py/protocols/modbus/readwrite/ModbusDataType.py
@@ -19,10 +19,10 @@
 
 # Code generated by code-generation. DO NOT EDIT.
 from ctypes import c_uint8
-from enum import Enum
+from enum import IntEnum
 
 
-class ModbusDataType(Enum):
+class ModbusDataType(IntEnum):
     BOOL: c_uint8 = (1, c_uint8(2))
     BYTE: c_uint8 = (2, c_uint8(2))
     WORD: c_uint8 = (3, c_uint8(2))
@@ -51,7 +51,7 @@ class ModbusDataType(Enum):
     STRING: c_uint8 = (26, c_uint8(1))
     WSTRING: c_uint8 = (27, c_uint8(2))
 
-    def __new__(cls, value, dataTypeSize):
+    def __new__(cls, value, data_type_size):
         obj = object.__new__(cls)
         obj._value_ = value
         obj.dataTypeSize = dataTypeSize
diff --git a/sandbox/plc4py/plc4py/protocols/modbus/readwrite/ModbusDeviceInformationConformityLevel.py b/sandbox/plc4py/plc4py/protocols/modbus/readwrite/ModbusDeviceInformationConformityLevel.py
index 714b8f4c1a..35f8cf4800 100644
--- a/sandbox/plc4py/plc4py/protocols/modbus/readwrite/ModbusDeviceInformationConformityLevel.py
+++ b/sandbox/plc4py/plc4py/protocols/modbus/readwrite/ModbusDeviceInformationConformityLevel.py
@@ -19,10 +19,10 @@
 
 # Code generated by code-generation. DO NOT EDIT.
 from ctypes import c_uint8
-from enum import Enum
+from enum import IntEnum
 
 
-class ModbusDeviceInformationConformityLevel(Enum):
+class ModbusDeviceInformationConformityLevel(IntEnum):
     BASIC_STREAM_ONLY: c_uint8 = 0x01
     REGULAR_STREAM_ONLY: c_uint8 = 0x02
     EXTENDED_STREAM_ONLY: c_uint8 = 0x03
diff --git a/sandbox/plc4py/plc4py/protocols/modbus/readwrite/ModbusDeviceInformationLevel.py b/sandbox/plc4py/plc4py/protocols/modbus/readwrite/ModbusDeviceInformationLevel.py
index 524da5a86d..3e689b521e 100644
--- a/sandbox/plc4py/plc4py/protocols/modbus/readwrite/ModbusDeviceInformationLevel.py
+++ b/sandbox/plc4py/plc4py/protocols/modbus/readwrite/ModbusDeviceInformationLevel.py
@@ -19,10 +19,10 @@
 
 # Code generated by code-generation. DO NOT EDIT.
 from ctypes import c_uint8
-from enum import Enum
+from enum import IntEnum
 
 
-class ModbusDeviceInformationLevel(Enum):
+class ModbusDeviceInformationLevel(IntEnum):
     BASIC: c_uint8 = 0x01
     REGULAR: c_uint8 = 0x02
     EXTENDED: c_uint8 = 0x03
diff --git a/sandbox/plc4py/plc4py/protocols/modbus/readwrite/ModbusDeviceInformationMoreFollows.py b/sandbox/plc4py/plc4py/protocols/modbus/readwrite/ModbusDeviceInformationMoreFollows.py
index 9144a09fcf..fafecd5f54 100644
--- a/sandbox/plc4py/plc4py/protocols/modbus/readwrite/ModbusDeviceInformationMoreFollows.py
+++ b/sandbox/plc4py/plc4py/protocols/modbus/readwrite/ModbusDeviceInformationMoreFollows.py
@@ -19,9 +19,9 @@
 
 # Code generated by code-generation. DO NOT EDIT.
 from ctypes import c_uint8
-from enum import Enum
+from enum import IntEnum
 
 
-class ModbusDeviceInformationMoreFollows(Enum):
+class ModbusDeviceInformationMoreFollows(IntEnum):
     NO_MORE_OBJECTS_AVAILABLE: c_uint8 = 0x00
     MORE_OBJECTS_AVAILABLE: c_uint8 = 0xFF
diff --git a/sandbox/plc4py/plc4py/protocols/modbus/readwrite/ModbusDeviceInformationObject.py b/sandbox/plc4py/plc4py/protocols/modbus/readwrite/ModbusDeviceInformationObject.py
index 6d919290c2..259271e9c5 100644
--- a/sandbox/plc4py/plc4py/protocols/modbus/readwrite/ModbusDeviceInformationObject.py
+++ b/sandbox/plc4py/plc4py/protocols/modbus/readwrite/ModbusDeviceInformationObject.py
@@ -22,6 +22,7 @@ from dataclasses import dataclass
 from ctypes import c_byte
 from ctypes import c_uint8
 from plc4py.api.messages.PlcMessage import PlcMessage
+from plc4py.spi.generation.WriteBuffer import WriteBuffer
 from typing import List
 import math
 
@@ -35,23 +36,18 @@ class ModbusDeviceInformationObject(PlcMessage):
         super().__init__()
 
     def serialize(self, write_buffer: WriteBuffer):
-        position_aware: PositionAware = write_buffer
-        start_pos: int = position_aware.get_pos()
+        start_pos: int = write_buffer.get_pos()
         write_buffer.push_context("ModbusDeviceInformationObject")
 
         # Simple Field (objectId)
-        write_simple_field(
-            "objectId", self.object_id, write_unsigned_short(write_buffer, 8)
-        )
+        write_buffer.write_unsigned_byte(self.object_id, logical_name="objectId")
 
         # Implicit Field (object_length) (Used for parsing, but its value is not stored as it's implicitly given by the objects content)
-        object_length: c_uint8 = c_uint8((COUNT(self.data())))
-        write_implicit_field(
-            "objectLength", object_length, write_unsigned_short(write_buffer, 8)
-        )
+        object_length: c_uint8 = c_uint8(len(self.data))
+        write_buffer.write_unsigned_byte(object_length, logical_name="objectLength")
 
         # Array Field (data)
-        write_byte_array_field("data", self.data, writeByteArray(write_buffer, 8))
+        write_buffer.write_byte_array(self.data, 8, logical_name="data")
 
         write_buffer.pop_context("ModbusDeviceInformationObject")
 
@@ -75,14 +71,12 @@ class ModbusDeviceInformationObject(PlcMessage):
         return length_in_bits
 
     def static_parse(read_buffer: ReadBuffer, args):
-        position_aware: PositionAware = read_buffer
         return staticParse(read_buffer)
 
     @staticmethod
     def static_parse_context(read_buffer: ReadBuffer):
         read_buffer.pull_context("ModbusDeviceInformationObject")
-        position_aware: PositionAware = read_buffer
-        start_pos: int = position_aware.get_pos()
+        start_pos: int = read_buffer.get_pos()
         cur_pos: int = 0
 
         object_id: c_uint8 = read_simple_field(
diff --git a/sandbox/plc4py/plc4py/protocols/modbus/readwrite/ModbusErrorCode.py b/sandbox/plc4py/plc4py/protocols/modbus/readwrite/ModbusErrorCode.py
index 7d14fdc976..572896afe1 100644
--- a/sandbox/plc4py/plc4py/protocols/modbus/readwrite/ModbusErrorCode.py
+++ b/sandbox/plc4py/plc4py/protocols/modbus/readwrite/ModbusErrorCode.py
@@ -19,10 +19,10 @@
 
 # Code generated by code-generation. DO NOT EDIT.
 from ctypes import c_uint8
-from enum import Enum
+from enum import IntEnum
 
 
-class ModbusErrorCode(Enum):
+class ModbusErrorCode(IntEnum):
     ILLEGAL_FUNCTION: c_uint8 = 1
     ILLEGAL_DATA_ADDRESS: c_uint8 = 2
     ILLEGAL_DATA_VALUE: c_uint8 = 3
diff --git a/sandbox/plc4py/plc4py/protocols/modbus/readwrite/ModbusPDU.py b/sandbox/plc4py/plc4py/protocols/modbus/readwrite/ModbusPDU.py
index df8afc62c1..3f4e929ee4 100644
--- a/sandbox/plc4py/plc4py/protocols/modbus/readwrite/ModbusPDU.py
+++ b/sandbox/plc4py/plc4py/protocols/modbus/readwrite/ModbusPDU.py
@@ -24,6 +24,7 @@ from abc import abstractmethod
 from ctypes import c_bool
 from ctypes import c_uint8
 from plc4py.api.messages.PlcMessage import PlcMessage
+from plc4py.spi.generation.WriteBuffer import WriteBuffer
 import math
 
 
@@ -49,22 +50,19 @@ class ModbusPDU(ABC, PlcMessage):
         pass
 
     @abstractmethod
-    def serialize_modbus_pduChild(write_buffer: WriteBuffer) -> None:
+    def serialize_modbus_pdu_child(write_buffer: WriteBuffer) -> None:
         pass
 
     def serialize(self, write_buffer: WriteBuffer):
-        position_aware: PositionAware = write_buffer
-        start_pos: int = position_aware.get_pos()
+        start_pos: int = write_buffer.get_pos()
         write_buffer.push_context("ModbusPDU")
 
         # Discriminator Field (errorFlag) (Used as input to a switch field)
-        write_discriminator_field(
-            "errorFlag", self.error_flag(), write_boolean(write_buffer)
-        )
+        write_buffer.write_boolean(self.error_flag(), logical_name="errorFlag")
 
         # Discriminator Field (functionFlag) (Used as input to a switch field)
-        write_discriminator_field(
-            "functionFlag", self.function_flag(), write_unsigned_short(write_buffer, 7)
+        write_buffer.write_unsigned_byte(
+            self.function_flag(), logical_name="functionFlag"
         )
 
         # Switch field (Serialize the sub-type)
@@ -90,7 +88,6 @@ class ModbusPDU(ABC, PlcMessage):
         return length_in_bits
 
     def static_parse(read_buffer: ReadBuffer, args):
-        position_aware: PositionAware = read_buffer
         if (args is None) or (args.length is not 1):
             raise PlcRuntimeException(
                 "Wrong number of arguments, expected 1, but got " + args.length
@@ -112,8 +109,7 @@ class ModbusPDU(ABC, PlcMessage):
     @staticmethod
     def static_parse_context(read_buffer: ReadBuffer, response: c_bool):
         read_buffer.pull_context("ModbusPDU")
-        position_aware: PositionAware = read_buffer
-        start_pos: int = position_aware.get_pos()
+        start_pos: int = read_buffer.get_pos()
         cur_pos: int = 0
 
         error_flag: c_bool = read_discriminator_field(
@@ -126,140 +122,140 @@ class ModbusPDU(ABC, PlcMessage):
 
         # Switch Field (Depending on the discriminator values, passes the instantiation to a sub-type)
         builder: ModbusPDUBuilder = None
-        if EvaluationHelper.equals(errorFlag, c_bool(True)):
+        if EvaluationHelper.equals(errorFlag, c_bool(c_bool(true))):
             builder = ModbusPDUError.staticParseBuilder(read_buffer, response)
         if (
-            EvaluationHelper.equals(errorFlag, c_bool(False))
+            EvaluationHelper.equals(errorFlag, c_bool(c_bool(false)))
             and EvaluationHelper.equals(functionFlag, c_uint8(0x02))
-            and EvaluationHelper.equals(response, c_bool(False))
+            and EvaluationHelper.equals(response, c_bool(c_bool(false)))
         ):
             builder = ModbusPDUReadDiscreteInputsRequest.staticParseBuilder(
                 read_buffer, response
             )
         if (
-            EvaluationHelper.equals(errorFlag, c_bool(False))
+            EvaluationHelper.equals(errorFlag, c_bool(c_bool(false)))
             and EvaluationHelper.equals(functionFlag, c_uint8(0x02))
-            and EvaluationHelper.equals(response, c_bool(True))
+            and EvaluationHelper.equals(response, c_bool(c_bool(true)))
         ):
             builder = ModbusPDUReadDiscreteInputsResponse.staticParseBuilder(
                 read_buffer, response
             )
         if (
-            EvaluationHelper.equals(errorFlag, c_bool(False))
+            EvaluationHelper.equals(errorFlag, c_bool(c_bool(false)))
             and EvaluationHelper.equals(functionFlag, c_uint8(0x01))
-            and EvaluationHelper.equals(response, c_bool(False))
+            and EvaluationHelper.equals(response, c_bool(c_bool(false)))
         ):
             builder = ModbusPDUReadCoilsRequest.staticParseBuilder(
                 read_buffer, response
             )
         if (
-            EvaluationHelper.equals(errorFlag, c_bool(False))
+            EvaluationHelper.equals(errorFlag, c_bool(c_bool(false)))
             and EvaluationHelper.equals(functionFlag, c_uint8(0x01))
-            and EvaluationHelper.equals(response, c_bool(True))
+            and EvaluationHelper.equals(response, c_bool(c_bool(true)))
         ):
             builder = ModbusPDUReadCoilsResponse.staticParseBuilder(
                 read_buffer, response
             )
         if (
-            EvaluationHelper.equals(errorFlag, c_bool(False))
+            EvaluationHelper.equals(errorFlag, c_bool(c_bool(false)))
             and EvaluationHelper.equals(functionFlag, c_uint8(0x05))
-            and EvaluationHelper.equals(response, c_bool(False))
+            and EvaluationHelper.equals(response, c_bool(c_bool(false)))
         ):
             builder = ModbusPDUWriteSingleCoilRequest.staticParseBuilder(
                 read_buffer, response
             )
         if (
-            EvaluationHelper.equals(errorFlag, c_bool(False))
+            EvaluationHelper.equals(errorFlag, c_bool(c_bool(false)))
             and EvaluationHelper.equals(functionFlag, c_uint8(0x05))
-            and EvaluationHelper.equals(response, c_bool(True))
+            and EvaluationHelper.equals(response, c_bool(c_bool(true)))
         ):
             builder = ModbusPDUWriteSingleCoilResponse.staticParseBuilder(
                 read_buffer, response
             )
         if (
-            EvaluationHelper.equals(errorFlag, c_bool(False))
+            EvaluationHelper.equals(errorFlag, c_bool(c_bool(false)))
             and EvaluationHelper.equals(functionFlag, c_uint8(0x0F))
-            and EvaluationHelper.equals(response, c_bool(False))
+            and EvaluationHelper.equals(response, c_bool(c_bool(false)))
         ):
             builder = ModbusPDUWriteMultipleCoilsRequest.staticParseBuilder(
                 read_buffer, response
             )
         if (
-            EvaluationHelper.equals(errorFlag, c_bool(False))
+            EvaluationHelper.equals(errorFlag, c_bool(c_bool(false)))
             and EvaluationHelper.equals(functionFlag, c_uint8(0x0F))
-            and EvaluationHelper.equals(response, c_bool(True))
+            and EvaluationHelper.equals(response, c_bool(c_bool(true)))
         ):
             builder = ModbusPDUWriteMultipleCoilsResponse.staticParseBuilder(
                 read_buffer, response
             )
         if (
-            EvaluationHelper.equals(errorFlag, c_bool(False))
+            EvaluationHelper.equals(errorFlag, c_bool(c_bool(false)))
             and EvaluationHelper.equals(functionFlag, c_uint8(0x04))
-            and EvaluationHelper.equals(response, c_bool(False))
+            and EvaluationHelper.equals(response, c_bool(c_bool(false)))
         ):
             builder = ModbusPDUReadInputRegistersRequest.staticParseBuilder(
                 read_buffer, response
             )
         if (
-            EvaluationHelper.equals(errorFlag, c_bool(False))
+            EvaluationHelper.equals(errorFlag, c_bool(c_bool(false)))
             and EvaluationHelper.equals(functionFlag, c_uint8(0x04))
-            and EvaluationHelper.equals(response, c_bool(True))
+            and EvaluationHelper.equals(response, c_bool(c_bool(true)))
         ):
             builder = ModbusPDUReadInputRegistersResponse.staticParseBuilder(
                 read_buffer, response
             )
         if (
-            EvaluationHelper.equals(errorFlag, c_bool(False))
+            EvaluationHelper.equals(errorFlag, c_bool(c_bool(false)))
             and EvaluationHelper.equals(functionFlag, c_uint8(0x03))
-            and EvaluationHelper.equals(response, c_bool(False))
+            and EvaluationHelper.equals(response, c_bool(c_bool(false)))
         ):
             builder = ModbusPDUReadHoldingRegistersRequest.staticParseBuilder(
                 read_buffer, response
             )
         if (
-            EvaluationHelper.equals(errorFlag, c_bool(False))
+            EvaluationHelper.equals(errorFlag, c_bool(c_bool(false)))
             and EvaluationHelper.equals(functionFlag, c_uint8(0x03))
-            and EvaluationHelper.equals(response, c_bool(True))
+            and EvaluationHelper.equals(response, c_bool(c_bool(true)))
         ):
             builder = ModbusPDUReadHoldingRegistersResponse.staticParseBuilder(
                 read_buffer, response
             )
         if (
-            EvaluationHelper.equals(errorFlag, c_bool(False))
+            EvaluationHelper.equals(errorFlag, c_bool(c_bool(false)))
             and EvaluationHelper.equals(functionFlag, c_uint8(0x06))
-            and EvaluationHelper.equals(response, c_bool(False))
+            and EvaluationHelper.equals(response, c_bool(c_bool(false)))
         ):
             builder = ModbusPDUWriteSingleRegisterRequest.staticParseBuilder(
                 read_buffer, response
             )
         if (
-            EvaluationHelper.equals(errorFlag, c_bool(False))
+            EvaluationHelper.equals(errorFlag, c_bool(c_bool(false)))
             and EvaluationHelper.equals(functionFlag, c_uint8(0x06))
-            and EvaluationHelper.equals(response, c_bool(True))
+            and EvaluationHelper.equals(response, c_bool(c_bool(true)))
         ):
             builder = ModbusPDUWriteSingleRegisterResponse.staticParseBuilder(
                 read_buffer, response
             )
         if (
-            EvaluationHelper.equals(errorFlag, c_bool(False))
+            EvaluationHelper.equals(errorFlag, c_bool(c_bool(false)))
             and EvaluationHelper.equals(functionFlag, c_uint8(0x10))
-            and EvaluationHelper.equals(response, c_bool(False))
+            and EvaluationHelper.equals(response, c_bool(c_bool(false)))
         ):
             builder = ModbusPDUWriteMultipleHoldingRegistersRequest.staticParseBuilder(
                 read_buffer, response
             )
         if (
-            EvaluationHelper.equals(errorFlag, c_bool(False))
+            EvaluationHelper.equals(errorFlag, c_bool(c_bool(false)))
             and EvaluationHelper.equals(functionFlag, c_uint8(0x10))
-            and EvaluationHelper.equals(response, c_bool(True))
+            and EvaluationHelper.equals(response, c_bool(c_bool(true)))
         ):
             builder = ModbusPDUWriteMultipleHoldingRegistersResponse.staticParseBuilder(
                 read_buffer, response
             )
         if (
-            EvaluationHelper.equals(errorFlag, c_bool(False))
+            EvaluationHelper.equals(errorFlag, c_bool(c_bool(false)))
             and EvaluationHelper.equals(functionFlag, c_uint8(0x17))
-            and EvaluationHelper.equals(response, c_bool(False))
+            and EvaluationHelper.equals(response, c_bool(c_bool(false)))
         ):
             builder = (
                 ModbusPDUReadWriteMultipleHoldingRegistersRequest.staticParseBuilder(
@@ -267,9 +263,9 @@ class ModbusPDU(ABC, PlcMessage):
                 )
             )
         if (
-            EvaluationHelper.equals(errorFlag, c_bool(False))
+            EvaluationHelper.equals(errorFlag, c_bool(c_bool(false)))
             and EvaluationHelper.equals(functionFlag, c_uint8(0x17))
-            and EvaluationHelper.equals(response, c_bool(True))
+            and EvaluationHelper.equals(response, c_bool(c_bool(true)))
         ):
             builder = (
                 ModbusPDUReadWriteMultipleHoldingRegistersResponse.staticParseBuilder(
@@ -277,161 +273,161 @@ class ModbusPDU(ABC, PlcMessage):
                 )
             )
         if (
-            EvaluationHelper.equals(errorFlag, c_bool(False))
+            EvaluationHelper.equals(errorFlag, c_bool(c_bool(false)))
             and EvaluationHelper.equals(functionFlag, c_uint8(0x16))
-            and EvaluationHelper.equals(response, c_bool(False))
+            and EvaluationHelper.equals(response, c_bool(c_bool(false)))
         ):
             builder = ModbusPDUMaskWriteHoldingRegisterRequest.staticParseBuilder(
                 read_buffer, response
             )
         if (
-            EvaluationHelper.equals(errorFlag, c_bool(False))
+            EvaluationHelper.equals(errorFlag, c_bool(c_bool(false)))
             and EvaluationHelper.equals(functionFlag, c_uint8(0x16))
-            and EvaluationHelper.equals(response, c_bool(True))
+            and EvaluationHelper.equals(response, c_bool(c_bool(true)))
         ):
             builder = ModbusPDUMaskWriteHoldingRegisterResponse.staticParseBuilder(
                 read_buffer, response
             )
         if (
-            EvaluationHelper.equals(errorFlag, c_bool(False))
+            EvaluationHelper.equals(errorFlag, c_bool(c_bool(false)))
             and EvaluationHelper.equals(functionFlag, c_uint8(0x18))
-            and EvaluationHelper.equals(response, c_bool(False))
+            and EvaluationHelper.equals(response, c_bool(c_bool(false)))
         ):
             builder = ModbusPDUReadFifoQueueRequest.staticParseBuilder(
                 read_buffer, response
             )
         if (
-            EvaluationHelper.equals(errorFlag, c_bool(False))
+            EvaluationHelper.equals(errorFlag, c_bool(c_bool(false)))
             and EvaluationHelper.equals(functionFlag, c_uint8(0x18))
-            and EvaluationHelper.equals(response, c_bool(True))
+            and EvaluationHelper.equals(response, c_bool(c_bool(true)))
         ):
             builder = ModbusPDUReadFifoQueueResponse.staticParseBuilder(
                 read_buffer, response
             )
         if (
-            EvaluationHelper.equals(errorFlag, c_bool(False))
+            EvaluationHelper.equals(errorFlag, c_bool(c_bool(false)))
             and EvaluationHelper.equals(functionFlag, c_uint8(0x14))
-            and EvaluationHelper.equals(response, c_bool(False))
+            and EvaluationHelper.equals(response, c_bool(c_bool(false)))
         ):
             builder = ModbusPDUReadFileRecordRequest.staticParseBuilder(
                 read_buffer, response
             )
         if (
-            EvaluationHelper.equals(errorFlag, c_bool(False))
+            EvaluationHelper.equals(errorFlag, c_bool(c_bool(false)))
             and EvaluationHelper.equals(functionFlag, c_uint8(0x14))
-            and EvaluationHelper.equals(response, c_bool(True))
+            and EvaluationHelper.equals(response, c_bool(c_bool(true)))
         ):
             builder = ModbusPDUReadFileRecordResponse.staticParseBuilder(
                 read_buffer, response
             )
         if (
-            EvaluationHelper.equals(errorFlag, c_bool(False))
+            EvaluationHelper.equals(errorFlag, c_bool(c_bool(false)))
             and EvaluationHelper.equals(functionFlag, c_uint8(0x15))
-            and EvaluationHelper.equals(response, c_bool(False))
+            and EvaluationHelper.equals(response, c_bool(c_bool(false)))
         ):
             builder = ModbusPDUWriteFileRecordRequest.staticParseBuilder(
                 read_buffer, response
             )
         if (
-            EvaluationHelper.equals(errorFlag, c_bool(False))
+            EvaluationHelper.equals(errorFlag, c_bool(c_bool(false)))
             and EvaluationHelper.equals(functionFlag, c_uint8(0x15))
-            and EvaluationHelper.equals(response, c_bool(True))
+            and EvaluationHelper.equals(response, c_bool(c_bool(true)))
         ):
             builder = ModbusPDUWriteFileRecordResponse.staticParseBuilder(
                 read_buffer, response
             )
         if (
-            EvaluationHelper.equals(errorFlag, c_bool(False))
+            EvaluationHelper.equals(errorFlag, c_bool(c_bool(false)))
             and EvaluationHelper.equals(functionFlag, c_uint8(0x07))
-            and EvaluationHelper.equals(response, c_bool(False))
+            and EvaluationHelper.equals(response, c_bool(c_bool(false)))
         ):
             builder = ModbusPDUReadExceptionStatusRequest.staticParseBuilder(
                 read_buffer, response
             )
         if (
-            EvaluationHelper.equals(errorFlag, c_bool(False))
+            EvaluationHelper.equals(errorFlag, c_bool(c_bool(false)))
             and EvaluationHelper.equals(functionFlag, c_uint8(0x07))
-            and EvaluationHelper.equals(response, c_bool(True))
+            and EvaluationHelper.equals(response, c_bool(c_bool(true)))
         ):
             builder = ModbusPDUReadExceptionStatusResponse.staticParseBuilder(
                 read_buffer, response
             )
         if (
-            EvaluationHelper.equals(errorFlag, c_bool(False))
+            EvaluationHelper.equals(errorFlag, c_bool(c_bool(false)))
             and EvaluationHelper.equals(functionFlag, c_uint8(0x08))
-            and EvaluationHelper.equals(response, c_bool(False))
+            and EvaluationHelper.equals(response, c_bool(c_bool(false)))
         ):
             builder = ModbusPDUDiagnosticRequest.staticParseBuilder(
                 read_buffer, response
             )
         if (
-            EvaluationHelper.equals(errorFlag, c_bool(False))
+            EvaluationHelper.equals(errorFlag, c_bool(c_bool(false)))
             and EvaluationHelper.equals(functionFlag, c_uint8(0x08))
-            and EvaluationHelper.equals(response, c_bool(True))
+            and EvaluationHelper.equals(response, c_bool(c_bool(true)))
         ):
             builder = ModbusPDUDiagnosticResponse.staticParseBuilder(
                 read_buffer, response
             )
         if (
-            EvaluationHelper.equals(errorFlag, c_bool(False))
+            EvaluationHelper.equals(errorFlag, c_bool(c_bool(false)))
             and EvaluationHelper.equals(functionFlag, c_uint8(0x0B))
-            and EvaluationHelper.equals(response, c_bool(False))
+            and EvaluationHelper.equals(response, c_bool(c_bool(false)))
         ):
             builder = ModbusPDUGetComEventCounterRequest.staticParseBuilder(
                 read_buffer, response
             )
         if (
-            EvaluationHelper.equals(errorFlag, c_bool(False))
+            EvaluationHelper.equals(errorFlag, c_bool(c_bool(false)))
             and EvaluationHelper.equals(functionFlag, c_uint8(0x0B))
-            and EvaluationHelper.equals(response, c_bool(True))
+            and EvaluationHelper.equals(response, c_bool(c_bool(true)))
         ):
             builder = ModbusPDUGetComEventCounterResponse.staticParseBuilder(
                 read_buffer, response
             )
         if (
-            EvaluationHelper.equals(errorFlag, c_bool(False))
+            EvaluationHelper.equals(errorFlag, c_bool(c_bool(false)))
             and EvaluationHelper.equals(functionFlag, c_uint8(0x0C))
-            and EvaluationHelper.equals(response, c_bool(False))
+            and EvaluationHelper.equals(response, c_bool(c_bool(false)))
         ):
             builder = ModbusPDUGetComEventLogRequest.staticParseBuilder(
                 read_buffer, response
             )
         if (
-            EvaluationHelper.equals(errorFlag, c_bool(False))
+            EvaluationHelper.equals(errorFlag, c_bool(c_bool(false)))
             and EvaluationHelper.equals(functionFlag, c_uint8(0x0C))
-            and EvaluationHelper.equals(response, c_bool(True))
+            and EvaluationHelper.equals(response, c_bool(c_bool(true)))
         ):
             builder = ModbusPDUGetComEventLogResponse.staticParseBuilder(
                 read_buffer, response
             )
         if (
-            EvaluationHelper.equals(errorFlag, c_bool(False))
+            EvaluationHelper.equals(errorFlag, c_bool(c_bool(false)))
             and EvaluationHelper.equals(functionFlag, c_uint8(0x11))
-            and EvaluationHelper.equals(response, c_bool(False))
+            and EvaluationHelper.equals(response, c_bool(c_bool(false)))
         ):
             builder = ModbusPDUReportServerIdRequest.staticParseBuilder(
                 read_buffer, response
             )
         if (
-            EvaluationHelper.equals(errorFlag, c_bool(False))
+            EvaluationHelper.equals(errorFlag, c_bool(c_bool(false)))
             and EvaluationHelper.equals(functionFlag, c_uint8(0x11))
-            and EvaluationHelper.equals(response, c_bool(True))
+            and EvaluationHelper.equals(response, c_bool(c_bool(true)))
         ):
             builder = ModbusPDUReportServerIdResponse.staticParseBuilder(
                 read_buffer, response
             )
         if (
-            EvaluationHelper.equals(errorFlag, c_bool(False))
+            EvaluationHelper.equals(errorFlag, c_bool(c_bool(false)))
             and EvaluationHelper.equals(functionFlag, c_uint8(0x2B))
-            and EvaluationHelper.equals(response, c_bool(False))
+            and EvaluationHelper.equals(response, c_bool(c_bool(false)))
         ):
             builder = ModbusPDUReadDeviceIdentificationRequest.staticParseBuilder(
                 read_buffer, response
             )
         if (
-            EvaluationHelper.equals(errorFlag, c_bool(False))
+            EvaluationHelper.equals(errorFlag, c_bool(c_bool(false)))
             and EvaluationHelper.equals(functionFlag, c_uint8(0x2B))
-            and EvaluationHelper.equals(response, c_bool(True))
+            and EvaluationHelper.equals(response, c_bool(c_bool(true)))
         ):
             builder = ModbusPDUReadDeviceIdentificationResponse.staticParseBuilder(
                 read_buffer, response
diff --git a/sandbox/plc4py/plc4py/protocols/modbus/readwrite/ModbusPDUDiagnosticRequest.py b/sandbox/plc4py/plc4py/protocols/modbus/readwrite/ModbusPDUDiagnosticRequest.py
index 6780d3938d..c64daebf0b 100644
--- a/sandbox/plc4py/plc4py/protocols/modbus/readwrite/ModbusPDUDiagnosticRequest.py
+++ b/sandbox/plc4py/plc4py/protocols/modbus/readwrite/ModbusPDUDiagnosticRequest.py
@@ -25,6 +25,7 @@ from ctypes import c_uint8
 from plc4py.api.messages.PlcMessage import PlcMessage
 from plc4py.protocols.modbus.readwrite.ModbusPDU import ModbusPDU
 from plc4py.protocols.modbus.readwrite.ModbusPDU import ModbusPDUBuilder
+from plc4py.spi.generation.WriteBuffer import WriteBuffer
 import math
 
 
@@ -33,25 +34,22 @@ class ModbusPDUDiagnosticRequest(PlcMessage, ModbusPDU):
     sub_function: c_uint16
     data: c_uint16
     # Accessors for discriminator values.
-    error_flag: c_bool = False
+    error_flag: c_bool = c_bool(false)
     function_flag: c_uint8 = 0x08
-    response: c_bool = False
+    response: c_bool = c_bool(false)
 
     def __post_init__(self):
         super().__init__()
 
     def serialize_modbus_pdu_child(self, write_buffer: WriteBuffer):
-        position_aware: PositionAware = write_buffer
-        start_pos: int = position_aware.get_pos()
+        start_pos: int = write_buffer.get_pos()
         write_buffer.push_context("ModbusPDUDiagnosticRequest")
 
         # Simple Field (subFunction)
-        write_simple_field(
-            "subFunction", self.sub_function, write_unsigned_int(write_buffer, 16)
-        )
+        write_buffer.write_unsigned_short(self.sub_function, logical_name="subFunction")
 
         # Simple Field (data)
-        write_simple_field("data", self.data, write_unsigned_int(write_buffer, 16))
+        write_buffer.write_unsigned_short(self.data, logical_name="data")
 
         write_buffer.pop_context("ModbusPDUDiagnosticRequest")
 
@@ -73,8 +71,7 @@ class ModbusPDUDiagnosticRequest(PlcMessage, ModbusPDU):
     @staticmethod
     def static_parse_builder(read_buffer: ReadBuffer, response: c_bool):
         read_buffer.pull_context("ModbusPDUDiagnosticRequest")
-        position_aware: PositionAware = read_buffer
-        start_pos: int = position_aware.get_pos()
+        start_pos: int = read_buffer.get_pos()
         cur_pos: int = 0
 
         sub_function: c_uint16 = read_simple_field(
diff --git a/sandbox/plc4py/plc4py/protocols/modbus/readwrite/ModbusPDUDiagnosticResponse.py b/sandbox/plc4py/plc4py/protocols/modbus/readwrite/ModbusPDUDiagnosticResponse.py
index 5fbd869b97..ae00e09287 100644
--- a/sandbox/plc4py/plc4py/protocols/modbus/readwrite/ModbusPDUDiagnosticResponse.py
+++ b/sandbox/plc4py/plc4py/protocols/modbus/readwrite/ModbusPDUDiagnosticResponse.py
@@ -25,6 +25,7 @@ from ctypes import c_uint8
 from plc4py.api.messages.PlcMessage import PlcMessage
 from plc4py.protocols.modbus.readwrite.ModbusPDU import ModbusPDU
 from plc4py.protocols.modbus.readwrite.ModbusPDU import ModbusPDUBuilder
+from plc4py.spi.generation.WriteBuffer import WriteBuffer
 import math
 
 
@@ -33,25 +34,22 @@ class ModbusPDUDiagnosticResponse(PlcMessage, ModbusPDU):
     sub_function: c_uint16
     data: c_uint16
     # Accessors for discriminator values.
-    error_flag: c_bool = False
+    error_flag: c_bool = c_bool(false)
     function_flag: c_uint8 = 0x08
-    response: c_bool = True
+    response: c_bool = c_bool(true)
 
     def __post_init__(self):
         super().__init__()
 
     def serialize_modbus_pdu_child(self, write_buffer: WriteBuffer):
-        position_aware: PositionAware = write_buffer
-        start_pos: int = position_aware.get_pos()
+        start_pos: int = write_buffer.get_pos()
         write_buffer.push_context("ModbusPDUDiagnosticResponse")
 
         # Simple Field (subFunction)
-        write_simple_field(
-            "subFunction", self.sub_function, write_unsigned_int(write_buffer, 16)
-        )
+        write_buffer.write_unsigned_short(self.sub_function, logical_name="subFunction")
 
         # Simple Field (data)
-        write_simple_field("data", self.data, write_unsigned_int(write_buffer, 16))
+        write_buffer.write_unsigned_short(self.data, logical_name="data")
 
         write_buffer.pop_context("ModbusPDUDiagnosticResponse")
 
@@ -73,8 +71,7 @@ class ModbusPDUDiagnosticResponse(PlcMessage, ModbusPDU):
     @staticmethod
     def static_parse_builder(read_buffer: ReadBuffer, response: c_bool):
         read_buffer.pull_context("ModbusPDUDiagnosticResponse")
-        position_aware: PositionAware = read_buffer
-        start_pos: int = position_aware.get_pos()
+        start_pos: int = read_buffer.get_pos()
         cur_pos: int = 0
 
         sub_function: c_uint16 = read_simple_field(
diff --git a/sandbox/plc4py/plc4py/protocols/modbus/readwrite/ModbusPDUError.py b/sandbox/plc4py/plc4py/protocols/modbus/readwrite/ModbusPDUError.py
index cd156df49d..0bc22be06f 100644
--- a/sandbox/plc4py/plc4py/protocols/modbus/readwrite/ModbusPDUError.py
+++ b/sandbox/plc4py/plc4py/protocols/modbus/readwrite/ModbusPDUError.py
@@ -25,6 +25,7 @@ from plc4py.api.messages.PlcMessage import PlcMessage
 from plc4py.protocols.modbus.readwrite.ModbusErrorCode import ModbusErrorCode
 from plc4py.protocols.modbus.readwrite.ModbusPDU import ModbusPDU
 from plc4py.protocols.modbus.readwrite.ModbusPDU import ModbusPDUBuilder
+from plc4py.spi.generation.WriteBuffer import WriteBuffer
 import math
 
 
@@ -32,7 +33,7 @@ import math
 class ModbusPDUError(PlcMessage, ModbusPDU):
     exception_code: ModbusErrorCode
     # Accessors for discriminator values.
-    error_flag: c_bool = True
+    error_flag: c_bool = c_bool(true)
     function_flag: c_uint8 = 0
     response: c_bool = False
 
@@ -40,21 +41,13 @@ class ModbusPDUError(PlcMessage, ModbusPDU):
         super().__init__()
 
     def serialize_modbus_pdu_child(self, write_buffer: WriteBuffer):
-        position_aware: PositionAware = write_buffer
-        start_pos: int = position_aware.get_pos()
+        start_pos: int = write_buffer.get_pos()
         write_buffer.push_context("ModbusPDUError")
 
         # Simple Field (exceptionCode)
-        write_simple_enum_field(
-            "exceptionCode",
-            "ModbusErrorCode",
-            self.exception_code,
-            DataWriterEnumDefault(
-                ModbusErrorCode.value,
-                ModbusErrorCode.name,
-                write_unsigned_short(write_buffer, 8),
-            ),
-        )
+        write_buffer.DataWriterEnumDefault(
+            ModbusErrorCode.value, ModbusErrorCode.name, write_unsigned_byte
+        )(self.exception_code, logical_name="exceptionCode")
 
         write_buffer.pop_context("ModbusPDUError")
 
@@ -73,8 +66,7 @@ class ModbusPDUError(PlcMessage, ModbusPDU):
     @staticmethod
     def static_parse_builder(read_buffer: ReadBuffer, response: c_bool):
         read_buffer.pull_context("ModbusPDUError")
-        position_aware: PositionAware = read_buffer
-        start_pos: int = position_aware.get_pos()
+        start_pos: int = read_buffer.get_pos()
         cur_pos: int = 0
 
         exception_code: ModbusErrorCode = read_enum_field(
diff --git a/sandbox/plc4py/plc4py/protocols/modbus/readwrite/ModbusPDUGetComEventCounterRequest.py b/sandbox/plc4py/plc4py/protocols/modbus/readwrite/ModbusPDUGetComEventCounterRequest.py
index fec6e32e88..ebd135c89c 100644
--- a/sandbox/plc4py/plc4py/protocols/modbus/readwrite/ModbusPDUGetComEventCounterRequest.py
+++ b/sandbox/plc4py/plc4py/protocols/modbus/readwrite/ModbusPDUGetComEventCounterRequest.py
@@ -24,22 +24,22 @@ from ctypes import c_uint8
 from plc4py.api.messages.PlcMessage import PlcMessage
 from plc4py.protocols.modbus.readwrite.ModbusPDU import ModbusPDU
 from plc4py.protocols.modbus.readwrite.ModbusPDU import ModbusPDUBuilder
+from plc4py.spi.generation.WriteBuffer import WriteBuffer
 import math
 
 
 @dataclass
 class ModbusPDUGetComEventCounterRequest(PlcMessage, ModbusPDU):
     # Accessors for discriminator values.
-    error_flag: c_bool = False
+    error_flag: c_bool = c_bool(false)
     function_flag: c_uint8 = 0x0B
-    response: c_bool = False
+    response: c_bool = c_bool(false)
 
     def __post_init__(self):
         super().__init__()
 
     def serialize_modbus_pdu_child(self, write_buffer: WriteBuffer):
-        position_aware: PositionAware = write_buffer
-        start_pos: int = position_aware.get_pos()
+        start_pos: int = write_buffer.get_pos()
         write_buffer.push_context("ModbusPDUGetComEventCounterRequest")
 
         write_buffer.pop_context("ModbusPDUGetComEventCounterRequest")
@@ -56,8 +56,7 @@ class ModbusPDUGetComEventCounterRequest(PlcMessage, ModbusPDU):
     @staticmethod
     def static_parse_builder(read_buffer: ReadBuffer, response: c_bool):
         read_buffer.pull_context("ModbusPDUGetComEventCounterRequest")
-        position_aware: PositionAware = read_buffer
-        start_pos: int = position_aware.get_pos()
+        start_pos: int = read_buffer.get_pos()
         cur_pos: int = 0
 
         read_buffer.close_context("ModbusPDUGetComEventCounterRequest")
diff --git a/sandbox/plc4py/plc4py/protocols/modbus/readwrite/ModbusPDUGetComEventCounterResponse.py b/sandbox/plc4py/plc4py/protocols/modbus/readwrite/ModbusPDUGetComEventCounterResponse.py
index 9bc8ed844f..c9bb72146c 100644
--- a/sandbox/plc4py/plc4py/protocols/modbus/readwrite/ModbusPDUGetComEventCounterResponse.py
+++ b/sandbox/plc4py/plc4py/protocols/modbus/readwrite/ModbusPDUGetComEventCounterResponse.py
@@ -25,6 +25,7 @@ from ctypes import c_uint8
 from plc4py.api.messages.PlcMessage import PlcMessage
 from plc4py.protocols.modbus.readwrite.ModbusPDU import ModbusPDU
 from plc4py.protocols.modbus.readwrite.ModbusPDU import ModbusPDUBuilder
+from plc4py.spi.generation.WriteBuffer import WriteBuffer
 import math
 
 
@@ -33,25 +34,22 @@ class ModbusPDUGetComEventCounterResponse(PlcMessage, ModbusPDU):
     status: c_uint16
     event_count: c_uint16
     # Accessors for discriminator values.
-    error_flag: c_bool = False
+    error_flag: c_bool = c_bool(false)
     function_flag: c_uint8 = 0x0B
-    response: c_bool = True
+    response: c_bool = c_bool(true)
 
     def __post_init__(self):
         super().__init__()
 
     def serialize_modbus_pdu_child(self, write_buffer: WriteBuffer):
-        position_aware: PositionAware = write_buffer
-        start_pos: int = position_aware.get_pos()
+        start_pos: int = write_buffer.get_pos()
         write_buffer.push_context("ModbusPDUGetComEventCounterResponse")
 
         # Simple Field (status)
-        write_simple_field("status", self.status, write_unsigned_int(write_buffer, 16))
+        write_buffer.write_unsigned_short(self.status, logical_name="status")
 
         # Simple Field (eventCount)
-        write_simple_field(
-            "eventCount", self.event_count, write_unsigned_int(write_buffer, 16)
-        )
+        write_buffer.write_unsigned_short(self.event_count, logical_name="eventCount")
 
         write_buffer.pop_context("ModbusPDUGetComEventCounterResponse")
 
@@ -73,8 +71,7 @@ class ModbusPDUGetComEventCounterResponse(PlcMessage, ModbusPDU):
     @staticmethod
     def static_parse_builder(read_buffer: ReadBuffer, response: c_bool):
         read_buffer.pull_context("ModbusPDUGetComEventCounterResponse")
-        position_aware: PositionAware = read_buffer
-        start_pos: int = position_aware.get_pos()
+        start_pos: int = read_buffer.get_pos()
         cur_pos: int = 0
 
         status: c_uint16 = read_simple_field(
diff --git a/sandbox/plc4py/plc4py/protocols/modbus/readwrite/ModbusPDUGetComEventLogRequest.py b/sandbox/plc4py/plc4py/protocols/modbus/readwrite/ModbusPDUGetComEventLogRequest.py
index a0f7534979..6d641496d2 100644
--- a/sandbox/plc4py/plc4py/protocols/modbus/readwrite/ModbusPDUGetComEventLogRequest.py
+++ b/sandbox/plc4py/plc4py/protocols/modbus/readwrite/ModbusPDUGetComEventLogRequest.py
@@ -24,22 +24,22 @@ from ctypes import c_uint8
 from plc4py.api.messages.PlcMessage import PlcMessage
 from plc4py.protocols.modbus.readwrite.ModbusPDU import ModbusPDU
 from plc4py.protocols.modbus.readwrite.ModbusPDU import ModbusPDUBuilder
+from plc4py.spi.generation.WriteBuffer import WriteBuffer
 import math
 
 
 @dataclass
 class ModbusPDUGetComEventLogRequest(PlcMessage, ModbusPDU):
     # Accessors for discriminator values.
-    error_flag: c_bool = False
+    error_flag: c_bool = c_bool(false)
     function_flag: c_uint8 = 0x0C
-    response: c_bool = False
+    response: c_bool = c_bool(false)
 
     def __post_init__(self):
         super().__init__()
 
     def serialize_modbus_pdu_child(self, write_buffer: WriteBuffer):
-        position_aware: PositionAware = write_buffer
-        start_pos: int = position_aware.get_pos()
+        start_pos: int = write_buffer.get_pos()
         write_buffer.push_context("ModbusPDUGetComEventLogRequest")
 
         write_buffer.pop_context("ModbusPDUGetComEventLogRequest")
@@ -56,8 +56,7 @@ class ModbusPDUGetComEventLogRequest(PlcMessage, ModbusPDU):
     @staticmethod
     def static_parse_builder(read_buffer: ReadBuffer, response: c_bool):
         read_buffer.pull_context("ModbusPDUGetComEventLogRequest")
-        position_aware: PositionAware = read_buffer
-        start_pos: int = position_aware.get_pos()
+        start_pos: int = read_buffer.get_pos()
         cur_pos: int = 0
 
         read_buffer.close_context("ModbusPDUGetComEventLogRequest")
diff --git a/sandbox/plc4py/plc4py/protocols/modbus/readwrite/ModbusPDUGetComEventLogResponse.py b/sandbox/plc4py/plc4py/protocols/modbus/readwrite/ModbusPDUGetComEventLogResponse.py
index 11f94ac204..cd8d6286c5 100644
--- a/sandbox/plc4py/plc4py/protocols/modbus/readwrite/ModbusPDUGetComEventLogResponse.py
+++ b/sandbox/plc4py/plc4py/protocols/modbus/readwrite/ModbusPDUGetComEventLogResponse.py
@@ -21,11 +21,13 @@ from dataclasses import dataclass
 
 from ctypes import c_bool
 from ctypes import c_byte
+from ctypes import c_int32
 from ctypes import c_uint16
 from ctypes import c_uint8
 from plc4py.api.messages.PlcMessage import PlcMessage
 from plc4py.protocols.modbus.readwrite.ModbusPDU import ModbusPDU
 from plc4py.protocols.modbus.readwrite.ModbusPDU import ModbusPDUBuilder
+from plc4py.spi.generation.WriteBuffer import WriteBuffer
 from typing import List
 import math
 
@@ -37,39 +39,34 @@ class ModbusPDUGetComEventLogResponse(PlcMessage, ModbusPDU):
     message_count: c_uint16
     events: List[c_byte]
     # Accessors for discriminator values.
-    error_flag: c_bool = False
+    error_flag: c_bool = c_bool(false)
     function_flag: c_uint8 = 0x0C
-    response: c_bool = True
+    response: c_bool = c_bool(true)
 
     def __post_init__(self):
         super().__init__()
 
     def serialize_modbus_pdu_child(self, write_buffer: WriteBuffer):
-        position_aware: PositionAware = write_buffer
-        start_pos: int = position_aware.get_pos()
+        start_pos: int = write_buffer.get_pos()
         write_buffer.push_context("ModbusPDUGetComEventLogResponse")
 
         # Implicit Field (byte_count) (Used for parsing, but its value is not stored as it's implicitly given by the objects content)
-        byte_count: c_uint8 = c_uint8(((COUNT(self.events())) + (6)))
-        write_implicit_field(
-            "byteCount", byte_count, write_unsigned_short(write_buffer, 8)
-        )
+        byte_count: c_uint8 = c_uint8(c_uint8(len(self.events))) + c_uint8(c_uint8(6))
+        write_buffer.write_unsigned_byte(byte_count, logical_name="byteCount")
 
         # Simple Field (status)
-        write_simple_field("status", self.status, write_unsigned_int(write_buffer, 16))
+        write_buffer.write_unsigned_short(self.status, logical_name="status")
 
         # Simple Field (eventCount)
-        write_simple_field(
-            "eventCount", self.event_count, write_unsigned_int(write_buffer, 16)
-        )
+        write_buffer.write_unsigned_short(self.event_count, logical_name="eventCount")
 
         # Simple Field (messageCount)
-        write_simple_field(
-            "messageCount", self.message_count, write_unsigned_int(write_buffer, 16)
+        write_buffer.write_unsigned_short(
+            self.message_count, logical_name="messageCount"
         )
 
         # Array Field (events)
-        write_byte_array_field("events", self.events, writeByteArray(write_buffer, 8))
+        write_buffer.write_byte_array(self.events, 8, logical_name="events")
 
         write_buffer.pop_context("ModbusPDUGetComEventLogResponse")
 
@@ -101,8 +98,7 @@ class ModbusPDUGetComEventLogResponse(PlcMessage, ModbusPDU):
     @staticmethod
     def static_parse_builder(read_buffer: ReadBuffer, response: c_bool):
         read_buffer.pull_context("ModbusPDUGetComEventLogResponse")
-        position_aware: PositionAware = read_buffer
-        start_pos: int = position_aware.get_pos()
+        start_pos: int = read_buffer.get_pos()
         cur_pos: int = 0
 
         byte_count: c_uint8 = read_implicit_field(
@@ -122,7 +118,7 @@ class ModbusPDUGetComEventLogResponse(PlcMessage, ModbusPDU):
         )
 
         events: List[c_byte] = read_buffer.read_byte_array(
-            "events", int((byteCount) - (6))
+            "events", int(c_int32(byteCount) - c_int32(c_int32(6)))
         )
 
         read_buffer.close_context("ModbusPDUGetComEventLogResponse")
diff --git a/sandbox/plc4py/plc4py/protocols/modbus/readwrite/ModbusPDUMaskWriteHoldingRegisterRequest.py b/sandbox/plc4py/plc4py/protocols/modbus/readwrite/ModbusPDUMaskWriteHoldingRegisterRequest.py
index 385a468145..51137cb412 100644
--- a/sandbox/plc4py/plc4py/protocols/modbus/readwrite/ModbusPDUMaskWriteHoldingRegisterRequest.py
+++ b/sandbox/plc4py/plc4py/protocols/modbus/readwrite/ModbusPDUMaskWriteHoldingRegisterRequest.py
@@ -25,6 +25,7 @@ from ctypes import c_uint8
 from plc4py.api.messages.PlcMessage import PlcMessage
 from plc4py.protocols.modbus.readwrite.ModbusPDU import ModbusPDU
 from plc4py.protocols.modbus.readwrite.ModbusPDU import ModbusPDUBuilder
+from plc4py.spi.generation.WriteBuffer import WriteBuffer
 import math
 
 
@@ -34,32 +35,27 @@ class ModbusPDUMaskWriteHoldingRegisterRequest(PlcMessage, ModbusPDU):
     and_mask: c_uint16
     or_mask: c_uint16
     # Accessors for discriminator values.
-    error_flag: c_bool = False
+    error_flag: c_bool = c_bool(false)
     function_flag: c_uint8 = 0x16
-    response: c_bool = False
+    response: c_bool = c_bool(false)
 
     def __post_init__(self):
         super().__init__()
 
     def serialize_modbus_pdu_child(self, write_buffer: WriteBuffer):
-        position_aware: PositionAware = write_buffer
-        start_pos: int = position_aware.get_pos()
+        start_pos: int = write_buffer.get_pos()
         write_buffer.push_context("ModbusPDUMaskWriteHoldingRegisterRequest")
 
         # Simple Field (referenceAddress)
-        write_simple_field(
-            "referenceAddress",
-            self.reference_address,
-            write_unsigned_int(write_buffer, 16),
+        write_buffer.write_unsigned_short(
+            self.reference_address, logical_name="referenceAddress"
         )
 
         # Simple Field (andMask)
-        write_simple_field(
-            "andMask", self.and_mask, write_unsigned_int(write_buffer, 16)
-        )
+        write_buffer.write_unsigned_short(self.and_mask, logical_name="andMask")
 
         # Simple Field (orMask)
-        write_simple_field("orMask", self.or_mask, write_unsigned_int(write_buffer, 16))
+        write_buffer.write_unsigned_short(self.or_mask, logical_name="orMask")
 
         write_buffer.pop_context("ModbusPDUMaskWriteHoldingRegisterRequest")
 
@@ -84,8 +80,7 @@ class ModbusPDUMaskWriteHoldingRegisterRequest(PlcMessage, ModbusPDU):
     @staticmethod
     def static_parse_builder(read_buffer: ReadBuffer, response: c_bool):
         read_buffer.pull_context("ModbusPDUMaskWriteHoldingRegisterRequest")
-        position_aware: PositionAware = read_buffer
-        start_pos: int = position_aware.get_pos()
+        start_pos: int = read_buffer.get_pos()
         cur_pos: int = 0
 
         reference_address: c_uint16 = read_simple_field(
diff --git a/sandbox/plc4py/plc4py/protocols/modbus/readwrite/ModbusPDUMaskWriteHoldingRegisterResponse.py b/sandbox/plc4py/plc4py/protocols/modbus/readwrite/ModbusPDUMaskWriteHoldingRegisterResponse.py
index 0a800bb7a9..b67c7e9946 100644
--- a/sandbox/plc4py/plc4py/protocols/modbus/readwrite/ModbusPDUMaskWriteHoldingRegisterResponse.py
+++ b/sandbox/plc4py/plc4py/protocols/modbus/readwrite/ModbusPDUMaskWriteHoldingRegisterResponse.py
@@ -25,6 +25,7 @@ from ctypes import c_uint8
 from plc4py.api.messages.PlcMessage import PlcMessage
 from plc4py.protocols.modbus.readwrite.ModbusPDU import ModbusPDU
 from plc4py.protocols.modbus.readwrite.ModbusPDU import ModbusPDUBuilder
+from plc4py.spi.generation.WriteBuffer import WriteBuffer
 import math
 
 
@@ -34,32 +35,27 @@ class ModbusPDUMaskWriteHoldingRegisterResponse(PlcMessage, ModbusPDU):
     and_mask: c_uint16
     or_mask: c_uint16
     # Accessors for discriminator values.
-    error_flag: c_bool = False
+    error_flag: c_bool = c_bool(false)
     function_flag: c_uint8 = 0x16
-    response: c_bool = True
+    response: c_bool = c_bool(true)
 
     def __post_init__(self):
         super().__init__()
 
     def serialize_modbus_pdu_child(self, write_buffer: WriteBuffer):
-        position_aware: PositionAware = write_buffer
-        start_pos: int = position_aware.get_pos()
+        start_pos: int = write_buffer.get_pos()
         write_buffer.push_context("ModbusPDUMaskWriteHoldingRegisterResponse")
 
         # Simple Field (referenceAddress)
-        write_simple_field(
-            "referenceAddress",
-            self.reference_address,
-            write_unsigned_int(write_buffer, 16),
+        write_buffer.write_unsigned_short(
+            self.reference_address, logical_name="referenceAddress"
         )
 
         # Simple Field (andMask)
-        write_simple_field(
-            "andMask", self.and_mask, write_unsigned_int(write_buffer, 16)
-        )
+        write_buffer.write_unsigned_short(self.and_mask, logical_name="andMask")
 
         # Simple Field (orMask)
-        write_simple_field("orMask", self.or_mask, write_unsigned_int(write_buffer, 16))
+        write_buffer.write_unsigned_short(self.or_mask, logical_name="orMask")
 
         write_buffer.pop_context("ModbusPDUMaskWriteHoldingRegisterResponse")
 
@@ -84,8 +80,7 @@ class ModbusPDUMaskWriteHoldingRegisterResponse(PlcMessage, ModbusPDU):
     @staticmethod
     def static_parse_builder(read_buffer: ReadBuffer, response: c_bool):
         read_buffer.pull_context("ModbusPDUMaskWriteHoldingRegisterResponse")
-        position_aware: PositionAware = read_buffer
-        start_pos: int = position_aware.get_pos()
+        start_pos: int = read_buffer.get_pos()
         cur_pos: int = 0
 
         reference_address: c_uint16 = read_simple_field(
diff --git a/sandbox/plc4py/plc4py/protocols/modbus/readwrite/ModbusPDUReadCoilsRequest.py b/sandbox/plc4py/plc4py/protocols/modbus/readwrite/ModbusPDUReadCoilsRequest.py
index 3b554f41cb..444b90bedc 100644
--- a/sandbox/plc4py/plc4py/protocols/modbus/readwrite/ModbusPDUReadCoilsRequest.py
+++ b/sandbox/plc4py/plc4py/protocols/modbus/readwrite/ModbusPDUReadCoilsRequest.py
@@ -25,6 +25,7 @@ from ctypes import c_uint8
 from plc4py.api.messages.PlcMessage import PlcMessage
 from plc4py.protocols.modbus.readwrite.ModbusPDU import ModbusPDU
 from plc4py.protocols.modbus.readwrite.ModbusPDU import ModbusPDUBuilder
+from plc4py.spi.generation.WriteBuffer import WriteBuffer
 import math
 
 
@@ -33,29 +34,24 @@ class ModbusPDUReadCoilsRequest(PlcMessage, ModbusPDU):
     starting_address: c_uint16
     quantity: c_uint16
     # Accessors for discriminator values.
-    error_flag: c_bool = False
+    error_flag: c_bool = c_bool(false)
     function_flag: c_uint8 = 0x01
-    response: c_bool = False
+    response: c_bool = c_bool(false)
 
     def __post_init__(self):
         super().__init__()
 
     def serialize_modbus_pdu_child(self, write_buffer: WriteBuffer):
-        position_aware: PositionAware = write_buffer
-        start_pos: int = position_aware.get_pos()
+        start_pos: int = write_buffer.get_pos()
         write_buffer.push_context("ModbusPDUReadCoilsRequest")
 
         # Simple Field (startingAddress)
-        write_simple_field(
-            "startingAddress",
-            self.starting_address,
-            write_unsigned_int(write_buffer, 16),
+        write_buffer.write_unsigned_short(
+            self.starting_address, logical_name="startingAddress"
         )
 
         # Simple Field (quantity)
-        write_simple_field(
-            "quantity", self.quantity, write_unsigned_int(write_buffer, 16)
-        )
+        write_buffer.write_unsigned_short(self.quantity, logical_name="quantity")
 
         write_buffer.pop_context("ModbusPDUReadCoilsRequest")
 
@@ -77,8 +73,7 @@ class ModbusPDUReadCoilsRequest(PlcMessage, ModbusPDU):
     @staticmethod
     def static_parse_builder(read_buffer: ReadBuffer, response: c_bool):
         read_buffer.pull_context("ModbusPDUReadCoilsRequest")
-        position_aware: PositionAware = read_buffer
-        start_pos: int = position_aware.get_pos()
+        start_pos: int = read_buffer.get_pos()
         cur_pos: int = 0
 
         starting_address: c_uint16 = read_simple_field(
diff --git a/sandbox/plc4py/plc4py/protocols/modbus/readwrite/ModbusPDUReadCoilsResponse.py b/sandbox/plc4py/plc4py/protocols/modbus/readwrite/ModbusPDUReadCoilsResponse.py
index 923d3055a2..0ccdd3a6f0 100644
--- a/sandbox/plc4py/plc4py/protocols/modbus/readwrite/ModbusPDUReadCoilsResponse.py
+++ b/sandbox/plc4py/plc4py/protocols/modbus/readwrite/ModbusPDUReadCoilsResponse.py
@@ -25,6 +25,7 @@ from ctypes import c_uint8
 from plc4py.api.messages.PlcMessage import PlcMessage
 from plc4py.protocols.modbus.readwrite.ModbusPDU import ModbusPDU
 from plc4py.protocols.modbus.readwrite.ModbusPDU import ModbusPDUBuilder
+from plc4py.spi.generation.WriteBuffer import WriteBuffer
 from typing import List
 import math
 
@@ -33,26 +34,23 @@ import math
 class ModbusPDUReadCoilsResponse(PlcMessage, ModbusPDU):
     value: List[c_byte]
     # Accessors for discriminator values.
-    error_flag: c_bool = False
+    error_flag: c_bool = c_bool(false)
     function_flag: c_uint8 = 0x01
-    response: c_bool = True
+    response: c_bool = c_bool(true)
 
     def __post_init__(self):
         super().__init__()
 
     def serialize_modbus_pdu_child(self, write_buffer: WriteBuffer):
-        position_aware: PositionAware = write_buffer
-        start_pos: int = position_aware.get_pos()
+        start_pos: int = write_buffer.get_pos()
         write_buffer.push_context("ModbusPDUReadCoilsResponse")
 
         # Implicit Field (byte_count) (Used for parsing, but its value is not stored as it's implicitly given by the objects content)
-        byte_count: c_uint8 = c_uint8((COUNT(self.value())))
-        write_implicit_field(
-            "byteCount", byte_count, write_unsigned_short(write_buffer, 8)
-        )
+        byte_count: c_uint8 = c_uint8(len(self.value))
+        write_buffer.write_unsigned_byte(byte_count, logical_name="byteCount")
 
         # Array Field (value)
-        write_byte_array_field("value", self.value, writeByteArray(write_buffer, 8))
+        write_buffer.write_byte_array(self.value, 8, logical_name="value")
 
         write_buffer.pop_context("ModbusPDUReadCoilsResponse")
 
@@ -75,8 +73,7 @@ class ModbusPDUReadCoilsResponse(PlcMessage, ModbusPDU):
     @staticmethod
     def static_parse_builder(read_buffer: ReadBuffer, response: c_bool):
         read_buffer.pull_context("ModbusPDUReadCoilsResponse")
-        position_aware: PositionAware = read_buffer
-        start_pos: int = position_aware.get_pos()
+        start_pos: int = read_buffer.get_pos()
         cur_pos: int = 0
 
         byte_count: c_uint8 = read_implicit_field(
diff --git a/sandbox/plc4py/plc4py/protocols/modbus/readwrite/ModbusPDUReadDeviceIdentificationRequest.py b/sandbox/plc4py/plc4py/protocols/modbus/readwrite/ModbusPDUReadDeviceIdentificationRequest.py
index 759a360cd8..7f2be71e4b 100644
--- a/sandbox/plc4py/plc4py/protocols/modbus/readwrite/ModbusPDUReadDeviceIdentificationRequest.py
+++ b/sandbox/plc4py/plc4py/protocols/modbus/readwrite/ModbusPDUReadDeviceIdentificationRequest.py
@@ -27,6 +27,7 @@ from plc4py.protocols.modbus.readwrite.ModbusDeviceInformationLevel import (
 )
 from plc4py.protocols.modbus.readwrite.ModbusPDU import ModbusPDU
 from plc4py.protocols.modbus.readwrite.ModbusPDU import ModbusPDUBuilder
+from plc4py.spi.generation.WriteBuffer import WriteBuffer
 import math
 
 
@@ -36,39 +37,29 @@ class ModbusPDUReadDeviceIdentificationRequest(PlcMessage, ModbusPDU):
     object_id: c_uint8
     MEITYPE: c_uint8 = 0x0E
     # Accessors for discriminator values.
-    error_flag: c_bool = False
+    error_flag: c_bool = c_bool(false)
     function_flag: c_uint8 = 0x2B
-    response: c_bool = False
+    response: c_bool = c_bool(false)
 
     def __post_init__(self):
         super().__init__()
 
     def serialize_modbus_pdu_child(self, write_buffer: WriteBuffer):
-        position_aware: PositionAware = write_buffer
-        start_pos: int = position_aware.get_pos()
+        start_pos: int = write_buffer.get_pos()
         write_buffer.push_context("ModbusPDUReadDeviceIdentificationRequest")
 
         # Const Field (meiType)
-        write_const_field(
-            "meiType", self.mei_type, write_unsigned_short(write_buffer, 8)
-        )
+        write_buffer.write_unsigned_byte(self.mei_type.value, logical_name="meiType")
 
         # Simple Field (level)
-        write_simple_enum_field(
-            "level",
-            "ModbusDeviceInformationLevel",
-            self.level,
-            DataWriterEnumDefault(
-                ModbusDeviceInformationLevel.value,
-                ModbusDeviceInformationLevel.name,
-                write_unsigned_short(write_buffer, 8),
-            ),
-        )
+        write_buffer.DataWriterEnumDefault(
+            ModbusDeviceInformationLevel.value,
+            ModbusDeviceInformationLevel.name,
+            write_unsigned_byte,
+        )(self.level, logical_name="level")
 
         # Simple Field (objectId)
-        write_simple_field(
-            "objectId", self.object_id, write_unsigned_short(write_buffer, 8)
-        )
+        write_buffer.write_unsigned_byte(self.object_id, logical_name="objectId")
 
         write_buffer.pop_context("ModbusPDUReadDeviceIdentificationRequest")
 
@@ -93,8 +84,7 @@ class ModbusPDUReadDeviceIdentificationRequest(PlcMessage, ModbusPDU):
     @staticmethod
     def static_parse_builder(read_buffer: ReadBuffer, response: c_bool):
         read_buffer.pull_context("ModbusPDUReadDeviceIdentificationRequest")
-        position_aware: PositionAware = read_buffer
-        start_pos: int = position_aware.get_pos()
+        start_pos: int = read_buffer.get_pos()
         cur_pos: int = 0
 
         mei_type: c_uint8 = read_const_field(
diff --git a/sandbox/plc4py/plc4py/protocols/modbus/readwrite/ModbusPDUReadDeviceIdentificationResponse.py b/sandbox/plc4py/plc4py/protocols/modbus/readwrite/ModbusPDUReadDeviceIdentificationResponse.py
index 312c83f35b..4a35f54d77 100644
--- a/sandbox/plc4py/plc4py/protocols/modbus/readwrite/ModbusPDUReadDeviceIdentificationResponse.py
+++ b/sandbox/plc4py/plc4py/protocols/modbus/readwrite/ModbusPDUReadDeviceIdentificationResponse.py
@@ -36,6 +36,7 @@ from plc4py.protocols.modbus.readwrite.ModbusDeviceInformationObject import (
 )
 from plc4py.protocols.modbus.readwrite.ModbusPDU import ModbusPDU
 from plc4py.protocols.modbus.readwrite.ModbusPDU import ModbusPDUBuilder
+from plc4py.spi.generation.WriteBuffer import WriteBuffer
 from typing import List
 import math
 
@@ -50,77 +51,59 @@ class ModbusPDUReadDeviceIdentificationResponse(PlcMessage, ModbusPDU):
     objects: List[ModbusDeviceInformationObject]
     MEITYPE: c_uint8 = 0x0E
     # Accessors for discriminator values.
-    error_flag: c_bool = False
+    error_flag: c_bool = c_bool(false)
     function_flag: c_uint8 = 0x2B
-    response: c_bool = True
+    response: c_bool = c_bool(true)
 
     def __post_init__(self):
         super().__init__()
 
     def serialize_modbus_pdu_child(self, write_buffer: WriteBuffer):
-        position_aware: PositionAware = write_buffer
-        start_pos: int = position_aware.get_pos()
+        start_pos: int = write_buffer.get_pos()
         write_buffer.push_context("ModbusPDUReadDeviceIdentificationResponse")
 
         # Const Field (meiType)
-        write_const_field(
-            "meiType", self.mei_type, write_unsigned_short(write_buffer, 8)
-        )
+        write_buffer.write_unsigned_byte(self.mei_type.value, logical_name="meiType")
 
         # Simple Field (level)
-        write_simple_enum_field(
-            "level",
-            "ModbusDeviceInformationLevel",
-            self.level,
-            DataWriterEnumDefault(
-                ModbusDeviceInformationLevel.value,
-                ModbusDeviceInformationLevel.name,
-                write_unsigned_short(write_buffer, 8),
-            ),
-        )
+        write_buffer.DataWriterEnumDefault(
+            ModbusDeviceInformationLevel.value,
+            ModbusDeviceInformationLevel.name,
+            write_unsigned_byte,
+        )(self.level, logical_name="level")
 
         # Simple Field (individualAccess)
-        write_simple_field(
-            "individualAccess", self.individual_access, write_boolean(write_buffer)
+        write_buffer.write_boolean(
+            self.individual_access, logical_name="individualAccess"
         )
 
         # Simple Field (conformityLevel)
-        write_simple_enum_field(
-            "conformityLevel",
-            "ModbusDeviceInformationConformityLevel",
-            self.conformity_level,
-            DataWriterEnumDefault(
-                ModbusDeviceInformationConformityLevel.value,
-                ModbusDeviceInformationConformityLevel.name,
-                write_unsigned_short(write_buffer, 7),
-            ),
-        )
+        write_buffer.DataWriterEnumDefault(
+            ModbusDeviceInformationConformityLevel.value,
+            ModbusDeviceInformationConformityLevel.name,
+            write_unsigned_byte,
+        )(self.conformity_level, logical_name="conformityLevel")
 
         # Simple Field (moreFollows)
-        write_simple_enum_field(
-            "moreFollows",
-            "ModbusDeviceInformationMoreFollows",
-            self.more_follows,
-            DataWriterEnumDefault(
-                ModbusDeviceInformationMoreFollows.value,
-                ModbusDeviceInformationMoreFollows.name,
-                write_unsigned_short(write_buffer, 8),
-            ),
-        )
+        write_buffer.DataWriterEnumDefault(
+            ModbusDeviceInformationMoreFollows.value,
+            ModbusDeviceInformationMoreFollows.name,
+            write_unsigned_byte,
+        )(self.more_follows, logical_name="moreFollows")
 
         # Simple Field (nextObjectId)
-        write_simple_field(
-            "nextObjectId", self.next_object_id, write_unsigned_short(write_buffer, 8)
+        write_buffer.write_unsigned_byte(
+            self.next_object_id, logical_name="nextObjectId"
         )
 
         # Implicit Field (number_of_objects) (Used for parsing, but its value is not stored as it's implicitly given by the objects content)
-        number_of_objects: c_uint8 = c_uint8((COUNT(self.objects())))
-        write_implicit_field(
-            "numberOfObjects", number_of_objects, write_unsigned_short(write_buffer, 8)
+        number_of_objects: c_uint8 = c_uint8(len(self.objects))
+        write_buffer.write_unsigned_byte(
+            number_of_objects, logical_name="numberOfObjects"
         )
 
         # Array Field (objects)
-        write_complex_type_array_field("objects", self.objects, write_buffer)
+        write_buffer.write_complex_array(self.objects, logical_name="objects")
 
         write_buffer.pop_context("ModbusPDUReadDeviceIdentificationResponse")
 
@@ -164,8 +147,7 @@ class ModbusPDUReadDeviceIdentificationResponse(PlcMessage, ModbusPDU):
     @staticmethod
     def static_parse_builder(read_buffer: ReadBuffer, response: c_bool):
         read_buffer.pull_context("ModbusPDUReadDeviceIdentificationResponse")
-        position_aware: PositionAware = read_buffer
-        start_pos: int = position_aware.get_pos()
+        start_pos: int = read_buffer.get_pos()
         cur_pos: int = 0
 
         mei_type: c_uint8 = read_const_field(
diff --git a/sandbox/plc4py/plc4py/protocols/modbus/readwrite/ModbusPDUReadDiscreteInputsRequest.py b/sandbox/plc4py/plc4py/protocols/modbus/readwrite/ModbusPDUReadDiscreteInputsRequest.py
index c2fba3ef26..97b20800b8 100644
--- a/sandbox/plc4py/plc4py/protocols/modbus/readwrite/ModbusPDUReadDiscreteInputsRequest.py
+++ b/sandbox/plc4py/plc4py/protocols/modbus/readwrite/ModbusPDUReadDiscreteInputsRequest.py
@@ -25,6 +25,7 @@ from ctypes import c_uint8
 from plc4py.api.messages.PlcMessage import PlcMessage
 from plc4py.protocols.modbus.readwrite.ModbusPDU import ModbusPDU
 from plc4py.protocols.modbus.readwrite.ModbusPDU import ModbusPDUBuilder
+from plc4py.spi.generation.WriteBuffer import WriteBuffer
 import math
 
 
@@ -33,29 +34,24 @@ class ModbusPDUReadDiscreteInputsRequest(PlcMessage, ModbusPDU):
     starting_address: c_uint16
     quantity: c_uint16
     # Accessors for discriminator values.
-    error_flag: c_bool = False
+    error_flag: c_bool = c_bool(false)
     function_flag: c_uint8 = 0x02
-    response: c_bool = False
+    response: c_bool = c_bool(false)
 
     def __post_init__(self):
         super().__init__()
 
     def serialize_modbus_pdu_child(self, write_buffer: WriteBuffer):
-        position_aware: PositionAware = write_buffer
-        start_pos: int = position_aware.get_pos()
+        start_pos: int = write_buffer.get_pos()
         write_buffer.push_context("ModbusPDUReadDiscreteInputsRequest")
 
         # Simple Field (startingAddress)
-        write_simple_field(
-            "startingAddress",
-            self.starting_address,
-            write_unsigned_int(write_buffer, 16),
+        write_buffer.write_unsigned_short(
+            self.starting_address, logical_name="startingAddress"
         )
 
         # Simple Field (quantity)
-        write_simple_field(
-            "quantity", self.quantity, write_unsigned_int(write_buffer, 16)
-        )
+        write_buffer.write_unsigned_short(self.quantity, logical_name="quantity")
 
         write_buffer.pop_context("ModbusPDUReadDiscreteInputsRequest")
 
@@ -77,8 +73,7 @@ class ModbusPDUReadDiscreteInputsRequest(PlcMessage, ModbusPDU):
     @staticmethod
     def static_parse_builder(read_buffer: ReadBuffer, response: c_bool):
         read_buffer.pull_context("ModbusPDUReadDiscreteInputsRequest")
-        position_aware: PositionAware = read_buffer
-        start_pos: int = position_aware.get_pos()
+        start_pos: int = read_buffer.get_pos()
         cur_pos: int = 0
 
         starting_address: c_uint16 = read_simple_field(
diff --git a/sandbox/plc4py/plc4py/protocols/modbus/readwrite/ModbusPDUReadDiscreteInputsResponse.py b/sandbox/plc4py/plc4py/protocols/modbus/readwrite/ModbusPDUReadDiscreteInputsResponse.py
index 0bafeb94f4..afa39fcc4e 100644
--- a/sandbox/plc4py/plc4py/protocols/modbus/readwrite/ModbusPDUReadDiscreteInputsResponse.py
+++ b/sandbox/plc4py/plc4py/protocols/modbus/readwrite/ModbusPDUReadDiscreteInputsResponse.py
@@ -25,6 +25,7 @@ from ctypes import c_uint8
 from plc4py.api.messages.PlcMessage import PlcMessage
 from plc4py.protocols.modbus.readwrite.ModbusPDU import ModbusPDU
 from plc4py.protocols.modbus.readwrite.ModbusPDU import ModbusPDUBuilder
+from plc4py.spi.generation.WriteBuffer import WriteBuffer
 from typing import List
 import math
 
@@ -33,26 +34,23 @@ import math
 class ModbusPDUReadDiscreteInputsResponse(PlcMessage, ModbusPDU):
     value: List[c_byte]
     # Accessors for discriminator values.
-    error_flag: c_bool = False
+    error_flag: c_bool = c_bool(false)
     function_flag: c_uint8 = 0x02
-    response: c_bool = True
+    response: c_bool = c_bool(true)
 
     def __post_init__(self):
         super().__init__()
 
     def serialize_modbus_pdu_child(self, write_buffer: WriteBuffer):
-        position_aware: PositionAware = write_buffer
-        start_pos: int = position_aware.get_pos()
+        start_pos: int = write_buffer.get_pos()
         write_buffer.push_context("ModbusPDUReadDiscreteInputsResponse")
 
         # Implicit Field (byte_count) (Used for parsing, but its value is not stored as it's implicitly given by the objects content)
-        byte_count: c_uint8 = c_uint8((COUNT(self.value())))
-        write_implicit_field(
-            "byteCount", byte_count, write_unsigned_short(write_buffer, 8)
-        )
+        byte_count: c_uint8 = c_uint8(len(self.value))
+        write_buffer.write_unsigned_byte(byte_count, logical_name="byteCount")
 
         # Array Field (value)
-        write_byte_array_field("value", self.value, writeByteArray(write_buffer, 8))
+        write_buffer.write_byte_array(self.value, 8, logical_name="value")
 
         write_buffer.pop_context("ModbusPDUReadDiscreteInputsResponse")
 
@@ -75,8 +73,7 @@ class ModbusPDUReadDiscreteInputsResponse(PlcMessage, ModbusPDU):
     @staticmethod
     def static_parse_builder(read_buffer: ReadBuffer, response: c_bool):
         read_buffer.pull_context("ModbusPDUReadDiscreteInputsResponse")
-        position_aware: PositionAware = read_buffer
-        start_pos: int = position_aware.get_pos()
+        start_pos: int = read_buffer.get_pos()
         cur_pos: int = 0
 
         byte_count: c_uint8 = read_implicit_field(
diff --git a/sandbox/plc4py/plc4py/protocols/modbus/readwrite/ModbusPDUReadExceptionStatusRequest.py b/sandbox/plc4py/plc4py/protocols/modbus/readwrite/ModbusPDUReadExceptionStatusRequest.py
index 8b69cb93ac..be5fd8d8d2 100644
--- a/sandbox/plc4py/plc4py/protocols/modbus/readwrite/ModbusPDUReadExceptionStatusRequest.py
+++ b/sandbox/plc4py/plc4py/protocols/modbus/readwrite/ModbusPDUReadExceptionStatusRequest.py
@@ -24,22 +24,22 @@ from ctypes import c_uint8
 from plc4py.api.messages.PlcMessage import PlcMessage
 from plc4py.protocols.modbus.readwrite.ModbusPDU import ModbusPDU
 from plc4py.protocols.modbus.readwrite.ModbusPDU import ModbusPDUBuilder
+from plc4py.spi.generation.WriteBuffer import WriteBuffer
 import math
 
 
 @dataclass
 class ModbusPDUReadExceptionStatusRequest(PlcMessage, ModbusPDU):
     # Accessors for discriminator values.
-    error_flag: c_bool = False
+    error_flag: c_bool = c_bool(false)
     function_flag: c_uint8 = 0x07
-    response: c_bool = False
+    response: c_bool = c_bool(false)
 
     def __post_init__(self):
         super().__init__()
 
     def serialize_modbus_pdu_child(self, write_buffer: WriteBuffer):
-        position_aware: PositionAware = write_buffer
-        start_pos: int = position_aware.get_pos()
+        start_pos: int = write_buffer.get_pos()
         write_buffer.push_context("ModbusPDUReadExceptionStatusRequest")
 
         write_buffer.pop_context("ModbusPDUReadExceptionStatusRequest")
@@ -56,8 +56,7 @@ class ModbusPDUReadExceptionStatusRequest(PlcMessage, ModbusPDU):
     @staticmethod
     def static_parse_builder(read_buffer: ReadBuffer, response: c_bool):
         read_buffer.pull_context("ModbusPDUReadExceptionStatusRequest")
-        position_aware: PositionAware = read_buffer
-        start_pos: int = position_aware.get_pos()
+        start_pos: int = read_buffer.get_pos()
         cur_pos: int = 0
 
         read_buffer.close_context("ModbusPDUReadExceptionStatusRequest")
diff --git a/sandbox/plc4py/plc4py/protocols/modbus/readwrite/ModbusPDUReadExceptionStatusResponse.py b/sandbox/plc4py/plc4py/protocols/modbus/readwrite/ModbusPDUReadExceptionStatusResponse.py
index afb01ded60..7e66a893f9 100644
--- a/sandbox/plc4py/plc4py/protocols/modbus/readwrite/ModbusPDUReadExceptionStatusResponse.py
+++ b/sandbox/plc4py/plc4py/protocols/modbus/readwrite/ModbusPDUReadExceptionStatusResponse.py
@@ -24,6 +24,7 @@ from ctypes import c_uint8
 from plc4py.api.messages.PlcMessage import PlcMessage
 from plc4py.protocols.modbus.readwrite.ModbusPDU import ModbusPDU
 from plc4py.protocols.modbus.readwrite.ModbusPDU import ModbusPDUBuilder
+from plc4py.spi.generation.WriteBuffer import WriteBuffer
 import math
 
 
@@ -31,20 +32,19 @@ import math
 class ModbusPDUReadExceptionStatusResponse(PlcMessage, ModbusPDU):
     value: c_uint8
     # Accessors for discriminator values.
-    error_flag: c_bool = False
+    error_flag: c_bool = c_bool(false)
     function_flag: c_uint8 = 0x07
-    response: c_bool = True
+    response: c_bool = c_bool(true)
 
     def __post_init__(self):
         super().__init__()
 
     def serialize_modbus_pdu_child(self, write_buffer: WriteBuffer):
-        position_aware: PositionAware = write_buffer
-        start_pos: int = position_aware.get_pos()
+        start_pos: int = write_buffer.get_pos()
         write_buffer.push_context("ModbusPDUReadExceptionStatusResponse")
 
         # Simple Field (value)
-        write_simple_field("value", self.value, write_unsigned_short(write_buffer, 8))
+        write_buffer.write_unsigned_byte(self.value, logical_name="value")
 
         write_buffer.pop_context("ModbusPDUReadExceptionStatusResponse")
 
@@ -63,8 +63,7 @@ class ModbusPDUReadExceptionStatusResponse(PlcMessage, ModbusPDU):
     @staticmethod
     def static_parse_builder(read_buffer: ReadBuffer, response: c_bool):
         read_buffer.pull_context("ModbusPDUReadExceptionStatusResponse")
-        position_aware: PositionAware = read_buffer
-        start_pos: int = position_aware.get_pos()
+        start_pos: int = read_buffer.get_pos()
         cur_pos: int = 0
 
         value: c_uint8 = read_simple_field("value", read_unsigned_short(read_buffer, 8))
diff --git a/sandbox/plc4py/plc4py/protocols/modbus/readwrite/ModbusPDUReadFifoQueueRequest.py b/sandbox/plc4py/plc4py/protocols/modbus/readwrite/ModbusPDUReadFifoQueueRequest.py
index 0afea69b9d..1a5dd76b9d 100644
--- a/sandbox/plc4py/plc4py/protocols/modbus/readwrite/ModbusPDUReadFifoQueueRequest.py
+++ b/sandbox/plc4py/plc4py/protocols/modbus/readwrite/ModbusPDUReadFifoQueueRequest.py
@@ -25,6 +25,7 @@ from ctypes import c_uint8
 from plc4py.api.messages.PlcMessage import PlcMessage
 from plc4py.protocols.modbus.readwrite.ModbusPDU import ModbusPDU
 from plc4py.protocols.modbus.readwrite.ModbusPDU import ModbusPDUBuilder
+from plc4py.spi.generation.WriteBuffer import WriteBuffer
 import math
 
 
@@ -32,23 +33,20 @@ import math
 class ModbusPDUReadFifoQueueRequest(PlcMessage, ModbusPDU):
     fifo_pointer_address: c_uint16
     # Accessors for discriminator values.
-    error_flag: c_bool = False
+    error_flag: c_bool = c_bool(false)
     function_flag: c_uint8 = 0x18
-    response: c_bool = False
+    response: c_bool = c_bool(false)
 
     def __post_init__(self):
         super().__init__()
 
     def serialize_modbus_pdu_child(self, write_buffer: WriteBuffer):
-        position_aware: PositionAware = write_buffer
-        start_pos: int = position_aware.get_pos()
+        start_pos: int = write_buffer.get_pos()
         write_buffer.push_context("ModbusPDUReadFifoQueueRequest")
 
         # Simple Field (fifoPointerAddress)
-        write_simple_field(
-            "fifoPointerAddress",
-            self.fifo_pointer_address,
-            write_unsigned_int(write_buffer, 16),
+        write_buffer.write_unsigned_short(
+            self.fifo_pointer_address, logical_name="fifoPointerAddress"
         )
 
         write_buffer.pop_context("ModbusPDUReadFifoQueueRequest")
@@ -68,8 +66,7 @@ class ModbusPDUReadFifoQueueRequest(PlcMessage, ModbusPDU):
     @staticmethod
     def static_parse_builder(read_buffer: ReadBuffer, response: c_bool):
         read_buffer.pull_context("ModbusPDUReadFifoQueueRequest")
-        position_aware: PositionAware = read_buffer
-        start_pos: int = position_aware.get_pos()
+        start_pos: int = read_buffer.get_pos()
         cur_pos: int = 0
 
         fifo_pointer_address: c_uint16 = read_simple_field(
diff --git a/sandbox/plc4py/plc4py/protocols/modbus/readwrite/ModbusPDUReadFifoQueueResponse.py b/sandbox/plc4py/plc4py/protocols/modbus/readwrite/ModbusPDUReadFifoQueueResponse.py
index 7cc80730fa..cfa769833e 100644
--- a/sandbox/plc4py/plc4py/protocols/modbus/readwrite/ModbusPDUReadFifoQueueResponse.py
+++ b/sandbox/plc4py/plc4py/protocols/modbus/readwrite/ModbusPDUReadFifoQueueResponse.py
@@ -25,6 +25,7 @@ from ctypes import c_uint8
 from plc4py.api.messages.PlcMessage import PlcMessage
 from plc4py.protocols.modbus.readwrite.ModbusPDU import ModbusPDU
 from plc4py.protocols.modbus.readwrite.ModbusPDU import ModbusPDUBuilder
+from plc4py.spi.generation.WriteBuffer import WriteBuffer
 from typing import List
 import math
 
@@ -33,33 +34,32 @@ import math
 class ModbusPDUReadFifoQueueResponse(PlcMessage, ModbusPDU):
     fifo_value: List[c_uint16]
     # Accessors for discriminator values.
-    error_flag: c_bool = False
+    error_flag: c_bool = c_bool(false)
     function_flag: c_uint8 = 0x18
-    response: c_bool = True
+    response: c_bool = c_bool(true)
 
     def __post_init__(self):
         super().__init__()
 
     def serialize_modbus_pdu_child(self, write_buffer: WriteBuffer):
-        position_aware: PositionAware = write_buffer
-        start_pos: int = position_aware.get_pos()
+        start_pos: int = write_buffer.get_pos()
         write_buffer.push_context("ModbusPDUReadFifoQueueResponse")
 
         # Implicit Field (byte_count) (Used for parsing, but its value is not stored as it's implicitly given by the objects content)
-        byte_count: c_uint16 = c_uint16(((((COUNT(self.fifo_value())) * (2))) + (2)))
-        write_implicit_field(
-            "byteCount", byte_count, write_unsigned_int(write_buffer, 16)
-        )
+        byte_count: c_uint16 = c_uint16(
+            (c_uint16(c_uint16(len(self.fifo_value))) * c_uint16(c_uint16(2)))
+        ) + c_uint16(c_uint16(2))
+        write_buffer.write_unsigned_short(byte_count, logical_name="byteCount")
 
         # Implicit Field (fifo_count) (Used for parsing, but its value is not stored as it's implicitly given by the objects content)
-        fifo_count: c_uint16 = c_uint16(((((COUNT(self.fifo_value())) * (2))) / (2)))
-        write_implicit_field(
-            "fifoCount", fifo_count, write_unsigned_int(write_buffer, 16)
-        )
+        fifo_count: c_uint16 = c_uint16(
+            (c_uint16(c_uint16(len(self.fifo_value))) * c_uint16(c_uint16(2)))
+        ) / c_uint16(c_uint16(2))
+        write_buffer.write_unsigned_short(fifo_count, logical_name="fifoCount")
 
         # Array Field (fifoValue)
-        write_simple_type_array_field(
-            "fifoValue", self.fifo_value, write_unsigned_int(write_buffer, 16)
+        write_buffer.write_simple_array(
+            self.fifo_value, write_unsigned_short, logical_name="fifoValue"
         )
 
         write_buffer.pop_context("ModbusPDUReadFifoQueueResponse")
@@ -86,8 +86,7 @@ class ModbusPDUReadFifoQueueResponse(PlcMessage, ModbusPDU):
     @staticmethod
     def static_parse_builder(read_buffer: ReadBuffer, response: c_bool):
         read_buffer.pull_context("ModbusPDUReadFifoQueueResponse")
-        position_aware: PositionAware = read_buffer
-        start_pos: int = position_aware.get_pos()
+        start_pos: int = read_buffer.get_pos()
         cur_pos: int = 0
 
         byte_count: c_uint16 = read_implicit_field(
diff --git a/sandbox/plc4py/plc4py/protocols/modbus/readwrite/ModbusPDUReadFileRecordRequest.py b/sandbox/plc4py/plc4py/protocols/modbus/readwrite/ModbusPDUReadFileRecordRequest.py
index 932031abad..99850b8f93 100644
--- a/sandbox/plc4py/plc4py/protocols/modbus/readwrite/ModbusPDUReadFileRecordRequest.py
+++ b/sandbox/plc4py/plc4py/protocols/modbus/readwrite/ModbusPDUReadFileRecordRequest.py
@@ -27,6 +27,7 @@ from plc4py.protocols.modbus.readwrite.ModbusPDU import ModbusPDUBuilder
 from plc4py.protocols.modbus.readwrite.ModbusPDUReadFileRecordRequestItem import (
     ModbusPDUReadFileRecordRequestItem,
 )
+from plc4py.spi.generation.WriteBuffer import WriteBuffer
 from typing import List
 import math
 
@@ -35,26 +36,23 @@ import math
 class ModbusPDUReadFileRecordRequest(PlcMessage, ModbusPDU):
     items: List[ModbusPDUReadFileRecordRequestItem]
     # Accessors for discriminator values.
-    error_flag: c_bool = False
+    error_flag: c_bool = c_bool(false)
     function_flag: c_uint8 = 0x14
-    response: c_bool = False
+    response: c_bool = c_bool(false)
 
     def __post_init__(self):
         super().__init__()
 
     def serialize_modbus_pdu_child(self, write_buffer: WriteBuffer):
-        position_aware: PositionAware = write_buffer
-        start_pos: int = position_aware.get_pos()
+        start_pos: int = write_buffer.get_pos()
         write_buffer.push_context("ModbusPDUReadFileRecordRequest")
 
         # Implicit Field (byte_count) (Used for parsing, but its value is not stored as it's implicitly given by the objects content)
-        byte_count: c_uint8 = c_uint8((ARRAY_SIZE_IN_BYTES(self.items())))
-        write_implicit_field(
-            "byteCount", byte_count, write_unsigned_short(write_buffer, 8)
-        )
+        byte_count: c_uint8 = c_uint8(itemsArraySizeInBytes(self.items))
+        write_buffer.write_unsigned_byte(byte_count, logical_name="byteCount")
 
         # Array Field (items)
-        write_complex_type_array_field("items", self.items, write_buffer)
+        write_buffer.write_complex_array(self.items, logical_name="items")
 
         write_buffer.pop_context("ModbusPDUReadFileRecordRequest")
 
@@ -78,8 +76,7 @@ class ModbusPDUReadFileRecordRequest(PlcMessage, ModbusPDU):
     @staticmethod
     def static_parse_builder(read_buffer: ReadBuffer, response: c_bool):
         read_buffer.pull_context("ModbusPDUReadFileRecordRequest")
-        position_aware: PositionAware = read_buffer
-        start_pos: int = position_aware.get_pos()
+        start_pos: int = read_buffer.get_pos()
         cur_pos: int = 0
 
         byte_count: c_uint8 = read_implicit_field(
diff --git a/sandbox/plc4py/plc4py/protocols/modbus/readwrite/ModbusPDUReadFileRecordRequestItem.py b/sandbox/plc4py/plc4py/protocols/modbus/readwrite/ModbusPDUReadFileRecordRequestItem.py
index 61475ad25f..d7b322ba45 100644
--- a/sandbox/plc4py/plc4py/protocols/modbus/readwrite/ModbusPDUReadFileRecordRequestItem.py
+++ b/sandbox/plc4py/plc4py/protocols/modbus/readwrite/ModbusPDUReadFileRecordRequestItem.py
@@ -22,6 +22,7 @@ from dataclasses import dataclass
 from ctypes import c_uint16
 from ctypes import c_uint8
 from plc4py.api.messages.PlcMessage import PlcMessage
+from plc4py.spi.generation.WriteBuffer import WriteBuffer
 import math
 
 
@@ -36,28 +37,25 @@ class ModbusPDUReadFileRecordRequestItem(PlcMessage):
         super().__init__()
 
     def serialize(self, write_buffer: WriteBuffer):
-        position_aware: PositionAware = write_buffer
-        start_pos: int = position_aware.get_pos()
+        start_pos: int = write_buffer.get_pos()
         write_buffer.push_context("ModbusPDUReadFileRecordRequestItem")
 
         # Simple Field (referenceType)
-        write_simple_field(
-            "referenceType", self.reference_type, write_unsigned_short(write_buffer, 8)
+        write_buffer.write_unsigned_byte(
+            self.reference_type, logical_name="referenceType"
         )
 
         # Simple Field (fileNumber)
-        write_simple_field(
-            "fileNumber", self.file_number, write_unsigned_int(write_buffer, 16)
-        )
+        write_buffer.write_unsigned_short(self.file_number, logical_name="fileNumber")
 
         # Simple Field (recordNumber)
-        write_simple_field(
-            "recordNumber", self.record_number, write_unsigned_int(write_buffer, 16)
+        write_buffer.write_unsigned_short(
+            self.record_number, logical_name="recordNumber"
         )
 
         # Simple Field (recordLength)
-        write_simple_field(
-            "recordLength", self.record_length, write_unsigned_int(write_buffer, 16)
+        write_buffer.write_unsigned_short(
+            self.record_length, logical_name="recordLength"
         )
 
         write_buffer.pop_context("ModbusPDUReadFileRecordRequestItem")
@@ -84,14 +82,12 @@ class ModbusPDUReadFileRecordRequestItem(PlcMessage):
         return length_in_bits
 
     def static_parse(read_buffer: ReadBuffer, args):
-        position_aware: PositionAware = read_buffer
         return staticParse(read_buffer)
 
     @staticmethod
     def static_parse_context(read_buffer: ReadBuffer):
         read_buffer.pull_context("ModbusPDUReadFileRecordRequestItem")
-        position_aware: PositionAware = read_buffer
-        start_pos: int = position_aware.get_pos()
+        start_pos: int = read_buffer.get_pos()
         cur_pos: int = 0
 
         reference_type: c_uint8 = read_simple_field(
diff --git a/sandbox/plc4py/plc4py/protocols/modbus/readwrite/ModbusPDUReadFileRecordResponse.py b/sandbox/plc4py/plc4py/protocols/modbus/readwrite/ModbusPDUReadFileRecordResponse.py
index ea7489803a..d00ce01c9c 100644
--- a/sandbox/plc4py/plc4py/protocols/modbus/readwrite/ModbusPDUReadFileRecordResponse.py
+++ b/sandbox/plc4py/plc4py/protocols/modbus/readwrite/ModbusPDUReadFileRecordResponse.py
@@ -27,6 +27,7 @@ from plc4py.protocols.modbus.readwrite.ModbusPDU import ModbusPDUBuilder
 from plc4py.protocols.modbus.readwrite.ModbusPDUReadFileRecordResponseItem import (
     ModbusPDUReadFileRecordResponseItem,
 )
+from plc4py.spi.generation.WriteBuffer import WriteBuffer
 from typing import List
 import math
 
@@ -35,26 +36,23 @@ import math
 class ModbusPDUReadFileRecordResponse(PlcMessage, ModbusPDU):
     items: List[ModbusPDUReadFileRecordResponseItem]
     # Accessors for discriminator values.
-    error_flag: c_bool = False
+    error_flag: c_bool = c_bool(false)
     function_flag: c_uint8 = 0x14
-    response: c_bool = True
+    response: c_bool = c_bool(true)
 
     def __post_init__(self):
         super().__init__()
 
     def serialize_modbus_pdu_child(self, write_buffer: WriteBuffer):
-        position_aware: PositionAware = write_buffer
-        start_pos: int = position_aware.get_pos()
+        start_pos: int = write_buffer.get_pos()
         write_buffer.push_context("ModbusPDUReadFileRecordResponse")
 
         # Implicit Field (byte_count) (Used for parsing, but its value is not stored as it's implicitly given by the objects content)
-        byte_count: c_uint8 = c_uint8((ARRAY_SIZE_IN_BYTES(self.items())))
-        write_implicit_field(
-            "byteCount", byte_count, write_unsigned_short(write_buffer, 8)
-        )
+        byte_count: c_uint8 = c_uint8(itemsArraySizeInBytes(self.items))
+        write_buffer.write_unsigned_byte(byte_count, logical_name="byteCount")
 
         # Array Field (items)
-        write_complex_type_array_field("items", self.items, write_buffer)
+        write_buffer.write_complex_array(self.items, logical_name="items")
 
         write_buffer.pop_context("ModbusPDUReadFileRecordResponse")
 
@@ -78,8 +76,7 @@ class ModbusPDUReadFileRecordResponse(PlcMessage, ModbusPDU):
     @staticmethod
     def static_parse_builder(read_buffer: ReadBuffer, response: c_bool):
         read_buffer.pull_context("ModbusPDUReadFileRecordResponse")
-        position_aware: PositionAware = read_buffer
-        start_pos: int = position_aware.get_pos()
+        start_pos: int = read_buffer.get_pos()
         cur_pos: int = 0
 
         byte_count: c_uint8 = read_implicit_field(
diff --git a/sandbox/plc4py/plc4py/protocols/modbus/readwrite/ModbusPDUReadFileRecordResponseItem.py b/sandbox/plc4py/plc4py/protocols/modbus/readwrite/ModbusPDUReadFileRecordResponseItem.py
index 2bd4936c80..63dc78d3d0 100644
--- a/sandbox/plc4py/plc4py/protocols/modbus/readwrite/ModbusPDUReadFileRecordResponseItem.py
+++ b/sandbox/plc4py/plc4py/protocols/modbus/readwrite/ModbusPDUReadFileRecordResponseItem.py
@@ -20,8 +20,10 @@
 from dataclasses import dataclass
 
 from ctypes import c_byte
+from ctypes import c_int32
 from ctypes import c_uint8
 from plc4py.api.messages.PlcMessage import PlcMessage
+from plc4py.spi.generation.WriteBuffer import WriteBuffer
 from typing import List
 import math
 
@@ -35,23 +37,20 @@ class ModbusPDUReadFileRecordResponseItem(PlcMessage):
         super().__init__()
 
     def serialize(self, write_buffer: WriteBuffer):
-        position_aware: PositionAware = write_buffer
-        start_pos: int = position_aware.get_pos()
+        start_pos: int = write_buffer.get_pos()
         write_buffer.push_context("ModbusPDUReadFileRecordResponseItem")
 
         # Implicit Field (data_length) (Used for parsing, but its value is not stored as it's implicitly given by the objects content)
-        data_length: c_uint8 = c_uint8(((COUNT(self.data())) + (1)))
-        write_implicit_field(
-            "dataLength", data_length, write_unsigned_short(write_buffer, 8)
-        )
+        data_length: c_uint8 = c_uint8(c_uint8(len(self.data))) + c_uint8(c_uint8(1))
+        write_buffer.write_unsigned_byte(data_length, logical_name="dataLength")
 
         # Simple Field (referenceType)
-        write_simple_field(
-            "referenceType", self.reference_type, write_unsigned_short(write_buffer, 8)
+        write_buffer.write_unsigned_byte(
+            self.reference_type, logical_name="referenceType"
         )
 
         # Array Field (data)
-        write_byte_array_field("data", self.data, writeByteArray(write_buffer, 8))
+        write_buffer.write_byte_array(self.data, 8, logical_name="data")
 
         write_buffer.pop_context("ModbusPDUReadFileRecordResponseItem")
 
@@ -75,14 +74,12 @@ class ModbusPDUReadFileRecordResponseItem(PlcMessage):
         return length_in_bits
 
     def static_parse(read_buffer: ReadBuffer, args):
-        position_aware: PositionAware = read_buffer
         return staticParse(read_buffer)
 
     @staticmethod
     def static_parse_context(read_buffer: ReadBuffer):
         read_buffer.pull_context("ModbusPDUReadFileRecordResponseItem")
-        position_aware: PositionAware = read_buffer
-        start_pos: int = position_aware.get_pos()
+        start_pos: int = read_buffer.get_pos()
         cur_pos: int = 0
 
         data_length: c_uint8 = read_implicit_field(
@@ -94,7 +91,7 @@ class ModbusPDUReadFileRecordResponseItem(PlcMessage):
         )
 
         data: List[c_byte] = read_buffer.read_byte_array(
-            "data", int((dataLength) - (1))
+            "data", int(c_int32(dataLength) - c_int32(c_int32(1)))
         )
 
         read_buffer.close_context("ModbusPDUReadFileRecordResponseItem")
diff --git a/sandbox/plc4py/plc4py/protocols/modbus/readwrite/ModbusPDUReadHoldingRegistersRequest.py b/sandbox/plc4py/plc4py/protocols/modbus/readwrite/ModbusPDUReadHoldingRegistersRequest.py
index 31034ea6bd..d647466eb1 100644
--- a/sandbox/plc4py/plc4py/protocols/modbus/readwrite/ModbusPDUReadHoldingRegistersRequest.py
+++ b/sandbox/plc4py/plc4py/protocols/modbus/readwrite/ModbusPDUReadHoldingRegistersRequest.py
@@ -25,6 +25,7 @@ from ctypes import c_uint8
 from plc4py.api.messages.PlcMessage import PlcMessage
 from plc4py.protocols.modbus.readwrite.ModbusPDU import ModbusPDU
 from plc4py.protocols.modbus.readwrite.ModbusPDU import ModbusPDUBuilder
+from plc4py.spi.generation.WriteBuffer import WriteBuffer
 import math
 
 
@@ -33,29 +34,24 @@ class ModbusPDUReadHoldingRegistersRequest(PlcMessage, ModbusPDU):
     starting_address: c_uint16
     quantity: c_uint16
     # Accessors for discriminator values.
-    error_flag: c_bool = False
+    error_flag: c_bool = c_bool(false)
     function_flag: c_uint8 = 0x03
-    response: c_bool = False
+    response: c_bool = c_bool(false)
 
     def __post_init__(self):
         super().__init__()
 
     def serialize_modbus_pdu_child(self, write_buffer: WriteBuffer):
-        position_aware: PositionAware = write_buffer
-        start_pos: int = position_aware.get_pos()
+        start_pos: int = write_buffer.get_pos()
         write_buffer.push_context("ModbusPDUReadHoldingRegistersRequest")
 
         # Simple Field (startingAddress)
-        write_simple_field(
-            "startingAddress",
-            self.starting_address,
-            write_unsigned_int(write_buffer, 16),
+        write_buffer.write_unsigned_short(
+            self.starting_address, logical_name="startingAddress"
         )
 
         # Simple Field (quantity)
-        write_simple_field(
-            "quantity", self.quantity, write_unsigned_int(write_buffer, 16)
-        )
+        write_buffer.write_unsigned_short(self.quantity, logical_name="quantity")
 
         write_buffer.pop_context("ModbusPDUReadHoldingRegistersRequest")
 
@@ -77,8 +73,7 @@ class ModbusPDUReadHoldingRegistersRequest(PlcMessage, ModbusPDU):
     @staticmethod
     def static_parse_builder(read_buffer: ReadBuffer, response: c_bool):
         read_buffer.pull_context("ModbusPDUReadHoldingRegistersRequest")
-        position_aware: PositionAware = read_buffer
-        start_pos: int = position_aware.get_pos()
+        start_pos: int = read_buffer.get_pos()
         cur_pos: int = 0
 
         starting_address: c_uint16 = read_simple_field(
diff --git a/sandbox/plc4py/plc4py/protocols/modbus/readwrite/ModbusPDUReadHoldingRegistersResponse.py b/sandbox/plc4py/plc4py/protocols/modbus/readwrite/ModbusPDUReadHoldingRegistersResponse.py
index a7f2104f90..2f34aa9447 100644
--- a/sandbox/plc4py/plc4py/protocols/modbus/readwrite/ModbusPDUReadHoldingRegistersResponse.py
+++ b/sandbox/plc4py/plc4py/protocols/modbus/readwrite/ModbusPDUReadHoldingRegistersResponse.py
@@ -25,6 +25,7 @@ from ctypes import c_uint8
 from plc4py.api.messages.PlcMessage import PlcMessage
 from plc4py.protocols.modbus.readwrite.ModbusPDU import ModbusPDU
 from plc4py.protocols.modbus.readwrite.ModbusPDU import ModbusPDUBuilder
+from plc4py.spi.generation.WriteBuffer import WriteBuffer
 from typing import List
 import math
 
@@ -33,26 +34,23 @@ import math
 class ModbusPDUReadHoldingRegistersResponse(PlcMessage, ModbusPDU):
     value: List[c_byte]
     # Accessors for discriminator values.
-    error_flag: c_bool = False
+    error_flag: c_bool = c_bool(false)
     function_flag: c_uint8 = 0x03
-    response: c_bool = True
+    response: c_bool = c_bool(true)
 
     def __post_init__(self):
         super().__init__()
 
     def serialize_modbus_pdu_child(self, write_buffer: WriteBuffer):
-        position_aware: PositionAware = write_buffer
-        start_pos: int = position_aware.get_pos()
+        start_pos: int = write_buffer.get_pos()
         write_buffer.push_context("ModbusPDUReadHoldingRegistersResponse")
 
         # Implicit Field (byte_count) (Used for parsing, but its value is not stored as it's implicitly given by the objects content)
-        byte_count: c_uint8 = c_uint8((COUNT(self.value())))
-        write_implicit_field(
-            "byteCount", byte_count, write_unsigned_short(write_buffer, 8)
-        )
+        byte_count: c_uint8 = c_uint8(len(self.value))
+        write_buffer.write_unsigned_byte(byte_count, logical_name="byteCount")
 
         # Array Field (value)
-        write_byte_array_field("value", self.value, writeByteArray(write_buffer, 8))
+        write_buffer.write_byte_array(self.value, 8, logical_name="value")
 
         write_buffer.pop_context("ModbusPDUReadHoldingRegistersResponse")
 
@@ -75,8 +73,7 @@ class ModbusPDUReadHoldingRegistersResponse(PlcMessage, ModbusPDU):
     @staticmethod
     def static_parse_builder(read_buffer: ReadBuffer, response: c_bool):
         read_buffer.pull_context("ModbusPDUReadHoldingRegistersResponse")
-        position_aware: PositionAware = read_buffer
-        start_pos: int = position_aware.get_pos()
+        start_pos: int = read_buffer.get_pos()
         cur_pos: int = 0
 
         byte_count: c_uint8 = read_implicit_field(
diff --git a/sandbox/plc4py/plc4py/protocols/modbus/readwrite/ModbusPDUReadInputRegistersRequest.py b/sandbox/plc4py/plc4py/protocols/modbus/readwrite/ModbusPDUReadInputRegistersRequest.py
index 094b818271..f417da4e02 100644
--- a/sandbox/plc4py/plc4py/protocols/modbus/readwrite/ModbusPDUReadInputRegistersRequest.py
+++ b/sandbox/plc4py/plc4py/protocols/modbus/readwrite/ModbusPDUReadInputRegistersRequest.py
@@ -25,6 +25,7 @@ from ctypes import c_uint8
 from plc4py.api.messages.PlcMessage import PlcMessage
 from plc4py.protocols.modbus.readwrite.ModbusPDU import ModbusPDU
 from plc4py.protocols.modbus.readwrite.ModbusPDU import ModbusPDUBuilder
+from plc4py.spi.generation.WriteBuffer import WriteBuffer
 import math
 
 
@@ -33,29 +34,24 @@ class ModbusPDUReadInputRegistersRequest(PlcMessage, ModbusPDU):
     starting_address: c_uint16
     quantity: c_uint16
     # Accessors for discriminator values.
-    error_flag: c_bool = False
+    error_flag: c_bool = c_bool(false)
     function_flag: c_uint8 = 0x04
-    response: c_bool = False
+    response: c_bool = c_bool(false)
 
     def __post_init__(self):
         super().__init__()
 
     def serialize_modbus_pdu_child(self, write_buffer: WriteBuffer):
-        position_aware: PositionAware = write_buffer
-        start_pos: int = position_aware.get_pos()
+        start_pos: int = write_buffer.get_pos()
         write_buffer.push_context("ModbusPDUReadInputRegistersRequest")
 
         # Simple Field (startingAddress)
-        write_simple_field(
-            "startingAddress",
-            self.starting_address,
-            write_unsigned_int(write_buffer, 16),
+        write_buffer.write_unsigned_short(
+            self.starting_address, logical_name="startingAddress"
         )
 
         # Simple Field (quantity)
-        write_simple_field(
-            "quantity", self.quantity, write_unsigned_int(write_buffer, 16)
-        )
+        write_buffer.write_unsigned_short(self.quantity, logical_name="quantity")
 
         write_buffer.pop_context("ModbusPDUReadInputRegistersRequest")
 
@@ -77,8 +73,7 @@ class ModbusPDUReadInputRegistersRequest(PlcMessage, ModbusPDU):
     @staticmethod
     def static_parse_builder(read_buffer: ReadBuffer, response: c_bool):
         read_buffer.pull_context("ModbusPDUReadInputRegistersRequest")
-        position_aware: PositionAware = read_buffer
-        start_pos: int = position_aware.get_pos()
+        start_pos: int = read_buffer.get_pos()
         cur_pos: int = 0
 
         starting_address: c_uint16 = read_simple_field(
diff --git a/sandbox/plc4py/plc4py/protocols/modbus/readwrite/ModbusPDUReadInputRegistersResponse.py b/sandbox/plc4py/plc4py/protocols/modbus/readwrite/ModbusPDUReadInputRegistersResponse.py
index f075d15ffd..b540e08136 100644
--- a/sandbox/plc4py/plc4py/protocols/modbus/readwrite/ModbusPDUReadInputRegistersResponse.py
+++ b/sandbox/plc4py/plc4py/protocols/modbus/readwrite/ModbusPDUReadInputRegistersResponse.py
@@ -25,6 +25,7 @@ from ctypes import c_uint8
 from plc4py.api.messages.PlcMessage import PlcMessage
 from plc4py.protocols.modbus.readwrite.ModbusPDU import ModbusPDU
 from plc4py.protocols.modbus.readwrite.ModbusPDU import ModbusPDUBuilder
+from plc4py.spi.generation.WriteBuffer import WriteBuffer
 from typing import List
 import math
 
@@ -33,26 +34,23 @@ import math
 class ModbusPDUReadInputRegistersResponse(PlcMessage, ModbusPDU):
     value: List[c_byte]
     # Accessors for discriminator values.
-    error_flag: c_bool = False
+    error_flag: c_bool = c_bool(false)
     function_flag: c_uint8 = 0x04
-    response: c_bool = True
+    response: c_bool = c_bool(true)
 
     def __post_init__(self):
         super().__init__()
 
     def serialize_modbus_pdu_child(self, write_buffer: WriteBuffer):
-        position_aware: PositionAware = write_buffer
-        start_pos: int = position_aware.get_pos()
+        start_pos: int = write_buffer.get_pos()
         write_buffer.push_context("ModbusPDUReadInputRegistersResponse")
 
         # Implicit Field (byte_count) (Used for parsing, but its value is not stored as it's implicitly given by the objects content)
-        byte_count: c_uint8 = c_uint8((COUNT(self.value())))
-        write_implicit_field(
-            "byteCount", byte_count, write_unsigned_short(write_buffer, 8)
-        )
+        byte_count: c_uint8 = c_uint8(len(self.value))
+        write_buffer.write_unsigned_byte(byte_count, logical_name="byteCount")
 
         # Array Field (value)
-        write_byte_array_field("value", self.value, writeByteArray(write_buffer, 8))
+        write_buffer.write_byte_array(self.value, 8, logical_name="value")
 
         write_buffer.pop_context("ModbusPDUReadInputRegistersResponse")
 
@@ -75,8 +73,7 @@ class ModbusPDUReadInputRegistersResponse(PlcMessage, ModbusPDU):
     @staticmethod
     def static_parse_builder(read_buffer: ReadBuffer, response: c_bool):
         read_buffer.pull_context("ModbusPDUReadInputRegistersResponse")
-        position_aware: PositionAware = read_buffer
-        start_pos: int = position_aware.get_pos()
+        start_pos: int = read_buffer.get_pos()
         cur_pos: int = 0
 
         byte_count: c_uint8 = read_implicit_field(
diff --git a/sandbox/plc4py/plc4py/protocols/modbus/readwrite/ModbusPDUReadWriteMultipleHoldingRegistersRequest.py b/sandbox/plc4py/plc4py/protocols/modbus/readwrite/ModbusPDUReadWriteMultipleHoldingRegistersRequest.py
index 8f9663b0fb..ba29db1fd0 100644
--- a/sandbox/plc4py/plc4py/protocols/modbus/readwrite/ModbusPDUReadWriteMultipleHoldingRegistersRequest.py
+++ b/sandbox/plc4py/plc4py/protocols/modbus/readwrite/ModbusPDUReadWriteMultipleHoldingRegistersRequest.py
@@ -26,6 +26,7 @@ from ctypes import c_uint8
 from plc4py.api.messages.PlcMessage import PlcMessage
 from plc4py.protocols.modbus.readwrite.ModbusPDU import ModbusPDU
 from plc4py.protocols.modbus.readwrite.ModbusPDU import ModbusPDUBuilder
+from plc4py.spi.generation.WriteBuffer import WriteBuffer
 from typing import List
 import math
 
@@ -38,50 +39,43 @@ class ModbusPDUReadWriteMultipleHoldingRegistersRequest(PlcMessage, ModbusPDU):
     write_quantity: c_uint16
     value: List[c_byte]
     # Accessors for discriminator values.
-    error_flag: c_bool = False
+    error_flag: c_bool = c_bool(false)
     function_flag: c_uint8 = 0x17
-    response: c_bool = False
+    response: c_bool = c_bool(false)
 
     def __post_init__(self):
         super().__init__()
 
     def serialize_modbus_pdu_child(self, write_buffer: WriteBuffer):
-        position_aware: PositionAware = write_buffer
-        start_pos: int = position_aware.get_pos()
+        start_pos: int = write_buffer.get_pos()
         write_buffer.push_context("ModbusPDUReadWriteMultipleHoldingRegistersRequest")
 
         # Simple Field (readStartingAddress)
-        write_simple_field(
-            "readStartingAddress",
-            self.read_starting_address,
-            write_unsigned_int(write_buffer, 16),
+        write_buffer.write_unsigned_short(
+            self.read_starting_address, logical_name="readStartingAddress"
         )
 
         # Simple Field (readQuantity)
-        write_simple_field(
-            "readQuantity", self.read_quantity, write_unsigned_int(write_buffer, 16)
+        write_buffer.write_unsigned_short(
+            self.read_quantity, logical_name="readQuantity"
         )
 
         # Simple Field (writeStartingAddress)
-        write_simple_field(
-            "writeStartingAddress",
-            self.write_starting_address,
-            write_unsigned_int(write_buffer, 16),
+        write_buffer.write_unsigned_short(
+            self.write_starting_address, logical_name="writeStartingAddress"
         )
 
         # Simple Field (writeQuantity)
-        write_simple_field(
-            "writeQuantity", self.write_quantity, write_unsigned_int(write_buffer, 16)
+        write_buffer.write_unsigned_short(
+            self.write_quantity, logical_name="writeQuantity"
         )
 
         # Implicit Field (byte_count) (Used for parsing, but its value is not stored as it's implicitly given by the objects content)
-        byte_count: c_uint8 = c_uint8((COUNT(self.value())))
-        write_implicit_field(
-            "byteCount", byte_count, write_unsigned_short(write_buffer, 8)
-        )
+        byte_count: c_uint8 = c_uint8(len(self.value))
+        write_buffer.write_unsigned_byte(byte_count, logical_name="byteCount")
 
         # Array Field (value)
-        write_byte_array_field("value", self.value, writeByteArray(write_buffer, 8))
+        write_buffer.write_byte_array(self.value, 8, logical_name="value")
 
         write_buffer.pop_context("ModbusPDUReadWriteMultipleHoldingRegistersRequest")
 
@@ -116,8 +110,7 @@ class ModbusPDUReadWriteMultipleHoldingRegistersRequest(PlcMessage, ModbusPDU):
     @staticmethod
     def static_parse_builder(read_buffer: ReadBuffer, response: c_bool):
         read_buffer.pull_context("ModbusPDUReadWriteMultipleHoldingRegistersRequest")
-        position_aware: PositionAware = read_buffer
-        start_pos: int = position_aware.get_pos()
+        start_pos: int = read_buffer.get_pos()
         cur_pos: int = 0
 
         read_starting_address: c_uint16 = read_simple_field(
diff --git a/sandbox/plc4py/plc4py/protocols/modbus/readwrite/ModbusPDUReadWriteMultipleHoldingRegistersResponse.py b/sandbox/plc4py/plc4py/protocols/modbus/readwrite/ModbusPDUReadWriteMultipleHoldingRegistersResponse.py
index 9a204a0f3c..249c0da70b 100644
--- a/sandbox/plc4py/plc4py/protocols/modbus/readwrite/ModbusPDUReadWriteMultipleHoldingRegistersResponse.py
+++ b/sandbox/plc4py/plc4py/protocols/modbus/readwrite/ModbusPDUReadWriteMultipleHoldingRegistersResponse.py
@@ -25,6 +25,7 @@ from ctypes import c_uint8
 from plc4py.api.messages.PlcMessage import PlcMessage
 from plc4py.protocols.modbus.readwrite.ModbusPDU import ModbusPDU
 from plc4py.protocols.modbus.readwrite.ModbusPDU import ModbusPDUBuilder
+from plc4py.spi.generation.WriteBuffer import WriteBuffer
 from typing import List
 import math
 
@@ -33,26 +34,23 @@ import math
 class ModbusPDUReadWriteMultipleHoldingRegistersResponse(PlcMessage, ModbusPDU):
     value: List[c_byte]
     # Accessors for discriminator values.
-    error_flag: c_bool = False
+    error_flag: c_bool = c_bool(false)
     function_flag: c_uint8 = 0x17
-    response: c_bool = True
+    response: c_bool = c_bool(true)
 
     def __post_init__(self):
         super().__init__()
 
     def serialize_modbus_pdu_child(self, write_buffer: WriteBuffer):
-        position_aware: PositionAware = write_buffer
-        start_pos: int = position_aware.get_pos()
+        start_pos: int = write_buffer.get_pos()
         write_buffer.push_context("ModbusPDUReadWriteMultipleHoldingRegistersResponse")
 
         # Implicit Field (byte_count) (Used for parsing, but its value is not stored as it's implicitly given by the objects content)
-        byte_count: c_uint8 = c_uint8((COUNT(self.value())))
-        write_implicit_field(
-            "byteCount", byte_count, write_unsigned_short(write_buffer, 8)
-        )
+        byte_count: c_uint8 = c_uint8(len(self.value))
+        write_buffer.write_unsigned_byte(byte_count, logical_name="byteCount")
 
         # Array Field (value)
-        write_byte_array_field("value", self.value, writeByteArray(write_buffer, 8))
+        write_buffer.write_byte_array(self.value, 8, logical_name="value")
 
         write_buffer.pop_context("ModbusPDUReadWriteMultipleHoldingRegistersResponse")
 
@@ -75,8 +73,7 @@ class ModbusPDUReadWriteMultipleHoldingRegistersResponse(PlcMessage, ModbusPDU):
     @staticmethod
     def static_parse_builder(read_buffer: ReadBuffer, response: c_bool):
         read_buffer.pull_context("ModbusPDUReadWriteMultipleHoldingRegistersResponse")
-        position_aware: PositionAware = read_buffer
-        start_pos: int = position_aware.get_pos()
+        start_pos: int = read_buffer.get_pos()
         cur_pos: int = 0
 
         byte_count: c_uint8 = read_implicit_field(
diff --git a/sandbox/plc4py/plc4py/protocols/modbus/readwrite/ModbusPDUReportServerIdRequest.py b/sandbox/plc4py/plc4py/protocols/modbus/readwrite/ModbusPDUReportServerIdRequest.py
index b1d7ae4ed6..fd8e32be31 100644
--- a/sandbox/plc4py/plc4py/protocols/modbus/readwrite/ModbusPDUReportServerIdRequest.py
+++ b/sandbox/plc4py/plc4py/protocols/modbus/readwrite/ModbusPDUReportServerIdRequest.py
@@ -24,22 +24,22 @@ from ctypes import c_uint8
 from plc4py.api.messages.PlcMessage import PlcMessage
 from plc4py.protocols.modbus.readwrite.ModbusPDU import ModbusPDU
 from plc4py.protocols.modbus.readwrite.ModbusPDU import ModbusPDUBuilder
+from plc4py.spi.generation.WriteBuffer import WriteBuffer
 import math
 
 
 @dataclass
 class ModbusPDUReportServerIdRequest(PlcMessage, ModbusPDU):
     # Accessors for discriminator values.
-    error_flag: c_bool = False
+    error_flag: c_bool = c_bool(false)
     function_flag: c_uint8 = 0x11
-    response: c_bool = False
+    response: c_bool = c_bool(false)
 
     def __post_init__(self):
         super().__init__()
 
     def serialize_modbus_pdu_child(self, write_buffer: WriteBuffer):
-        position_aware: PositionAware = write_buffer
-        start_pos: int = position_aware.get_pos()
+        start_pos: int = write_buffer.get_pos()
         write_buffer.push_context("ModbusPDUReportServerIdRequest")
 
         write_buffer.pop_context("ModbusPDUReportServerIdRequest")
@@ -56,8 +56,7 @@ class ModbusPDUReportServerIdRequest(PlcMessage, ModbusPDU):
     @staticmethod
     def static_parse_builder(read_buffer: ReadBuffer, response: c_bool):
         read_buffer.pull_context("ModbusPDUReportServerIdRequest")
-        position_aware: PositionAware = read_buffer
-        start_pos: int = position_aware.get_pos()
+        start_pos: int = read_buffer.get_pos()
         cur_pos: int = 0
 
         read_buffer.close_context("ModbusPDUReportServerIdRequest")
diff --git a/sandbox/plc4py/plc4py/protocols/modbus/readwrite/ModbusPDUReportServerIdResponse.py b/sandbox/plc4py/plc4py/protocols/modbus/readwrite/ModbusPDUReportServerIdResponse.py
index 6ecc408459..a2087de9a9 100644
--- a/sandbox/plc4py/plc4py/protocols/modbus/readwrite/ModbusPDUReportServerIdResponse.py
+++ b/sandbox/plc4py/plc4py/protocols/modbus/readwrite/ModbusPDUReportServerIdResponse.py
@@ -25,6 +25,7 @@ from ctypes import c_uint8
 from plc4py.api.messages.PlcMessage import PlcMessage
 from plc4py.protocols.modbus.readwrite.ModbusPDU import ModbusPDU
 from plc4py.protocols.modbus.readwrite.ModbusPDU import ModbusPDUBuilder
+from plc4py.spi.generation.WriteBuffer import WriteBuffer
 from typing import List
 import math
 
@@ -33,26 +34,23 @@ import math
 class ModbusPDUReportServerIdResponse(PlcMessage, ModbusPDU):
     value: List[c_byte]
     # Accessors for discriminator values.
-    error_flag: c_bool = False
+    error_flag: c_bool = c_bool(false)
     function_flag: c_uint8 = 0x11
-    response: c_bool = True
+    response: c_bool = c_bool(true)
 
     def __post_init__(self):
         super().__init__()
 
     def serialize_modbus_pdu_child(self, write_buffer: WriteBuffer):
-        position_aware: PositionAware = write_buffer
-        start_pos: int = position_aware.get_pos()
+        start_pos: int = write_buffer.get_pos()
         write_buffer.push_context("ModbusPDUReportServerIdResponse")
 
         # Implicit Field (byte_count) (Used for parsing, but its value is not stored as it's implicitly given by the objects content)
-        byte_count: c_uint8 = c_uint8((COUNT(self.value())))
-        write_implicit_field(
-            "byteCount", byte_count, write_unsigned_short(write_buffer, 8)
-        )
+        byte_count: c_uint8 = c_uint8(len(self.value))
+        write_buffer.write_unsigned_byte(byte_count, logical_name="byteCount")
 
         # Array Field (value)
-        write_byte_array_field("value", self.value, writeByteArray(write_buffer, 8))
+        write_buffer.write_byte_array(self.value, 8, logical_name="value")
 
         write_buffer.pop_context("ModbusPDUReportServerIdResponse")
 
@@ -75,8 +73,7 @@ class ModbusPDUReportServerIdResponse(PlcMessage, ModbusPDU):
     @staticmethod
     def static_parse_builder(read_buffer: ReadBuffer, response: c_bool):
         read_buffer.pull_context("ModbusPDUReportServerIdResponse")
-        position_aware: PositionAware = read_buffer
-        start_pos: int = position_aware.get_pos()
+        start_pos: int = read_buffer.get_pos()
         cur_pos: int = 0
 
         byte_count: c_uint8 = read_implicit_field(
diff --git a/sandbox/plc4py/plc4py/protocols/modbus/readwrite/ModbusPDUWriteFileRecordRequest.py b/sandbox/plc4py/plc4py/protocols/modbus/readwrite/ModbusPDUWriteFileRecordRequest.py
index 8057d11edd..5b97b0ea39 100644
--- a/sandbox/plc4py/plc4py/protocols/modbus/readwrite/ModbusPDUWriteFileRecordRequest.py
+++ b/sandbox/plc4py/plc4py/protocols/modbus/readwrite/ModbusPDUWriteFileRecordRequest.py
@@ -27,6 +27,7 @@ from plc4py.protocols.modbus.readwrite.ModbusPDU import ModbusPDUBuilder
 from plc4py.protocols.modbus.readwrite.ModbusPDUWriteFileRecordRequestItem import (
     ModbusPDUWriteFileRecordRequestItem,
 )
+from plc4py.spi.generation.WriteBuffer import WriteBuffer
 from typing import List
 import math
 
@@ -35,26 +36,23 @@ import math
 class ModbusPDUWriteFileRecordRequest(PlcMessage, ModbusPDU):
     items: List[ModbusPDUWriteFileRecordRequestItem]
     # Accessors for discriminator values.
-    error_flag: c_bool = False
+    error_flag: c_bool = c_bool(false)
     function_flag: c_uint8 = 0x15
-    response: c_bool = False
+    response: c_bool = c_bool(false)
 
     def __post_init__(self):
         super().__init__()
 
     def serialize_modbus_pdu_child(self, write_buffer: WriteBuffer):
-        position_aware: PositionAware = write_buffer
-        start_pos: int = position_aware.get_pos()
+        start_pos: int = write_buffer.get_pos()
         write_buffer.push_context("ModbusPDUWriteFileRecordRequest")
 
         # Implicit Field (byte_count) (Used for parsing, but its value is not stored as it's implicitly given by the objects content)
-        byte_count: c_uint8 = c_uint8((ARRAY_SIZE_IN_BYTES(self.items())))
-        write_implicit_field(
-            "byteCount", byte_count, write_unsigned_short(write_buffer, 8)
-        )
+        byte_count: c_uint8 = c_uint8(itemsArraySizeInBytes(self.items))
+        write_buffer.write_unsigned_byte(byte_count, logical_name="byteCount")
 
         # Array Field (items)
-        write_complex_type_array_field("items", self.items, write_buffer)
+        write_buffer.write_complex_array(self.items, logical_name="items")
 
         write_buffer.pop_context("ModbusPDUWriteFileRecordRequest")
 
@@ -78,8 +76,7 @@ class ModbusPDUWriteFileRecordRequest(PlcMessage, ModbusPDU):
     @staticmethod
     def static_parse_builder(read_buffer: ReadBuffer, response: c_bool):
         read_buffer.pull_context("ModbusPDUWriteFileRecordRequest")
-        position_aware: PositionAware = read_buffer
-        start_pos: int = position_aware.get_pos()
+        start_pos: int = read_buffer.get_pos()
         cur_pos: int = 0
 
         byte_count: c_uint8 = read_implicit_field(
diff --git a/sandbox/plc4py/plc4py/protocols/modbus/readwrite/ModbusPDUWriteFileRecordRequestItem.py b/sandbox/plc4py/plc4py/protocols/modbus/readwrite/ModbusPDUWriteFileRecordRequestItem.py
index 71c86d9545..9f900ad63d 100644
--- a/sandbox/plc4py/plc4py/protocols/modbus/readwrite/ModbusPDUWriteFileRecordRequestItem.py
+++ b/sandbox/plc4py/plc4py/protocols/modbus/readwrite/ModbusPDUWriteFileRecordRequestItem.py
@@ -20,9 +20,11 @@
 from dataclasses import dataclass
 
 from ctypes import c_byte
+from ctypes import c_int32
 from ctypes import c_uint16
 from ctypes import c_uint8
 from plc4py.api.messages.PlcMessage import PlcMessage
+from plc4py.spi.generation.WriteBuffer import WriteBuffer
 from typing import List
 import math
 
@@ -38,35 +40,30 @@ class ModbusPDUWriteFileRecordRequestItem(PlcMessage):
         super().__init__()
 
     def serialize(self, write_buffer: WriteBuffer):
-        position_aware: PositionAware = write_buffer
-        start_pos: int = position_aware.get_pos()
+        start_pos: int = write_buffer.get_pos()
         write_buffer.push_context("ModbusPDUWriteFileRecordRequestItem")
 
         # Simple Field (referenceType)
-        write_simple_field(
-            "referenceType", self.reference_type, write_unsigned_short(write_buffer, 8)
+        write_buffer.write_unsigned_byte(
+            self.reference_type, logical_name="referenceType"
         )
 
         # Simple Field (fileNumber)
-        write_simple_field(
-            "fileNumber", self.file_number, write_unsigned_int(write_buffer, 16)
-        )
+        write_buffer.write_unsigned_short(self.file_number, logical_name="fileNumber")
 
         # Simple Field (recordNumber)
-        write_simple_field(
-            "recordNumber", self.record_number, write_unsigned_int(write_buffer, 16)
+        write_buffer.write_unsigned_short(
+            self.record_number, logical_name="recordNumber"
         )
 
         # Implicit Field (record_length) (Used for parsing, but its value is not stored as it's implicitly given by the objects content)
-        record_length: c_uint16 = c_uint16(((COUNT(self.record_data())) / (2)))
-        write_implicit_field(
-            "recordLength", record_length, write_unsigned_int(write_buffer, 16)
+        record_length: c_uint16 = c_uint16(c_uint16(len(self.record_data))) / c_uint16(
+            c_uint16(2)
         )
+        write_buffer.write_unsigned_short(record_length, logical_name="recordLength")
 
         # Array Field (recordData)
-        write_byte_array_field(
-            "recordData", self.record_data, writeByteArray(write_buffer, 8)
-        )
+        write_buffer.write_byte_array(self.record_data, 8, logical_name="recordData")
 
         write_buffer.pop_context("ModbusPDUWriteFileRecordRequestItem")
 
@@ -96,14 +93,12 @@ class ModbusPDUWriteFileRecordRequestItem(PlcMessage):
         return length_in_bits
 
     def static_parse(read_buffer: ReadBuffer, args):
-        position_aware: PositionAware = read_buffer
         return staticParse(read_buffer)
 
     @staticmethod
     def static_parse_context(read_buffer: ReadBuffer):
         read_buffer.pull_context("ModbusPDUWriteFileRecordRequestItem")
-        position_aware: PositionAware = read_buffer
-        start_pos: int = position_aware.get_pos()
+        start_pos: int = read_buffer.get_pos()
         cur_pos: int = 0
 
         reference_type: c_uint8 = read_simple_field(
@@ -123,7 +118,7 @@ class ModbusPDUWriteFileRecordRequestItem(PlcMessage):
         )
 
         record_data: List[c_byte] = read_buffer.read_byte_array(
-            "recordData", int((recordLength) * (2))
+            "recordData", int(c_int32(recordLength) * c_int32(c_int32(2)))
         )
 
         read_buffer.close_context("ModbusPDUWriteFileRecordRequestItem")
diff --git a/sandbox/plc4py/plc4py/protocols/modbus/readwrite/ModbusPDUWriteFileRecordResponse.py b/sandbox/plc4py/plc4py/protocols/modbus/readwrite/ModbusPDUWriteFileRecordResponse.py
index 5cea4aa7cf..0b6c5b10fd 100644
--- a/sandbox/plc4py/plc4py/protocols/modbus/readwrite/ModbusPDUWriteFileRecordResponse.py
+++ b/sandbox/plc4py/plc4py/protocols/modbus/readwrite/ModbusPDUWriteFileRecordResponse.py
@@ -27,6 +27,7 @@ from plc4py.protocols.modbus.readwrite.ModbusPDU import ModbusPDUBuilder
 from plc4py.protocols.modbus.readwrite.ModbusPDUWriteFileRecordResponseItem import (
     ModbusPDUWriteFileRecordResponseItem,
 )
+from plc4py.spi.generation.WriteBuffer import WriteBuffer
 from typing import List
 import math
 
@@ -35,26 +36,23 @@ import math
 class ModbusPDUWriteFileRecordResponse(PlcMessage, ModbusPDU):
     items: List[ModbusPDUWriteFileRecordResponseItem]
     # Accessors for discriminator values.
-    error_flag: c_bool = False
+    error_flag: c_bool = c_bool(false)
     function_flag: c_uint8 = 0x15
-    response: c_bool = True
+    response: c_bool = c_bool(true)
 
     def __post_init__(self):
         super().__init__()
 
     def serialize_modbus_pdu_child(self, write_buffer: WriteBuffer):
-        position_aware: PositionAware = write_buffer
-        start_pos: int = position_aware.get_pos()
+        start_pos: int = write_buffer.get_pos()
         write_buffer.push_context("ModbusPDUWriteFileRecordResponse")
 
         # Implicit Field (byte_count) (Used for parsing, but its value is not stored as it's implicitly given by the objects content)
-        byte_count: c_uint8 = c_uint8((ARRAY_SIZE_IN_BYTES(self.items())))
-        write_implicit_field(
-            "byteCount", byte_count, write_unsigned_short(write_buffer, 8)
-        )
+        byte_count: c_uint8 = c_uint8(itemsArraySizeInBytes(self.items))
+        write_buffer.write_unsigned_byte(byte_count, logical_name="byteCount")
 
         # Array Field (items)
-        write_complex_type_array_field("items", self.items, write_buffer)
+        write_buffer.write_complex_array(self.items, logical_name="items")
 
         write_buffer.pop_context("ModbusPDUWriteFileRecordResponse")
 
@@ -78,8 +76,7 @@ class ModbusPDUWriteFileRecordResponse(PlcMessage, ModbusPDU):
     @staticmethod
     def static_parse_builder(read_buffer: ReadBuffer, response: c_bool):
         read_buffer.pull_context("ModbusPDUWriteFileRecordResponse")
-        position_aware: PositionAware = read_buffer
-        start_pos: int = position_aware.get_pos()
+        start_pos: int = read_buffer.get_pos()
         cur_pos: int = 0
 
         byte_count: c_uint8 = read_implicit_field(
diff --git a/sandbox/plc4py/plc4py/protocols/modbus/readwrite/ModbusPDUWriteFileRecordResponseItem.py b/sandbox/plc4py/plc4py/protocols/modbus/readwrite/ModbusPDUWriteFileRecordResponseItem.py
index 89bfafa373..c4f92aefb7 100644
--- a/sandbox/plc4py/plc4py/protocols/modbus/readwrite/ModbusPDUWriteFileRecordResponseItem.py
+++ b/sandbox/plc4py/plc4py/protocols/modbus/readwrite/ModbusPDUWriteFileRecordResponseItem.py
@@ -23,6 +23,7 @@ from ctypes import c_byte
 from ctypes import c_uint16
 from ctypes import c_uint8
 from plc4py.api.messages.PlcMessage import PlcMessage
+from plc4py.spi.generation.WriteBuffer import WriteBuffer
 from typing import List
 import math
 
@@ -38,35 +39,30 @@ class ModbusPDUWriteFileRecordResponseItem(PlcMessage):
         super().__init__()
 
     def serialize(self, write_buffer: WriteBuffer):
-        position_aware: PositionAware = write_buffer
-        start_pos: int = position_aware.get_pos()
+        start_pos: int = write_buffer.get_pos()
         write_buffer.push_context("ModbusPDUWriteFileRecordResponseItem")
 
         # Simple Field (referenceType)
-        write_simple_field(
-            "referenceType", self.reference_type, write_unsigned_short(write_buffer, 8)
+        write_buffer.write_unsigned_byte(
+            self.reference_type, logical_name="referenceType"
         )
 
         # Simple Field (fileNumber)
-        write_simple_field(
-            "fileNumber", self.file_number, write_unsigned_int(write_buffer, 16)
-        )
+        write_buffer.write_unsigned_short(self.file_number, logical_name="fileNumber")
 
         # Simple Field (recordNumber)
-        write_simple_field(
-            "recordNumber", self.record_number, write_unsigned_int(write_buffer, 16)
+        write_buffer.write_unsigned_short(
+            self.record_number, logical_name="recordNumber"
         )
 
         # Implicit Field (record_length) (Used for parsing, but its value is not stored as it's implicitly given by the objects content)
-        record_length: c_uint16 = c_uint16(((COUNT(self.record_data())) / (2)))
-        write_implicit_field(
-            "recordLength", record_length, write_unsigned_int(write_buffer, 16)
+        record_length: c_uint16 = c_uint16(c_uint16(len(self.record_data))) / c_uint16(
+            c_uint16(2)
         )
+        write_buffer.write_unsigned_short(record_length, logical_name="recordLength")
 
         # Array Field (recordData)
-        write_byte_array_field(
-            "recordData", self.record_data, writeByteArray(write_buffer, 8)
-        )
+        write_buffer.write_byte_array(self.record_data, 8, logical_name="recordData")
 
         write_buffer.pop_context("ModbusPDUWriteFileRecordResponseItem")
 
@@ -96,14 +92,12 @@ class ModbusPDUWriteFileRecordResponseItem(PlcMessage):
         return length_in_bits
 
     def static_parse(read_buffer: ReadBuffer, args):
-        position_aware: PositionAware = read_buffer
         return staticParse(read_buffer)
 
     @staticmethod
     def static_parse_context(read_buffer: ReadBuffer):
         read_buffer.pull_context("ModbusPDUWriteFileRecordResponseItem")
-        position_aware: PositionAware = read_buffer
-        start_pos: int = position_aware.get_pos()
+        start_pos: int = read_buffer.get_pos()
         cur_pos: int = 0
 
         reference_type: c_uint8 = read_simple_field(
diff --git a/sandbox/plc4py/plc4py/protocols/modbus/readwrite/ModbusPDUWriteMultipleCoilsRequest.py b/sandbox/plc4py/plc4py/protocols/modbus/readwrite/ModbusPDUWriteMultipleCoilsRequest.py
index e66aa21caa..a57653364b 100644
--- a/sandbox/plc4py/plc4py/protocols/modbus/readwrite/ModbusPDUWriteMultipleCoilsRequest.py
+++ b/sandbox/plc4py/plc4py/protocols/modbus/readwrite/ModbusPDUWriteMultipleCoilsRequest.py
@@ -26,6 +26,7 @@ from ctypes import c_uint8
 from plc4py.api.messages.PlcMessage import PlcMessage
 from plc4py.protocols.modbus.readwrite.ModbusPDU import ModbusPDU
 from plc4py.protocols.modbus.readwrite.ModbusPDU import ModbusPDUBuilder
+from plc4py.spi.generation.WriteBuffer import WriteBuffer
 from typing import List
 import math
 
@@ -36,38 +37,31 @@ class ModbusPDUWriteMultipleCoilsRequest(PlcMessage, ModbusPDU):
     quantity: c_uint16
     value: List[c_byte]
     # Accessors for discriminator values.
-    error_flag: c_bool = False
+    error_flag: c_bool = c_bool(false)
     function_flag: c_uint8 = 0x0F
-    response: c_bool = False
+    response: c_bool = c_bool(false)
 
     def __post_init__(self):
         super().__init__()
 
     def serialize_modbus_pdu_child(self, write_buffer: WriteBuffer):
-        position_aware: PositionAware = write_buffer
-        start_pos: int = position_aware.get_pos()
+        start_pos: int = write_buffer.get_pos()
         write_buffer.push_context("ModbusPDUWriteMultipleCoilsRequest")
 
         # Simple Field (startingAddress)
-        write_simple_field(
-            "startingAddress",
-            self.starting_address,
-            write_unsigned_int(write_buffer, 16),
+        write_buffer.write_unsigned_short(
+            self.starting_address, logical_name="startingAddress"
         )
 
         # Simple Field (quantity)
-        write_simple_field(
-            "quantity", self.quantity, write_unsigned_int(write_buffer, 16)
-        )
+        write_buffer.write_unsigned_short(self.quantity, logical_name="quantity")
 
         # Implicit Field (byte_count) (Used for parsing, but its value is not stored as it's implicitly given by the objects content)
-        byte_count: c_uint8 = c_uint8((COUNT(self.value())))
-        write_implicit_field(
-            "byteCount", byte_count, write_unsigned_short(write_buffer, 8)
-        )
+        byte_count: c_uint8 = c_uint8(len(self.value))
+        write_buffer.write_unsigned_byte(byte_count, logical_name="byteCount")
 
         # Array Field (value)
-        write_byte_array_field("value", self.value, writeByteArray(write_buffer, 8))
+        write_buffer.write_byte_array(self.value, 8, logical_name="value")
 
         write_buffer.pop_context("ModbusPDUWriteMultipleCoilsRequest")
 
@@ -96,8 +90,7 @@ class ModbusPDUWriteMultipleCoilsRequest(PlcMessage, ModbusPDU):
     @staticmethod
     def static_parse_builder(read_buffer: ReadBuffer, response: c_bool):
         read_buffer.pull_context("ModbusPDUWriteMultipleCoilsRequest")
-        position_aware: PositionAware = read_buffer
-        start_pos: int = position_aware.get_pos()
+        start_pos: int = read_buffer.get_pos()
         cur_pos: int = 0
 
         starting_address: c_uint16 = read_simple_field(
diff --git a/sandbox/plc4py/plc4py/protocols/modbus/readwrite/ModbusPDUWriteMultipleCoilsResponse.py b/sandbox/plc4py/plc4py/protocols/modbus/readwrite/ModbusPDUWriteMultipleCoilsResponse.py
index 97c057b687..9575571c0a 100644
--- a/sandbox/plc4py/plc4py/protocols/modbus/readwrite/ModbusPDUWriteMultipleCoilsResponse.py
+++ b/sandbox/plc4py/plc4py/protocols/modbus/readwrite/ModbusPDUWriteMultipleCoilsResponse.py
@@ -25,6 +25,7 @@ from ctypes import c_uint8
 from plc4py.api.messages.PlcMessage import PlcMessage
 from plc4py.protocols.modbus.readwrite.ModbusPDU import ModbusPDU
 from plc4py.protocols.modbus.readwrite.ModbusPDU import ModbusPDUBuilder
+from plc4py.spi.generation.WriteBuffer import WriteBuffer
 import math
 
 
@@ -33,29 +34,24 @@ class ModbusPDUWriteMultipleCoilsResponse(PlcMessage, ModbusPDU):
     starting_address: c_uint16
     quantity: c_uint16
     # Accessors for discriminator values.
-    error_flag: c_bool = False
+    error_flag: c_bool = c_bool(false)
     function_flag: c_uint8 = 0x0F
-    response: c_bool = True
+    response: c_bool = c_bool(true)
 
     def __post_init__(self):
         super().__init__()
 
     def serialize_modbus_pdu_child(self, write_buffer: WriteBuffer):
-        position_aware: PositionAware = write_buffer
-        start_pos: int = position_aware.get_pos()
+        start_pos: int = write_buffer.get_pos()
         write_buffer.push_context("ModbusPDUWriteMultipleCoilsResponse")
 
         # Simple Field (startingAddress)
-        write_simple_field(
-            "startingAddress",
-            self.starting_address,
-            write_unsigned_int(write_buffer, 16),
+        write_buffer.write_unsigned_short(
+            self.starting_address, logical_name="startingAddress"
         )
 
         # Simple Field (quantity)
-        write_simple_field(
-            "quantity", self.quantity, write_unsigned_int(write_buffer, 16)
-        )
+        write_buffer.write_unsigned_short(self.quantity, logical_name="quantity")
 
         write_buffer.pop_context("ModbusPDUWriteMultipleCoilsResponse")
 
@@ -77,8 +73,7 @@ class ModbusPDUWriteMultipleCoilsResponse(PlcMessage, ModbusPDU):
     @staticmethod
     def static_parse_builder(read_buffer: ReadBuffer, response: c_bool):
         read_buffer.pull_context("ModbusPDUWriteMultipleCoilsResponse")
-        position_aware: PositionAware = read_buffer
-        start_pos: int = position_aware.get_pos()
+        start_pos: int = read_buffer.get_pos()
         cur_pos: int = 0
 
         starting_address: c_uint16 = read_simple_field(
diff --git a/sandbox/plc4py/plc4py/protocols/modbus/readwrite/ModbusPDUWriteMultipleHoldingRegistersRequest.py b/sandbox/plc4py/plc4py/protocols/modbus/readwrite/ModbusPDUWriteMultipleHoldingRegistersRequest.py
index 22f71b303c..d8c827ce03 100644
--- a/sandbox/plc4py/plc4py/protocols/modbus/readwrite/ModbusPDUWriteMultipleHoldingRegistersRequest.py
+++ b/sandbox/plc4py/plc4py/protocols/modbus/readwrite/ModbusPDUWriteMultipleHoldingRegistersRequest.py
@@ -26,6 +26,7 @@ from ctypes import c_uint8
 from plc4py.api.messages.PlcMessage import PlcMessage
 from plc4py.protocols.modbus.readwrite.ModbusPDU import ModbusPDU
 from plc4py.protocols.modbus.readwrite.ModbusPDU import ModbusPDUBuilder
+from plc4py.spi.generation.WriteBuffer import WriteBuffer
 from typing import List
 import math
 
@@ -36,38 +37,31 @@ class ModbusPDUWriteMultipleHoldingRegistersRequest(PlcMessage, ModbusPDU):
     quantity: c_uint16
     value: List[c_byte]
     # Accessors for discriminator values.
-    error_flag: c_bool = False
+    error_flag: c_bool = c_bool(false)
     function_flag: c_uint8 = 0x10
-    response: c_bool = False
+    response: c_bool = c_bool(false)
 
     def __post_init__(self):
         super().__init__()
 
     def serialize_modbus_pdu_child(self, write_buffer: WriteBuffer):
-        position_aware: PositionAware = write_buffer
-        start_pos: int = position_aware.get_pos()
+        start_pos: int = write_buffer.get_pos()
         write_buffer.push_context("ModbusPDUWriteMultipleHoldingRegistersRequest")
 
         # Simple Field (startingAddress)
-        write_simple_field(
-            "startingAddress",
-            self.starting_address,
-            write_unsigned_int(write_buffer, 16),
+        write_buffer.write_unsigned_short(
+            self.starting_address, logical_name="startingAddress"
         )
 
         # Simple Field (quantity)
-        write_simple_field(
-            "quantity", self.quantity, write_unsigned_int(write_buffer, 16)
-        )
+        write_buffer.write_unsigned_short(self.quantity, logical_name="quantity")
 
         # Implicit Field (byte_count) (Used for parsing, but its value is not stored as it's implicitly given by the objects content)
-        byte_count: c_uint8 = c_uint8((COUNT(self.value())))
-        write_implicit_field(
-            "byteCount", byte_count, write_unsigned_short(write_buffer, 8)
-        )
+        byte_count: c_uint8 = c_uint8(len(self.value))
+        write_buffer.write_unsigned_byte(byte_count, logical_name="byteCount")
 
         # Array Field (value)
-        write_byte_array_field("value", self.value, writeByteArray(write_buffer, 8))
+        write_buffer.write_byte_array(self.value, 8, logical_name="value")
 
         write_buffer.pop_context("ModbusPDUWriteMultipleHoldingRegistersRequest")
 
@@ -96,8 +90,7 @@ class ModbusPDUWriteMultipleHoldingRegistersRequest(PlcMessage, ModbusPDU):
     @staticmethod
     def static_parse_builder(read_buffer: ReadBuffer, response: c_bool):
         read_buffer.pull_context("ModbusPDUWriteMultipleHoldingRegistersRequest")
-        position_aware: PositionAware = read_buffer
-        start_pos: int = position_aware.get_pos()
+        start_pos: int = read_buffer.get_pos()
         cur_pos: int = 0
 
         starting_address: c_uint16 = read_simple_field(
diff --git a/sandbox/plc4py/plc4py/protocols/modbus/readwrite/ModbusPDUWriteMultipleHoldingRegistersResponse.py b/sandbox/plc4py/plc4py/protocols/modbus/readwrite/ModbusPDUWriteMultipleHoldingRegistersResponse.py
index 2a3d442adb..4ea61b0482 100644
--- a/sandbox/plc4py/plc4py/protocols/modbus/readwrite/ModbusPDUWriteMultipleHoldingRegistersResponse.py
+++ b/sandbox/plc4py/plc4py/protocols/modbus/readwrite/ModbusPDUWriteMultipleHoldingRegistersResponse.py
@@ -25,6 +25,7 @@ from ctypes import c_uint8
 from plc4py.api.messages.PlcMessage import PlcMessage
 from plc4py.protocols.modbus.readwrite.ModbusPDU import ModbusPDU
 from plc4py.protocols.modbus.readwrite.ModbusPDU import ModbusPDUBuilder
+from plc4py.spi.generation.WriteBuffer import WriteBuffer
 import math
 
 
@@ -33,29 +34,24 @@ class ModbusPDUWriteMultipleHoldingRegistersResponse(PlcMessage, ModbusPDU):
     starting_address: c_uint16
     quantity: c_uint16
     # Accessors for discriminator values.
-    error_flag: c_bool = False
+    error_flag: c_bool = c_bool(false)
     function_flag: c_uint8 = 0x10
-    response: c_bool = True
+    response: c_bool = c_bool(true)
 
     def __post_init__(self):
         super().__init__()
 
     def serialize_modbus_pdu_child(self, write_buffer: WriteBuffer):
-        position_aware: PositionAware = write_buffer
-        start_pos: int = position_aware.get_pos()
+        start_pos: int = write_buffer.get_pos()
         write_buffer.push_context("ModbusPDUWriteMultipleHoldingRegistersResponse")
 
         # Simple Field (startingAddress)
-        write_simple_field(
-            "startingAddress",
-            self.starting_address,
-            write_unsigned_int(write_buffer, 16),
+        write_buffer.write_unsigned_short(
+            self.starting_address, logical_name="startingAddress"
         )
 
         # Simple Field (quantity)
-        write_simple_field(
-            "quantity", self.quantity, write_unsigned_int(write_buffer, 16)
-        )
+        write_buffer.write_unsigned_short(self.quantity, logical_name="quantity")
 
         write_buffer.pop_context("ModbusPDUWriteMultipleHoldingRegistersResponse")
 
@@ -77,8 +73,7 @@ class ModbusPDUWriteMultipleHoldingRegistersResponse(PlcMessage, ModbusPDU):
     @staticmethod
     def static_parse_builder(read_buffer: ReadBuffer, response: c_bool):
         read_buffer.pull_context("ModbusPDUWriteMultipleHoldingRegistersResponse")
-        position_aware: PositionAware = read_buffer
-        start_pos: int = position_aware.get_pos()
+        start_pos: int = read_buffer.get_pos()
         cur_pos: int = 0
 
         starting_address: c_uint16 = read_simple_field(
diff --git a/sandbox/plc4py/plc4py/protocols/modbus/readwrite/ModbusPDUWriteSingleCoilRequest.py b/sandbox/plc4py/plc4py/protocols/modbus/readwrite/ModbusPDUWriteSingleCoilRequest.py
index ecd89d263f..8ce893a370 100644
--- a/sandbox/plc4py/plc4py/protocols/modbus/readwrite/ModbusPDUWriteSingleCoilRequest.py
+++ b/sandbox/plc4py/plc4py/protocols/modbus/readwrite/ModbusPDUWriteSingleCoilRequest.py
@@ -25,6 +25,7 @@ from ctypes import c_uint8
 from plc4py.api.messages.PlcMessage import PlcMessage
 from plc4py.protocols.modbus.readwrite.ModbusPDU import ModbusPDU
 from plc4py.protocols.modbus.readwrite.ModbusPDU import ModbusPDUBuilder
+from plc4py.spi.generation.WriteBuffer import WriteBuffer
 import math
 
 
@@ -33,25 +34,22 @@ class ModbusPDUWriteSingleCoilRequest(PlcMessage, ModbusPDU):
     address: c_uint16
     value: c_uint16
     # Accessors for discriminator values.
-    error_flag: c_bool = False
+    error_flag: c_bool = c_bool(false)
     function_flag: c_uint8 = 0x05
-    response: c_bool = False
+    response: c_bool = c_bool(false)
 
     def __post_init__(self):
         super().__init__()
 
     def serialize_modbus_pdu_child(self, write_buffer: WriteBuffer):
-        position_aware: PositionAware = write_buffer
-        start_pos: int = position_aware.get_pos()
+        start_pos: int = write_buffer.get_pos()
         write_buffer.push_context("ModbusPDUWriteSingleCoilRequest")
 
         # Simple Field (address)
-        write_simple_field(
-            "address", self.address, write_unsigned_int(write_buffer, 16)
-        )
+        write_buffer.write_unsigned_short(self.address, logical_name="address")
 
         # Simple Field (value)
-        write_simple_field("value", self.value, write_unsigned_int(write_buffer, 16))
+        write_buffer.write_unsigned_short(self.value, logical_name="value")
 
         write_buffer.pop_context("ModbusPDUWriteSingleCoilRequest")
 
@@ -73,8 +71,7 @@ class ModbusPDUWriteSingleCoilRequest(PlcMessage, ModbusPDU):
     @staticmethod
     def static_parse_builder(read_buffer: ReadBuffer, response: c_bool):
         read_buffer.pull_context("ModbusPDUWriteSingleCoilRequest")
-        position_aware: PositionAware = read_buffer
-        start_pos: int = position_aware.get_pos()
+        start_pos: int = read_buffer.get_pos()
         cur_pos: int = 0
 
         address: c_uint16 = read_simple_field(
diff --git a/sandbox/plc4py/plc4py/protocols/modbus/readwrite/ModbusPDUWriteSingleCoilResponse.py b/sandbox/plc4py/plc4py/protocols/modbus/readwrite/ModbusPDUWriteSingleCoilResponse.py
index 530937d2c3..d7d8728e1e 100644
--- a/sandbox/plc4py/plc4py/protocols/modbus/readwrite/ModbusPDUWriteSingleCoilResponse.py
+++ b/sandbox/plc4py/plc4py/protocols/modbus/readwrite/ModbusPDUWriteSingleCoilResponse.py
@@ -25,6 +25,7 @@ from ctypes import c_uint8
 from plc4py.api.messages.PlcMessage import PlcMessage
 from plc4py.protocols.modbus.readwrite.ModbusPDU import ModbusPDU
 from plc4py.protocols.modbus.readwrite.ModbusPDU import ModbusPDUBuilder
+from plc4py.spi.generation.WriteBuffer import WriteBuffer
 import math
 
 
@@ -33,25 +34,22 @@ class ModbusPDUWriteSingleCoilResponse(PlcMessage, ModbusPDU):
     address: c_uint16
     value: c_uint16
     # Accessors for discriminator values.
-    error_flag: c_bool = False
+    error_flag: c_bool = c_bool(false)
     function_flag: c_uint8 = 0x05
-    response: c_bool = True
+    response: c_bool = c_bool(true)
 
     def __post_init__(self):
         super().__init__()
 
     def serialize_modbus_pdu_child(self, write_buffer: WriteBuffer):
-        position_aware: PositionAware = write_buffer
-        start_pos: int = position_aware.get_pos()
+        start_pos: int = write_buffer.get_pos()
         write_buffer.push_context("ModbusPDUWriteSingleCoilResponse")
 
         # Simple Field (address)
-        write_simple_field(
-            "address", self.address, write_unsigned_int(write_buffer, 16)
-        )
+        write_buffer.write_unsigned_short(self.address, logical_name="address")
 
         # Simple Field (value)
-        write_simple_field("value", self.value, write_unsigned_int(write_buffer, 16))
+        write_buffer.write_unsigned_short(self.value, logical_name="value")
 
         write_buffer.pop_context("ModbusPDUWriteSingleCoilResponse")
 
@@ -73,8 +71,7 @@ class ModbusPDUWriteSingleCoilResponse(PlcMessage, ModbusPDU):
     @staticmethod
     def static_parse_builder(read_buffer: ReadBuffer, response: c_bool):
         read_buffer.pull_context("ModbusPDUWriteSingleCoilResponse")
-        position_aware: PositionAware = read_buffer
-        start_pos: int = position_aware.get_pos()
+        start_pos: int = read_buffer.get_pos()
         cur_pos: int = 0
 
         address: c_uint16 = read_simple_field(
diff --git a/sandbox/plc4py/plc4py/protocols/modbus/readwrite/ModbusPDUWriteSingleRegisterRequest.py b/sandbox/plc4py/plc4py/protocols/modbus/readwrite/ModbusPDUWriteSingleRegisterRequest.py
index c5b747a557..c6e6276f39 100644
--- a/sandbox/plc4py/plc4py/protocols/modbus/readwrite/ModbusPDUWriteSingleRegisterRequest.py
+++ b/sandbox/plc4py/plc4py/protocols/modbus/readwrite/ModbusPDUWriteSingleRegisterRequest.py
@@ -25,6 +25,7 @@ from ctypes import c_uint8
 from plc4py.api.messages.PlcMessage import PlcMessage
 from plc4py.protocols.modbus.readwrite.ModbusPDU import ModbusPDU
 from plc4py.protocols.modbus.readwrite.ModbusPDU import ModbusPDUBuilder
+from plc4py.spi.generation.WriteBuffer import WriteBuffer
 import math
 
 
@@ -33,25 +34,22 @@ class ModbusPDUWriteSingleRegisterRequest(PlcMessage, ModbusPDU):
     address: c_uint16
     value: c_uint16
     # Accessors for discriminator values.
-    error_flag: c_bool = False
+    error_flag: c_bool = c_bool(false)
     function_flag: c_uint8 = 0x06
-    response: c_bool = False
+    response: c_bool = c_bool(false)
 
     def __post_init__(self):
         super().__init__()
 
     def serialize_modbus_pdu_child(self, write_buffer: WriteBuffer):
-        position_aware: PositionAware = write_buffer
-        start_pos: int = position_aware.get_pos()
+        start_pos: int = write_buffer.get_pos()
         write_buffer.push_context("ModbusPDUWriteSingleRegisterRequest")
 
         # Simple Field (address)
-        write_simple_field(
-            "address", self.address, write_unsigned_int(write_buffer, 16)
-        )
+        write_buffer.write_unsigned_short(self.address, logical_name="address")
 
         # Simple Field (value)
-        write_simple_field("value", self.value, write_unsigned_int(write_buffer, 16))
+        write_buffer.write_unsigned_short(self.value, logical_name="value")
 
         write_buffer.pop_context("ModbusPDUWriteSingleRegisterRequest")
 
@@ -73,8 +71,7 @@ class ModbusPDUWriteSingleRegisterRequest(PlcMessage, ModbusPDU):
     @staticmethod
     def static_parse_builder(read_buffer: ReadBuffer, response: c_bool):
         read_buffer.pull_context("ModbusPDUWriteSingleRegisterRequest")
-        position_aware: PositionAware = read_buffer
-        start_pos: int = position_aware.get_pos()
+        start_pos: int = read_buffer.get_pos()
         cur_pos: int = 0
 
         address: c_uint16 = read_simple_field(
diff --git a/sandbox/plc4py/plc4py/protocols/modbus/readwrite/ModbusPDUWriteSingleRegisterResponse.py b/sandbox/plc4py/plc4py/protocols/modbus/readwrite/ModbusPDUWriteSingleRegisterResponse.py
index a390983f66..2a9adefeed 100644
--- a/sandbox/plc4py/plc4py/protocols/modbus/readwrite/ModbusPDUWriteSingleRegisterResponse.py
+++ b/sandbox/plc4py/plc4py/protocols/modbus/readwrite/ModbusPDUWriteSingleRegisterResponse.py
@@ -25,6 +25,7 @@ from ctypes import c_uint8
 from plc4py.api.messages.PlcMessage import PlcMessage
 from plc4py.protocols.modbus.readwrite.ModbusPDU import ModbusPDU
 from plc4py.protocols.modbus.readwrite.ModbusPDU import ModbusPDUBuilder
+from plc4py.spi.generation.WriteBuffer import WriteBuffer
 import math
 
 
@@ -33,25 +34,22 @@ class ModbusPDUWriteSingleRegisterResponse(PlcMessage, ModbusPDU):
     address: c_uint16
     value: c_uint16
     # Accessors for discriminator values.
-    error_flag: c_bool = False
+    error_flag: c_bool = c_bool(false)
     function_flag: c_uint8 = 0x06
-    response: c_bool = True
+    response: c_bool = c_bool(true)
 
     def __post_init__(self):
         super().__init__()
 
     def serialize_modbus_pdu_child(self, write_buffer: WriteBuffer):
-        position_aware: PositionAware = write_buffer
-        start_pos: int = position_aware.get_pos()
+        start_pos: int = write_buffer.get_pos()
         write_buffer.push_context("ModbusPDUWriteSingleRegisterResponse")
 
         # Simple Field (address)
-        write_simple_field(
-            "address", self.address, write_unsigned_int(write_buffer, 16)
-        )
+        write_buffer.write_unsigned_short(self.address, logical_name="address")
 
         # Simple Field (value)
-        write_simple_field("value", self.value, write_unsigned_int(write_buffer, 16))
+        write_buffer.write_unsigned_short(self.value, logical_name="value")
 
         write_buffer.pop_context("ModbusPDUWriteSingleRegisterResponse")
 
@@ -73,8 +71,7 @@ class ModbusPDUWriteSingleRegisterResponse(PlcMessage, ModbusPDU):
     @staticmethod
     def static_parse_builder(read_buffer: ReadBuffer, response: c_bool):
         read_buffer.pull_context("ModbusPDUWriteSingleRegisterResponse")
-        position_aware: PositionAware = read_buffer
-        start_pos: int = position_aware.get_pos()
+        start_pos: int = read_buffer.get_pos()
         cur_pos: int = 0
 
         address: c_uint16 = read_simple_field(
diff --git a/sandbox/plc4py/plc4py/protocols/modbus/readwrite/ModbusRtuADU.py b/sandbox/plc4py/plc4py/protocols/modbus/readwrite/ModbusRtuADU.py
index 1c4cab2ad6..9386f1e799 100644
--- a/sandbox/plc4py/plc4py/protocols/modbus/readwrite/ModbusRtuADU.py
+++ b/sandbox/plc4py/plc4py/protocols/modbus/readwrite/ModbusRtuADU.py
@@ -27,6 +27,7 @@ from plc4py.protocols.modbus.readwrite.DriverType import DriverType
 from plc4py.protocols.modbus.readwrite.ModbusADU import ModbusADU
 from plc4py.protocols.modbus.readwrite.ModbusADU import ModbusADUBuilder
 from plc4py.protocols.modbus.readwrite.ModbusPDU import ModbusPDU
+from plc4py.spi.generation.WriteBuffer import WriteBuffer
 import math
 
 
@@ -37,37 +38,26 @@ class ModbusRtuADU(PlcMessage, ModbusADU):
     # Arguments.
     response: c_bool
     # Accessors for discriminator values.
-    driver_type: DriverType = DriverType.MODBUS_RTU
+    driver_type: DriverType = DriverType.get_modbu_s__rtu()
 
     def __post_init__(self):
         super().__init__(self.response)
 
     def serialize_modbus_adu_child(self, write_buffer: WriteBuffer):
-        position_aware: PositionAware = write_buffer
-        start_pos: int = position_aware.get_pos()
+        start_pos: int = write_buffer.get_pos()
         write_buffer.push_context("ModbusRtuADU")
 
         # Simple Field (address)
-        write_simple_field(
-            "address",
-            self.address,
-            write_unsigned_short(write_buffer, 8),
-            WithOption.WithByteOrder(ByteOrder.BIG_ENDIAN),
-        )
+        write_buffer.write_unsigned_byte(self.address, logical_name="address")
 
         # Simple Field (pdu)
-        write_simple_field(
-            "pdu",
-            self.pdu,
-            DataWriterComplexDefault(write_buffer),
-            WithOption.WithByteOrder(ByteOrder.BIG_ENDIAN),
+        write_buffer.DataWriterComplexDefault(write_buffer)(
+            self.pdu, logical_name="pdu"
         )
 
         # Checksum Field (checksum) (Calculated)
-        write_checksum_field(
-            "crc",
-            c_uint16(modbus.readwrite.utils.StaticHelper.rtuCrcCheck(address, pdu)),
-            write_unsigned_int(write_buffer, 16),
+        write_buffer.write_unsigned_short(
+            c_uint16(rtu_crc_check(address, pdu)), logical_name="crc"
         )
 
         write_buffer.pop_context("ModbusRtuADU")
@@ -95,14 +85,13 @@ class ModbusRtuADU(PlcMessage, ModbusADU):
         read_buffer: ReadBuffer, driver_type: DriverType, response: c_bool
     ):
         read_buffer.pull_context("ModbusRtuADU")
-        position_aware: PositionAware = read_buffer
-        start_pos: int = position_aware.get_pos()
+        start_pos: int = read_buffer.get_pos()
         cur_pos: int = 0
 
         address: c_uint8 = read_simple_field(
             "address",
             read_unsigned_short(read_buffer, 8),
-            WithOption.WithByteOrder(ByteOrder.BIG_ENDIAN),
+            WithOption.WithByteOrder(get_bi_g__endian()),
         )
 
         pdu: ModbusPDU = read_simple_field(
@@ -110,14 +99,14 @@ class ModbusRtuADU(PlcMessage, ModbusADU):
             DataReaderComplexDefault(
                 ModbusPDU.static_parse(read_buffer, c_bool(response)), read_buffer
             ),
-            WithOption.WithByteOrder(ByteOrder.BIG_ENDIAN),
+            WithOption.WithByteOrder(get_bi_g__endian()),
         )
 
         crc: c_uint16 = read_checksum_field(
             "crc",
             read_unsigned_int(read_buffer, 16),
-            (c_uint16)(modbus.readwrite.utils.StaticHelper.rtuCrcCheck(address, pdu)),
-            WithOption.WithByteOrder(ByteOrder.BIG_ENDIAN),
+            (c_uint16)(rtu_crc_check(address, pdu)),
+            WithOption.WithByteOrder(get_bi_g__endian()),
         )
 
         read_buffer.close_context("ModbusRtuADU")
diff --git a/sandbox/plc4py/plc4py/protocols/modbus/readwrite/ModbusTcpADU.py b/sandbox/plc4py/plc4py/protocols/modbus/readwrite/ModbusTcpADU.py
index 5fb53a9d18..b8016d45cb 100644
--- a/sandbox/plc4py/plc4py/protocols/modbus/readwrite/ModbusTcpADU.py
+++ b/sandbox/plc4py/plc4py/protocols/modbus/readwrite/ModbusTcpADU.py
@@ -27,6 +27,7 @@ from plc4py.protocols.modbus.readwrite.DriverType import DriverType
 from plc4py.protocols.modbus.readwrite.ModbusADU import ModbusADU
 from plc4py.protocols.modbus.readwrite.ModbusADU import ModbusADUBuilder
 from plc4py.protocols.modbus.readwrite.ModbusPDU import ModbusPDU
+from plc4py.spi.generation.WriteBuffer import WriteBuffer
 import math
 
 
@@ -39,49 +40,39 @@ class ModbusTcpADU(PlcMessage, ModbusADU):
     response: c_bool
     PROTOCOLIDENTIFIER: c_uint16 = 0x0000
     # Accessors for discriminator values.
-    driver_type: DriverType = DriverType.MODBUS_TCP
+    driver_type: DriverType = DriverType.get_modbu_s__tcp()
 
     def __post_init__(self):
         super().__init__(self.response)
 
     def serialize_modbus_adu_child(self, write_buffer: WriteBuffer):
-        position_aware: PositionAware = write_buffer
-        start_pos: int = position_aware.get_pos()
+        start_pos: int = write_buffer.get_pos()
         write_buffer.push_context("ModbusTcpADU")
 
         # Simple Field (transactionIdentifier)
-        write_simple_field(
-            "transactionIdentifier",
-            self.transaction_identifier,
-            write_unsigned_int(write_buffer, 16),
-            WithOption.WithByteOrder(ByteOrder.BIG_ENDIAN),
+        write_buffer.write_unsigned_short(
+            self.transaction_identifier, logical_name="transactionIdentifier"
         )
 
         # Const Field (protocolIdentifier)
-        write_const_field(
-            "protocolIdentifier",
-            self.protocol_identifier,
-            write_unsigned_int(write_buffer, 16),
+        write_buffer.write_unsigned_short(
+            self.protocol_identifier.value, logical_name="protocolIdentifier"
         )
 
         # Implicit Field (length) (Used for parsing, but its value is not stored as it's implicitly given by the objects content)
-        length: c_uint16 = c_uint16(((self.pdu().self.length_in_bytes()) + (1)))
-        write_implicit_field("length", length, write_unsigned_int(write_buffer, 16))
+        length: c_uint16 = c_uint16(self.pdu.getlength_in_bytes(ctx)) + c_uint16(
+            c_uint16(1)
+        )
+        write_buffer.write_unsigned_short(length, logical_name="length")
 
         # Simple Field (unitIdentifier)
-        write_simple_field(
-            "unitIdentifier",
-            self.unit_identifier,
-            write_unsigned_short(write_buffer, 8),
-            WithOption.WithByteOrder(ByteOrder.BIG_ENDIAN),
+        write_buffer.write_unsigned_byte(
+            self.unit_identifier, logical_name="unitIdentifier"
         )
 
         # Simple Field (pdu)
-        write_simple_field(
-            "pdu",
-            self.pdu,
-            DataWriterComplexDefault(write_buffer),
-            WithOption.WithByteOrder(ByteOrder.BIG_ENDIAN),
+        write_buffer.DataWriterComplexDefault(write_buffer)(
+            self.pdu, logical_name="pdu"
         )
 
         write_buffer.pop_context("ModbusTcpADU")
@@ -115,33 +106,32 @@ class ModbusTcpADU(PlcMessage, ModbusADU):
         read_buffer: ReadBuffer, driver_type: DriverType, response: c_bool
     ):
         read_buffer.pull_context("ModbusTcpADU")
-        position_aware: PositionAware = read_buffer
-        start_pos: int = position_aware.get_pos()
+        start_pos: int = read_buffer.get_pos()
         cur_pos: int = 0
 
         transaction_identifier: c_uint16 = read_simple_field(
             "transactionIdentifier",
             read_unsigned_int(read_buffer, 16),
-            WithOption.WithByteOrder(ByteOrder.BIG_ENDIAN),
+            WithOption.WithByteOrder(get_bi_g__endian()),
         )
 
         protocol_identifier: c_uint16 = read_const_field(
             "protocolIdentifier",
             read_unsigned_int(read_buffer, 16),
             ModbusTcpADU.PROTOCOLIDENTIFIER,
-            WithOption.WithByteOrder(ByteOrder.BIG_ENDIAN),
+            WithOption.WithByteOrder(get_bi_g__endian()),
         )
 
         length: c_uint16 = read_implicit_field(
             "length",
             read_unsigned_int(read_buffer, 16),
-            WithOption.WithByteOrder(ByteOrder.BIG_ENDIAN),
+            WithOption.WithByteOrder(get_bi_g__endian()),
         )
 
         unit_identifier: c_uint8 = read_simple_field(
             "unitIdentifier",
             read_unsigned_short(read_buffer, 8),
-            WithOption.WithByteOrder(ByteOrder.BIG_ENDIAN),
+            WithOption.WithByteOrder(get_bi_g__endian()),
         )
 
         pdu: ModbusPDU = read_simple_field(
@@ -149,7 +139,7 @@ class ModbusTcpADU(PlcMessage, ModbusADU):
             DataReaderComplexDefault(
                 ModbusPDU.static_parse(read_buffer, c_bool(response)), read_buffer
             ),
-            WithOption.WithByteOrder(ByteOrder.BIG_ENDIAN),
+            WithOption.WithByteOrder(get_bi_g__endian()),
         )
 
         read_buffer.close_context("ModbusTcpADU")
diff --git a/sandbox/plc4py/plc4py/protocols/simulated/readwrite/DataItem.py b/sandbox/plc4py/plc4py/protocols/simulated/readwrite/DataItem.py
index 1843b14718..e64f50970e 100644
--- a/sandbox/plc4py/plc4py/protocols/simulated/readwrite/DataItem.py
+++ b/sandbox/plc4py/plc4py/protocols/simulated/readwrite/DataItem.py
@@ -39,7 +39,7 @@ class DataItem:
         read_buffer: ReadBuffer, data_type: str, number_of_values: c_uint16
     ):
         if EvaluationHelper.equals(data_type, "_bool") and EvaluationHelper.equals(
-            number_of_values, 1
+            number_of_values, c_uint16(1)
         ):  # BOOL
             # Simple Field (value)
             value: c_bool = read_buffer.readBit("")
@@ -63,7 +63,7 @@ class DataItem:
 
             return PlcList(value)
         if EvaluationHelper.equals(data_type, "_byte") and EvaluationHelper.equals(
-            number_of_values, 1
+            number_of_values, c_uint16(1)
         ):  # BYTE
             # Simple Field (value)
             value: c_uint8 = read_buffer.readUnsignedShort("", 8)
@@ -87,7 +87,7 @@ class DataItem:
 
             return PlcList(value)
         if EvaluationHelper.equals(data_type, "_word") and EvaluationHelper.equals(
-            number_of_values, 1
+            number_of_values, c_uint16(1)
         ):  # WORD
             # Simple Field (value)
             value: c_uint16 = read_buffer.readUnsignedInt("", 16)
@@ -111,7 +111,7 @@ class DataItem:
 
             return PlcList(value)
         if EvaluationHelper.equals(data_type, "_dword") and EvaluationHelper.equals(
-            number_of_values, 1
+            number_of_values, c_uint16(1)
         ):  # DWORD
             # Simple Field (value)
             value: c_uint32 = read_buffer.readUnsignedLong("", 32)
@@ -135,7 +135,7 @@ class DataItem:
 
             return PlcList(value)
         if EvaluationHelper.equals(data_type, "_lword") and EvaluationHelper.equals(
-            number_of_values, 1
+            number_of_values, c_uint16(1)
         ):  # LWORD
             # Simple Field (value)
             value: c_uint64 = read_buffer.readUnsignedBigInteger("", 64)
@@ -161,7 +161,7 @@ class DataItem:
 
             return PlcList(value)
         if EvaluationHelper.equals(data_type, "_sint") and EvaluationHelper.equals(
-            number_of_values, 1
+            number_of_values, c_uint16(1)
         ):  # SINT
             # Simple Field (value)
             value: c_int8 = read_buffer.readSignedByte("", 8)
@@ -185,7 +185,7 @@ class DataItem:
 
             return PlcList(value)
         if EvaluationHelper.equals(data_type, "_int") and EvaluationHelper.equals(
-            number_of_values, 1
+            number_of_values, c_uint16(1)
         ):  # INT
             # Simple Field (value)
             value: c_int16 = read_buffer.readShort("", 16)
@@ -209,7 +209,7 @@ class DataItem:
 
             return PlcList(value)
         if EvaluationHelper.equals(data_type, "_dint") and EvaluationHelper.equals(
-            number_of_values, 1
+            number_of_values, c_uint16(1)
         ):  # DINT
             # Simple Field (value)
             value: c_int32 = read_buffer.readInt("", 32)
@@ -233,7 +233,7 @@ class DataItem:
 
             return PlcList(value)
         if EvaluationHelper.equals(data_type, "_lint") and EvaluationHelper.equals(
-            number_of_values, 1
+            number_of_values, c_uint16(1)
         ):  # LINT
             # Simple Field (value)
             value: c_int64 = read_buffer.readLong("", 64)
@@ -257,7 +257,7 @@ class DataItem:
 
             return PlcList(value)
         if EvaluationHelper.equals(data_type, "_usint") and EvaluationHelper.equals(
-            number_of_values, 1
+            number_of_values, c_uint16(1)
         ):  # USINT
             # Simple Field (value)
             value: c_uint8 = read_buffer.readUnsignedShort("", 8)
@@ -281,7 +281,7 @@ class DataItem:
 
             return PlcList(value)
         if EvaluationHelper.equals(data_type, "_uint") and EvaluationHelper.equals(
-            number_of_values, 1
+            number_of_values, c_uint16(1)
         ):  # UINT
             # Simple Field (value)
             value: c_uint16 = read_buffer.readUnsignedInt("", 16)
@@ -305,7 +305,7 @@ class DataItem:
 
             return PlcList(value)
         if EvaluationHelper.equals(data_type, "_udint") and EvaluationHelper.equals(
-            number_of_values, 1
+            number_of_values, c_uint16(1)
         ):  # UDINT
             # Simple Field (value)
             value: c_uint32 = read_buffer.readUnsignedLong("", 32)
@@ -329,7 +329,7 @@ class DataItem:
 
             return PlcList(value)
         if EvaluationHelper.equals(data_type, "_ulint") and EvaluationHelper.equals(
-            number_of_values, 1
+            number_of_values, c_uint16(1)
         ):  # ULINT
             # Simple Field (value)
             value: c_uint64 = read_buffer.readUnsignedBigInteger("", 64)
@@ -355,7 +355,7 @@ class DataItem:
 
             return PlcList(value)
         if EvaluationHelper.equals(data_type, "_real") and EvaluationHelper.equals(
-            number_of_values, 1
+            number_of_values, c_uint16(1)
         ):  # REAL
             # Simple Field (value)
             value: c_float = read_buffer.readFloat("", 32)
@@ -379,7 +379,7 @@ class DataItem:
 
             return PlcList(value)
         if EvaluationHelper.equals(data_type, "_lreal") and EvaluationHelper.equals(
-            number_of_values, 1
+            number_of_values, c_uint16(1)
         ):  # LREAL
             # Simple Field (value)
             value: c_double = read_buffer.readDouble("", 64)
@@ -403,7 +403,7 @@ class DataItem:
 
             return PlcList(value)
         if EvaluationHelper.equals(data_type, "_char") and EvaluationHelper.equals(
-            number_of_values, 1
+            number_of_values, c_uint16(1)
         ):  # CHAR
             # Simple Field (value)
             value: str = read_buffer.readString("", 8, "UTF-8")
@@ -427,7 +427,7 @@ class DataItem:
 
             return PlcList(value)
         if EvaluationHelper.equals(data_type, "_wchar") and EvaluationHelper.equals(
-            number_of_values, 1
+            number_of_values, c_uint16(1)
         ):  # WCHAR
             # Simple Field (value)
             value: str = read_buffer.readString("", 16, "UTF-16")
@@ -482,234 +482,234 @@ class DataItem:
         byteOrder: ByteOrder,
     ) -> None:
         if EvaluationHelper.equals(dataType, "BOOL") and EvaluationHelper.equals(
-            numberOfValues, 1
+            numberOfValues, c_uint16(1)
         ):  # BOOL
             # Simple Field (value)
             value: c_bool = _value.getC_bool()
-            writeBuffer.writeBit("", bool((value)))
+            writeBuffer.WriteBit("value", (value))
         if EvaluationHelper.equals(dataType, "BOOL"):  # List
             values: PlcList = _value
 
             for val in values.getList():
                 value: c_bool = val.getC_bool()
-                writeBuffer.writeBit("", bool((value)))
+                writeBuffer.WriteBit("value", (value))
 
         if EvaluationHelper.equals(dataType, "BYTE") and EvaluationHelper.equals(
-            numberOfValues, 1
+            numberOfValues, c_uint16(1)
         ):  # BYTE
             # Simple Field (value)
             value: c_uint8 = _value.getC_uint8()
-            writeBuffer.writeUnsignedShort("", 8, (value).shortValue())
+            writeBuffer.WriteUint8("value", 8, (value))
         if EvaluationHelper.equals(dataType, "BYTE"):  # List
             values: PlcList = _value
 
             for val in values.getList():
                 value: c_uint8 = val.getC_uint8()
-                writeBuffer.writeUnsignedShort("", 8, (value).shortValue())
+                writeBuffer.WriteUint8("value", 8, (value))
 
         if EvaluationHelper.equals(dataType, "WORD") and EvaluationHelper.equals(
-            numberOfValues, 1
+            numberOfValues, c_uint16(1)
         ):  # WORD
             # Simple Field (value)
             value: c_uint16 = _value.getC_uint16()
-            writeBuffer.writeUnsignedInt("", 16, (value).intValue())
+            writeBuffer.WriteUint16("value", 16, (value))
         if EvaluationHelper.equals(dataType, "WORD"):  # List
             values: PlcList = _value
 
             for val in values.getList():
                 value: c_uint16 = val.getC_uint16()
-                writeBuffer.writeUnsignedInt("", 16, (value).intValue())
+                writeBuffer.WriteUint16("value", 16, (value))
 
         if EvaluationHelper.equals(dataType, "DWORD") and EvaluationHelper.equals(
-            numberOfValues, 1
+            numberOfValues, c_uint16(1)
         ):  # DWORD
             # Simple Field (value)
             value: c_uint32 = _value.getC_uint32()
-            writeBuffer.writeUnsignedLong("", 32, (value).longValue())
+            writeBuffer.WriteUint32("value", 32, (value))
         if EvaluationHelper.equals(dataType, "DWORD"):  # List
             values: PlcList = _value
 
             for val in values.getList():
                 value: c_uint32 = val.getC_uint32()
-                writeBuffer.writeUnsignedLong("", 32, (value).longValue())
+                writeBuffer.WriteUint32("value", 32, (value))
 
         if EvaluationHelper.equals(dataType, "LWORD") and EvaluationHelper.equals(
-            numberOfValues, 1
+            numberOfValues, c_uint16(1)
         ):  # LWORD
             # Simple Field (value)
             value: c_uint64 = _value.getC_uint64()
-            writeBuffer.writeUnsignedBigInteger("", 64, (value))
+            writeBuffer.WriteUint64("value", 64, (value))
         if EvaluationHelper.equals(dataType, "LWORD"):  # List
             values: PlcList = _value
 
             for val in values.getList():
                 value: c_uint64 = val.getC_uint64()
-                writeBuffer.writeUnsignedBigInteger("", 64, (value))
+                writeBuffer.WriteUint64("value", 64, (value))
 
         if EvaluationHelper.equals(dataType, "SINT") and EvaluationHelper.equals(
-            numberOfValues, 1
+            numberOfValues, c_uint16(1)
         ):  # SINT
             # Simple Field (value)
             value: c_int8 = _value.getC_int8()
-            writeBuffer.writeSignedByte("", 8, (value).byteValue())
+            writeBuffer.WriteInt8("value", 8, (value))
         if EvaluationHelper.equals(dataType, "SINT"):  # List
             values: PlcList = _value
 
             for val in values.getList():
                 value: c_int8 = val.getC_int8()
-                writeBuffer.writeSignedByte("", 8, (value).byteValue())
+                writeBuffer.WriteInt8("value", 8, (value))
 
         if EvaluationHelper.equals(dataType, "INT") and EvaluationHelper.equals(
-            numberOfValues, 1
+            numberOfValues, c_uint16(1)
         ):  # INT
             # Simple Field (value)
             value: c_int16 = _value.getC_int16()
-            writeBuffer.writeShort("", 16, (value).shortValue())
+            writeBuffer.WriteInt16("value", 16, (value))
         if EvaluationHelper.equals(dataType, "INT"):  # List
             values: PlcList = _value
 
             for val in values.getList():
                 value: c_int16 = val.getC_int16()
-                writeBuffer.writeShort("", 16, (value).shortValue())
+                writeBuffer.WriteInt16("value", 16, (value))
 
         if EvaluationHelper.equals(dataType, "DINT") and EvaluationHelper.equals(
-            numberOfValues, 1
+            numberOfValues, c_uint16(1)
         ):  # DINT
             # Simple Field (value)
             value: c_int32 = _value.getC_int32()
-            writeBuffer.writeInt("", 32, (value).intValue())
+            writeBuffer.WriteInt32("value", 32, (value))
         if EvaluationHelper.equals(dataType, "DINT"):  # List
             values: PlcList = _value
 
             for val in values.getList():
                 value: c_int32 = val.getC_int32()
-                writeBuffer.writeInt("", 32, (value).intValue())
+                writeBuffer.WriteInt32("value", 32, (value))
 
         if EvaluationHelper.equals(dataType, "LINT") and EvaluationHelper.equals(
-            numberOfValues, 1
+            numberOfValues, c_uint16(1)
         ):  # LINT
             # Simple Field (value)
             value: c_int64 = _value.getC_int64()
-            writeBuffer.writeLong("", 64, (value).longValue())
+            writeBuffer.WriteInt64("value", 64, (value))
         if EvaluationHelper.equals(dataType, "LINT"):  # List
             values: PlcList = _value
 
             for val in values.getList():
                 value: c_int64 = val.getC_int64()
-                writeBuffer.writeLong("", 64, (value).longValue())
+                writeBuffer.WriteInt64("value", 64, (value))
 
         if EvaluationHelper.equals(dataType, "USINT") and EvaluationHelper.equals(
-            numberOfValues, 1
+            numberOfValues, c_uint16(1)
         ):  # USINT
             # Simple Field (value)
             value: c_uint8 = _value.getC_uint8()
-            writeBuffer.writeUnsignedShort("", 8, (value).shortValue())
+            writeBuffer.WriteUint8("value", 8, (value))
         if EvaluationHelper.equals(dataType, "USINT"):  # List
             values: PlcList = _value
 
             for val in values.getList():
                 value: c_uint8 = val.getC_uint8()
-                writeBuffer.writeUnsignedShort("", 8, (value).shortValue())
+                writeBuffer.WriteUint8("value", 8, (value))
 
         if EvaluationHelper.equals(dataType, "UINT") and EvaluationHelper.equals(
-            numberOfValues, 1
+            numberOfValues, c_uint16(1)
         ):  # UINT
             # Simple Field (value)
             value: c_uint16 = _value.getC_uint16()
-            writeBuffer.writeUnsignedInt("", 16, (value).intValue())
+            writeBuffer.WriteUint16("value", 16, (value))
         if EvaluationHelper.equals(dataType, "UINT"):  # List
             values: PlcList = _value
 
             for val in values.getList():
                 value: c_uint16 = val.getC_uint16()
-                writeBuffer.writeUnsignedInt("", 16, (value).intValue())
+                writeBuffer.WriteUint16("value", 16, (value))
 
         if EvaluationHelper.equals(dataType, "UDINT") and EvaluationHelper.equals(
-            numberOfValues, 1
+            numberOfValues, c_uint16(1)
         ):  # UDINT
             # Simple Field (value)
             value: c_uint32 = _value.getC_uint32()
-            writeBuffer.writeUnsignedLong("", 32, (value).longValue())
+            writeBuffer.WriteUint32("value", 32, (value))
         if EvaluationHelper.equals(dataType, "UDINT"):  # List
             values: PlcList = _value
 
             for val in values.getList():
                 value: c_uint32 = val.getC_uint32()
-                writeBuffer.writeUnsignedLong("", 32, (value).longValue())
+                writeBuffer.WriteUint32("value", 32, (value))
 
         if EvaluationHelper.equals(dataType, "ULINT") and EvaluationHelper.equals(
-            numberOfValues, 1
+            numberOfValues, c_uint16(1)
         ):  # ULINT
             # Simple Field (value)
             value: c_uint64 = _value.getC_uint64()
-            writeBuffer.writeUnsignedBigInteger("", 64, (value))
+            writeBuffer.WriteUint64("value", 64, (value))
         if EvaluationHelper.equals(dataType, "ULINT"):  # List
             values: PlcList = _value
 
             for val in values.getList():
                 value: c_uint64 = val.getC_uint64()
-                writeBuffer.writeUnsignedBigInteger("", 64, (value))
+                writeBuffer.WriteUint64("value", 64, (value))
 
         if EvaluationHelper.equals(dataType, "REAL") and EvaluationHelper.equals(
-            numberOfValues, 1
+            numberOfValues, c_uint16(1)
         ):  # REAL
             # Simple Field (value)
             value: c_float = _value.getC_float()
-            writeBuffer.writeFloat("", 32, (value))
+            writeBuffer.WriteFloat32("value", 32, (value))
         if EvaluationHelper.equals(dataType, "REAL"):  # List
             values: PlcList = _value
 
             for val in values.getList():
                 value: c_float = val.getC_float()
-                writeBuffer.writeFloat("", 32, (value))
+                writeBuffer.WriteFloat32("value", 32, (value))
 
         if EvaluationHelper.equals(dataType, "LREAL") and EvaluationHelper.equals(
-            numberOfValues, 1
+            numberOfValues, c_uint16(1)
         ):  # LREAL
             # Simple Field (value)
             value: c_double = _value.getC_double()
-            writeBuffer.writeDouble("", 64, (value))
+            writeBuffer.WriteFloat64("value", 64, (value))
         if EvaluationHelper.equals(dataType, "LREAL"):  # List
             values: PlcList = _value
 
             for val in values.getList():
                 value: c_double = val.getC_double()
-                writeBuffer.writeDouble("", 64, (value))
+                writeBuffer.WriteFloat64("value", 64, (value))
 
         if EvaluationHelper.equals(dataType, "CHAR") and EvaluationHelper.equals(
-            numberOfValues, 1
+            numberOfValues, c_uint16(1)
         ):  # CHAR
             # Simple Field (value)
             value: str = _value.getStr()
-            writeBuffer.writeString("", 8, "UTF-8", (String)(value))
+            writeBuffer.WriteString("value", uint32(8), "UTF-8", (value))
         if EvaluationHelper.equals(dataType, "CHAR"):  # List
             values: PlcList = _value
 
             for val in values.getList():
                 value: str = val.getStr()
-                writeBuffer.writeString("", 8, "UTF-8", (String)(value))
+                writeBuffer.WriteString("value", uint32(8), "UTF-8", (value))
 
         if EvaluationHelper.equals(dataType, "WCHAR") and EvaluationHelper.equals(
-            numberOfValues, 1
+            numberOfValues, c_uint16(1)
         ):  # WCHAR
             # Simple Field (value)
             value: str = _value.getStr()
-            writeBuffer.writeString("", 16, "UTF-16", (String)(value))
+            writeBuffer.WriteString("value", uint32(16), "UTF-16", (value))
         if EvaluationHelper.equals(dataType, "WCHAR"):  # List
             values: PlcList = _value
 
             for val in values.getList():
                 value: str = val.getStr()
-                writeBuffer.writeString("", 16, "UTF-16", (String)(value))
+                writeBuffer.WriteString("value", uint32(16), "UTF-16", (value))
 
         if EvaluationHelper.equals(dataType, "STRING"):  # STRING
             # Simple Field (value)
             value: str = _value.getStr()
-            writeBuffer.writeString("", 255, "UTF-8", (String)(value))
+            writeBuffer.WriteString("value", uint32(255), "UTF-8", (value))
         if EvaluationHelper.equals(dataType, "WSTRING"):  # STRING
             # Simple Field (value)
             value: str = _value.getStr()
-            writeBuffer.writeString("", 255, "UTF-16", (String)(value))
+            writeBuffer.WriteString("value", uint32(255), "UTF-16", (value))
 
     @staticmethod
     def get_length_in_bytes(
@@ -725,7 +725,7 @@ class DataItem:
     ) -> int:
         sizeInBits: int = 0
         if EvaluationHelper.equals(dataType, "BOOL") and EvaluationHelper.equals(
-            numberOfValues, 1
+            numberOfValues, c_uint16(1)
         ):  # BOOL
             # Simple Field (value)
             sizeInBits += 1
@@ -733,7 +733,7 @@ class DataItem:
             values: PlcList = _value
             sizeInBits += values.getList().size() * 1
         if EvaluationHelper.equals(dataType, "BYTE") and EvaluationHelper.equals(
-            numberOfValues, 1
+            numberOfValues, c_uint16(1)
         ):  # BYTE
             # Simple Field (value)
             sizeInBits += 8
@@ -741,7 +741,7 @@ class DataItem:
             values: PlcList = _value
             sizeInBits += values.getList().size() * 8
         if EvaluationHelper.equals(dataType, "WORD") and EvaluationHelper.equals(
-            numberOfValues, 1
+            numberOfValues, c_uint16(1)
         ):  # WORD
             # Simple Field (value)
             sizeInBits += 16
@@ -749,7 +749,7 @@ class DataItem:
             values: PlcList = _value
             sizeInBits += values.getList().size() * 16
         if EvaluationHelper.equals(dataType, "DWORD") and EvaluationHelper.equals(
-            numberOfValues, 1
+            numberOfValues, c_uint16(1)
         ):  # DWORD
             # Simple Field (value)
             sizeInBits += 32
@@ -757,7 +757,7 @@ class DataItem:
             values: PlcList = _value
             sizeInBits += values.getList().size() * 32
         if EvaluationHelper.equals(dataType, "LWORD") and EvaluationHelper.equals(
-            numberOfValues, 1
+            numberOfValues, c_uint16(1)
         ):  # LWORD
             # Simple Field (value)
             sizeInBits += 64
@@ -765,7 +765,7 @@ class DataItem:
             values: PlcList = _value
             sizeInBits += values.getList().size() * 64
         if EvaluationHelper.equals(dataType, "SINT") and EvaluationHelper.equals(
-            numberOfValues, 1
+            numberOfValues, c_uint16(1)
         ):  # SINT
             # Simple Field (value)
             sizeInBits += 8
@@ -773,7 +773,7 @@ class DataItem:
             values: PlcList = _value
             sizeInBits += values.getList().size() * 8
         if EvaluationHelper.equals(dataType, "INT") and EvaluationHelper.equals(
-            numberOfValues, 1
+            numberOfValues, c_uint16(1)
         ):  # INT
             # Simple Field (value)
             sizeInBits += 16
@@ -781,7 +781,7 @@ class DataItem:
             values: PlcList = _value
             sizeInBits += values.getList().size() * 16
         if EvaluationHelper.equals(dataType, "DINT") and EvaluationHelper.equals(
-            numberOfValues, 1
+            numberOfValues, c_uint16(1)
         ):  # DINT
             # Simple Field (value)
             sizeInBits += 32
@@ -789,7 +789,7 @@ class DataItem:
             values: PlcList = _value
             sizeInBits += values.getList().size() * 32
         if EvaluationHelper.equals(dataType, "LINT") and EvaluationHelper.equals(
-            numberOfValues, 1
+            numberOfValues, c_uint16(1)
         ):  # LINT
             # Simple Field (value)
             sizeInBits += 64
@@ -797,7 +797,7 @@ class DataItem:
             values: PlcList = _value
             sizeInBits += values.getList().size() * 64
         if EvaluationHelper.equals(dataType, "USINT") and EvaluationHelper.equals(
-            numberOfValues, 1
+            numberOfValues, c_uint16(1)
         ):  # USINT
             # Simple Field (value)
             sizeInBits += 8
@@ -805,7 +805,7 @@ class DataItem:
             values: PlcList = _value
             sizeInBits += values.getList().size() * 8
         if EvaluationHelper.equals(dataType, "UINT") and EvaluationHelper.equals(
-            numberOfValues, 1
+            numberOfValues, c_uint16(1)
         ):  # UINT
             # Simple Field (value)
             sizeInBits += 16
@@ -813,7 +813,7 @@ class DataItem:
             values: PlcList = _value
             sizeInBits += values.getList().size() * 16
         if EvaluationHelper.equals(dataType, "UDINT") and EvaluationHelper.equals(
-            numberOfValues, 1
+            numberOfValues, c_uint16(1)
         ):  # UDINT
             # Simple Field (value)
             sizeInBits += 32
@@ -821,7 +821,7 @@ class DataItem:
             values: PlcList = _value
             sizeInBits += values.getList().size() * 32
         if EvaluationHelper.equals(dataType, "ULINT") and EvaluationHelper.equals(
-            numberOfValues, 1
+            numberOfValues, c_uint16(1)
         ):  # ULINT
             # Simple Field (value)
             sizeInBits += 64
@@ -829,7 +829,7 @@ class DataItem:
             values: PlcList = _value
             sizeInBits += values.getList().size() * 64
         if EvaluationHelper.equals(dataType, "REAL") and EvaluationHelper.equals(
-            numberOfValues, 1
+            numberOfValues, c_uint16(1)
         ):  # REAL
             # Simple Field (value)
             sizeInBits += 32
@@ -837,7 +837,7 @@ class DataItem:
             values: PlcList = _value
             sizeInBits += values.getList().size() * 32
         if EvaluationHelper.equals(dataType, "LREAL") and EvaluationHelper.equals(
-            numberOfValues, 1
+            numberOfValues, c_uint16(1)
         ):  # LREAL
             # Simple Field (value)
             sizeInBits += 64
@@ -845,7 +845,7 @@ class DataItem:
             values: PlcList = _value
             sizeInBits += values.getList().size() * 64
         if EvaluationHelper.equals(dataType, "CHAR") and EvaluationHelper.equals(
-            numberOfValues, 1
+            numberOfValues, c_uint16(1)
         ):  # CHAR
             # Simple Field (value)
             sizeInBits += 8
@@ -853,7 +853,7 @@ class DataItem:
             values: PlcList = _value
             sizeInBits += values.getList().size() * 8
         if EvaluationHelper.equals(dataType, "WCHAR") and EvaluationHelper.equals(
-            numberOfValues, 1
+            numberOfValues, c_uint16(1)
         ):  # WCHAR
             # Simple Field (value)
             sizeInBits += 16
diff --git a/sandbox/plc4py/plc4py/protocols/simulated/readwrite/Dummy.py b/sandbox/plc4py/plc4py/protocols/simulated/readwrite/Dummy.py
index 9f7050dd6b..7a4c5e59a5 100644
--- a/sandbox/plc4py/plc4py/protocols/simulated/readwrite/Dummy.py
+++ b/sandbox/plc4py/plc4py/protocols/simulated/readwrite/Dummy.py
@@ -21,6 +21,7 @@ from dataclasses import dataclass
 
 from ctypes import c_uint16
 from plc4py.api.messages.PlcMessage import PlcMessage
+from plc4py.spi.generation.WriteBuffer import WriteBuffer
 import math
 
 
@@ -32,17 +33,11 @@ class Dummy(PlcMessage):
         super().__init__()
 
     def serialize(self, write_buffer: WriteBuffer):
-        position_aware: PositionAware = write_buffer
-        start_pos: int = position_aware.get_pos()
+        start_pos: int = write_buffer.get_pos()
         write_buffer.push_context("Dummy")
 
         # Simple Field (dummy)
-        write_simple_field(
-            "dummy",
-            self.dummy,
-            write_unsigned_int(write_buffer, 16),
-            WithOption.WithByteOrder(ByteOrder.BIG_ENDIAN),
-        )
+        write_buffer.write_unsigned_short(self.dummy, logical_name="dummy")
 
         write_buffer.pop_context("Dummy")
 
@@ -59,20 +54,18 @@ class Dummy(PlcMessage):
         return length_in_bits
 
     def static_parse(read_buffer: ReadBuffer, args):
-        position_aware: PositionAware = read_buffer
         return staticParse(read_buffer)
 
     @staticmethod
     def static_parse_context(read_buffer: ReadBuffer):
         read_buffer.pull_context("Dummy")
-        position_aware: PositionAware = read_buffer
-        start_pos: int = position_aware.get_pos()
+        start_pos: int = read_buffer.get_pos()
         cur_pos: int = 0
 
         dummy: c_uint16 = read_simple_field(
             "dummy",
             read_unsigned_int(read_buffer, 16),
-            WithOption.WithByteOrder(ByteOrder.BIG_ENDIAN),
+            WithOption.WithByteOrder(get_bi_g__endian()),
         )
 
         read_buffer.close_context("Dummy")
diff --git a/sandbox/plc4py/plc4py/protocols/simulated/readwrite/SimulatedDataTypeSizes.py b/sandbox/plc4py/plc4py/protocols/simulated/readwrite/SimulatedDataTypeSizes.py
index fdcdd77e0e..928671c12e 100644
--- a/sandbox/plc4py/plc4py/protocols/simulated/readwrite/SimulatedDataTypeSizes.py
+++ b/sandbox/plc4py/plc4py/protocols/simulated/readwrite/SimulatedDataTypeSizes.py
@@ -19,10 +19,10 @@
 
 # Code generated by code-generation. DO NOT EDIT.
 from ctypes import c_uint8
-from enum import Enum
+from enum import IntEnum
 
 
-class SimulatedDataTypeSizes(Enum):
+class SimulatedDataTypeSizes(IntEnum):
     BOOL: c_uint8 = (1, c_uint8(1))
     BYTE: c_uint8 = (2, c_uint8(1))
     WORD: c_uint8 = (3, c_uint8(2))
@@ -51,7 +51,7 @@ class SimulatedDataTypeSizes(Enum):
     STRING: c_uint8 = (26, c_uint8(255))
     WSTRING: c_uint8 = (27, c_uint8(127))
 
-    def __new__(cls, value, dataTypeSize):
+    def __new__(cls, value, data_type_size):
         obj = object.__new__(cls)
         obj._value_ = value
         obj.dataTypeSize = dataTypeSize
diff --git a/sandbox/plc4py/plc4py/spi/generation/WriteBuffer.py b/sandbox/plc4py/plc4py/spi/generation/WriteBuffer.py
index 31fa7ed6e2..25c85c0c5b 100644
--- a/sandbox/plc4py/plc4py/spi/generation/WriteBuffer.py
+++ b/sandbox/plc4py/plc4py/spi/generation/WriteBuffer.py
@@ -14,8 +14,21 @@
 #  KIND, either express or implied.  See the License for the
 #  specific language governing permissions and limitations
 #  under the License.
-from ctypes import c_bool, c_byte, c_ubyte, c_uint16, c_uint32, c_uint64, c_int16, c_int32, c_int64, c_float, c_double, \
-    c_int8, c_uint8
+from ctypes import (
+    c_bool,
+    c_byte,
+    c_ubyte,
+    c_uint16,
+    c_uint32,
+    c_uint64,
+    c_int16,
+    c_int32,
+    c_int64,
+    c_float,
+    c_double,
+    c_int8,
+    c_uint8,
+)
 from dataclasses import dataclass
 from typing import List, Union
 
@@ -27,7 +40,6 @@ from plc4py.utils.GenericTypes import ByteOrder, ByteOrderAware
 
 
 class PositionAware:
-
     def get_pos(self) -> int:
         raise NotImplementedError
 
@@ -51,40 +63,64 @@ class WriteBuffer(ByteOrderAware, PositionAware):
     def write_byte(self, value: c_byte, logical_name: str = "", **kwargs) -> None:
         self.write_signed_byte(value, 8, logical_name, **kwargs)
 
-    def write_byte_array(self, value: List[c_byte], logical_name: str = "", **kwargs) -> None:
+    def write_byte_array(
+        self, value: List[c_byte], logical_name: str = "", **kwargs
+    ) -> None:
         raise NotImplementedError
 
-    def write_unsigned_byte(self, value: c_ubyte, bit_length: int = 8, logical_name: str = "", **kwargs) -> None:
+    def write_unsigned_byte(
+        self, value: c_uint8, bit_length: int = 8, logical_name: str = "", **kwargs
+    ) -> None:
         raise NotImplementedError
 
-    def write_unsigned_short(self, value: c_uint16, bit_length: int = 16, logical_name: str = "", **kwargs) -> None:
+    def write_unsigned_short(
+        self, value: c_uint16, bit_length: int = 16, logical_name: str = "", **kwargs
+    ) -> None:
         raise NotImplementedError
 
-    def write_unsigned_int(self, value: c_uint32, bit_length: int = 32, logical_name: str = "", **kwargs) -> None:
+    def write_unsigned_int(
+        self, value: c_uint32, bit_length: int = 32, logical_name: str = "", **kwargs
+    ) -> None:
         raise NotImplementedError
 
-    def write_unsigned_long(self, value: c_uint64, bit_length: int = 64, logical_name: str = "", **kwargs) -> None:
+    def write_unsigned_long(
+        self, value: c_uint64, bit_length: int = 64, logical_name: str = "", **kwargs
+    ) -> None:
         raise NotImplementedError
 
-    def write_signed_byte(self, value: c_int8, bit_length: int = 8, logical_name: str = "", **kwargs) -> None:
+    def write_signed_byte(
+        self, value: c_int8, bit_length: int = 8, logical_name: str = "", **kwargs
+    ) -> None:
         raise NotImplementedError
 
-    def write_short(self, value: c_int16, bit_length: int = 16, logical_name: str = "", **kwargs) -> None:
+    def write_short(
+        self, value: c_int16, bit_length: int = 16, logical_name: str = "", **kwargs
+    ) -> None:
         raise NotImplementedError
 
-    def write_int(self, value: c_int32, bit_length: int = 32, logical_name: str = "", **kwargs) -> None:
+    def write_int(
+        self, value: c_int32, bit_length: int = 32, logical_name: str = "", **kwargs
+    ) -> None:
         raise NotImplementedError
 
-    def write_long(self, value: c_int64, bit_length: int = 64, logical_name: str = "", **kwargs) -> None:
+    def write_long(
+        self, value: c_int64, bit_length: int = 64, logical_name: str = "", **kwargs
+    ) -> None:
         raise NotImplementedError
 
-    def write_float(self, value: c_float, bit_length: int = 32, logical_name: str = "", **kwargs) -> None:
+    def write_float(
+        self, value: c_float, bit_length: int = 32, logical_name: str = "", **kwargs
+    ) -> None:
         raise NotImplementedError
 
-    def write_double(self, value: c_double, bit_length: int = 64, logical_name: str = "", **kwargs) -> None:
+    def write_double(
+        self, value: c_double, bit_length: int = 64, logical_name: str = "", **kwargs
+    ) -> None:
         raise NotImplementedError
 
-    def write_str(self, value: str, bit_length: int = -1, logical_name: str = "", **kwargs) -> None:
+    def write_str(
+        self, value: str, bit_length: int = -1, logical_name: str = "", **kwargs
+    ) -> None:
         raise NotImplementedError
 
     def write_virtual(self, value: str, logical_name: str = "", **kwargs) -> None:
@@ -105,7 +141,19 @@ class WriteBufferByteBased(WriteBuffer):
     position: int = 0
     bb: bitarray
 
-    NUMERIC_UNION = Union[c_byte, c_uint8, c_uint16, c_uint32, c_uint64, c_int8, c_int16, c_int32, c_int64, c_float, c_double]
+    NUMERIC_UNION = Union[
+        c_byte,
+        c_uint8,
+        c_uint16,
+        c_uint32,
+        c_uint64,
+        c_int8,
+        c_int16,
+        c_int32,
+        c_int64,
+        c_float,
+        c_double,
+    ]
 
     def __init__(self, size: int, byte_order: ByteOrder):
         self.bb = zeros(size * 8, endian=ByteOrder.get_short_name(byte_order))
@@ -126,13 +174,17 @@ class WriteBufferByteBased(WriteBuffer):
         self.position += 1
 
     def write_byte(self, value: c_byte, logical_name: str = "", **kwargs) -> None:
-        self.write_signed_byte(value, logical_name, **kwargs)
+        self.write_signed_byte(value, 8, logical_name, **kwargs)
 
-    def write_byte_array(self, value: List[c_byte], logical_name: str = "", **kwargs) -> None:
+    def write_byte_array(
+        self, value: List[c_byte], logical_name: str = "", **kwargs
+    ) -> None:
         for a_byte in value:
-            self.write_signed_byte(a_byte, logical_name, **kwargs)
+            self.write_signed_byte(a_byte, 8, logical_name, **kwargs)
 
-    def write_unsigned_byte(self, value: c_byte, bit_length: int = 8, logical_name: str = "", **kwargs) -> None:
+    def write_unsigned_byte(
+        self, value: c_uint8, bit_length: int = 8, logical_name: str = "", **kwargs
+    ) -> None:
         if bit_length <= 0:
             raise SerializationException("unsigned byte must contain at least 1 bit")
         elif bit_length > 8:
@@ -140,7 +192,9 @@ class WriteBufferByteBased(WriteBuffer):
         else:
             self._handle_numeric_encoding(c_byte(value.value), bit_length, **kwargs)
 
-    def write_unsigned_short(self, value: c_uint16, bit_length: int = 16, logical_name: str = "", **kwargs) -> None:
+    def write_unsigned_short(
+        self, value: c_uint16, bit_length: int = 16, logical_name: str = "", **kwargs
+    ) -> None:
         if bit_length <= 0:
             raise SerializationException("unsigned short must contain at least 1 bit")
         elif bit_length > 16:
@@ -148,7 +202,9 @@ class WriteBufferByteBased(WriteBuffer):
         else:
             self._handle_numeric_encoding(c_uint16(value.value), bit_length, **kwargs)
 
-    def write_unsigned_int(self, value: c_uint32, bit_length: int = 32, logical_name: str = "", **kwargs) -> None:
+    def write_unsigned_int(
+        self, value: c_uint32, bit_length: int = 32, logical_name: str = "", **kwargs
+    ) -> None:
         if bit_length <= 0:
             raise SerializationException("unsigned int must contain at least 1 bit")
         elif bit_length > 32:
@@ -156,7 +212,9 @@ class WriteBufferByteBased(WriteBuffer):
         else:
             self._handle_numeric_encoding(c_uint32(value.value), bit_length, **kwargs)
 
-    def write_unsigned_long(self, value: c_uint64, bit_length: int = 64, logical_name: str = "", **kwargs) -> None:
+    def write_unsigned_long(
+        self, value: c_uint64, bit_length: int = 64, logical_name: str = "", **kwargs
+    ) -> None:
         if bit_length <= 0:
             raise SerializationException("unsigned long must contain at least 1 bit")
         elif bit_length > 64:
@@ -164,42 +222,54 @@ class WriteBufferByteBased(WriteBuffer):
         else:
             self._handle_numeric_encoding(c_uint64(value.value), bit_length, **kwargs)
 
-    def write_signed_byte(self, value: c_int8, bit_length: int = 8, logical_name: str = "", **kwargs) -> None:
+    def write_signed_byte(
+        self, value: c_int8, bit_length: int = 8, logical_name: str = "", **kwargs
+    ) -> None:
         if bit_length <= 0:
             raise SerializationException("Signed byte must contain at least 1 bit")
         elif bit_length > 8:
             raise SerializationException("Signed byte can only contain max 8 bits")
         self._handle_numeric_encoding(c_int8(value.value), bit_length, **kwargs)
 
-    def write_short(self, value: c_int16, bit_length: int = 16, logical_name: str = "", **kwargs) -> None:
+    def write_short(
+        self, value: c_int16, bit_length: int = 16, logical_name: str = "", **kwargs
+    ) -> None:
         if bit_length <= 0:
             raise SerializationException("Signed short must contain at least 1 bit")
         elif bit_length > 16:
             raise SerializationException("Signed short can only contain max 16 bits")
         self._handle_numeric_encoding(c_int16(value.value), bit_length, **kwargs)
 
-    def write_int(self, value: c_int32, bit_length: int = 32, logical_name: str = "", **kwargs) -> None:
+    def write_int(
+        self, value: c_int32, bit_length: int = 32, logical_name: str = "", **kwargs
+    ) -> None:
         if bit_length <= 0:
             raise SerializationException("Signed int must contain at least 1 bit")
         elif bit_length > 32:
             raise SerializationException("Signed int can only contain max 32 bits")
         self._handle_numeric_encoding(c_int32(value.value), bit_length, **kwargs)
 
-    def write_long(self, value: c_int64, bit_length: int = 64, logical_name: str = "", **kwargs) -> None:
+    def write_long(
+        self, value: c_int64, bit_length: int = 64, logical_name: str = "", **kwargs
+    ) -> None:
         if bit_length <= 0:
             raise SerializationException("Signed long must contain at least 1 bit")
         elif bit_length > 64:
             raise SerializationException("Signed long can only contain max 64 bits")
         self._handle_numeric_encoding(c_int64(value.value), bit_length, **kwargs)
 
-    def write_float(self, value: c_float, bit_length: int = 32, logical_name: str = "", **kwargs) -> None:
+    def write_float(
+        self, value: c_float, bit_length: int = 32, logical_name: str = "", **kwargs
+    ) -> None:
         if bit_length <= 0:
             raise SerializationException("Float must contain at least 1 bit")
         elif bit_length > 32:
             raise SerializationException("Float can only contain max 32 bits")
         self._handle_numeric_encoding(c_float(value.value), bit_length, **kwargs)
 
-    def write_double(self, value: c_double, bit_length: int = 64, logical_name: str = "", **kwargs) -> None:
+    def write_double(
+        self, value: c_double, bit_length: int = 64, logical_name: str = "", **kwargs
+    ) -> None:
         if bit_length <= 0:
             raise SerializationException("Double must contain at least 1 bit")
         elif bit_length > 64:
@@ -212,19 +282,24 @@ class WriteBufferByteBased(WriteBuffer):
         if value_encoding == "ASCII":
             if bit_length % 8 != 0:
                 raise SerializationException(
-                    "'ASCII' encoded fields must have a length that is a multiple of 8 bits long")
+                    "'ASCII' encoded fields must have a length that is a multiple of 8 bits long"
+                )
             char_len: int = int(bit_length / 8)
-            max_value: int = int(10 ** char_len - 1)
+            max_value: int = int(10**char_len - 1)
             if value.value > max_value:
                 raise SerializationException(
-                    "Provided value of " + str(value) + " exceeds the max value of " + str(max_value))
+                    "Provided value of "
+                    + str(value)
+                    + " exceeds the max value of "
+                    + str(max_value)
+                )
             string_value: str = "{}".format(value.value)
             src = bitarray(endian=ByteOrder.get_short_name(byte_order))
             src.frombytes(bytearray(string_value, value_encoding))
-            self.bb[self.position:bit_length] = src[:bit_length]
+            self.bb[self.position : bit_length] = src[:bit_length]
             self.position += bit_length
         elif value_encoding == "default":
             src = bitarray(endian=ByteOrder.get_short_name(byte_order))
             src.frombytes(value)
-            self.bb[self.position:bit_length] = src[:bit_length]
+            self.bb[self.position : bit_length] = src[:bit_length]
             self.position += bit_length
diff --git a/sandbox/plc4py/plc4py/spi/generation/__init__.py b/sandbox/plc4py/plc4py/spi/generation/__init__.py
index c3434ab60d..a67d5ea255 100644
--- a/sandbox/plc4py/plc4py/spi/generation/__init__.py
+++ b/sandbox/plc4py/plc4py/spi/generation/__init__.py
@@ -14,4 +14,3 @@
 #  KIND, either express or implied.  See the License for the
 #  specific language governing permissions and limitations
 #  under the License.
-
diff --git a/sandbox/plc4py/plc4py/spi/values/Common.py b/sandbox/plc4py/plc4py/spi/values/Common.py
index 886a61162e..a407235b3f 100644
--- a/sandbox/plc4py/plc4py/spi/values/Common.py
+++ b/sandbox/plc4py/plc4py/spi/values/Common.py
@@ -21,6 +21,5 @@ from plc4py.spi.generation import WriteBuffer
 
 
 class Serializable:
-
     def serialize(self, write_buffer: WriteBuffer):
-        pass
\ No newline at end of file
+        pass
diff --git a/sandbox/plc4py/setup.py b/sandbox/plc4py/setup.py
index 6543000684..8a7416a31e 100644
--- a/sandbox/plc4py/setup.py
+++ b/sandbox/plc4py/setup.py
@@ -44,7 +44,7 @@ setup(
         "black",
         "pip",
         "aenum",
-        "bitarray"
+        "bitarray",
     ],
     extras_require={
         "dev": [
diff --git a/sandbox/plc4py/tests/unit/plc4py/spi/test_write_buffer.py b/sandbox/plc4py/tests/unit/plc4py/spi/test_write_buffer.py
index af25806dfb..1c313ac4c6 100644
--- a/sandbox/plc4py/tests/unit/plc4py/spi/test_write_buffer.py
+++ b/sandbox/plc4py/tests/unit/plc4py/spi/test_write_buffer.py
@@ -29,34 +29,34 @@ from plc4py.utils.GenericTypes import ByteOrder
 def test_write_buffer_get_bytes(mocker) -> None:
     wb: WriteBufferByteBased = WriteBufferByteBased(10, ByteOrder.LITTLE_ENDIAN)
     ba: memoryview = wb.get_bytes()
-    assert(10 == ba.nbytes)
+    assert 10 == ba.nbytes
 
 
 def test_write_buffer_get_pos(mocker) -> None:
     wb: WriteBufferByteBased = WriteBufferByteBased(10, ByteOrder.LITTLE_ENDIAN)
     pos: int = wb.get_pos()
-    assert(0 == pos)
+    assert 0 == pos
 
 
 def test_write_buffer_set_bit_little_endian(mocker) -> None:
     wb: WriteBufferByteBased = WriteBufferByteBased(1, ByteOrder.LITTLE_ENDIAN)
     wb.write_bit(c_bool(True))
     ba: memoryview = wb.get_bytes()
-    assert(b'\x01' == ba.tobytes())
+    assert b"\x01" == ba.tobytes()
 
 
 def test_write_buffer_set_bit_big_endian(mocker) -> None:
     wb: WriteBufferByteBased = WriteBufferByteBased(1, ByteOrder.BIG_ENDIAN)
     wb.write_bit(c_bool(True))
     ba: memoryview = wb.get_bytes()
-    assert(b'\x80' == ba.tobytes())
+    assert b"\x80" == ba.tobytes()
 
 
 def test_write_buffer_set_bit_get_pos(mocker) -> None:
     wb: WriteBufferByteBased = WriteBufferByteBased(1, ByteOrder.LITTLE_ENDIAN)
     wb.write_bit(c_bool(True))
     pos: int = wb.get_pos()
-    assert(1 == pos)
+    assert 1 == pos
 
 
 def test_write_buffer_set_bit_x2_little_endian(mocker) -> None:
@@ -64,7 +64,7 @@ def test_write_buffer_set_bit_x2_little_endian(mocker) -> None:
     wb.write_bit(c_bool(True))
     wb.write_bit(c_bool(True))
     ba: memoryview = wb.get_bytes()
-    assert (b'\x03' == ba.tobytes())
+    assert b"\x03" == ba.tobytes()
 
 
 def test_write_buffer_set_bit_x2_big_endian(mocker) -> None:
@@ -72,7 +72,7 @@ def test_write_buffer_set_bit_x2_big_endian(mocker) -> None:
     wb.write_bit(c_bool(True))
     wb.write_bit(c_bool(True))
     ba: memoryview = wb.get_bytes()
-    assert (b'\xc0' == ba.tobytes())
+    assert b"\xc0" == ba.tobytes()
 
 
 def test_write_buffer_set_bit_get_pos_dual(mocker) -> None:
@@ -80,56 +80,56 @@ def test_write_buffer_set_bit_get_pos_dual(mocker) -> None:
     wb.write_bit(c_bool(True))
     wb.write_bit(c_bool(True))
     pos: int = wb.get_pos()
-    assert(pos == 2)
+    assert pos == 2
 
 
 def test_write_buffer_set_unsigned_byte_get_pos(mocker) -> None:
     wb: WriteBufferByteBased = WriteBufferByteBased(1, ByteOrder.LITTLE_ENDIAN)
     wb.write_unsigned_byte(c_byte(0xFF), 8)
     pos: int = wb.get_pos()
-    assert(pos == 8)
+    assert pos == 8
 
 
 def test_write_buffer_set_unsigned_byte_little_endian(mocker) -> None:
     wb: WriteBufferByteBased = WriteBufferByteBased(1, ByteOrder.LITTLE_ENDIAN)
     wb.write_unsigned_byte(c_byte(0x12), 8)
     ba: memoryview = wb.get_bytes()
-    assert (ba.obj == bitarray("01001000"))
+    assert ba.obj == bitarray("01001000")
 
 
 def test_write_buffer_set_unsigned_byte_big_endian(mocker) -> None:
     wb: WriteBufferByteBased = WriteBufferByteBased(1, ByteOrder.BIG_ENDIAN)
     wb.write_unsigned_byte(c_byte(0x12), 8)
     ba: memoryview = wb.get_bytes()
-    assert (ba.obj == bitarray("00010010"))
+    assert ba.obj == bitarray("00010010")
 
 
 def test_write_buffer_set_unsigned_byte_little_endian_niblet(mocker) -> None:
     wb: WriteBufferByteBased = WriteBufferByteBased(1, ByteOrder.LITTLE_ENDIAN)
     wb.write_unsigned_byte(c_byte(0x12), 4)
     ba: memoryview = wb.get_bytes()
-    assert (ba.obj == bitarray("01000000"))
+    assert ba.obj == bitarray("01000000")
 
 
 def test_write_buffer_set_unsigned_byte_big_endian_niblet(mocker) -> None:
     wb: WriteBufferByteBased = WriteBufferByteBased(1, ByteOrder.BIG_ENDIAN)
     wb.write_unsigned_byte(c_byte(0x12), 4)
     ba: memoryview = wb.get_bytes()
-    assert (ba.obj == bitarray("00010000"))
+    assert ba.obj == bitarray("00010000")
 
 
 def test_write_buffer_write_unsigned_short_little_endian(mocker) -> None:
     wb: WriteBufferByteBased = WriteBufferByteBased(2, ByteOrder.LITTLE_ENDIAN)
     wb.write_unsigned_short(c_uint16(0x12), 16)
     ba: memoryview = wb.get_bytes()
-    assert (ba.obj == bitarray("01001000 00000000", endian="little"))
+    assert ba.obj == bitarray("01001000 00000000", endian="little")
 
 
 def test_write_buffer_write_unsigned_short_big_endian(mocker) -> None:
     wb: WriteBufferByteBased = WriteBufferByteBased(2, ByteOrder.BIG_ENDIAN)
     wb.write_unsigned_short(c_uint16(0x12), 16)
     ba: memoryview = wb.get_bytes()
-    assert (ba.obj == bitarray("00010010 00000000", endian="big"))
+    assert ba.obj == bitarray("00010010 00000000", endian="big")
 
 
 def test_write_buffer_write_unsigned_short_little_endian_dual(mocker) -> None:
@@ -137,7 +137,7 @@ def test_write_buffer_write_unsigned_short_little_endian_dual(mocker) -> None:
     wb.write_unsigned_short(c_uint16(0x12), 16)
     wb.write_unsigned_short(c_uint16(0x34), 16)
     ba: memoryview = wb.get_bytes()
-    assert (ba.obj == bitarray("01001000 00000000 00101100 00000000", endian="little"))
+    assert ba.obj == bitarray("01001000 00000000 00101100 00000000", endian="little")
 
 
 def test_write_buffer_write_unsigned_short_big_endian_dual(mocker) -> None:
@@ -145,14 +145,14 @@ def test_write_buffer_write_unsigned_short_big_endian_dual(mocker) -> None:
     wb.write_unsigned_short(c_uint16(0x12), 16)
     wb.write_unsigned_short(c_uint16(0x34), 16)
     ba: memoryview = wb.get_bytes()
-    assert (ba.obj == bitarray("00010010 00000000 00110100 00000000", endian="big"))
+    assert ba.obj == bitarray("00010010 00000000 00110100 00000000", endian="big")
 
 
 def test_write_buffer_write_unsigned_short_big_endian_full(mocker) -> None:
     wb: WriteBufferByteBased = WriteBufferByteBased(2, ByteOrder.BIG_ENDIAN)
     wb.write_unsigned_short(c_uint16(-1), 16)
     ba: memoryview = wb.get_bytes()
-    assert (ba.obj == bitarray("11111111 11111111", endian="big"))
+    assert ba.obj == bitarray("11111111 11111111", endian="big")
 
 
 def test_write_buffer_write_unsigned_short_bit_big_endian_full(mocker) -> None:
@@ -161,21 +161,25 @@ def test_write_buffer_write_unsigned_short_bit_big_endian_full(mocker) -> None:
     wb.write_bit(c_bool(False))
     wb.write_unsigned_short(c_uint16(-1), 16)
     ba: memoryview = wb.get_bytes()
-    assert (ba.obj == bitarray("10 11111111 11111111", endian="big"))
+    assert ba.obj == bitarray("10 11111111 11111111", endian="big")
 
 
 def test_write_buffer_write_unsigned_short_ascii_encoding_little_endian(mocker) -> None:
     wb: WriteBufferByteBased = WriteBufferByteBased(2, ByteOrder.LITTLE_ENDIAN)
-    wb.write_unsigned_short(c_uint16(1), 16, "ASCII Value of 1 - 0x31", encoding="ASCII")
+    wb.write_unsigned_short(
+        c_uint16(1), 16, "ASCII Value of 1 - 0x31", encoding="ASCII"
+    )
     ba: memoryview = wb.get_bytes()
-    assert (ba.obj == bitarray("10001100", endian="little"))
+    assert ba.obj == bitarray("10001100", endian="little")
 
 
 def test_write_buffer_write_unsigned_short_ascii_encoding_big_endian(mocker) -> None:
     wb: WriteBufferByteBased = WriteBufferByteBased(2, ByteOrder.BIG_ENDIAN)
-    wb.write_unsigned_short(c_uint16(1), 16, "ASCII Value of 1 - 0x31", encoding="ASCII")
+    wb.write_unsigned_short(
+        c_uint16(1), 16, "ASCII Value of 1 - 0x31", encoding="ASCII"
+    )
     ba: memoryview = wb.get_bytes()
-    assert (ba.obj == bitarray("00110001", endian="big"))
+    assert ba.obj == bitarray("00110001", endian="big")
 
 
 def test_write_buffer_write_unsigned_int_little_endian(mocker) -> None:
@@ -183,7 +187,7 @@ def test_write_buffer_write_unsigned_int_little_endian(mocker) -> None:
     # Testing incompatible format being sent to it.
     wb.write_unsigned_int(c_uint16(0x12), 32)
     ba: memoryview = wb.get_bytes()
-    assert (ba.obj == bitarray("01001000 00000000 00000000 00000000", endian="little"))
+    assert ba.obj == bitarray("01001000 00000000 00000000 00000000", endian="little")
 
 
 def test_write_buffer_write_unsigned_int_big_endian(mocker) -> None:
@@ -191,62 +195,82 @@ def test_write_buffer_write_unsigned_int_big_endian(mocker) -> None:
     # Testing incompatible format being sent to it.
     wb.write_unsigned_int(c_uint16(0x12), 32)
     ba: memoryview = wb.get_bytes()
-    assert (ba.obj == bitarray("00010010 00000000 00000000 00000000", endian="big"))
+    assert ba.obj == bitarray("00010010 00000000 00000000 00000000", endian="big")
 
 
 def test_write_buffer_write_unsigned_long_little_endian(mocker) -> None:
     wb: WriteBufferByteBased = WriteBufferByteBased(2, ByteOrder.LITTLE_ENDIAN)
     wb.write_unsigned_long(c_uint64(0x12), 64)
     ba: memoryview = wb.get_bytes()
-    assert (ba.obj == bitarray("01001000 00000000 00000000 00000000 00000000 00000000 00000000 00000000", endian="little"))
+    assert ba.obj == bitarray(
+        "01001000 00000000 00000000 00000000 00000000 00000000 00000000 00000000",
+        endian="little",
+    )
 
 
 def test_write_buffer_write_unsigned_long_big_endian(mocker) -> None:
     wb: WriteBufferByteBased = WriteBufferByteBased(2, ByteOrder.BIG_ENDIAN)
     wb.write_unsigned_long(c_uint64(0x12), 64)
     ba: memoryview = wb.get_bytes()
-    assert (ba.obj == bitarray("00010010 00000000 00000000 00000000 00000000 00000000 00000000 00000000", endian="big"))
+    assert ba.obj == bitarray(
+        "00010010 00000000 00000000 00000000 00000000 00000000 00000000 00000000",
+        endian="big",
+    )
 
 
 def test_write_buffer_write_unsigned_long_ascii_encoding_little_endian(mocker) -> None:
     wb: WriteBufferByteBased = WriteBufferByteBased(8, ByteOrder.LITTLE_ENDIAN)
-    wb.write_unsigned_long(c_uint64(11111111), 64, "ASCII Value of 1111 1111 - 0x3131313131313131", encoding="ASCII")
+    wb.write_unsigned_long(
+        c_uint64(11111111),
+        64,
+        "ASCII Value of 1111 1111 - 0x3131313131313131",
+        encoding="ASCII",
+    )
     ba: memoryview = wb.get_bytes()
-    assert (ba.obj == bitarray("10001100 10001100 10001100 10001100 10001100 10001100 10001100 10001100", endian="little"))
+    assert ba.obj == bitarray(
+        "10001100 10001100 10001100 10001100 10001100 10001100 10001100 10001100",
+        endian="little",
+    )
 
 
 def test_write_buffer_write_unsigned_long_ascii_encoding_big_endian(mocker) -> None:
     wb: WriteBufferByteBased = WriteBufferByteBased(8, ByteOrder.BIG_ENDIAN)
-    wb.write_unsigned_long(c_uint64(11111111), 64, "ASCII Value of 1111 1111 - 0x3131313131313131", encoding="ASCII")
+    wb.write_unsigned_long(
+        c_uint64(11111111),
+        64,
+        "ASCII Value of 1111 1111 - 0x3131313131313131",
+        encoding="ASCII",
+    )
     ba: memoryview = wb.get_bytes()
-    assert (ba.obj == bitarray("00110001 00110001 00110001 00110001 00110001 00110001 00110001 00110001", endian="big"))
+    assert ba.obj == bitarray(
+        "00110001 00110001 00110001 00110001 00110001 00110001 00110001 00110001",
+        endian="big",
+    )
 
 
 def test_write_buffer_set_signed_byte(mocker) -> None:
     wb: WriteBufferByteBased = WriteBufferByteBased(1, ByteOrder.LITTLE_ENDIAN)
     wb.write_signed_byte(c_int8(-1), 8)
     ba: memoryview = wb.get_bytes()
-    assert (ba.obj == bitarray("11111111",
-                               endian="little"))
+    assert ba.obj == bitarray("11111111", endian="little")
 
 
 def test_write_buffer_set_signed_byte_three(mocker) -> None:
     wb: WriteBufferByteBased = WriteBufferByteBased(1, ByteOrder.LITTLE_ENDIAN)
     wb.write_signed_byte(c_int8(3), 8)
     ba: memoryview = wb.get_bytes()
-    assert (ba.obj == bitarray("11000000",
-                               endian="little"))
+    assert ba.obj == bitarray("11000000", endian="little")
+
 
 def test_write_buffer_set_float_little_endian(mocker) -> None:
     wb: WriteBufferByteBased = WriteBufferByteBased(1, ByteOrder.LITTLE_ENDIAN)
     wb.write_float(c_float(-1), 32)
     ba: memoryview = wb.get_bytes()
-    assert (ba.obj == bitarray("00000000000000000000000111111101",
-                               endian="little"))
+    assert ba.obj == bitarray("00000000000000000000000111111101", endian="little")
+
 
 def test_write_buffer_set_float_big_endian(mocker) -> None:
     wb: WriteBufferByteBased = WriteBufferByteBased(1, ByteOrder.BIG_ENDIAN)
     wb.write_float(c_float(-1), 32)
     ba: memoryview = wb.get_bytes()
-    assert (ba.obj == bitarray("00000000000000001000000010111111",
-                               endian="big"))
+    assert ba.obj == bitarray("00000000000000001000000010111111", endian="big")