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

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

commit a28fac5a883e7f889172586c9b56f5a1228020df
Author: Sebastian Rühl <[email protected]>
AuthorDate: Mon Apr 19 23:39:01 2021 +0200

    plc4j: converted ReadBuffer and WriteBuffer to interfaces
    
    + added logical names to all calls
---
 .../language/java/JavaLanguageTemplateHelper.java  |  72 +++--
 .../templates/java/data-io-template.java.ftlh      |   8 +-
 .../resources/templates/java/io-template.java.ftlh |  74 +++--
 go.mod                                             |   2 +-
 go.sum                                             |   2 +
 .../plc4x/java/ads/protocol/AdsProtocolLogic.java  |  18 +-
 .../protocol/ads/ManualParserSerializerTest.java   |   3 +-
 .../canopen/CANOpenConversationBase.java           |   4 +-
 .../canopen/protocol/CANOpenProtocolLogic.java     |   8 +-
 .../plc4x/java/canopen/ManualParserTest.java       |   5 +-
 .../eip/readwrite/protocol/EipProtocolLogic.java   |   9 +-
 .../java/firmata/readwrite/utils/FirmataUtils.java |   3 +-
 .../knxnetip/protocol/KnxNetIpProtocolLogic.java   |  12 +-
 .../plc4x/java/knxnetip/utils/KnxHelper.java       |   3 +-
 .../org/apache/plc4x/java/knxnetip/IOTest.java     |  10 +-
 .../java/modbus/protocol/ModbusProtocolLogic.java  |  16 +-
 .../plc4x/java/s7/readwrite/field/S7Field.java     |   3 +-
 .../s7/readwrite/protocol/S7ProtocolLogic.java     |   8 +-
 .../s7/src/test/java/BenchmarkGeneratedS7.java     |   6 +-
 .../java/simulated/connection/SimulatedDevice.java |   3 +-
 .../spi/GeneratedDriverByteToMessageCodec.java     |   9 +-
 .../plc4x/java/spi/generation/ReadBuffer.java      | 339 +++++----------------
 .../{ReadBuffer.java => ReadBufferByteBased.java}  |  68 +++--
 .../plc4x/java/spi/generation/StaticHelper.java    |  63 ++--
 .../plc4x/java/spi/generation/WriteBuffer.java     | 306 +++++--------------
 ...{WriteBuffer.java => WriteBufferByteBased.java} |  86 ++++--
 .../plc4x/java/spi/generation/ReadBufferTest.java  |   6 +-
 .../plc4x/test/driver/DriverTestsuiteRunner.java   |   4 +-
 .../ParserSerializerTestsuiteRunner.java           |   4 +-
 29 files changed, 438 insertions(+), 716 deletions(-)

diff --git 
a/build-utils/language-java/src/main/java/org/apache/plc4x/language/java/JavaLanguageTemplateHelper.java
 
b/build-utils/language-java/src/main/java/org/apache/plc4x/language/java/JavaLanguageTemplateHelper.java
index 19bbedd..fcd6ec2 100644
--- 
a/build-utils/language-java/src/main/java/org/apache/plc4x/language/java/JavaLanguageTemplateHelper.java
+++ 
b/build-utils/language-java/src/main/java/org/apache/plc4x/language/java/JavaLanguageTemplateHelper.java
@@ -316,39 +316,43 @@ public class JavaLanguageTemplateHelper extends 
BaseFreemarkerLanguageTemplateHe
 
     @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: {
-                return "io.readBit()";
+                return "io.readBit(\"" + logicalName + "\")";
             }
             case UINT: {
                 IntegerTypeReference integerTypeReference = 
(IntegerTypeReference) simpleTypeReference;
                 if (integerTypeReference.getSizeInBits() <= 4) {
-                    return "io.readUnsignedByte(" + 
integerTypeReference.getSizeInBits() + ")";
+                    return "io.readUnsignedByte(\"" + logicalName + "\", " + 
integerTypeReference.getSizeInBits() + ")";
                 }
                 if (integerTypeReference.getSizeInBits() <= 8) {
-                    return "io.readUnsignedShort(" + 
integerTypeReference.getSizeInBits() + ")";
+                    return "io.readUnsignedShort(\"" + logicalName + "\", " + 
integerTypeReference.getSizeInBits() + ")";
                 }
                 if (integerTypeReference.getSizeInBits() <= 16) {
-                    return "io.readUnsignedInt(" + 
integerTypeReference.getSizeInBits() + ")";
+                    return "io.readUnsignedInt(\"" + logicalName + "\", " + 
integerTypeReference.getSizeInBits() + ")";
                 }
                 if (integerTypeReference.getSizeInBits() <= 32) {
-                    return "io.readUnsignedLong(" + 
integerTypeReference.getSizeInBits() + ")";
+                    return "io.readUnsignedLong(\"" + logicalName + "\", " + 
integerTypeReference.getSizeInBits() + ")";
                 }
-                return "io.readUnsignedBigInteger(" + 
integerTypeReference.getSizeInBits() + ")";
+                return "io.readUnsignedBigInteger(\"" + logicalName + "\", " + 
integerTypeReference.getSizeInBits() + ")";
             }
             case INT: {
                 IntegerTypeReference integerTypeReference = 
(IntegerTypeReference) simpleTypeReference;
                 if (integerTypeReference.getSizeInBits() <= 8) {
-                    return "io.readByte(" + 
integerTypeReference.getSizeInBits() + ")";
+                    return "io.readByte(\"" + logicalName + "\", " + 
integerTypeReference.getSizeInBits() + ")";
                 }
                 if (integerTypeReference.getSizeInBits() <= 16) {
-                    return "io.readShort(" + 
integerTypeReference.getSizeInBits() + ")";
+                    return "io.readShort(\"" + logicalName + "\", " + 
integerTypeReference.getSizeInBits() + ")";
                 }
                 if (integerTypeReference.getSizeInBits() <= 32) {
-                    return "io.readInt(" + 
integerTypeReference.getSizeInBits() + ")";
+                    return "io.readInt(\"" + logicalName + "\", " + 
integerTypeReference.getSizeInBits() + ")";
                 }
                 if (integerTypeReference.getSizeInBits() <= 64) {
-                    return "io.readLong(" + 
integerTypeReference.getSizeInBits() + ")";
+                    return "io.readLong(\"" + logicalName + "\", " + 
integerTypeReference.getSizeInBits() + ")";
                 }
                 return "io.readBigInteger(" + 
integerTypeReference.getSizeInBits() + ")";
             }
@@ -357,17 +361,17 @@ public class JavaLanguageTemplateHelper extends 
BaseFreemarkerLanguageTemplateHe
                 String type = (floatTypeReference.getSizeInBits() <= 32) ? 
"Float" : "Double";
                 String typeCast = (floatTypeReference.getSizeInBits() <= 32) ? 
"float" : "double";
                 String defaultNull = (floatTypeReference.getSizeInBits() <= 
32) ? "0.0f" : "0.0";
-                StringBuilder sb = new 
StringBuilder("((Supplier<").append(type).append(">) (() -> {");
-                sb.append("\n            return (").append(typeCast).append(") 
toFloat(io, ").append(
-                    (floatTypeReference.getBaseType() == 
SimpleTypeReference.SimpleBaseType.FLOAT) ? "true" : "false")
-                    .append(", 
").append(floatTypeReference.getExponent()).append(", ")
-                    .append(floatTypeReference.getMantissa()).append(");");
-                sb.append("\n        })).get()");
-                return sb.toString();
+                // TODO: insert logical name
+                return  "((Supplier<" + type + ">) (() -> {" +
+                    "\n            return (" + typeCast + ") toFloat(io, 
\""+logicalName +"\", "+
+                    ((floatTypeReference.getBaseType() == 
SimpleTypeReference.SimpleBaseType.FLOAT) ? "true" : "false") +
+                    ", " + floatTypeReference.getExponent() + ", " +
+                    floatTypeReference.getMantissa() + ");" +
+                    "\n        })).get()";
             }
             case STRING: {
                 StringTypeReference stringTypeReference = 
(StringTypeReference) simpleTypeReference;
-                return "io.readString(" + toParseExpression(field, 
stringTypeReference.getLengthExpression(), null) + ", \"" +
+                return "io.readString(\"" + logicalName + "\", " + 
toParseExpression(field, stringTypeReference.getLengthExpression(), null) + ", 
\"" +
                     stringTypeReference.getEncoding() + "\")";
             }
         }
@@ -376,56 +380,60 @@ public class JavaLanguageTemplateHelper extends 
BaseFreemarkerLanguageTemplateHe
 
     @Override
     public String getWriteBufferWriteMethodCall(SimpleTypeReference 
simpleTypeReference, String fieldName, TypedField field) {
+        return getWriteBufferWriteMethodCall("", 
simpleTypeReference,fieldName,field);
+    }
+
+    public String getWriteBufferWriteMethodCall(String logicalName, 
SimpleTypeReference simpleTypeReference, String fieldName, TypedField field) {
         switch (simpleTypeReference.getBaseType()) {
             case BIT: {
-                return "io.writeBit((boolean) " + fieldName + ")";
+                return "io.writeBit(\""+logicalName+"\", (boolean) " + 
fieldName + ")";
             }
             case UINT: {
                 IntegerTypeReference integerTypeReference = 
(IntegerTypeReference) simpleTypeReference;
                 if (integerTypeReference.getSizeInBits() <= 4) {
-                    return "io.writeUnsignedByte(" + 
integerTypeReference.getSizeInBits() + ", ((Number) " + fieldName + 
").byteValue())";
+                    return "io.writeUnsignedByte(\""+logicalName+"\", " + 
integerTypeReference.getSizeInBits() + ", ((Number) " + fieldName + 
").byteValue())";
                 }
                 if (integerTypeReference.getSizeInBits() <= 8) {
-                    return "io.writeUnsignedShort(" + 
integerTypeReference.getSizeInBits() + ", ((Number) " + fieldName + 
").shortValue())";
+                    return "io.writeUnsignedShort(\""+logicalName+"\", " + 
integerTypeReference.getSizeInBits() + ", ((Number) " + fieldName + 
").shortValue())";
                 }
                 if (integerTypeReference.getSizeInBits() <= 16) {
-                    return "io.writeUnsignedInt(" + 
integerTypeReference.getSizeInBits() + ", ((Number) " + fieldName + 
").intValue())";
+                    return "io.writeUnsignedInt(\""+logicalName+"\", " + 
integerTypeReference.getSizeInBits() + ", ((Number) " + fieldName + 
").intValue())";
                 }
                 if (integerTypeReference.getSizeInBits() <= 32) {
-                    return "io.writeUnsignedLong(" + 
integerTypeReference.getSizeInBits() + ", ((Number) " + fieldName + 
").longValue())";
+                    return "io.writeUnsignedLong(\""+logicalName+"\", " + 
integerTypeReference.getSizeInBits() + ", ((Number) " + fieldName + 
").longValue())";
                 }
-                return "io.writeUnsignedBigInteger(" + 
integerTypeReference.getSizeInBits() + ", (BigInteger) " + fieldName + ")";
+                return "io.writeUnsignedBigInteger(\""+logicalName+"\", " + 
integerTypeReference.getSizeInBits() + ", (BigInteger) " + fieldName + ")";
             }
             case INT: {
                 IntegerTypeReference integerTypeReference = 
(IntegerTypeReference) simpleTypeReference;
                 if (integerTypeReference.getSizeInBits() <= 8) {
-                    return "io.writeByte(" + 
integerTypeReference.getSizeInBits() + ", ((Number) " + fieldName + 
").byteValue())";
+                    return "io.writeByte(\""+logicalName+"\", " + 
integerTypeReference.getSizeInBits() + ", ((Number) " + fieldName + 
").byteValue())";
                 }
                 if (integerTypeReference.getSizeInBits() <= 16) {
-                    return "io.writeShort(" + 
integerTypeReference.getSizeInBits() + ", ((Number) " + fieldName + 
").shortValue())";
+                    return "io.writeShort(\""+logicalName+"\", " + 
integerTypeReference.getSizeInBits() + ", ((Number) " + fieldName + 
").shortValue())";
                 }
                 if (integerTypeReference.getSizeInBits() <= 32) {
-                    return "io.writeInt(" + 
integerTypeReference.getSizeInBits() + ", ((Number) " + fieldName + 
").intValue())";
+                    return "io.writeInt(\""+logicalName+"\", " + 
integerTypeReference.getSizeInBits() + ", ((Number) " + fieldName + 
").intValue())";
                 }
                 if (integerTypeReference.getSizeInBits() <= 64) {
-                    return "io.writeLong(" + 
integerTypeReference.getSizeInBits() + ", ((Number) " + fieldName + 
").longValue())";
+                    return "io.writeLong(\""+logicalName+"\", " + 
integerTypeReference.getSizeInBits() + ", ((Number) " + fieldName + 
").longValue())";
                 }
-                return "io.writeBigInteger(" + 
integerTypeReference.getSizeInBits() + ", BigInteger.valueOf( " + fieldName + 
"))";
+                return "io.writeBigInteger(\""+logicalName+"\", " + 
integerTypeReference.getSizeInBits() + ", BigInteger.valueOf( " + fieldName + 
"))";
             }
             case FLOAT:
             case UFLOAT: {
                 FloatTypeReference floatTypeReference = (FloatTypeReference) 
simpleTypeReference;
                 if (floatTypeReference.getSizeInBits() <= 32) {
-                    return "io.writeFloat(" + fieldName + "," + 
floatTypeReference.getExponent() + "," + floatTypeReference.getMantissa() + ")";
+                    return "io.writeFloat(\""+logicalName+"\", " + fieldName + 
"," + floatTypeReference.getExponent() + "," + floatTypeReference.getMantissa() 
+ ")";
                 } else if (floatTypeReference.getSizeInBits() <= 64) {
-                    return "io.writeDouble(" + fieldName + "," + 
floatTypeReference.getExponent() + "," + floatTypeReference.getMantissa() + ")";
+                    return "io.writeDouble(\""+logicalName+"\", " + fieldName 
+ "," + floatTypeReference.getExponent() + "," + 
floatTypeReference.getMantissa() + ")";
                 } else {
                     throw new RuntimeException("Unsupported float type");
                 }
             }
             case STRING: {
                 StringTypeReference stringTypeReference = 
(StringTypeReference) simpleTypeReference;
-                return "io.writeString(" + toSerializationExpression(field, 
stringTypeReference.getLengthExpression(), 
getThisTypeDefinition().getParserArguments()) + ", \"" +
+                return "io.writeString(\""+logicalName+"\", " + 
toSerializationExpression(field, stringTypeReference.getLengthExpression(), 
getThisTypeDefinition().getParserArguments()) + ", \"" +
                     stringTypeReference.getEncoding() + "\", (String) " + 
fieldName + ")";
             }
         }
diff --git 
a/build-utils/language-java/src/main/resources/templates/java/data-io-template.java.ftlh
 
b/build-utils/language-java/src/main/resources/templates/java/data-io-template.java.ftlh
index f03f904..2353894 100644
--- 
a/build-utils/language-java/src/main/resources/templates/java/data-io-template.java.ftlh
+++ 
b/build-utils/language-java/src/main/resources/templates/java/data-io-template.java.ftlh
@@ -70,7 +70,7 @@ import org.apache.plc4x.java.api.value.*;
 import org.apache.plc4x.java.spi.generation.EvaluationHelper;
 import org.apache.plc4x.java.spi.generation.ParseException;
 import org.apache.plc4x.java.spi.generation.ReadBuffer;
-import org.apache.plc4x.java.spi.generation.WriteBuffer;
+import org.apache.plc4x.java.spi.generation.WriteBufferByteBased;
 import ${helper.packageName(protocolName, languageName, outputFlavor)}.*;
 import ${helper.packageName(protocolName, languageName, outputFlavor)}.types.*;
 import org.apache.plc4x.java.spi.values.*;
@@ -315,14 +315,14 @@ public class ${type.name}IO {
     }
 
 <#if outputFlavor != "passive">
-    public static WriteBuffer staticSerialize(PlcValue _value<#if 
type.parserArguments?has_content>, <#list type.parserArguments as 
parserArgument>${helper.getLanguageTypeNameForTypeReference(parserArgument.type,
 false)} ${parserArgument.name}<#sep>, </#sep></#list></#if>) throws 
ParseException {
+    public static WriteBufferByteBased staticSerialize(PlcValue _value<#if 
type.parserArguments?has_content>, <#list type.parserArguments as 
parserArgument>${helper.getLanguageTypeNameForTypeReference(parserArgument.type,
 false)} ${parserArgument.name}<#sep>, </#sep></#list></#if>) throws 
ParseException {
         return staticSerialize(_value<#if type.parserArguments?has_content>, 
<#list type.parserArguments as parserArgument>${parserArgument.name}<#sep>, 
</#sep></#list></#if>, false);
     }
 
-    public static WriteBuffer staticSerialize(PlcValue _value<#if 
type.parserArguments?has_content>, <#list type.parserArguments as 
parserArgument>${helper.getLanguageTypeNameForTypeReference(parserArgument.type,
 false)} ${parserArgument.name}<#sep>, </#sep></#list></#if>, boolean 
littleEndian) throws ParseException {
+    public static WriteBufferByteBased staticSerialize(PlcValue _value<#if 
type.parserArguments?has_content>, <#list type.parserArguments as 
parserArgument>${helper.getLanguageTypeNameForTypeReference(parserArgument.type,
 false)} ${parserArgument.name}<#sep>, </#sep></#list></#if>, boolean 
littleEndian) throws ParseException {
         <#assign defaultCaseOutput=false>
         <#list type.switchField.cases as case><#if 
case.discriminatorValues?has_content>if(<#list case.discriminatorValues as 
discriminatorValue>EvaluationHelper.equals(${helper.toParseExpression(null, 
type.switchField.discriminatorExpressions[discriminatorValue?index], 
type.parserArguments)},<#if 
helper.discriminatorValueNeedsStringEqualityCheck(type.switchField.discriminatorExpressions[discriminatorValue?index])>"${discriminatorValue}"<#elseif
 helper.isComplexTypeReference(type.parserA [...]
-            WriteBuffer io = new WriteBuffer((int) Math.ceil(((float) 
${helper.getSizeInBits(case, type.parserArguments)}) / 8.0f), littleEndian);
+        WriteBufferByteBased io = new WriteBufferByteBased((int) 
Math.ceil(((float) ${helper.getSizeInBits(case, type.parserArguments)}) / 
8.0f), littleEndian);
 
             <#list case.fields as field>
                 <#switch field.typeName>
diff --git 
a/build-utils/language-java/src/main/resources/templates/java/io-template.java.ftlh
 
b/build-utils/language-java/src/main/resources/templates/java/io-template.java.ftlh
index 7f62994..68c0865 100644
--- 
a/build-utils/language-java/src/main/resources/templates/java/io-template.java.ftlh
+++ 
b/build-utils/language-java/src/main/resources/templates/java/io-template.java.ftlh
@@ -146,6 +146,7 @@ public class ${type.name}IO implements <#if outputFlavor != 
"passive">MessageIO<
 </#if>
 <#-- Here come the actual parse and serialize methods that actually do the 
parsing and serlaizing -->
     public static ${type.name}<#if 
helper.isDiscriminatedChildTypeDefinition()>Builder</#if> 
staticParse(ReadBuffer io<#if type.parserArguments?has_content>, <#list 
type.parserArguments as 
parserArgument>${helper.getLanguageTypeNameForTypeReference(parserArgument.type,
 false)} ${parserArgument.name}<#sep>, </#sep></#list></#if>) throws 
ParseException {
+        io.pullContext("${type.name}");
         int startPos = io.getPos();
         int curPos;
 <#list type.fields as field>
@@ -154,6 +155,7 @@ public class ${type.name}IO implements <#if outputFlavor != 
"passive">MessageIO<
         <#assign arrayField = field>
 
         // Array field (${arrayField.name})
+        io.pullContext("${arrayField.name}");
         <#-- Only update curPos if the length expression uses it -->
         <#if arrayField.loopExpression.contains("curPos")>
         curPos = io.getPos() - startPos;
@@ -171,7 +173,7 @@ public class ${type.name}IO implements <#if outputFlavor != 
"passive">MessageIO<
             for(int curItem = 0; curItem < itemCount; curItem++) {
                 <#-- When parsing simple types, there is nothing that could 
require the "lastItem" -->
                 <#if !helper.isSimpleTypeReference(arrayField.type)>boolean 
lastItem = curItem == (itemCount - 1);</#if>
-                ${arrayField.name}[curItem] = <#if 
helper.isSimpleTypeReference(arrayField.type)><#assign simpleTypeReference = 
arrayField.type>${helper.getReadBufferReadMethodCall(simpleTypeReference, "", 
arrayField)}<#else>${arrayField.type.name}IO.staticParse(io<#if 
field.params?has_content>, <#list field.params as 
parserArgument>(${helper.getLanguageTypeNameForTypeReference(helper.getArgumentType(arrayField.type,
 parserArgument?index), true)}) (${helper.toParseExpression(arrayField,  [...]
+                ${arrayField.name}[curItem] = <#if 
helper.isSimpleTypeReference(arrayField.type)><#assign simpleTypeReference = 
arrayField.type>${helper.getReadBufferReadMethodCall("", simpleTypeReference, 
"", arrayField)}<#else>${arrayField.type.name}IO.staticParse(io<#if 
field.params?has_content>, <#list field.params as 
parserArgument>(${helper.getLanguageTypeNameForTypeReference(helper.getArgumentType(arrayField.type,
 parserArgument?index), true)}) (${helper.toParseExpression(arrayFie [...]
             }
         }
         <#-- In all other cases do we have to work with a list, that is later 
converted to an array -->
@@ -183,7 +185,7 @@ public class ${type.name}IO implements <#if outputFlavor != 
"passive">MessageIO<
         List<${helper.getNonPrimitiveLanguageTypeNameForField(arrayField)}> 
_${arrayField.name}List = new LinkedList<>();
         int ${arrayField.name}EndPos = io.getPos() + _${arrayField.name}Length;
         while(io.getPos() < ${arrayField.name}EndPos) {
-            _${arrayField.name}List.add(<#if 
helper.isSimpleTypeReference(arrayField.type)><#assign simpleTypeReference = 
arrayField.type>${helper.getReadBufferReadMethodCall(simpleTypeReference, "", 
arrayField)}<#else>${arrayField.type.name}IO.staticParse(io<#if 
field.params?has_content>, <#list field.params as 
parserArgument>(${helper.getLanguageTypeNameForTypeReference(helper.getArgumentType(arrayField.type,
 parserArgument?index), true)}) (${helper.toParseExpression(arrayField, parser 
[...]
+            _${arrayField.name}List.add(<#if 
helper.isSimpleTypeReference(arrayField.type)><#assign simpleTypeReference = 
arrayField.type>${helper.getReadBufferReadMethodCall("", simpleTypeReference, 
"", arrayField)}<#else>${arrayField.type.name}IO.staticParse(io<#if 
field.params?has_content>, <#list field.params as 
parserArgument>(${helper.getLanguageTypeNameForTypeReference(helper.getArgumentType(arrayField.type,
 parserArgument?index), true)}) (${helper.toParseExpression(arrayField, pa [...]
             <#-- After parsing, update the current position, but only if it's 
needed -->
             <#if arrayField.loopExpression.contains("curPos")>
             curPos = io.getPos() - startPos;
@@ -194,7 +196,7 @@ public class ${type.name}IO implements <#if outputFlavor != 
"passive">MessageIO<
         // Terminated array
         List<${helper.getNonPrimitiveLanguageTypeNameForField(arrayField)}> 
_${arrayField.name}List = new LinkedList<>();
         while(!((boolean) (${helper.toParseExpression(arrayField, 
arrayField.loopExpression, type.parserArguments)}))) {
-            _${arrayField.name}List.add(<#if 
helper.isSimpleTypeReference(arrayField.type)><#assign simpleTypeReference = 
arrayField.type>${helper.getReadBufferReadMethodCall(simpleTypeReference, "", 
arrayField)}<#else>${arrayField.type.name}IO.staticParse(io<#if 
field.params?has_content>, <#list field.params as 
parserArgument>(${helper.getLanguageTypeNameForTypeReference(helper.getArgumentType(arrayField.type,
 parserArgument?index), true)}) (${helper.toParseExpression(arrayField, parser 
[...]
+            _${arrayField.name}List.add(<#if 
helper.isSimpleTypeReference(arrayField.type)><#assign simpleTypeReference = 
arrayField.type>${helper.getReadBufferReadMethodCall("", simpleTypeReference, 
"", arrayField)}<#else>${arrayField.type.name}IO.staticParse(io<#if 
field.params?has_content>, <#list field.params as 
parserArgument>(${helper.getLanguageTypeNameForTypeReference(helper.getArgumentType(arrayField.type,
 parserArgument?index), true)}) (${helper.toParseExpression(arrayField, pa [...]
 
             <#-- After parsing, update the current position, but only if it's 
needed -->
             <#if arrayField.loopExpression.contains("curPos")>
@@ -217,6 +219,7 @@ public class ${type.name}IO implements <#if outputFlavor != 
"passive">MessageIO<
             </#if>
         </#if>
         <#break>
+        io.closeContext("${arrayField.name}");
     <#case "checksum">
         <#assign checksumField = field>
         <#assign simpleTypeReference = checksumField.type>
@@ -226,7 +229,7 @@ public class ${type.name}IO implements <#if outputFlavor != 
"passive">MessageIO<
             ${helper.getLanguageTypeNameForField(field)} checksum = 
${helper.getNullValueForTypeReference(checksumField.type)};
             // Create an array of all the bytes read in this message element 
so far.
             byte[] checksumRawData = io.getBytes(startPos, io.getPos());
-            ${helper.getLanguageTypeNameForField(field)} checksumRef = 
${helper.getReadBufferReadMethodCall(simpleTypeReference, "", checksumField)};
+            ${helper.getLanguageTypeNameForField(field)} checksumRef = 
${helper.getReadBufferReadMethodCall("checksum", simpleTypeReference, "", 
checksumField)};
             checksum = (${helper.getLanguageTypeNameForField(field)}) 
(${helper.toParseExpression(checksumField, checksumField.checksumExpression, 
type.parserArguments)});
             if(checksum != checksumRef) {
                 throw new ParseException(String.format("Checksum verification 
failed. Expected %04X but got %04X", checksumRef & 0xFFFF, checksum & 0xFFFF));
@@ -238,7 +241,7 @@ public class ${type.name}IO implements <#if outputFlavor != 
"passive">MessageIO<
         <#assign simpleTypeReference = constField.type>
 
         // Const Field (${constField.name})
-        ${helper.getLanguageTypeNameForField(field)} ${constField.name} = 
${helper.getReadBufferReadMethodCall(simpleTypeReference, "", constField)};
+        ${helper.getLanguageTypeNameForField(field)} ${constField.name} = 
${helper.getReadBufferReadMethodCall(constField.name, simpleTypeReference, "", 
constField)};
         if(${constField.name} != ${type.name}.${constField.name?upper_case}) {
             throw new ParseException("Expected constant value " + 
${type.name}.${constField.name?upper_case} + " but got " + ${constField.name});
         }
@@ -249,9 +252,9 @@ public class ${type.name}IO implements <#if outputFlavor != 
"passive">MessageIO<
 
         // Discriminator Field (${discriminatorField.name}) (Used as input to 
a switch field)
         <#if helper.isEnumField(field)>
-        ${helper.getLanguageTypeNameForField(field)} 
${discriminatorField.name} = 
${helper.getLanguageTypeNameForField(discriminatorField)}.enumForValue(${helper.getReadBufferReadMethodCall(helper.getEnumBaseTypeReference(discriminatorField.type),
 "", discriminatorField)});
+        ${helper.getLanguageTypeNameForField(field)} 
${discriminatorField.name} = 
${helper.getLanguageTypeNameForField(discriminatorField)}.enumForValue(${helper.getReadBufferReadMethodCall(discriminatorField.name,
 helper.getEnumBaseTypeReference(discriminatorField.type), "", 
discriminatorField)});
         <#else>
-        ${helper.getLanguageTypeNameForField(field)} 
${discriminatorField.name} = <#if 
helper.isSimpleTypeReference(discriminatorField.type)>${helper.getReadBufferReadMethodCall(discriminatorField.type,
 "", 
discriminatorField)}<#else>${discriminatorField.type.name}IO.staticParse(io<#if 
field.params?has_content>, <#list field.params as 
parserArgument>(${helper.getLanguageTypeNameForTypeReference(helper.getArgumentType(discriminatorField.type,
 parserArgument?index), true)}) (${helper.toPar [...]
+        ${helper.getLanguageTypeNameForField(field)} 
${discriminatorField.name} = <#if 
helper.isSimpleTypeReference(discriminatorField.type)>${helper.getReadBufferReadMethodCall(discriminatorField.name,
 discriminatorField.type, "", 
discriminatorField)}<#else>${discriminatorField.type.name}IO.staticParse(io<#if 
field.params?has_content>, <#list field.params as 
parserArgument>(${helper.getLanguageTypeNameForTypeReference(helper.getArgumentType(discriminatorField.type,
 parserArgument?index) [...]
         </#if>
 
         <#break>
@@ -260,9 +263,9 @@ public class ${type.name}IO implements <#if outputFlavor != 
"passive">MessageIO<
 
         // Enum field (${enumField.name})
         <#if enumField.fieldName?has_content>
-        ${helper.getLanguageTypeNameForField(field)} ${enumField.name} = 
${helper.getLanguageTypeNameForField(field)}.firstEnumForField${enumField.fieldName?cap_first}(${helper.getReadBufferReadMethodCall(helper.getEnumBaseTypeReference(enumField.type),
 "", enumField)});
+        ${helper.getLanguageTypeNameForField(field)} ${enumField.name} = 
${helper.getLanguageTypeNameForField(field)}.firstEnumForField${enumField.fieldName?cap_first}(${helper.getReadBufferReadMethodCall(enumField.name,
 helper.getEnumBaseTypeReference(enumField.type), "", enumField)});
         <#else>
-        ${helper.getLanguageTypeNameForField(field)} ${enumField.name} = 
${helper.getLanguageTypeNameForField(field)}.enumForValue(${helper.getReadBufferReadMethodCall(helper.getEnumBaseTypeReference(enumField.type),
 "", enumField)});
+        ${helper.getLanguageTypeNameForField(field)} ${enumField.name} = 
${helper.getLanguageTypeNameForField(field)}.enumForValue(${helper.getReadBufferReadMethodCall(enumField.name,
 helper.getEnumBaseTypeReference(enumField.type), "", enumField)});
         </#if>
         <#break>
     <#case "implicit">
@@ -270,11 +273,12 @@ public class ${type.name}IO implements <#if outputFlavor 
!= "passive">MessageIO<
         <#assign simpleTypeReference = implicitField.type>
 
         // Implicit Field (${implicitField.name}) (Used for parsing, but it's 
value is not stored as it's implicitly given by the objects content)
-        ${helper.getLanguageTypeNameForField(field)} ${implicitField.name} = 
${helper.getReadBufferReadMethodCall(simpleTypeReference, "", implicitField)};
+        ${helper.getLanguageTypeNameForField(field)} ${implicitField.name} = 
${helper.getReadBufferReadMethodCall(implicitField.name, simpleTypeReference, 
"", implicitField)};
         <#break>
     <#case "manualArray">
         <#assign manualArrayField = field>
 
+        io.pullContext("${manualArrayField.name}");
         // Manual Array Field (${manualArrayField.name})
         <#-- Only update curPos if the length expression uses it -->
         <#if manualArrayField.loopExpression.contains("curPos")>
@@ -330,6 +334,7 @@ public class ${type.name}IO implements <#if outputFlavor != 
"passive">MessageIO<
         ${helper.getLanguageTypeNameForField(field)}[] 
${manualArrayField.name} = _${manualArrayField.name}List.toArray(new 
${helper.getNonPrimitiveLanguageTypeNameForField(manualArrayField)}[0]);
             </#if>
         </#if>
+        io.closeContext("${manualArrayField.name}");
         <#break>
     <#case "manual">
         <#assign manualField = field>
@@ -347,9 +352,9 @@ public class ${type.name}IO implements <#if outputFlavor != 
"passive">MessageIO<
         ${helper.getLanguageTypeNameForField(field)} ${optionalField.name} = 
null;
         if(${helper.toParseExpression(optionalField, 
optionalField.conditionExpression, type.parserArguments)}) {
             <#if helper.isEnumField(field)>
-            ${optionalField.name} = 
${helper.getLanguageTypeNameForField(optionalField)}.enumForValue(${helper.getReadBufferReadMethodCall(helper.getEnumBaseTypeReference(optionalField.type),
 "", optionalField)});
+            ${optionalField.name} = 
${helper.getLanguageTypeNameForField(optionalField)}.enumForValue(${helper.getReadBufferReadMethodCall(optionalField.name,
 helper.getEnumBaseTypeReference(optionalField.type), "", optionalField)});
             <#else>
-            ${optionalField.name} = <#if 
helper.isSimpleTypeReference(optionalField.type)>${helper.getReadBufferReadMethodCall(optionalField.type,
 "", optionalField)}<#else>${optionalField.type.name}IO.staticParse(io<#if 
field.params?has_content>, <#list field.params as 
parserArgument>(${helper.getLanguageTypeNameForTypeReference(helper.getArgumentType(optionalField.type,
 parserArgument?index), true)}) (${helper.toParseExpression(optionalField, 
parserArgument, type.parserArguments)})<#se [...]
+            ${optionalField.name} = <#if 
helper.isSimpleTypeReference(optionalField.type)>${helper.getReadBufferReadMethodCall(optionalField.name,
 optionalField.type, "", 
optionalField)}<#else>${optionalField.type.name}IO.staticParse(io<#if 
field.params?has_content>, <#list field.params as 
parserArgument>(${helper.getLanguageTypeNameForTypeReference(helper.getArgumentType(optionalField.type,
 parserArgument?index), true)}) (${helper.toParseExpression(optionalField, 
parserArgument, type.pa [...]
             </#if>
         }
         <#break>
@@ -359,11 +364,13 @@ public class ${type.name}IO implements <#if outputFlavor 
!= "passive">MessageIO<
 
         // Padding Field (padding)
         {
+            io.pullContext("padding");
             int _timesPadding = (int) 
(${helper.toParseExpression(paddingField, paddingField.paddingCondition, 
type.parserArguments)});
             while ((io.hasMore(${helper.getNumBits(simpleTypeReference)})) && 
(_timesPadding-- > 0)) {
                 // Just read the padding data and ignore it
                 ${helper.getReadBufferReadMethodCall(simpleTypeReference, "", 
paddingField)};
             }
+            io.closeContext("padding");
         }
         <#break>
     <#case "reserved">
@@ -372,7 +379,7 @@ public class ${type.name}IO implements <#if outputFlavor != 
"passive">MessageIO<
 
         // Reserved Field (Compartmentalized so the "reserved" variable can't 
leak)
         {
-            ${helper.getLanguageTypeNameForField(field)} reserved = 
${helper.getReadBufferReadMethodCall(simpleTypeReference, "", reservedField)};
+            ${helper.getLanguageTypeNameForField(field)} reserved = 
${helper.getReadBufferReadMethodCall("reserved", simpleTypeReference, "", 
reservedField)};
             if(reserved != ${helper.getReservedValue(reservedField)}) {
                 LOGGER.info("Expected constant value " + 
${reservedField.referenceValue} + " but got " + reserved + " for reserved 
field.");
             }
@@ -383,9 +390,9 @@ public class ${type.name}IO implements <#if outputFlavor != 
"passive">MessageIO<
 
         // Simple Field (${simpleField.name})
         <#if helper.isEnumField(field)>
-        ${helper.getLanguageTypeNameForField(simpleField)} ${simpleField.name} 
= 
${helper.getLanguageTypeNameForField(simpleField)}.enumForValue(${helper.getReadBufferReadMethodCall(helper.getEnumBaseTypeReference(simpleField.type),
 "", simpleField)});
+        ${helper.getLanguageTypeNameForField(simpleField)} ${simpleField.name} 
= 
${helper.getLanguageTypeNameForField(simpleField)}.enumForValue(${helper.getReadBufferReadMethodCall(simpleField.name,
 helper.getEnumBaseTypeReference(simpleField.type), "", simpleField)});
         <#else>
-        ${helper.getLanguageTypeNameForField(simpleField)} ${simpleField.name} 
= <#if helper.isSimpleTypeReference(simpleField.type)><#assign 
simpleTypeReference = 
simpleField.type>${helper.getReadBufferReadMethodCall(simpleTypeReference, "", 
simpleField)}<#else><#assign complexTypeReference = 
simpleField.type>${complexTypeReference.name}IO.staticParse(io<#if 
field.params?has_content>, <#list field.params as 
parserArgument>(${helper.getLanguageTypeNameForTypeReference(helper.getArgumentT
 [...]
+        ${helper.getLanguageTypeNameForField(simpleField)} ${simpleField.name} 
= <#if helper.isSimpleTypeReference(simpleField.type)><#assign 
simpleTypeReference = 
simpleField.type>${helper.getReadBufferReadMethodCall(simpleField.name, 
simpleTypeReference, "", simpleField)}<#else><#assign complexTypeReference = 
simpleField.type>${complexTypeReference.name}IO.staticParse(io<#if 
field.params?has_content>, <#list field.params as 
parserArgument>(${helper.getLanguageTypeNameForTypeReference(h [...]
         </#if>
         <#break>
     <#case "switch">
@@ -429,7 +436,7 @@ public class ${type.name}IO implements <#if outputFlavor != 
"passive">MessageIO<
 <#if outputFlavor != "passive">
     public static void staticSerialize(WriteBuffer io, ${type.name} _value<#if 
helper.getSerializerArguments(type.parserArguments)?has_content>, <#list 
helper.getSerializerArguments(type.parserArguments) as 
parserArgument>${helper.getLanguageTypeNameForTypeReference(parserArgument.type,
 false)} ${parserArgument.name}<#sep>, </#sep></#list></#if>) throws 
ParseException {
         int startPos = io.getPos();
-
+        io.pushContext("${type.name}");
 <#list type.fields as field>
 <#switch field.typeName>
     <#case "array">
@@ -438,12 +445,13 @@ public class ${type.name}IO implements <#if outputFlavor 
!= "passive">MessageIO<
 
         // Array Field (${arrayField.name})
         if(_value.get${arrayField.name?cap_first}() != null) {
+            io.pushContext("${arrayField.name}");
             int itemCount = (int) 
_value.get${arrayField.name?cap_first}().length;
             int curItem = 0;
             for(${helper.getLanguageTypeNameForField(field)} element : 
_value.get${arrayField.name?cap_first}()) {
                 <#if helper.isSimpleTypeReference(arrayField.type)>
                     <#assign simpleTypeReference = arrayField.type>
-                ${helper.getWriteBufferWriteMethodCall(simpleTypeReference, 
"element", field)};
+                ${helper.getWriteBufferWriteMethodCall("", 
simpleTypeReference, "element", field)};
                 <#else>
                     <#assign complexTypeReference = arrayField.type>
                 boolean lastItem = curItem == (itemCount - 1);
@@ -451,6 +459,7 @@ public class ${type.name}IO implements <#if outputFlavor != 
"passive">MessageIO<
                 </#if>
                 curItem++;
             }
+            io.popContext("${arrayField.name}");
         }
         <#break>
     <#case "checksum">
@@ -463,7 +472,7 @@ public class ${type.name}IO implements <#if outputFlavor != 
"passive">MessageIO<
             // Create an array of all the bytes written in this message 
element so far.
             byte[] checksumRawData = io.getBytes(startPos, io.getPos());
             _checksum = (${helper.getLanguageTypeNameForField(field)}) 
(${helper.toSerializationExpression(checksumField, 
checksumField.checksumExpression, type.parserArguments)});
-            ${helper.getWriteBufferWriteMethodCall(simpleTypeReference, 
"(_checksum)", field)};
+            ${helper.getWriteBufferWriteMethodCall("checksum", 
simpleTypeReference, "(_checksum)", field)};
         }
         <#break>
     <#case "const">
@@ -472,7 +481,7 @@ public class ${type.name}IO implements <#if outputFlavor != 
"passive">MessageIO<
 
         // Const Field (${constField.name})
         <#if helper.getLanguageTypeNameForField(field) = 
'float'>${helper.getWriteBufferWriteMethodCall(simpleTypeReference, 
constField.referenceValue + "f", field)};
-        <#else>${helper.getWriteBufferWriteMethodCall(simpleTypeReference, 
constField.referenceValue, field)};
+        <#else>${helper.getWriteBufferWriteMethodCall(constField.name, 
simpleTypeReference, constField.referenceValue, field)};
         </#if>
         <#break>
     <#case "discriminator">
@@ -483,11 +492,11 @@ public class ${type.name}IO implements <#if outputFlavor 
!= "passive">MessageIO<
         ${helper.getLanguageTypeNameForField(field)} 
${discriminatorField.name} = (${helper.getLanguageTypeNameForField(field)}) 
_value.get${discriminatorField.name?cap_first}();
         <#if helper.isSimpleTypeReference(discriminatorField.type)>
             <#assign simpleTypeReference = discriminatorField.type>
-            ${helper.getWriteBufferWriteMethodCall(simpleTypeReference, "(" + 
discriminatorField.name + ")", field)};
+            ${helper.getWriteBufferWriteMethodCall(discriminatorField.name, 
simpleTypeReference, "(" + discriminatorField.name + ")", field)};
         <#else>
             <#assign complexTypeReference = discriminatorField.type>
             <#if helper.isEnumField(field)>
-                
${helper.getWriteBufferWriteMethodCall(helper.getEnumBaseTypeReference(discriminatorField.type),
 "(" + discriminatorField.name + ".getValue())", field)};
+                
${helper.getWriteBufferWriteMethodCall(discriminatorField.name, 
helper.getEnumBaseTypeReference(discriminatorField.type), "(" + 
discriminatorField.name + ".getValue())", field)};
             <#else>
                 ${complexTypeReference.name}IO.staticSerialize(io, 
${discriminatorField.name});
             </#if>
@@ -499,9 +508,9 @@ public class ${type.name}IO implements <#if outputFlavor != 
"passive">MessageIO<
         // Enum field (${enumField.name})
         ${helper.getLanguageTypeNameForField(field)} ${enumField.name} = 
(${helper.getLanguageTypeNameForField(field)}) 
_value.get${enumField.name?cap_first}();
         <#if enumField.fieldName?has_content>
-        
${helper.getWriteBufferWriteMethodCall(helper.getEnumFieldSimpleTypeReference(enumField.type,
 enumField.fieldName), "(" + enumField.name + ".get" + 
enumField.fieldName?cap_first + "())", field)};
+        ${helper.getWriteBufferWriteMethodCall(enumField.name, 
helper.getEnumFieldSimpleTypeReference(enumField.type, enumField.fieldName), 
"(" + enumField.name + ".get" + enumField.fieldName?cap_first + "())", field)};
         <#else>
-        
${helper.getWriteBufferWriteMethodCall(helper.getEnumBaseTypeReference(enumField.type),
 "(" + enumField.name + ".getValue())", field)};
+        ${helper.getWriteBufferWriteMethodCall(enumField.name, 
helper.getEnumBaseTypeReference(enumField.type), "(" + enumField.name + 
".getValue())", field)};
         </#if>
         <#break>
     <#case "implicit">
@@ -510,16 +519,18 @@ public class ${type.name}IO implements <#if outputFlavor 
!= "passive">MessageIO<
 
         // Implicit Field (${implicitField.name}) (Used for parsing, but it's 
value is not stored as it's implicitly given by the objects content)
         ${helper.getLanguageTypeNameForField(field)} ${implicitField.name} = 
(${helper.getLanguageTypeNameForField(field)}) 
(${helper.toSerializationExpression(implicitField, 
implicitField.serializeExpression, type.parserArguments)});
-        ${helper.getWriteBufferWriteMethodCall(simpleTypeReference, "(" + 
implicitField.name + ")", field)};
+        ${helper.getWriteBufferWriteMethodCall(implicitField.name, 
simpleTypeReference, "(" + implicitField.name + ")", field)};
         <#break>
     <#case "manualArray">
         <#assign manualArrayField = field>
 
         // Manual Array Field (${manualArrayField.name})
         if(_value.get${manualArrayField.name?cap_first}() != null) {
+            io.pushContext("${manualArrayField.name}");
             for(${helper.getLanguageTypeNameForField(field)} element : 
_value.get${manualArrayField.name?cap_first}()) {
                 ${helper.toSerializationExpression(manualArrayField, 
manualArrayField.serializeExpression, type.parserArguments)};
             }
+            io.pushContext("${manualArrayField.name}");
         }
         <#break>
     <#case "manual">
@@ -537,11 +548,11 @@ public class ${type.name}IO implements <#if outputFlavor 
!= "passive">MessageIO<
             ${optionalField.name} = 
(${helper.getLanguageTypeNameForField(field)}) 
_value.get${optionalField.name?cap_first}();
             <#if helper.isSimpleTypeReference(optionalField.type)>
                 <#assign simpleTypeReference = optionalField.type>
-            ${helper.getWriteBufferWriteMethodCall(simpleTypeReference, "(" + 
optionalField.name + ")", field)};
+            ${helper.getWriteBufferWriteMethodCall(optionalField.name, 
simpleTypeReference, "(" + optionalField.name + ")", field)};
             <#else>
                 <#assign complexTypeReference = optionalField.type>
                 <#if helper.isEnumField(field)>
-            
${helper.getWriteBufferWriteMethodCall(helper.getEnumBaseTypeReference(optionalField.type),
 "(" + optionalField.name + ".getValue())", field)};
+            ${helper.getWriteBufferWriteMethodCall(optionalField.name, 
helper.getEnumBaseTypeReference(optionalField.type), "(" + optionalField.name + 
".getValue())", field)};
                 <#else>
             ${complexTypeReference.name}IO.staticSerialize(io, 
${optionalField.name});
                 </#if>
@@ -554,11 +565,13 @@ public class ${type.name}IO implements <#if outputFlavor 
!= "passive">MessageIO<
 
         // Padding Field (padding)
         {
+            io.pushContext("padding");
             int _timesPadding = (int) 
(${helper.toSerializationExpression(paddingField, 
paddingField.paddingCondition, type.parserArguments)});
             while (_timesPadding-- > 0) {
                 ${helper.getLanguageTypeNameForField(field)} _paddingValue = 
(${helper.getLanguageTypeNameForField(field)}) 
(${helper.toSerializationExpression(paddingField, paddingField.paddingValue, 
type.parserArguments)});
-                ${helper.getWriteBufferWriteMethodCall(simpleTypeReference, 
"(_paddingValue)", field)};
+                ${helper.getWriteBufferWriteMethodCall("", 
simpleTypeReference, "(_paddingValue)", field)};
             }
+            io.popContext("padding");
         }
         <#break>
     <#case "reserved">
@@ -566,7 +579,7 @@ public class ${type.name}IO implements <#if outputFlavor != 
"passive">MessageIO<
         <#assign simpleTypeReference = reservedField.type>
 
         // Reserved Field (reserved)
-        ${helper.getWriteBufferWriteMethodCall(simpleTypeReference, 
helper.getReservedValue(field), field)};
+        ${helper.getWriteBufferWriteMethodCall("reserved", 
simpleTypeReference, helper.getReservedValue(field), field)};
         <#break>
     <#case "simple">
         <#assign simpleField = field>
@@ -575,11 +588,11 @@ public class ${type.name}IO implements <#if outputFlavor 
!= "passive">MessageIO<
         ${helper.getLanguageTypeNameForField(field)} ${simpleField.name} = 
(${helper.getLanguageTypeNameForField(field)}) 
_value.get${simpleField.name?cap_first}();
         <#if helper.isSimpleTypeReference(simpleField.type)>
             <#assign simpleTypeReference = simpleField.type>
-        ${helper.getWriteBufferWriteMethodCall(simpleTypeReference, "(" + 
simpleField.name + ")", simpleField)};
+        ${helper.getWriteBufferWriteMethodCall(simpleField.name, 
simpleTypeReference, "(" + simpleField.name + ")", simpleField)};
         <#else>
             <#assign complexTypeReference = simpleField.type>
             <#if helper.isEnumField(field)>
-        
${helper.getWriteBufferWriteMethodCall(helper.getEnumBaseTypeReference(simpleField.type),
 "(" + simpleField.name + ".getValue())", simpleField)};
+        ${helper.getWriteBufferWriteMethodCall(simpleField.name, 
helper.getEnumBaseTypeReference(simpleField.type), "(" + simpleField.name + 
".getValue())", simpleField)};
             <#else>
         ${complexTypeReference.name}IO.staticSerialize(io, 
${simpleField.name});
             </#if>
@@ -599,6 +612,7 @@ public class ${type.name}IO implements <#if outputFlavor != 
"passive">MessageIO<
         <#break>
 </#switch>
 </#list>
+        io.popContext("${type.name}");
     }
 </#if>
 
diff --git a/go.mod b/go.mod
index e2ec48f..cab7d85 100644
--- a/go.mod
+++ b/go.mod
@@ -21,6 +21,6 @@ module github.com/apache/plc4x
 go 1.15
 
 require (
-       github.com/apache/plc4x/plc4go v0.0.0-20210419100902-f62f7dd9c377 // 
indirect
+       github.com/apache/plc4x/plc4go v0.0.0-20210419161206-de2ecac62cce // 
indirect
        github.com/sirupsen/logrus v1.7.0 // indirect
 )
diff --git a/go.sum b/go.sum
index 4e0b305..25fb7d0 100644
--- a/go.sum
+++ b/go.sum
@@ -90,6 +90,8 @@ github.com/apache/plc4x/plc4go 
v0.0.0-20210419074057-6deb18d3d472 h1:Z4OnG7I8U3Q
 github.com/apache/plc4x/plc4go v0.0.0-20210419074057-6deb18d3d472/go.mod 
h1:d7O6kgWHhwFxXbMbl1DSu55qCYcQz9uwjdsSSJOEA/4=
 github.com/apache/plc4x/plc4go v0.0.0-20210419100902-f62f7dd9c377 
h1:fFZl6lI4JFMC9PCmoob0D/ZLmLo62yDVvINSy41NRtg=
 github.com/apache/plc4x/plc4go v0.0.0-20210419100902-f62f7dd9c377/go.mod 
h1:d7O6kgWHhwFxXbMbl1DSu55qCYcQz9uwjdsSSJOEA/4=
+github.com/apache/plc4x/plc4go v0.0.0-20210419161206-de2ecac62cce 
h1:6niN+3NLO6jQxXPhr6R9YBAloipJzajur6GVlGAhvBg=
+github.com/apache/plc4x/plc4go v0.0.0-20210419161206-de2ecac62cce/go.mod 
h1:NqpWaMMhsu3sTm418XwsUWgmY7e2zjgpRMyddBUwmGk=
 github.com/coreos/go-systemd v0.0.0-20190321100706-95778dfbb74e/go.mod 
h1:F5haX7vjVVG0kc13fIWeqUViNPyEJxv/OmvnBo0Yme4=
 github.com/davecgh/go-spew v1.1.1/go.mod 
h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
 github.com/dnephin/pflag v1.0.7/go.mod 
h1:uxE91IoWURlOiTUIA8Mq5ZZkAv3dPUfZNaT80Zm7OQE=
diff --git 
a/plc4j/drivers/ads/src/main/java/org/apache/plc4x/java/ads/protocol/AdsProtocolLogic.java
 
b/plc4j/drivers/ads/src/main/java/org/apache/plc4x/java/ads/protocol/AdsProtocolLogic.java
index eb95ba1..ec1b6ce 100644
--- 
a/plc4j/drivers/ads/src/main/java/org/apache/plc4x/java/ads/protocol/AdsProtocolLogic.java
+++ 
b/plc4j/drivers/ads/src/main/java/org/apache/plc4x/java/ads/protocol/AdsProtocolLogic.java
@@ -38,9 +38,7 @@ import org.apache.plc4x.java.api.value.PlcValue;
 import org.apache.plc4x.java.spi.ConversationContext;
 import org.apache.plc4x.java.spi.Plc4xProtocolBase;
 import org.apache.plc4x.java.spi.configuration.HasConfiguration;
-import org.apache.plc4x.java.spi.generation.ParseException;
-import org.apache.plc4x.java.spi.generation.ReadBuffer;
-import org.apache.plc4x.java.spi.generation.WriteBuffer;
+import org.apache.plc4x.java.spi.generation.*;
 import org.apache.plc4x.java.spi.messages.DefaultPlcReadResponse;
 import org.apache.plc4x.java.spi.messages.DefaultPlcWriteResponse;
 import org.apache.plc4x.java.spi.messages.utils.ResponseItem;
@@ -290,12 +288,12 @@ public class AdsProtocolLogic extends 
Plc4xProtocolBase<AmsTCPPacket> implements
         Map<String, PlcResponseCode> responseCodes = new HashMap<>();
         if (adsData instanceof AdsReadResponse) {
             AdsReadResponse adsReadResponse = (AdsReadResponse) adsData;
-            readBuffer = new ReadBuffer(adsReadResponse.getData(), true);
+            readBuffer = new ReadBufferByteBased(adsReadResponse.getData(), 
true);
             
responseCodes.put(readRequest.getFieldNames().stream().findFirst().orElse(""),
                 parsePlcResponseCode(adsReadResponse.getResult()));
         } else if (adsData instanceof AdsReadWriteResponse) {
             AdsReadWriteResponse adsReadWriteResponse = (AdsReadWriteResponse) 
adsData;
-            readBuffer = new ReadBuffer(adsReadWriteResponse.getData(), true);
+            readBuffer = new 
ReadBufferByteBased(adsReadWriteResponse.getData(), true);
             // When parsing a multi-item response, the error codes of each 
items come
             // in sequence and then come the values.
             for (String fieldName : readRequest.getFieldNames()) {
@@ -432,7 +430,7 @@ public class AdsProtocolLogic extends 
Plc4xProtocolBase<AmsTCPPacket> implements
             plcValue.getString().length() + 1 : 
(directAdsField.getAdsDataType() == AdsDataType.WSTRING) ?
             (plcValue.getString().length() + 1) * 2 : 0;
         try {
-            WriteBuffer writeBuffer = DataItemIO.staticSerialize(plcValue,
+            WriteBufferByteBased writeBuffer = 
DataItemIO.staticSerialize(plcValue,
                 plcField.getAdsDataType().getDataFormatName(), stringLength, 
true);
             AdsData adsData = new AdsWriteRequest(
                 directAdsField.getIndexGroup(), 
directAdsField.getIndexOffset(), writeBuffer.getData());
@@ -483,7 +481,7 @@ public class AdsProtocolLogic extends 
Plc4xProtocolBase<AmsTCPPacket> implements
                 plcValue.getString().length() + 1 : (field.getAdsDataType() == 
AdsDataType.WSTRING) ?
                 (plcValue.getString().length() + 1) * 2 : 0;
             try {
-                final WriteBuffer itemWriteBuffer = 
DataItemIO.staticSerialize(plcValue,
+                final WriteBufferByteBased itemWriteBuffer = 
DataItemIO.staticSerialize(plcValue,
                     field.getAdsDataType().getDataFormatName(), stringLength, 
true);
                 int numBytes = itemWriteBuffer.getPos();
                 System.arraycopy(itemWriteBuffer.getData(), 0, writeBuffer, 
pos, numBytes);
@@ -537,7 +535,7 @@ public class AdsProtocolLogic extends 
Plc4xProtocolBase<AmsTCPPacket> implements
                 parsePlcResponseCode(adsWriteResponse.getResult()));
         } else if (adsData instanceof AdsReadWriteResponse) {
             AdsReadWriteResponse adsReadWriteResponse = (AdsReadWriteResponse) 
adsData;
-            ReadBuffer readBuffer = new 
ReadBuffer(adsReadWriteResponse.getData(), true);
+            ReadBuffer readBuffer = new 
ReadBufferByteBased(adsReadWriteResponse.getData(), true);
             // When parsing a multi-item response, the error codes of each 
items come
             // in sequence and then come the values.
             for (String fieldName : writeRequest.getFieldNames()) {
@@ -659,7 +657,7 @@ public class AdsProtocolLogic extends 
Plc4xProtocolBase<AmsTCPPacket> implements
                     future.completeExceptionally(new PlcException("Couldn't 
retrieve handle for symbolic field " +
                         symbolicAdsField.getSymbolicAddress() + " got return 
code " + responseAdsData.getResult().name()));
                 } else {
-                    ReadBuffer readBuffer = new 
ReadBuffer(responseAdsData.getData(), true);
+                    ReadBuffer readBuffer = new 
ReadBufferByteBased(responseAdsData.getData(), true);
                     try {
                         // Read the handle.
                         long handle = readBuffer.readUnsignedLong(32);
@@ -707,7 +705,7 @@ public class AdsProtocolLogic extends 
Plc4xProtocolBase<AmsTCPPacket> implements
             .check(adsDataResponse -> adsDataResponse instanceof 
AdsReadWriteResponse)
             .unwrap(adsDataResponse -> (AdsReadWriteResponse) adsDataResponse)
             .handle(responseAdsData -> {
-                ReadBuffer readBuffer = new 
ReadBuffer(responseAdsData.getData(), true);
+                ReadBuffer readBuffer = new 
ReadBufferByteBased(responseAdsData.getData(), true);
                 Map<SymbolicAdsField, Long> returnCodes = new HashMap<>();
                 // In the response first come the return codes and the 
data-lengths for each item.
                 symbolicAdsFields.forEach(symbolicAdsField -> {
diff --git 
a/plc4j/drivers/ads/src/test/java/org/apache/plc4x/protocol/ads/ManualParserSerializerTest.java
 
b/plc4j/drivers/ads/src/test/java/org/apache/plc4x/protocol/ads/ManualParserSerializerTest.java
index f6dd3c2..03961e8 100644
--- 
a/plc4j/drivers/ads/src/test/java/org/apache/plc4x/protocol/ads/ManualParserSerializerTest.java
+++ 
b/plc4j/drivers/ads/src/test/java/org/apache/plc4x/protocol/ads/ManualParserSerializerTest.java
@@ -22,13 +22,14 @@ import org.apache.commons.codec.binary.Hex;
 import org.apache.plc4x.java.ads.readwrite.AmsTCPPacket;
 import org.apache.plc4x.java.ads.readwrite.io.AmsTCPPacketIO;
 import org.apache.plc4x.java.spi.generation.ReadBuffer;
+import org.apache.plc4x.java.spi.generation.ReadBufferByteBased;
 
 public class ManualParserSerializerTest {
 
     public static void main(String[] args) throws Exception {
         byte[] data = 
Hex.decodeHex("0000f1000000c0a817c80101feffc0a817140101530309000500d1000000000000002f00000000000000c90000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000012a00a07d0f7e1c8e31489f8cf1006b3604b888defc88f64eb6fbb217d11fc5cf5f148b0abf05407c941a93b8263301db0f4940d66875727a0000000000d2040000ab6459032bbf7e03b888defcb8a5b249044de82ee03a2ab
 [...]
         //byte[] data = 
Hex.decodeHex("0000f1000000c0a817c80101feffc0a817140101530309000500d1000000000000002f00000000000000c90000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000012a00a07d0f7e1c8e31489f8cf1006b3604b888defc");
-        ReadBuffer readBuffer = new ReadBuffer(data, true);
+        ReadBuffer readBuffer = new ReadBufferByteBased(data, true);
         final AmsTCPPacket amsTCPPacket = 
AmsTCPPacketIO.staticParse(readBuffer);
         System.out.println(amsTCPPacket);
     }
diff --git 
a/plc4j/drivers/canopen/src/main/java/org/apache/plc4x/java/canopen/api/conversation/canopen/CANOpenConversationBase.java
 
b/plc4j/drivers/canopen/src/main/java/org/apache/plc4x/java/canopen/api/conversation/canopen/CANOpenConversationBase.java
index 4ff6fdb..ca81dc6 100644
--- 
a/plc4j/drivers/canopen/src/main/java/org/apache/plc4x/java/canopen/api/conversation/canopen/CANOpenConversationBase.java
+++ 
b/plc4j/drivers/canopen/src/main/java/org/apache/plc4x/java/canopen/api/conversation/canopen/CANOpenConversationBase.java
@@ -27,7 +27,7 @@ import org.apache.plc4x.java.canopen.readwrite.io.DataItemIO;
 import org.apache.plc4x.java.canopen.readwrite.types.CANOpenDataType;
 import org.apache.plc4x.java.canopen.readwrite.types.CANOpenService;
 import org.apache.plc4x.java.spi.generation.ParseException;
-import org.apache.plc4x.java.spi.generation.ReadBuffer;
+import org.apache.plc4x.java.spi.generation.ReadBufferByteBased;
 
 import java.util.concurrent.CompletableFuture;
 import java.util.function.Predicate;
@@ -45,7 +45,7 @@ public abstract class CANOpenConversationBase {
     }
 
     protected PlcValue decodeFrom(byte[] data, CANOpenDataType type, int 
length) throws ParseException {
-        return DataItemIO.staticParse(new ReadBuffer(data, true), type, 
length);
+        return DataItemIO.staticParse(new ReadBufferByteBased(data, true), 
type, length);
     }
 
     protected <T> void onError(CompletableFuture<T> receiver, 
CANOpenSDOResponse response, Throwable error) {
diff --git 
a/plc4j/drivers/canopen/src/main/java/org/apache/plc4x/java/canopen/protocol/CANOpenProtocolLogic.java
 
b/plc4j/drivers/canopen/src/main/java/org/apache/plc4x/java/canopen/protocol/CANOpenProtocolLogic.java
index 6ef4ebd..9dad461 100644
--- 
a/plc4j/drivers/canopen/src/main/java/org/apache/plc4x/java/canopen/protocol/CANOpenProtocolLogic.java
+++ 
b/plc4j/drivers/canopen/src/main/java/org/apache/plc4x/java/canopen/protocol/CANOpenProtocolLogic.java
@@ -62,9 +62,7 @@ import org.apache.plc4x.java.spi.ConversationContext;
 import org.apache.plc4x.java.spi.Plc4xProtocolBase;
 import org.apache.plc4x.java.spi.configuration.HasConfiguration;
 import org.apache.plc4x.java.spi.context.DriverContext;
-import org.apache.plc4x.java.spi.generation.ParseException;
-import org.apache.plc4x.java.spi.generation.ReadBuffer;
-import org.apache.plc4x.java.spi.generation.WriteBuffer;
+import org.apache.plc4x.java.spi.generation.*;
 import org.apache.plc4x.java.spi.messages.DefaultPlcReadResponse;
 import org.apache.plc4x.java.spi.messages.DefaultPlcSubscriptionEvent;
 import org.apache.plc4x.java.spi.messages.DefaultPlcSubscriptionRequest;
@@ -223,7 +221,7 @@ public class CANOpenProtocolLogic extends 
Plc4xProtocolBase<CANOpenFrame> implem
 
         try {
             String fieldName = writeRequest.getFieldNames().iterator().next();
-            WriteBuffer buffer = DataItemIO.staticSerialize(writeValue, 
field.getCanOpenDataType(), writeValue.getLength(), true);
+            WriteBufferByteBased buffer = 
DataItemIO.staticSerialize(writeValue, field.getCanOpenDataType(), 
writeValue.getLength(), true);
             if (buffer != null) {
                 final CANOpenPDOPayload payload = new CANOpenPDOPayload(new 
CANOpenPDO(buffer.getData()));
                 context.sendToWire(factory.createBuilder()
@@ -377,7 +375,7 @@ public class CANOpenProtocolLogic extends 
Plc4xProtocolBase<CANOpenFrame> implem
                         CANOpenPDOField field = (CANOpenPDOField) 
handle.getField();
                         byte[] data = ((CANOpenPDOPayload) 
payload).getPdo().getData();
                         try {
-                            PlcValue value = DataItemIO.staticParse(new 
ReadBuffer(data, true), field.getCanOpenDataType(), data.length);
+                            PlcValue value = DataItemIO.staticParse(new 
ReadBufferByteBased(data, true), field.getCanOpenDataType(), data.length);
                             DefaultPlcSubscriptionEvent event = new 
DefaultPlcSubscriptionEvent(
                                 Instant.now(),
                                 Collections.singletonMap(
diff --git 
a/plc4j/drivers/canopen/src/test/java/org/apache/plc4x/java/canopen/ManualParserTest.java
 
b/plc4j/drivers/canopen/src/test/java/org/apache/plc4x/java/canopen/ManualParserTest.java
index 7bbfd40..1a4f925 100644
--- 
a/plc4j/drivers/canopen/src/test/java/org/apache/plc4x/java/canopen/ManualParserTest.java
+++ 
b/plc4j/drivers/canopen/src/test/java/org/apache/plc4x/java/canopen/ManualParserTest.java
@@ -20,6 +20,7 @@ package org.apache.plc4x.java.canopen;
 
 import org.apache.commons.codec.binary.Hex;
 import org.apache.plc4x.java.spi.generation.ReadBuffer;
+import org.apache.plc4x.java.spi.generation.ReadBufferByteBased;
 import org.junit.jupiter.api.Test;
 
 import static org.junit.jupiter.api.Assertions.assertEquals;
@@ -44,7 +45,7 @@ public class ManualParserTest {
 
     @Test
     public void readBufferTest() throws Exception {
-        ReadBuffer buffer = new ReadBuffer(new byte[]{(byte) 0xA1, 0x05, 0x00, 
0x00}, true);
+        ReadBuffer buffer = new ReadBufferByteBased(new byte[]{(byte) 0xA1, 
0x05, 0x00, 0x00}, true);
         int value = buffer.readInt(32);
 
         assertEquals(value, 0x5A1);
@@ -77,7 +78,7 @@ public class ManualParserTest {
     public final static SocketCanFrameStub parse(String hex) throws Exception {
         byte[] input = Hex.decodeHex(hex.toCharArray());
 
-        ReadBuffer readBuffer = new ReadBuffer(input, true);
+        ReadBufferByteBased readBuffer = new ReadBufferByteBased(input, true);
         int rawId = readBuffer.readInt(32);
         boolean extended = (rawId & EXTENDED_FRAME_FORMAT_FLAG) != 0;
         boolean remote = (rawId & REMOTE_TRANSMISSION_FLAG) != 0;
diff --git 
a/plc4j/drivers/eip/src/main/java/org/apache/plc4x/java/eip/readwrite/protocol/EipProtocolLogic.java
 
b/plc4j/drivers/eip/src/main/java/org/apache/plc4x/java/eip/readwrite/protocol/EipProtocolLogic.java
index b0197cc..bc4e9fd 100644
--- 
a/plc4j/drivers/eip/src/main/java/org/apache/plc4x/java/eip/readwrite/protocol/EipProtocolLogic.java
+++ 
b/plc4j/drivers/eip/src/main/java/org/apache/plc4x/java/eip/readwrite/protocol/EipProtocolLogic.java
@@ -34,6 +34,7 @@ import org.apache.plc4x.java.spi.Plc4xProtocolBase;
 import org.apache.plc4x.java.spi.configuration.HasConfiguration;
 import org.apache.plc4x.java.spi.generation.ParseException;
 import org.apache.plc4x.java.spi.generation.ReadBuffer;
+import org.apache.plc4x.java.spi.generation.ReadBufferByteBased;
 import org.apache.plc4x.java.spi.messages.*;
 import org.apache.plc4x.java.spi.messages.utils.ResponseItem;
 import org.apache.plc4x.java.spi.transaction.RequestTransactionManager;
@@ -278,7 +279,7 @@ public class EipProtocolLogic extends 
Plc4xProtocolBase<EipPacket> implements Ha
             MultipleServiceResponse responses = (MultipleServiceResponse) p;
             int nb = responses.getServiceNb();
             CipService[] arr = new CipService[nb];
-            ReadBuffer read = new ReadBuffer(responses.getServicesData(), 
true);
+            ReadBufferByteBased read = new 
ReadBufferByteBased(responses.getServicesData(), true);
             int total = (int) read.getTotalBytes();
             for (int i = 0; i < nb; i++) {
                 int length = 0;
@@ -288,7 +289,7 @@ public class EipProtocolLogic extends 
Plc4xProtocolBase<EipPacket> implements Ha
                 } else {
                     length = responses.getOffsets()[i + 1] - offset - 
responses.getOffsets()[0]; //Calculate length with offsets (substracting first 
offset)
                 }
-                ReadBuffer serviceBuf = new ReadBuffer(read.getBytes(offset, 
offset + length), true);
+                ReadBuffer serviceBuf = new 
ReadBufferByteBased(read.getBytes(offset, offset + length), true);
                 CipService service = null;
                 try {
                     service = CipServiceIO.staticParse(read, length);
@@ -489,7 +490,7 @@ public class EipProtocolLogic extends 
Plc4xProtocolBase<EipPacket> implements Ha
             MultipleServiceResponse resp = (MultipleServiceResponse) p;
             int nb = resp.getServiceNb();
             CipService[] arr = new CipService[nb];
-            ReadBuffer read = new ReadBuffer(resp.getServicesData());
+            ReadBufferByteBased read = new 
ReadBufferByteBased(resp.getServicesData());
             int total = (int) read.getTotalBytes();
             for (int i = 0; i < nb; i++) {
                 int length = 0;
@@ -499,7 +500,7 @@ public class EipProtocolLogic extends 
Plc4xProtocolBase<EipPacket> implements Ha
                 } else {
                     length = resp.getOffsets()[i + 1] - offset; //Calculate 
length with offsets
                 }
-                ReadBuffer serviceBuf = new ReadBuffer(read.getBytes(offset, 
length), true);
+                ReadBuffer serviceBuf = new 
ReadBufferByteBased(read.getBytes(offset, length), true);
                 CipService service = null;
                 try {
                     service = CipServiceIO.staticParse(read, length);
diff --git 
a/plc4j/drivers/firmata/src/main/java/org/apache/plc4x/java/firmata/readwrite/utils/FirmataUtils.java
 
b/plc4j/drivers/firmata/src/main/java/org/apache/plc4x/java/firmata/readwrite/utils/FirmataUtils.java
index 2dc3169..71a42fe 100644
--- 
a/plc4j/drivers/firmata/src/main/java/org/apache/plc4x/java/firmata/readwrite/utils/FirmataUtils.java
+++ 
b/plc4j/drivers/firmata/src/main/java/org/apache/plc4x/java/firmata/readwrite/utils/FirmataUtils.java
@@ -20,12 +20,13 @@ package org.apache.plc4x.java.firmata.readwrite.utils;
 
 import org.apache.plc4x.java.spi.generation.ParseException;
 import org.apache.plc4x.java.spi.generation.ReadBuffer;
+import org.apache.plc4x.java.spi.generation.ReadBufferByteBased;
 import org.apache.plc4x.java.spi.generation.WriteBuffer;
 
 public class FirmataUtils {
 
     public static boolean isSysexEnd(ReadBuffer io) {
-        return io.getBytes(io.getPos(), io.getPos() + 1)[0] == (byte) 0xF7;
+        return ((ReadBufferByteBased) io).getBytes(io.getPos(), io.getPos() + 
1)[0] == (byte) 0xF7;
     }
 
     public static byte parseSysexString(ReadBuffer io) {
diff --git 
a/plc4j/drivers/knxnetip/src/main/java/org/apache/plc4x/java/knxnetip/protocol/KnxNetIpProtocolLogic.java
 
b/plc4j/drivers/knxnetip/src/main/java/org/apache/plc4x/java/knxnetip/protocol/KnxNetIpProtocolLogic.java
index 0bcbb7f..7c6bc5e 100644
--- 
a/plc4j/drivers/knxnetip/src/main/java/org/apache/plc4x/java/knxnetip/protocol/KnxNetIpProtocolLogic.java
+++ 
b/plc4j/drivers/knxnetip/src/main/java/org/apache/plc4x/java/knxnetip/protocol/KnxNetIpProtocolLogic.java
@@ -42,9 +42,7 @@ import org.apache.plc4x.java.spi.ConversationContext;
 import org.apache.plc4x.java.spi.Plc4xProtocolBase;
 import org.apache.plc4x.java.knxnetip.readwrite.*;
 import org.apache.plc4x.java.spi.context.DriverContext;
-import org.apache.plc4x.java.spi.generation.ParseException;
-import org.apache.plc4x.java.spi.generation.ReadBuffer;
-import org.apache.plc4x.java.spi.generation.WriteBuffer;
+import org.apache.plc4x.java.spi.generation.*;
 import org.apache.plc4x.java.spi.messages.*;
 import org.apache.plc4x.java.spi.messages.utils.ResponseItem;
 import org.apache.plc4x.java.spi.model.DefaultPlcConsumerRegistration;
@@ -288,7 +286,7 @@ public class KnxNetIpProtocolLogic extends 
Plc4xProtocolBase<KnxNetIpMessage> im
 
                 // Use the data in the ets5 model to correctly check and 
serialize the PlcValue
                 try {
-                    final WriteBuffer writeBuffer = 
KnxDatapointIO.staticSerialize(value,
+                    final WriteBufferByteBased writeBuffer = 
KnxDatapointIO.staticSerialize(value,
                         groupAddress.getType());
                     final byte[] serialized = writeBuffer.getData();
                     dataFirstByte = serialized[0];
@@ -453,7 +451,7 @@ public class KnxNetIpProtocolLogic extends 
Plc4xProtocolBase<KnxNetIpMessage> im
         System.arraycopy(restBytes, 0, payload, 1, restBytes.length);
 
         // Decode the group address depending on the project settings.
-        ReadBuffer addressBuffer = new ReadBuffer(destinationGroupAddress);
+        ReadBuffer addressBuffer = new 
ReadBufferByteBased(destinationGroupAddress);
         final KnxGroupAddress knxGroupAddress =
             KnxGroupAddressIO.staticParse(addressBuffer, 
knxNetIpDriverContext.getGroupAddressType());
         final String destinationAddress = toString(knxGroupAddress);
@@ -472,7 +470,7 @@ public class KnxNetIpProtocolLogic extends 
Plc4xProtocolBase<KnxNetIpMessage> im
                     toString(sourceAddress), destinationAddress));
 
                 // Parse the payload depending on the type of the 
group-address.
-                ReadBuffer rawDataReader = new ReadBuffer(payload);
+                ReadBuffer rawDataReader = new ReadBufferByteBased(payload);
                 final PlcValue value = 
KnxDatapointIO.staticParse(rawDataReader,
                     groupAddress.getType());
 
@@ -574,7 +572,7 @@ public class KnxNetIpProtocolLogic extends 
Plc4xProtocolBase<KnxNetIpMessage> im
     }
 
     protected byte[] toKnxAddressData(KnxNetIpField field) {
-        WriteBuffer address = new WriteBuffer(2);
+        WriteBufferByteBased address = new WriteBufferByteBased(2);
         try {
             switch (knxNetIpDriverContext.getGroupAddressType()) {
                 case 3:
diff --git 
a/plc4j/drivers/knxnetip/src/main/java/org/apache/plc4x/java/knxnetip/utils/KnxHelper.java
 
b/plc4j/drivers/knxnetip/src/main/java/org/apache/plc4x/java/knxnetip/utils/KnxHelper.java
index 6b25941..575feb3 100644
--- 
a/plc4j/drivers/knxnetip/src/main/java/org/apache/plc4x/java/knxnetip/utils/KnxHelper.java
+++ 
b/plc4j/drivers/knxnetip/src/main/java/org/apache/plc4x/java/knxnetip/utils/KnxHelper.java
@@ -22,6 +22,7 @@ import org.apache.commons.codec.binary.Hex;
 import org.apache.plc4x.java.api.exceptions.PlcRuntimeException;
 import org.apache.plc4x.java.spi.generation.ParseException;
 import org.apache.plc4x.java.spi.generation.ReadBuffer;
+import org.apache.plc4x.java.spi.generation.ReadBufferByteBased;
 import org.apache.plc4x.java.spi.generation.WriteBuffer;
 
 public class KnxHelper {
@@ -64,7 +65,7 @@ public class KnxHelper {
 
     public static void main(String[] args) throws Exception {
         final byte[] bytes = Hex.decodeHex("0C65");
-        ReadBuffer io = new ReadBuffer(bytes);
+        ReadBuffer io = new ReadBufferByteBased(bytes);
         final double v = bytesToF16(io);
         System.out.println(v);
     }
diff --git 
a/plc4j/drivers/knxnetip/src/test/java/org/apache/plc4x/java/knxnetip/IOTest.java
 
b/plc4j/drivers/knxnetip/src/test/java/org/apache/plc4x/java/knxnetip/IOTest.java
index c60de6c..f3d9a08 100644
--- 
a/plc4j/drivers/knxnetip/src/test/java/org/apache/plc4x/java/knxnetip/IOTest.java
+++ 
b/plc4j/drivers/knxnetip/src/test/java/org/apache/plc4x/java/knxnetip/IOTest.java
@@ -25,7 +25,9 @@ import org.apache.commons.codec.binary.Hex;
 import org.apache.plc4x.java.knxnetip.readwrite.KnxNetIpMessage;
 import org.apache.plc4x.java.knxnetip.readwrite.io.KnxNetIpMessageIO;
 import org.apache.plc4x.java.spi.generation.ReadBuffer;
+import org.apache.plc4x.java.spi.generation.ReadBufferByteBased;
 import org.apache.plc4x.java.spi.generation.WriteBuffer;
+import org.apache.plc4x.java.spi.generation.WriteBufferByteBased;
 import org.junit.jupiter.api.Test;
 
 import java.util.Arrays;
@@ -36,7 +38,7 @@ public class IOTest {
     public void testXml() throws Exception {
         byte[] rData = 
Hex.decodeHex("061004200019047f02002900bce0110509d405008044a68000");
         ObjectMapper mapper = new XmlMapper().enableDefaultTyping();
-        ReadBuffer rBuf = new ReadBuffer(rData);
+        ReadBuffer rBuf = new ReadBufferByteBased(rData);
         KnxNetIpMessage packet = new KnxNetIpMessageIO().parse(rBuf);
         String xml = 
mapper.writerWithDefaultPrettyPrinter().writeValueAsString(packet);
         System.out.println(xml);
@@ -48,7 +50,7 @@ public class IOTest {
     public void testJson() throws Exception {
         byte[] rData = 
Hex.decodeHex("0610020500180801c0a82a46c4090801c0a82a46c40a0203");
         ObjectMapper mapper = new ObjectMapper().enableDefaultTyping();
-        ReadBuffer rBuf = new ReadBuffer(rData);
+        ReadBuffer rBuf = new ReadBufferByteBased(rData);
         KnxNetIpMessage packet = new KnxNetIpMessageIO().parse(rBuf);
         String json = 
mapper.writerWithDefaultPrettyPrinter().writeValueAsString(packet);
         System.out.println(json);
@@ -67,7 +69,7 @@ public class IOTest {
         // Benchmark the parsing code
         KnxNetIpMessage packet = null;
         for(int i = 0; i < numRunsParse; i++) {
-            ReadBuffer rBuf = new ReadBuffer(rData);
+            ReadBuffer rBuf = new ReadBufferByteBased(rData);
             packet = KnxNetIpMessageIO.staticParse(rBuf);
         }
         long endParsing = System.currentTimeMillis();
@@ -79,7 +81,7 @@ public class IOTest {
         int numRunsSerialize = 20000;
         byte[] oData = null;
         for(int i = 0; i < numRunsSerialize; i++) {
-            WriteBuffer wBuf = new WriteBuffer(packet.getLengthInBytes());
+            WriteBufferByteBased wBuf = new 
WriteBufferByteBased(packet.getLengthInBytes());
             KnxNetIpMessageIO.staticSerialize(wBuf, packet);
             oData = wBuf.getData();
         }
diff --git 
a/plc4j/drivers/modbus/src/main/java/org/apache/plc4x/java/modbus/protocol/ModbusProtocolLogic.java
 
b/plc4j/drivers/modbus/src/main/java/org/apache/plc4x/java/modbus/protocol/ModbusProtocolLogic.java
index 264c0e2..d1b9991 100644
--- 
a/plc4j/drivers/modbus/src/main/java/org/apache/plc4x/java/modbus/protocol/ModbusProtocolLogic.java
+++ 
b/plc4j/drivers/modbus/src/main/java/org/apache/plc4x/java/modbus/protocol/ModbusProtocolLogic.java
@@ -36,9 +36,7 @@ import org.apache.plc4x.java.modbus.readwrite.io.DataItemIO;
 import org.apache.plc4x.java.spi.ConversationContext;
 import org.apache.plc4x.java.spi.Plc4xProtocolBase;
 import org.apache.plc4x.java.spi.configuration.HasConfiguration;
-import org.apache.plc4x.java.spi.generation.ParseException;
-import org.apache.plc4x.java.spi.generation.ReadBuffer;
-import org.apache.plc4x.java.spi.generation.WriteBuffer;
+import org.apache.plc4x.java.spi.generation.*;
 import org.apache.plc4x.java.spi.messages.DefaultPlcReadRequest;
 import org.apache.plc4x.java.spi.messages.DefaultPlcReadResponse;
 import org.apache.plc4x.java.spi.messages.DefaultPlcWriteRequest;
@@ -378,7 +376,7 @@ public class ModbusProtocolLogic extends 
Plc4xProtocolBase<ModbusTcpADU> impleme
             }
             ModbusPDUReadInputRegistersRequest req = 
(ModbusPDUReadInputRegistersRequest) request;
             ModbusPDUReadInputRegistersResponse resp = 
(ModbusPDUReadInputRegistersResponse) response;
-            ReadBuffer io = new ReadBuffer(resp.getValue());
+            ReadBuffer io = new ReadBufferByteBased(resp.getValue());
             if(fieldDataTypeSize < 2) {
                 io.readByte(8);
             }
@@ -390,7 +388,7 @@ public class ModbusProtocolLogic extends 
Plc4xProtocolBase<ModbusTcpADU> impleme
             }
             ModbusPDUReadHoldingRegistersRequest req = 
(ModbusPDUReadHoldingRegistersRequest) request;
             ModbusPDUReadHoldingRegistersResponse resp = 
(ModbusPDUReadHoldingRegistersResponse) response;
-            ReadBuffer io = new ReadBuffer(resp.getValue());
+            ReadBuffer io = new ReadBufferByteBased(resp.getValue());
             if((dataType != ModbusDataType.STRING) && fieldDataTypeSize < 2) {
                 io.readByte(8);
             }
@@ -407,11 +405,11 @@ public class ModbusProtocolLogic extends 
Plc4xProtocolBase<ModbusTcpADU> impleme
 
             if (resp.getItems().length == 2 && resp.getItems().length == 
req.getItems().length) {
               //If request was split over file records, two groups in reponse 
should be received.
-              io = new 
ReadBuffer(ArrayUtils.addAll(resp.getItems()[0].getData(), 
resp.getItems()[1].getData()));
+              io = new 
ReadBufferByteBased(ArrayUtils.addAll(resp.getItems()[0].getData(), 
resp.getItems()[1].getData()));
               dataLength = (short) (resp.getItems()[0].getLengthInBytes() + 
resp.getItems()[1].getLengthInBytes() - (2 * 
FC_EXTENDED_REGISTERS_GROUP_HEADER_LENGTH));
             } else if (resp.getItems().length == 1 && resp.getItems().length 
== req.getItems().length) {
               //If request was within a single file record, one group should 
be received.
-              io = new ReadBuffer(resp.getItems()[0].getData());
+              io = new ReadBufferByteBased(resp.getItems()[0].getData());
               dataLength = (short) (resp.getItems()[0].getLengthInBytes() - 
FC_EXTENDED_REGISTERS_GROUP_HEADER_LENGTH);
             } else {
               throw new PlcRuntimeException("Unexpected number of groups in 
response. " +
@@ -428,7 +426,7 @@ public class ModbusProtocolLogic extends 
Plc4xProtocolBase<ModbusTcpADU> impleme
     private byte[] fromPlcValue(PlcField field, PlcValue plcValue) {
         ModbusDataType fieldDataType = ((ModbusField) field).getDataType();
         try {
-            WriteBuffer buffer;
+            WriteBufferByteBased buffer;
             if(plcValue instanceof PlcList) {
                 buffer = DataItemIO.staticSerialize(plcValue, fieldDataType, 
plcValue.getLength(), false);
                 byte[] data = buffer.getData();
@@ -469,7 +467,7 @@ public class ModbusProtocolLogic extends 
Plc4xProtocolBase<ModbusTcpADU> impleme
     }
 
     private PlcValue readBooleanList(int count, byte[] data) throws 
ParseException {
-        ReadBuffer io = new ReadBuffer(data);
+        ReadBuffer io = new ReadBufferByteBased(data);
         if(count == 1) {
             return DataItemIO.staticParse(io, ModbusDataType.BOOL, 1);
         }
diff --git 
a/plc4j/drivers/s7/src/main/java/org/apache/plc4x/java/s7/readwrite/field/S7Field.java
 
b/plc4j/drivers/s7/src/main/java/org/apache/plc4x/java/s7/readwrite/field/S7Field.java
index 543a863..64b6aba 100644
--- 
a/plc4j/drivers/s7/src/main/java/org/apache/plc4x/java/s7/readwrite/field/S7Field.java
+++ 
b/plc4j/drivers/s7/src/main/java/org/apache/plc4x/java/s7/readwrite/field/S7Field.java
@@ -33,6 +33,7 @@ import org.apache.plc4x.java.s7.readwrite.types.MemoryArea;
 import org.apache.plc4x.java.s7.readwrite.types.TransportSize;
 import org.apache.plc4x.java.spi.generation.ParseException;
 import org.apache.plc4x.java.spi.generation.ReadBuffer;
+import org.apache.plc4x.java.spi.generation.ReadBufferByteBased;
 import org.apache.plc4x.java.spi.utils.XmlSerializable;
 import org.w3c.dom.Document;
 import org.w3c.dom.Element;
@@ -250,7 +251,7 @@ public class S7Field implements PlcField, XmlSerializable {
         } else if (PLC_PROXY_ADDRESS_PATTERN.matcher(fieldString).matches()) {
             try {
                 byte[] addressData = 
Hex.decodeHex(fieldString.replaceAll("[-]", ""));
-                ReadBuffer rb = new ReadBuffer(addressData);
+                ReadBuffer rb = new ReadBufferByteBased(addressData);
                 final S7Address s7Address = S7AddressIO.staticParse(rb);
                 if (s7Address instanceof S7AddressAny) {
                     S7AddressAny s7AddressAny = (S7AddressAny) s7Address;
diff --git 
a/plc4j/drivers/s7/src/main/java/org/apache/plc4x/java/s7/readwrite/protocol/S7ProtocolLogic.java
 
b/plc4j/drivers/s7/src/main/java/org/apache/plc4x/java/s7/readwrite/protocol/S7ProtocolLogic.java
index 7c7087c..40903d1 100644
--- 
a/plc4j/drivers/s7/src/main/java/org/apache/plc4x/java/s7/readwrite/protocol/S7ProtocolLogic.java
+++ 
b/plc4j/drivers/s7/src/main/java/org/apache/plc4x/java/s7/readwrite/protocol/S7ProtocolLogic.java
@@ -29,6 +29,7 @@ import org.apache.plc4x.java.api.messages.PlcWriteRequest;
 import org.apache.plc4x.java.api.messages.PlcWriteResponse;
 import org.apache.plc4x.java.api.model.PlcField;
 import org.apache.plc4x.java.api.types.PlcResponseCode;
+import org.apache.plc4x.java.spi.generation.*;
 import org.apache.plc4x.java.spi.values.PlcNull;
 import org.apache.plc4x.java.api.value.PlcValue;
 import org.apache.plc4x.java.spi.values.IEC61131ValueHandler;
@@ -41,9 +42,6 @@ import org.apache.plc4x.java.s7.readwrite.field.S7Field;
 import org.apache.plc4x.java.spi.ConversationContext;
 import org.apache.plc4x.java.spi.Plc4xProtocolBase;
 import org.apache.plc4x.java.spi.context.DriverContext;
-import org.apache.plc4x.java.spi.generation.ParseException;
-import org.apache.plc4x.java.spi.generation.ReadBuffer;
-import org.apache.plc4x.java.spi.generation.WriteBuffer;
 import org.apache.plc4x.java.spi.messages.DefaultPlcReadRequest;
 import org.apache.plc4x.java.spi.messages.DefaultPlcReadResponse;
 import org.apache.plc4x.java.spi.messages.DefaultPlcWriteRequest;
@@ -514,7 +512,7 @@ public class S7ProtocolLogic extends 
Plc4xProtocolBase<TPKTPacket> {
         try {
             DataTransportSize transportSize = 
field.getDataType().getDataTransportSize();
             int stringLength = (field instanceof S7StringField) ? 
((S7StringField) field).getStringLength() : 254;
-            WriteBuffer writeBuffer = DataItemIO.staticSerialize(plcValue, 
field.getDataType().getDataProtocolId(),
+            WriteBufferByteBased writeBuffer = 
DataItemIO.staticSerialize(plcValue, field.getDataType().getDataProtocolId(),
                 stringLength);
             if(writeBuffer != null) {
                 byte[] data = writeBuffer.getData();
@@ -527,7 +525,7 @@ public class S7ProtocolLogic extends 
Plc4xProtocolBase<TPKTPacket> {
     }
 
     private PlcValue parsePlcValue(S7Field field, ByteBuf data) {
-        ReadBuffer readBuffer = new ReadBuffer(data.array());
+        ReadBuffer readBuffer = new ReadBufferByteBased(data.array());
         try {
             int stringLength = (field instanceof S7StringField) ? 
((S7StringField) field).getStringLength() : 254;
             if (field.getNumberOfElements() == 1) {
diff --git a/plc4j/drivers/s7/src/test/java/BenchmarkGeneratedS7.java 
b/plc4j/drivers/s7/src/test/java/BenchmarkGeneratedS7.java
index a6d9c34..60ad96f 100644
--- a/plc4j/drivers/s7/src/test/java/BenchmarkGeneratedS7.java
+++ b/plc4j/drivers/s7/src/test/java/BenchmarkGeneratedS7.java
@@ -21,7 +21,9 @@ import org.apache.commons.codec.binary.Hex;
 import org.apache.plc4x.java.s7.readwrite.TPKTPacket;
 import org.apache.plc4x.java.s7.readwrite.io.TPKTPacketIO;
 import org.apache.plc4x.java.spi.generation.ReadBuffer;
+import org.apache.plc4x.java.spi.generation.ReadBufferByteBased;
 import org.apache.plc4x.java.spi.generation.WriteBuffer;
+import org.apache.plc4x.java.spi.generation.WriteBufferByteBased;
 
 import java.util.Arrays;
 
@@ -36,7 +38,7 @@ public class BenchmarkGeneratedS7 {
         // Benchmark the parsing code
         TPKTPacket packet = null;
         for(int i = 0; i < numRunsParse; i++) {
-            ReadBuffer rBuf = new ReadBuffer(rData);
+            ReadBuffer rBuf = new ReadBufferByteBased(rData);
             packet = TPKTPacketIO.staticParse(rBuf);
         }
         long endParsing = System.currentTimeMillis();
@@ -48,7 +50,7 @@ public class BenchmarkGeneratedS7 {
         int numRunsSerialize = 2000000;
         byte[] oData = null;
         for(int i = 0; i < numRunsSerialize; i++) {
-            WriteBuffer wBuf = new WriteBuffer(packet.getLengthInBytes());
+            WriteBufferByteBased wBuf = new 
WriteBufferByteBased(packet.getLengthInBytes());
             TPKTPacketIO.staticSerialize(wBuf, packet);
             oData = wBuf.getData();
         }
diff --git 
a/plc4j/drivers/simulated/src/main/java/org/apache/plc4x/java/simulated/connection/SimulatedDevice.java
 
b/plc4j/drivers/simulated/src/main/java/org/apache/plc4x/java/simulated/connection/SimulatedDevice.java
index 546914f..832440c 100644
--- 
a/plc4j/drivers/simulated/src/main/java/org/apache/plc4x/java/simulated/connection/SimulatedDevice.java
+++ 
b/plc4j/drivers/simulated/src/main/java/org/apache/plc4x/java/simulated/connection/SimulatedDevice.java
@@ -28,6 +28,7 @@ import 
org.apache.plc4x.java.simulated.readwrite.types.SimulatedDataTypeSizes;
 import org.apache.plc4x.java.spi.generation.ParseException;
 import org.apache.plc4x.java.spi.generation.ReadBuffer;
 
+import org.apache.plc4x.java.spi.generation.ReadBufferByteBased;
 import org.apache.plc4x.java.spi.model.DefaultPlcSubscriptionField;
 import org.apache.plc4x.java.spi.values.IEC61131ValueHandler;
 import org.apache.plc4x.java.simulated.field.SimulatedField;
@@ -122,7 +123,7 @@ public class SimulatedDevice {
         byte[] b = new byte[fieldDataTypeSize * field.getNumberOfElements()];
         new Random().nextBytes(b);
 
-        ReadBuffer io = new ReadBuffer(b);
+        ReadBuffer io = new ReadBufferByteBased(b);
         try {
             return DataItemIO.staticParse(io, field.getPlcDataType(), 
field.getNumberOfElements());
         } catch (ParseException e) {
diff --git 
a/plc4j/spi/src/main/java/org/apache/plc4x/java/spi/GeneratedDriverByteToMessageCodec.java
 
b/plc4j/spi/src/main/java/org/apache/plc4x/java/spi/GeneratedDriverByteToMessageCodec.java
index f5fc6f1..4398574 100644
--- 
a/plc4j/spi/src/main/java/org/apache/plc4x/java/spi/GeneratedDriverByteToMessageCodec.java
+++ 
b/plc4j/spi/src/main/java/org/apache/plc4x/java/spi/GeneratedDriverByteToMessageCodec.java
@@ -22,10 +22,7 @@ import io.netty.buffer.ByteBuf;
 import io.netty.channel.ChannelHandlerContext;
 import io.netty.handler.codec.ByteToMessageCodec;
 import org.apache.commons.codec.binary.Hex;
-import org.apache.plc4x.java.spi.generation.Message;
-import org.apache.plc4x.java.spi.generation.MessageIO;
-import org.apache.plc4x.java.spi.generation.ReadBuffer;
-import org.apache.plc4x.java.spi.generation.WriteBuffer;
+import org.apache.plc4x.java.spi.generation.*;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 
@@ -49,7 +46,7 @@ public abstract class GeneratedDriverByteToMessageCodec<T 
extends Message> exten
     @Override
     protected void encode(ChannelHandlerContext ctx, T packet, ByteBuf 
byteBuf) {
         try {
-            WriteBuffer buffer = new WriteBuffer(packet.getLengthInBytes(), 
!bigEndian);
+            WriteBufferByteBased buffer = new 
WriteBufferByteBased(packet.getLengthInBytes(), !bigEndian);
             io.serialize(buffer, packet);
             byteBuf.writeBytes(buffer.getData());
             LOGGER.debug("Sending bytes to PLC for message {} as data {}", 
packet, Hex.encodeHexString(buffer.getData()));
@@ -74,7 +71,7 @@ public abstract class GeneratedDriverByteToMessageCodec<T 
extends Message> exten
                 // Read the packet data into a new ReadBuffer
                 bytes = new byte[packetSize];
                 byteBuf.readBytes(bytes);
-                ReadBuffer readBuffer = new ReadBuffer(bytes, !bigEndian);
+                ReadBuffer readBuffer = new ReadBufferByteBased(bytes, 
!bigEndian);
 
                 // Parse the packet.
                 T packet = io.parse(readBuffer, parserArgs);
diff --git 
a/plc4j/spi/src/main/java/org/apache/plc4x/java/spi/generation/ReadBuffer.java 
b/plc4j/spi/src/main/java/org/apache/plc4x/java/spi/generation/ReadBuffer.java
index 1beef09..1c8f329 100644
--- 
a/plc4j/spi/src/main/java/org/apache/plc4x/java/spi/generation/ReadBuffer.java
+++ 
b/plc4j/spi/src/main/java/org/apache/plc4x/java/spi/generation/ReadBuffer.java
@@ -1,311 +1,124 @@
 /*
- * Licensed to the Apache Software Foundation (ASF) under one
- * or more contributor license agreements.  See the NOTICE file
- * distributed with this work for additional information
- * regarding copyright ownership.  The ASF licenses this file
- * to you under the Apache License, Version 2.0 (the
- * "License"); you may not use this file except in compliance
- * with the License.  You may obtain a copy of the License at
- *
- *   http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing,
- * software distributed under the License is distributed on an
- * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
- * KIND, either express or implied.  See the License for the
- * specific language governing permissions and limitations
- * under the License.
+ Licensed to the Apache Software Foundation (ASF) under one
+ or more contributor license agreements.  See the NOTICE file
+ distributed with this work for additional information
+ regarding copyright ownership.  The ASF licenses this file
+ to you under the Apache License, Version 2.0 (the
+ "License"); you may not use this file except in compliance
+ with the License.  You may obtain a copy of the License at
+
+   http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing,
+ software distributed under the License is distributed on an
+ "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ KIND, either express or implied.  See the License for the
+ specific language governing permissions and limitations
+ under the License.
  */
 
 package org.apache.plc4x.java.spi.generation;
 
-import com.github.jinahya.bit.io.ArrayByteInput;
-import org.apache.plc4x.java.api.exceptions.PlcRuntimeException;
-import org.apache.plc4x.java.spi.generation.io.MyDefaultBitInput;
-
-import java.io.IOException;
 import java.math.BigDecimal;
 import java.math.BigInteger;
-import java.nio.charset.Charset;
 
-public class ReadBuffer {
+public interface ReadBuffer {
+    int getPos();
 
-    private final MyDefaultBitInput bi;
-    private final boolean littleEndian;
-    private final long totalBytes;
+    boolean hasMore(int numBits);
 
-    public ReadBuffer(byte[] input) {
-        this(input, false);
-    }
+    void pullContext(String logicalName);
 
-    public ReadBuffer(byte[] input, boolean littleEndian) {
-        ArrayByteInput abi = new ArrayByteInput(input);
-        this.bi = new MyDefaultBitInput(abi);
-        this.littleEndian = littleEndian;
-        this.totalBytes = input.length;
-    }
+    boolean readBit(String logicalName) throws ParseException;
 
-    public int getPos() {
-        return (int) bi.getPos();
+    default boolean readBit() throws ParseException {
+        return readBit("");
     }
 
-    public byte[] getBytes(int startPos, int endPos) {
-        int numBytes = endPos - startPos;
-        byte[] data = new byte[numBytes];
-        System.arraycopy(bi.getDelegate().getSource(), startPos, data, 0, 
numBytes);
-        return data;
-    }
+    byte readUnsignedByte(String logicalName, int bitLength) throws 
ParseException;
 
-    public long getTotalBytes() {
-        return totalBytes;
+    default byte readUnsignedByte(int bitLength) throws ParseException {
+        return readUnsignedByte("", bitLength);
     }
 
-    public boolean hasMore(int numBits) {
-        return (numBits / 8) <= (totalBytes - getPos());
-    }
+    short readUnsignedShort(String logicalName, int bitLength) throws 
ParseException;
 
-    public byte peekByte(int offset) throws ParseException {
-        // Remember the old index.
-        int oldIndex = bi.getDelegate().getIndex();
-        try {
-            // Set the delegate to the desired position.
-            bi.getDelegate().index(oldIndex + offset);
-            // Read the byte.
-            return bi.readByte(false, 8);
-        } catch (IOException e) {
-            throw new ParseException("Error reading", e);
-        } finally {
-            // Reset the delegate to the old index.
-            bi.getDelegate().index(oldIndex);
-        }
+    default short readUnsignedShort(int bitLength) throws ParseException {
+        return readUnsignedShort("", bitLength);
     }
 
-    public boolean readBit() throws ParseException {
-        try {
-            return bi.readBoolean();
-        } catch (IOException e) {
-            throw new ParseException("Error reading", e);
-        }
-    }
+    int readUnsignedInt(String logicalName, int bitLength) throws 
ParseException;
 
-    public byte readUnsignedByte(int bitLength) throws ParseException {
-        if (bitLength <= 0) {
-            throw new ParseException("unsigned byte must contain at least 1 
bit");
-        }
-        if (bitLength > 7) {
-            throw new ParseException("unsigned byte can only contain max 4 
bits");
-        }
-        try {
-            return bi.readByte(true, bitLength);
-        } catch (IOException e) {
-            throw new ParseException("Error reading", e);
-        }
+    default int readUnsignedInt(int bitLength) throws ParseException {
+        return readUnsignedInt("", bitLength);
     }
 
-    public short readUnsignedShort(int bitLength) throws ParseException {
-        if (bitLength <= 0) {
-            throw new ParseException("unsigned short must contain at least 1 
bit");
-        }
-        if (bitLength > 15) {
-            throw new ParseException("unsigned short can only contain max 8 
bits");
-        }
-        try {
-            // No need to flip here as we're only reading one byte.
-            return bi.readShort(true, bitLength);
-        } catch (IOException e) {
-            throw new ParseException("Error reading", e);
-        }
-    }
+    long readUnsignedLong(String logicalName, int bitLength) throws 
ParseException;
 
-    public int readUnsignedInt(int bitLength) throws ParseException {
-        if (bitLength <= 0) {
-            throw new ParseException("unsigned int must contain at least 1 
bit");
-        }
-        if (bitLength > 31) {
-            throw new ParseException("unsigned int can only contain max 16 
bits");
-        }
-        try {
-            if (littleEndian) {
-                int intValue = bi.readInt(true, bitLength);
-                return Integer.reverseBytes(intValue) >>> 16;
-            }
-            return bi.readInt(true, bitLength);
-        } catch (IOException e) {
-            throw new ParseException("Error reading", e);
-        }
+    default long readUnsignedLong(int bitLength) throws ParseException {
+        return readUnsignedLong("", bitLength);
     }
 
-    public long readUnsignedLong(int bitLength) throws ParseException {
-        if (bitLength <= 0) {
-            throw new ParseException("unsigned long must contain at least 1 
bit");
-        }
-        if (bitLength > 63) {
-            throw new ParseException("unsigned long can only contain max 32 
bits");
-        }
-        try {
-            if (littleEndian) {
-                final long longValue = bi.readLong(true, bitLength);
-                return Long.reverseBytes(longValue) >>> 32;
-            }
-            return bi.readLong(true, bitLength);
-        } catch (IOException e) {
-            throw new ParseException("Error reading", e);
-        }
-    }
+    BigInteger readUnsignedBigInteger(String logicalName, int bitLength) 
throws ParseException;
 
-    public BigInteger readUnsignedBigInteger(int bitLength) throws 
ParseException {
-        //Support specific case where value less than 64 bits and big endian.
-        if (bitLength <= 0) {
-            throw new ParseException("unsigned long must contain at least 1 
bit");
-        }
-        if (bitLength > 64) {
-            throw new ParseException("unsigned long can only contain max 64 
bits");
-        }
-        try {
-            // Read as signed value
-            Long val = bi.readLong(false, bitLength);
-            if (littleEndian) {
-                val = Long.reverseBytes(val);
-            }
-            if (val >= 0) {
-                return BigInteger.valueOf(val);
-            } else {
-                BigInteger constant = 
BigInteger.valueOf(Long.MAX_VALUE).multiply(BigInteger.valueOf(2)).add(BigInteger.valueOf(2));
-                return BigInteger.valueOf(val).add(constant);
-            }
-        } catch (IOException e) {
-            throw new ParseException("Error reading", e);
-        }
+    default BigInteger readUnsignedBigInteger(int bitLength) throws 
ParseException {
+        return readUnsignedBigInteger("", bitLength);
     }
 
-    public byte readByte(int bitLength) throws ParseException {
-        if (bitLength <= 0) {
-            throw new ParseException("byte must contain at least 1 bit");
-        }
-        if (bitLength > 8) {
-            throw new ParseException("byte can only contain max 8 bits");
-        }
-        try {
-            return bi.readByte(false, bitLength);
-        } catch (IOException e) {
-            throw new ParseException("Error reading", e);
-        }
+    byte readByte(String logicalName, int bitLength) throws ParseException;
+
+    default byte readByte(int bitLength) throws ParseException {
+        return readByte("", bitLength);
     }
 
-    public short readShort(int bitLength) throws ParseException {
-        if (bitLength <= 0) {
-            throw new ParseException("short must contain at least 1 bit");
-        }
-        if (bitLength > 16) {
-            throw new ParseException("short can only contain max 16 bits");
-        }
-        try {
-            if (littleEndian) {
-                return Short.reverseBytes(bi.readShort(false, bitLength));
-            }
-            return bi.readShort(false, bitLength);
-        } catch (IOException e) {
-            throw new ParseException("Error reading", e);
-        }
+    short readShort(String logicalName, int bitLength) throws ParseException;
+
+    default short readShort(int bitLength) throws ParseException {
+        return readShort("", bitLength);
     }
 
-    public int readInt(int bitLength) throws ParseException {
-        if (bitLength <= 0) {
-            throw new ParseException("int must contain at least 1 bit");
-        }
-        if (bitLength > 32) {
-            throw new ParseException("int can only contain max 32 bits");
-        }
-        try {
-            if (littleEndian) {
-                return Integer.reverseBytes(bi.readInt(false, bitLength));
-            }
-            return bi.readInt(false, bitLength);
-        } catch (IOException e) {
-            throw new ParseException("Error reading", e);
-        }
+    int readInt(String logicalName, int bitLength) throws ParseException;
+
+    default int readInt(int bitLength) throws ParseException {
+        return readInt("", bitLength);
     }
 
-    public long readLong(int bitLength) throws ParseException {
-        if (bitLength <= 0) {
-            throw new ParseException("long must contain at least 1 bit");
-        }
-        if (bitLength > 64) {
-            throw new ParseException("long can only contain max 64 bits");
-        }
-        try {
-            if (littleEndian) {
-                return Long.reverseBytes(bi.readLong(false, bitLength));
-            }
-            return bi.readLong(false, bitLength);
-        } catch (IOException e) {
-            throw new ParseException("Error reading", e);
-        }
+    long readLong(String logicalName, int bitLength) throws ParseException;
+
+    default long readLong(int bitLength) throws ParseException {
+        return readLong("", bitLength);
     }
 
-    public BigInteger readBigInteger(int bitLength) throws ParseException {
-        throw new UnsupportedOperationException("not implemented yet");
+    BigInteger readBigInteger(String logicalName, int bitLength) throws 
ParseException;
+
+    default BigInteger readBigInteger(int bitLength) throws ParseException {
+        return readBigInteger("", bitLength);
     }
 
-    public float readFloat(int bitLength) throws ParseException {
-        try {
-            if (bitLength == 16) {
-                // 
https://en.wikipedia.org/wiki/Half-precision_floating-point_format
-                final boolean sign = bi.readBoolean();
-                final byte exponent = bi.readByte(true, 5);
-                final short fraction = bi.readShort(true, 10);
-                if ((exponent >= 1) && (exponent <= 30)) {
-                    return (sign ? 1 : -1) * (2 ^ (exponent - 15)) * (1 + 
(fraction / 10f));
-                } else if (exponent == 0) {
-                    if (fraction == 0) {
-                        return 0.0f;
-                    } else {
-                        return (sign ? 1 : -1) * (2 ^ (-14)) * (fraction / 
10f);
-                    }
-                } else if (exponent == 31) {
-                    if (fraction == 0) {
-                        return sign ? Float.POSITIVE_INFINITY : 
Float.NEGATIVE_INFINITY;
-                    } else {
-                        return Float.NaN;
-                    }
-                } else {
-                    throw new NumberFormatException();
-                }
-            } else if (bitLength == 32) {
-                int intValue = readInt(32);
-                return Float.intBitsToFloat(intValue);
-            } else {
-                throw new UnsupportedOperationException("unsupported bit 
length (only 16 and 32 supported)");
-            }
-        } catch (IOException e) {
-            throw new ParseException("Error reading", e);
-        }
+    float readFloat(String logicalName, int bitLength) throws ParseException;
+
+    default float readFloat(int bitLength) throws ParseException {
+        return readFloat("", bitLength);
     }
 
-    public double readDouble(int bitLength) throws ParseException {
-        if(bitLength == 64) {
-            long longValue = readLong(64);
-            return Double.longBitsToDouble(longValue);
-        } else {
-            throw new UnsupportedOperationException("unsupported bit length 
(only 64 supported)");
-        }
+    double readDouble(String logicalName, int bitLength) throws ParseException;
+
+    default double readDouble(int bitLength) throws ParseException {
+        return readDouble("", bitLength);
     }
 
-    public BigDecimal readBigDecimal(int bitLength) throws ParseException {
-        throw new UnsupportedOperationException("not implemented yet");
+    BigDecimal readBigDecimal(String logicalName, int bitLength) throws 
ParseException;
+
+    default BigDecimal readBigDecimal(int bitLength) throws ParseException {
+        return readBigDecimal("", bitLength);
     }
 
-    public String readString(int bitLength, String encoding) {
-        byte[] strBytes = new byte[bitLength / 8];
-        for (int i = 0; (i < (bitLength / 8)) && hasMore(8); i++) {
-            try {
-                strBytes[i] = readByte(8);
-            } catch (Exception e) {
-                throw new PlcRuntimeException(e);
-            }
-        }
-        //replaceAll function removes and leading ' char or hypens.
-        return new String(strBytes, 
Charset.forName(encoding.replaceAll("[^a-zA-Z0-9]","")));
+    String readString(String logicalName, int bitLength, String encoding);
+
+    default String readString(int bitLength, String encoding) {
+        return readString("", bitLength,encoding);
     }
 
+
+    void closeContext(String logicalName);
 }
diff --git 
a/plc4j/spi/src/main/java/org/apache/plc4x/java/spi/generation/ReadBuffer.java 
b/plc4j/spi/src/main/java/org/apache/plc4x/java/spi/generation/ReadBufferByteBased.java
similarity index 83%
copy from 
plc4j/spi/src/main/java/org/apache/plc4x/java/spi/generation/ReadBuffer.java
copy to 
plc4j/spi/src/main/java/org/apache/plc4x/java/spi/generation/ReadBufferByteBased.java
index 1beef09..5e35310 100644
--- 
a/plc4j/spi/src/main/java/org/apache/plc4x/java/spi/generation/ReadBuffer.java
+++ 
b/plc4j/spi/src/main/java/org/apache/plc4x/java/spi/generation/ReadBufferByteBased.java
@@ -28,23 +28,24 @@ import java.math.BigDecimal;
 import java.math.BigInteger;
 import java.nio.charset.Charset;
 
-public class ReadBuffer {
+public class ReadBufferByteBased implements ReadBuffer {
 
     private final MyDefaultBitInput bi;
     private final boolean littleEndian;
     private final long totalBytes;
 
-    public ReadBuffer(byte[] input) {
+    public ReadBufferByteBased(byte[] input) {
         this(input, false);
     }
 
-    public ReadBuffer(byte[] input, boolean littleEndian) {
+    public ReadBufferByteBased(byte[] input, boolean littleEndian) {
         ArrayByteInput abi = new ArrayByteInput(input);
         this.bi = new MyDefaultBitInput(abi);
         this.littleEndian = littleEndian;
         this.totalBytes = input.length;
     }
 
+    @Override
     public int getPos() {
         return (int) bi.getPos();
     }
@@ -60,6 +61,7 @@ public class ReadBuffer {
         return totalBytes;
     }
 
+    @Override
     public boolean hasMore(int numBits) {
         return (numBits / 8) <= (totalBytes - getPos());
     }
@@ -80,7 +82,12 @@ public class ReadBuffer {
         }
     }
 
-    public boolean readBit() throws ParseException {
+    @Override
+    public void pullContext(String logicalName) {
+    }
+
+    @Override
+    public boolean readBit(String logicalName) throws ParseException {
         try {
             return bi.readBoolean();
         } catch (IOException e) {
@@ -88,7 +95,8 @@ public class ReadBuffer {
         }
     }
 
-    public byte readUnsignedByte(int bitLength) throws ParseException {
+    @Override
+    public byte readUnsignedByte(String logicalName, int bitLength) throws 
ParseException {
         if (bitLength <= 0) {
             throw new ParseException("unsigned byte must contain at least 1 
bit");
         }
@@ -102,7 +110,8 @@ public class ReadBuffer {
         }
     }
 
-    public short readUnsignedShort(int bitLength) throws ParseException {
+    @Override
+    public short readUnsignedShort(String logicalName, int bitLength) throws 
ParseException {
         if (bitLength <= 0) {
             throw new ParseException("unsigned short must contain at least 1 
bit");
         }
@@ -117,7 +126,8 @@ public class ReadBuffer {
         }
     }
 
-    public int readUnsignedInt(int bitLength) throws ParseException {
+    @Override
+    public int readUnsignedInt(String logicalName, int bitLength) throws 
ParseException {
         if (bitLength <= 0) {
             throw new ParseException("unsigned int must contain at least 1 
bit");
         }
@@ -135,7 +145,8 @@ public class ReadBuffer {
         }
     }
 
-    public long readUnsignedLong(int bitLength) throws ParseException {
+    @Override
+    public long readUnsignedLong(String logicalName, int bitLength) throws 
ParseException {
         if (bitLength <= 0) {
             throw new ParseException("unsigned long must contain at least 1 
bit");
         }
@@ -153,7 +164,8 @@ public class ReadBuffer {
         }
     }
 
-    public BigInteger readUnsignedBigInteger(int bitLength) throws 
ParseException {
+    @Override
+    public BigInteger readUnsignedBigInteger(String logicalName, int 
bitLength) throws ParseException {
         //Support specific case where value less than 64 bits and big endian.
         if (bitLength <= 0) {
             throw new ParseException("unsigned long must contain at least 1 
bit");
@@ -178,7 +190,8 @@ public class ReadBuffer {
         }
     }
 
-    public byte readByte(int bitLength) throws ParseException {
+    @Override
+    public byte readByte(String logicalName, int bitLength) throws 
ParseException {
         if (bitLength <= 0) {
             throw new ParseException("byte must contain at least 1 bit");
         }
@@ -192,7 +205,8 @@ public class ReadBuffer {
         }
     }
 
-    public short readShort(int bitLength) throws ParseException {
+    @Override
+    public short readShort(String logicalName, int bitLength) throws 
ParseException {
         if (bitLength <= 0) {
             throw new ParseException("short must contain at least 1 bit");
         }
@@ -209,7 +223,8 @@ public class ReadBuffer {
         }
     }
 
-    public int readInt(int bitLength) throws ParseException {
+    @Override
+    public int readInt(String logicalName, int bitLength) throws 
ParseException {
         if (bitLength <= 0) {
             throw new ParseException("int must contain at least 1 bit");
         }
@@ -226,7 +241,8 @@ public class ReadBuffer {
         }
     }
 
-    public long readLong(int bitLength) throws ParseException {
+    @Override
+    public long readLong(String logicalName, int bitLength) throws 
ParseException {
         if (bitLength <= 0) {
             throw new ParseException("long must contain at least 1 bit");
         }
@@ -243,11 +259,13 @@ public class ReadBuffer {
         }
     }
 
-    public BigInteger readBigInteger(int bitLength) throws ParseException {
+    @Override
+    public BigInteger readBigInteger(String logicalName, int bitLength) throws 
ParseException {
         throw new UnsupportedOperationException("not implemented yet");
     }
 
-    public float readFloat(int bitLength) throws ParseException {
+    @Override
+    public float readFloat(String logicalName, int bitLength) throws 
ParseException {
         try {
             if (bitLength == 16) {
                 // 
https://en.wikipedia.org/wiki/Half-precision_floating-point_format
@@ -272,7 +290,7 @@ public class ReadBuffer {
                     throw new NumberFormatException();
                 }
             } else if (bitLength == 32) {
-                int intValue = readInt(32);
+                int intValue = readInt(logicalName,32);
                 return Float.intBitsToFloat(intValue);
             } else {
                 throw new UnsupportedOperationException("unsupported bit 
length (only 16 and 32 supported)");
@@ -282,24 +300,27 @@ public class ReadBuffer {
         }
     }
 
-    public double readDouble(int bitLength) throws ParseException {
+    @Override
+    public double readDouble(String logicalName, int bitLength) throws 
ParseException {
         if(bitLength == 64) {
-            long longValue = readLong(64);
+            long longValue = readLong(logicalName,64);
             return Double.longBitsToDouble(longValue);
         } else {
             throw new UnsupportedOperationException("unsupported bit length 
(only 64 supported)");
         }
     }
 
-    public BigDecimal readBigDecimal(int bitLength) throws ParseException {
+    @Override
+    public BigDecimal readBigDecimal(String logicalName, int bitLength) throws 
ParseException {
         throw new UnsupportedOperationException("not implemented yet");
     }
 
-    public String readString(int bitLength, String encoding) {
+    @Override
+    public String readString(String logicalName, int bitLength, String 
encoding) {
         byte[] strBytes = new byte[bitLength / 8];
         for (int i = 0; (i < (bitLength / 8)) && hasMore(8); i++) {
             try {
-                strBytes[i] = readByte(8);
+                strBytes[i] = readByte(logicalName,8);
             } catch (Exception e) {
                 throw new PlcRuntimeException(e);
             }
@@ -308,4 +329,9 @@ public class ReadBuffer {
         return new String(strBytes, 
Charset.forName(encoding.replaceAll("[^a-zA-Z0-9]","")));
     }
 
+
+    @Override
+    public void closeContext(String logicalName) {
+    }
+
 }
diff --git 
a/plc4j/spi/src/main/java/org/apache/plc4x/java/spi/generation/StaticHelper.java
 
b/plc4j/spi/src/main/java/org/apache/plc4x/java/spi/generation/StaticHelper.java
index 26a37fa..5593f44 100644
--- 
a/plc4j/spi/src/main/java/org/apache/plc4x/java/spi/generation/StaticHelper.java
+++ 
b/plc4j/spi/src/main/java/org/apache/plc4x/java/spi/generation/StaticHelper.java
@@ -18,8 +18,6 @@
  */
 package org.apache.plc4x.java.spi.generation;
 
-import org.apache.commons.codec.binary.Hex;
-
 import java.util.Collection;
 
 public class StaticHelper {
@@ -29,7 +27,7 @@ public class StaticHelper {
             Object[] arr = (Object[]) obj;
             int numBytes = 0;
             for (Object element : arr) {
-                if(element instanceof Message) {
+                if (element instanceof Message) {
                     numBytes += ((Message) element).getLengthInBytes();
                 } else {
                     throw new RuntimeException(
@@ -42,36 +40,36 @@ public class StaticHelper {
     }
 
     public static int COUNT(Object obj) {
-        if(obj == null) {
+        if (obj == null) {
             return 0;
         }
         if (obj.getClass().isArray()) {
-            if(obj.getClass().getComponentType() != null && 
obj.getClass().getComponentType().isPrimitive()) {
-                if(obj.getClass().getComponentType() == boolean.class) {
+            if (obj.getClass().getComponentType() != null && 
obj.getClass().getComponentType().isPrimitive()) {
+                if (obj.getClass().getComponentType() == boolean.class) {
                     boolean[] arr = (boolean[]) obj;
                     return arr.length;
                 }
-                if(obj.getClass().getComponentType() == byte.class) {
-                    byte[] arr = (byte []) obj;
+                if (obj.getClass().getComponentType() == byte.class) {
+                    byte[] arr = (byte[]) obj;
                     return arr.length;
                 }
-                if(obj.getClass().getComponentType() == short.class) {
-                    short[] arr = (short []) obj;
+                if (obj.getClass().getComponentType() == short.class) {
+                    short[] arr = (short[]) obj;
                     return arr.length;
                 }
-                if(obj.getClass().getComponentType() == int.class) {
-                    int[] arr = (int []) obj;
+                if (obj.getClass().getComponentType() == int.class) {
+                    int[] arr = (int[]) obj;
                     return arr.length;
                 }
-                if(obj.getClass().getComponentType() == long.class) {
-                    long[] arr = (long []) obj;
+                if (obj.getClass().getComponentType() == long.class) {
+                    long[] arr = (long[]) obj;
                     return arr.length;
                 }
-                if(obj.getClass().getComponentType() == float.class) {
-                    float[] arr = (float []) obj;
+                if (obj.getClass().getComponentType() == float.class) {
+                    float[] arr = (float[]) obj;
                     return arr.length;
                 }
-                if(obj.getClass().getComponentType() == double.class) {
+                if (obj.getClass().getComponentType() == double.class) {
                     double[] arr = (double[]) obj;
                     return arr.length;
                 }
@@ -99,23 +97,28 @@ public class StaticHelper {
     }
 
     public static double toFloat(ReadBuffer io, boolean signed, int 
bitsExponent, int bitsMantissa) {
+        return toFloat(io, "", signed, bitsExponent, bitsMantissa);
+    }
+
+    // TODO: refactor so that we only emit one logical name
+    public static double toFloat(ReadBuffer io, String logicalName, boolean 
signed, int bitsExponent, int bitsMantissa) {
         try {
             if (signed && bitsExponent == 8 && bitsMantissa == 23) {
-                return io.readFloat(32);
+                return io.readFloat(logicalName, 32);
             } else if (signed && bitsExponent == 11 & bitsMantissa == 52) {
-                return io.readDouble(64);
+                return io.readDouble(logicalName, 64);
             }
-            boolean negative = (signed) && io.readBit();
-            long exponent = io.readUnsignedLong(bitsExponent);
+            boolean negative = (signed) && io.readBit(logicalName);
+            long exponent = io.readUnsignedLong(logicalName, bitsExponent);
             exponent = exponent - (((long) Math.pow(2, bitsExponent) / 2) - 1);
             double mantissa = 1D;
-            for(int i = 1; i <= bitsMantissa; i++) {
-                if(io.readBit()) {
+            for (int i = 1; i <= bitsMantissa; i++) {
+                if (io.readBit(logicalName)) {
                     mantissa += Math.pow(2, (double) i * -1);
                 }
             }
             return ((negative) ? -1 : 1) * mantissa * Math.pow(2, exponent);
-        } catch(ParseException e) {
+        } catch (ParseException e) {
             return 0.0f;
         }
     }
@@ -132,16 +135,4 @@ public class StaticHelper {
         return 0;
     }
 
-    public static void main(String[] args) throws Exception {
-        /*final byte[] bytes = Hex.decodeHex("420B9000");
-        ReadBuffer io = new ReadBuffer(bytes);
-        final double v = toFloat(io, true, 8, 23);
-        System.out.println(v);*/
-
-        final byte[] bytes = Hex.decodeHex("0C65");
-        ReadBuffer io = new ReadBuffer(bytes);
-        final double v = toFloat(io, true, 4, 11);
-        System.out.println(v);
-    }
-
 }
diff --git 
a/plc4j/spi/src/main/java/org/apache/plc4x/java/spi/generation/WriteBuffer.java 
b/plc4j/spi/src/main/java/org/apache/plc4x/java/spi/generation/WriteBuffer.java
index b8c94fd..cc74f17 100644
--- 
a/plc4j/spi/src/main/java/org/apache/plc4x/java/spi/generation/WriteBuffer.java
+++ 
b/plc4j/spi/src/main/java/org/apache/plc4x/java/spi/generation/WriteBuffer.java
@@ -1,277 +1,121 @@
 /*
- * Licensed to the Apache Software Foundation (ASF) under one
- * or more contributor license agreements.  See the NOTICE file
- * distributed with this work for additional information
- * regarding copyright ownership.  The ASF licenses this file
- * to you under the Apache License, Version 2.0 (the
- * "License"); you may not use this file except in compliance
- * with the License.  You may obtain a copy of the License at
- *
- *   http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing,
- * software distributed under the License is distributed on an
- * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
- * KIND, either express or implied.  See the License for the
- * specific language governing permissions and limitations
- * under the License.
+ Licensed to the Apache Software Foundation (ASF) under one
+ or more contributor license agreements.  See the NOTICE file
+ distributed with this work for additional information
+ regarding copyright ownership.  The ASF licenses this file
+ to you under the Apache License, Version 2.0 (the
+ "License"); you may not use this file except in compliance
+ with the License.  You may obtain a copy of the License at
+
+   http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing,
+ software distributed under the License is distributed on an
+ "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ KIND, either express or implied.  See the License for the
+ specific language governing permissions and limitations
+ under the License.
  */
 
 package org.apache.plc4x.java.spi.generation;
 
-import com.github.jinahya.bit.io.BufferByteOutput;
-import org.apache.plc4x.java.spi.generation.io.MyDefaultBitOutput;
-
-import java.io.IOException;
 import java.math.BigDecimal;
 import java.math.BigInteger;
-import java.nio.ByteBuffer;
-import java.nio.charset.Charset;
 
-public class WriteBuffer {
+public interface WriteBuffer {
+    int getPos();
 
-    private final ByteBuffer bb;
-    private final BufferByteOutput bbo;
-    private final MyDefaultBitOutput bo;
-    private final boolean littleEndian;
+    void pushContext(String logicalName);
 
-    public WriteBuffer(int size) {
-        this(size, false);
-    }
+    void writeBit(String logicalName, boolean value) throws ParseException;
 
-    public WriteBuffer(int size, boolean littleEndian) {
-        bb = ByteBuffer.allocate(size);
-        bbo = new BufferByteOutput(bb);
-        bo = new MyDefaultBitOutput(bbo);
-        this.littleEndian = littleEndian;
+    default void writeBit(boolean value) throws ParseException {
+        writeBit("", value);
     }
 
-    public byte[] getData() {
-        return bb.array();
-    }
+    void writeUnsignedByte(String logicalName, int bitLength, byte value) 
throws ParseException;
 
-    public int getPos() {
-        return (int) bo.getPos();
+    default void writeUnsignedByte(int bitLength, byte value) throws 
ParseException {
+        writeUnsignedByte("", bitLength,value);
     }
 
-    public byte[] getBytes(int startPos, int endPos) {
-        int numBytes = endPos - startPos;
-        byte[] data = new byte[numBytes];
-        System.arraycopy(bb.array(), startPos, data, 0, numBytes);
-        return data;
-    }
+    void writeUnsignedShort(String logicalName, int bitLength, short value) 
throws ParseException;
 
-    public void writeBit(boolean value) throws ParseException {
-        try {
-            bo.writeBoolean(value);
-        } catch (IOException e) {
-            throw new ParseException("Error reading", e);
-        }
+    default void writeUnsignedShort(int bitLength, short value) throws 
ParseException {
+        writeUnsignedShort("", bitLength, value);
     }
 
-    public void writeUnsignedByte(int bitLength, byte value) throws 
ParseException {
-        if(bitLength <= 0) {
-            throw new ParseException("unsigned byte must contain at least 1 
bit");
-        }
-        if(bitLength > 8) {
-            throw new ParseException("unsigned byte can only contain max 8 
bits");
-        }
-        try {
-            bo.writeByte(true, bitLength, value);
-        } catch (IOException e) {
-            throw new ParseException("Error reading", e);
-        }
-    }
+    void writeUnsignedInt(String logicalName, int bitLength, int value) throws 
ParseException;
 
-    public void writeUnsignedShort(int bitLength, short value) throws 
ParseException {
-        if(bitLength <= 0) {
-            throw new ParseException("unsigned short must contain at least 1 
bit");
-        }
-        if(bitLength > 16) {
-            throw new ParseException("unsigned short can only contain max 16 
bits");
-        }
-        try {
-            bo.writeShort(true, bitLength, value);
-        } catch (IOException e) {
-            throw new ParseException("Error reading", e);
-        }
+    default void writeUnsignedInt(int bitLength, int value) throws 
ParseException {
+        writeUnsignedInt("", bitLength, value);
     }
 
-    public void writeUnsignedInt(int bitLength, int value) throws 
ParseException {
-        if(bitLength <= 0) {
-            throw new ParseException("unsigned int must contain at least 1 
bit");
-        }
-        if(bitLength > 32) {
-            throw new ParseException("unsigned int can only contain max 32 
bits");
-        }
-        try {
-            if(littleEndian) {
-                value = Integer.reverseBytes(value) >> 16;
-            }
-            bo.writeInt(true, bitLength, value);
-        } catch (IOException e) {
-            throw new ParseException("Error reading", e);
-        }
-    }
+    void writeUnsignedLong(String logicalName, int bitLength, long value) 
throws ParseException;
 
-    public void writeUnsignedLong(int bitLength, long value) throws 
ParseException {
-        if(bitLength <= 0) {
-            throw new ParseException("unsigned long must contain at least 1 
bit");
-        }
-        if(bitLength > 63) {
-            throw new ParseException("unsigned long can only contain max 63 
bits");
-        }
-        try {
-            if(littleEndian) {
-                value = Long.reverseBytes(value) >> 32;
-            }
-            bo.writeLong(true, bitLength, value);
-        } catch (IOException e) {
-            throw new ParseException("Error reading", e);
-        }
+    default void writeUnsignedLong(int bitLength, long value) throws 
ParseException {
+        writeUnsignedLong("", bitLength, value);
     }
 
-    public void writeUnsignedBigInteger(int bitLength, BigInteger value) 
throws ParseException {
-        try {
-            if (bitLength == 64) {
-                if(littleEndian) {
-                    if (value.compareTo(BigInteger.valueOf(Long.MAX_VALUE)) >= 
0) {
-                        writeLong(32, value.longValue());
-                        writeLong(32, value.shiftRight(32).longValue());
-                    } else {
-                        writeLong(bitLength, value.longValue());
-                    }
-                } else {
-                    if (value.compareTo(BigInteger.valueOf(Long.MAX_VALUE)) >= 
0) {
-                        writeLong(32, value.shiftRight(32).longValue());
-                        writeLong(32, value.longValue());
-                    } else {
-                        writeLong(bitLength, value.longValue());
-                    }
-                }
-            } else if (bitLength < 64){
-                writeUnsignedLong(bitLength, value.longValue());
-            } else {
-                throw new ParseException("Unsigned Big Integer can only 
contain max 64 bits");
-            }
-        } catch (ArithmeticException e) {
-            throw new ParseException("Error reading", e);
-        }
+    void writeUnsignedBigInteger(String logicalName, int bitLength, BigInteger 
value) throws ParseException;
+
+    default void writeUnsignedBigInteger(int bitLength, BigInteger value) 
throws ParseException {
+        writeUnsignedBigInteger("", bitLength, value);
     }
 
-    public void writeByte(int bitLength, byte value) throws ParseException {
-        if(bitLength <= 0) {
-            throw new ParseException("byte must contain at least 1 bit");
-        }
-        if(bitLength > 8) {
-            throw new ParseException("byte can only contain max 8 bits");
-        }
-        try {
-            bo.writeByte(false, bitLength, value);
-        } catch (IOException e) {
-            throw new ParseException("Error reading", e);
-        }
+    void writeByte(String logicalName, int bitLength, byte value) throws 
ParseException;
+
+    default void writeByte(int bitLength, byte value) throws ParseException {
+        writeByte("", bitLength, value);
     }
 
-    public void writeShort(int bitLength, short value) throws ParseException {
-        if(bitLength <= 0) {
-            throw new ParseException("short must contain at least 1 bit");
-        }
-        if(bitLength > 16) {
-            throw new ParseException("short can only contain max 16 bits");
-        }
-        try {
-            if(littleEndian) {
-                value = Short.reverseBytes(value);
-            }
-            bo.writeShort(false, bitLength, value);
-        } catch (IOException e) {
-            throw new ParseException("Error reading", e);
-        }
+    void writeShort(String logicalName, int bitLength, short value) throws 
ParseException;
+
+    default void writeShort(int bitLength, short value) throws ParseException {
+        writeShort("", bitLength, value);
     }
 
-    public void writeInt(int bitLength, int value) throws ParseException {
-        if(bitLength <= 0) {
-            throw new ParseException("int must contain at least 1 bit");
-        }
-        if(bitLength > 32) {
-            throw new ParseException("int can only contain max 32 bits");
-        }
-        try {
-            if(littleEndian) {
-                value = Integer.reverseBytes(value);
-            }
-            bo.writeInt(false, bitLength, value);
-        } catch (IOException e) {
-            throw new ParseException("Error reading", e);
-        }
+    void writeInt(String logicalName, int bitLength, int value) throws 
ParseException;
+
+    default void writeInt(int bitLength, int value) throws ParseException {
+        writeInt("", bitLength, value);
     }
 
-    public void writeLong(int bitLength, long value) throws ParseException {
-        if(bitLength <= 0) {
-            throw new ParseException("long must contain at least 1 bit");
-        }
-        if(bitLength > 64) {
-            throw new ParseException("long can only contain max 64 bits");
-        }
-        try {
-            if(littleEndian) {
-                value = Long.reverseBytes(value);
-            }
-            bo.writeLong(false, bitLength, value);
-        } catch (IOException e) {
-            throw new ParseException("Error reading", e);
-        }
+    void writeLong(String logicalName, int bitLength, long value) throws 
ParseException;
+
+    default void writeLong(int bitLength, long value) throws ParseException {
+        writeLong("", bitLength, value);
     }
 
-    public void writeBigInteger(int bitLength, BigInteger value) throws 
ParseException {
-        try {
-            if(bitLength > 64) {
-                throw new ParseException("Big Integer can only contain max 64 
bits");
-            }
-            writeLong(bitLength, value.longValue());
-        } catch (ArithmeticException e) {
-            throw new ParseException("Error reading", e);
-        }
+    void writeBigInteger(String logicalName, int bitLength, BigInteger value) 
throws ParseException;
+
+    default void writeBigInteger(int bitLength, BigInteger value) throws 
ParseException {
+        writeBigInteger("", bitLength, value);
     }
 
-    public void writeFloat(float value, int bitsExponent, int bitsMantissa) 
throws ParseException {
-        if (bitsExponent != 8 || bitsMantissa != 23) {
-            throw new UnsupportedOperationException("Exponent and/or Mantissa 
non standard size");
-        }
-        writeInt(1 + bitsExponent + bitsMantissa, 
Float.floatToRawIntBits(value));
+    void writeFloat(String logicalName, float value, int bitsExponent, int 
bitsMantissa) throws ParseException;
+
+    default void writeFloat(float value, int bitsExponent, int bitsMantissa) 
throws ParseException {
+        writeFloat("", value, bitsExponent,bitsMantissa);
     }
 
-    public void writeDouble(double value, int bitsExponent, int bitsMantissa) 
throws ParseException {
-        if (bitsExponent != 11 || bitsMantissa != 52) {
-            throw new UnsupportedOperationException("Exponent and/or Mantissa 
non standard size");
-        }
-        writeLong(1 + bitsExponent + bitsMantissa, 
Double.doubleToRawLongBits(value));
+    void writeDouble(String logicalName, double value, int bitsExponent, int 
bitsMantissa) throws ParseException;
+
+    default void writeDouble(double value, int bitsExponent, int bitsMantissa) 
throws ParseException {
+        writeDouble("", value,bitsExponent,bitsMantissa);
     }
 
-    public void writeBigDecimal(int bitLength, BigDecimal value) throws 
ParseException {
-        throw new UnsupportedOperationException("not implemented yet");
+    void writeBigDecimal(String logicalName, int bitLength, BigDecimal value) 
throws ParseException;
+
+    default void writeBigDecimal(int bitLength, BigDecimal value) throws 
ParseException {
+        writeBigDecimal("", bitLength, value);
     }
 
-    public void writeString(int bitLength, String encoding, String value) 
throws ParseException {
-        final byte[] bytes = 
value.getBytes(Charset.forName(encoding.replaceAll("[^a-zA-Z0-9]","")));
-        int fixedByteLength = bitLength / 8;
-
-        if (bitLength == 0) {
-            fixedByteLength = bytes.length;
-        }
-
-        try {
-            for (int i = 0; i < fixedByteLength; i++) {
-                if (i >= bytes.length) {
-                    bo.writeByte(false, 8, (byte) 0x00);
-                } else {
-                    bo.writeByte(false, 8, bytes[i]);
-                }
-            }
-        } catch (IOException e) {
-           throw new ParseException("Error writing string", e);
-        }
+    void writeString(String logicalName, int bitLength, String encoding, 
String value) throws ParseException;
+
+    default void writeString(int bitLength, String encoding, String value) 
throws ParseException {
+        writeString("", bitLength,encoding, value);
     }
 
+    void popContext(String logicalName);
 }
diff --git 
a/plc4j/spi/src/main/java/org/apache/plc4x/java/spi/generation/WriteBuffer.java 
b/plc4j/spi/src/main/java/org/apache/plc4x/java/spi/generation/WriteBufferByteBased.java
similarity index 71%
copy from 
plc4j/spi/src/main/java/org/apache/plc4x/java/spi/generation/WriteBuffer.java
copy to 
plc4j/spi/src/main/java/org/apache/plc4x/java/spi/generation/WriteBufferByteBased.java
index b8c94fd..a85815c 100644
--- 
a/plc4j/spi/src/main/java/org/apache/plc4x/java/spi/generation/WriteBuffer.java
+++ 
b/plc4j/spi/src/main/java/org/apache/plc4x/java/spi/generation/WriteBufferByteBased.java
@@ -28,20 +28,20 @@ import java.math.BigInteger;
 import java.nio.ByteBuffer;
 import java.nio.charset.Charset;
 
-public class WriteBuffer {
+public class WriteBufferByteBased implements WriteBuffer {
 
     private final ByteBuffer bb;
-    private final BufferByteOutput bbo;
+    private final BufferByteOutput<?> bbo;
     private final MyDefaultBitOutput bo;
     private final boolean littleEndian;
 
-    public WriteBuffer(int size) {
+    public WriteBufferByteBased(int size) {
         this(size, false);
     }
 
-    public WriteBuffer(int size, boolean littleEndian) {
+    public WriteBufferByteBased(int size, boolean littleEndian) {
         bb = ByteBuffer.allocate(size);
-        bbo = new BufferByteOutput(bb);
+        bbo = new BufferByteOutput<>(bb);
         bo = new MyDefaultBitOutput(bbo);
         this.littleEndian = littleEndian;
     }
@@ -50,6 +50,7 @@ public class WriteBuffer {
         return bb.array();
     }
 
+    @Override
     public int getPos() {
         return (int) bo.getPos();
     }
@@ -61,7 +62,13 @@ public class WriteBuffer {
         return data;
     }
 
-    public void writeBit(boolean value) throws ParseException {
+    @Override
+    public void pushContext(String logicalName) {
+
+    }
+
+    @Override
+    public void writeBit(String logicalName, boolean value) throws 
ParseException {
         try {
             bo.writeBoolean(value);
         } catch (IOException e) {
@@ -69,7 +76,8 @@ public class WriteBuffer {
         }
     }
 
-    public void writeUnsignedByte(int bitLength, byte value) throws 
ParseException {
+    @Override
+    public void writeUnsignedByte(String logicalName, int bitLength, byte 
value) throws ParseException {
         if(bitLength <= 0) {
             throw new ParseException("unsigned byte must contain at least 1 
bit");
         }
@@ -83,7 +91,8 @@ public class WriteBuffer {
         }
     }
 
-    public void writeUnsignedShort(int bitLength, short value) throws 
ParseException {
+    @Override
+    public void writeUnsignedShort(String logicalName, int bitLength, short 
value) throws ParseException {
         if(bitLength <= 0) {
             throw new ParseException("unsigned short must contain at least 1 
bit");
         }
@@ -97,7 +106,8 @@ public class WriteBuffer {
         }
     }
 
-    public void writeUnsignedInt(int bitLength, int value) throws 
ParseException {
+    @Override
+    public void writeUnsignedInt(String logicalName, int bitLength, int value) 
throws ParseException {
         if(bitLength <= 0) {
             throw new ParseException("unsigned int must contain at least 1 
bit");
         }
@@ -114,7 +124,8 @@ public class WriteBuffer {
         }
     }
 
-    public void writeUnsignedLong(int bitLength, long value) throws 
ParseException {
+    @Override
+    public void writeUnsignedLong(String logicalName, int bitLength, long 
value) throws ParseException {
         if(bitLength <= 0) {
             throw new ParseException("unsigned long must contain at least 1 
bit");
         }
@@ -131,26 +142,27 @@ public class WriteBuffer {
         }
     }
 
-    public void writeUnsignedBigInteger(int bitLength, BigInteger value) 
throws ParseException {
+    @Override
+    public void writeUnsignedBigInteger(String logicalName, int bitLength, 
BigInteger value) throws ParseException {
         try {
             if (bitLength == 64) {
                 if(littleEndian) {
                     if (value.compareTo(BigInteger.valueOf(Long.MAX_VALUE)) >= 
0) {
-                        writeLong(32, value.longValue());
-                        writeLong(32, value.shiftRight(32).longValue());
+                        writeLong(logicalName,32, value.longValue());
+                        writeLong(logicalName,32, 
value.shiftRight(32).longValue());
                     } else {
-                        writeLong(bitLength, value.longValue());
+                        writeLong(logicalName,bitLength, value.longValue());
                     }
                 } else {
                     if (value.compareTo(BigInteger.valueOf(Long.MAX_VALUE)) >= 
0) {
-                        writeLong(32, value.shiftRight(32).longValue());
-                        writeLong(32, value.longValue());
+                        writeLong(logicalName,32, 
value.shiftRight(32).longValue());
+                        writeLong(logicalName,32, value.longValue());
                     } else {
-                        writeLong(bitLength, value.longValue());
+                        writeLong(logicalName,bitLength, value.longValue());
                     }
                 }
             } else if (bitLength < 64){
-                writeUnsignedLong(bitLength, value.longValue());
+                writeUnsignedLong(logicalName,bitLength, value.longValue());
             } else {
                 throw new ParseException("Unsigned Big Integer can only 
contain max 64 bits");
             }
@@ -159,7 +171,8 @@ public class WriteBuffer {
         }
     }
 
-    public void writeByte(int bitLength, byte value) throws ParseException {
+    @Override
+    public void writeByte(String logicalName, int bitLength, byte value) 
throws ParseException {
         if(bitLength <= 0) {
             throw new ParseException("byte must contain at least 1 bit");
         }
@@ -173,7 +186,8 @@ public class WriteBuffer {
         }
     }
 
-    public void writeShort(int bitLength, short value) throws ParseException {
+    @Override
+    public void writeShort(String logicalName, int bitLength, short value) 
throws ParseException {
         if(bitLength <= 0) {
             throw new ParseException("short must contain at least 1 bit");
         }
@@ -190,7 +204,8 @@ public class WriteBuffer {
         }
     }
 
-    public void writeInt(int bitLength, int value) throws ParseException {
+    @Override
+    public void writeInt(String logicalName, int bitLength, int value) throws 
ParseException {
         if(bitLength <= 0) {
             throw new ParseException("int must contain at least 1 bit");
         }
@@ -207,7 +222,8 @@ public class WriteBuffer {
         }
     }
 
-    public void writeLong(int bitLength, long value) throws ParseException {
+    @Override
+    public void writeLong(String logicalName, int bitLength, long value) 
throws ParseException {
         if(bitLength <= 0) {
             throw new ParseException("long must contain at least 1 bit");
         }
@@ -224,36 +240,41 @@ public class WriteBuffer {
         }
     }
 
-    public void writeBigInteger(int bitLength, BigInteger value) throws 
ParseException {
+    @Override
+    public void writeBigInteger(String logicalName, int bitLength, BigInteger 
value) throws ParseException {
         try {
             if(bitLength > 64) {
                 throw new ParseException("Big Integer can only contain max 64 
bits");
             }
-            writeLong(bitLength, value.longValue());
+            writeLong(logicalName, bitLength, value.longValue());
         } catch (ArithmeticException e) {
             throw new ParseException("Error reading", e);
         }
     }
 
-    public void writeFloat(float value, int bitsExponent, int bitsMantissa) 
throws ParseException {
+    @Override
+    public void writeFloat(String logicalName, float value, int bitsExponent, 
int bitsMantissa) throws ParseException {
         if (bitsExponent != 8 || bitsMantissa != 23) {
             throw new UnsupportedOperationException("Exponent and/or Mantissa 
non standard size");
         }
-        writeInt(1 + bitsExponent + bitsMantissa, 
Float.floatToRawIntBits(value));
+        writeInt(logicalName,1 + bitsExponent + bitsMantissa, 
Float.floatToRawIntBits(value));
     }
 
-    public void writeDouble(double value, int bitsExponent, int bitsMantissa) 
throws ParseException {
+    @Override
+    public void writeDouble(String logicalName, double value, int 
bitsExponent, int bitsMantissa) throws ParseException {
         if (bitsExponent != 11 || bitsMantissa != 52) {
             throw new UnsupportedOperationException("Exponent and/or Mantissa 
non standard size");
         }
-        writeLong(1 + bitsExponent + bitsMantissa, 
Double.doubleToRawLongBits(value));
+        writeLong(logicalName,1 + bitsExponent + bitsMantissa, 
Double.doubleToRawLongBits(value));
     }
 
-    public void writeBigDecimal(int bitLength, BigDecimal value) throws 
ParseException {
+    @Override
+    public void writeBigDecimal(String logicalName, int bitLength, BigDecimal 
value) throws ParseException {
         throw new UnsupportedOperationException("not implemented yet");
     }
 
-    public void writeString(int bitLength, String encoding, String value) 
throws ParseException {
+    @Override
+    public void writeString(String logicalName, int bitLength, String 
encoding, String value) throws ParseException {
         final byte[] bytes = 
value.getBytes(Charset.forName(encoding.replaceAll("[^a-zA-Z0-9]","")));
         int fixedByteLength = bitLength / 8;
 
@@ -274,4 +295,9 @@ public class WriteBuffer {
         }
     }
 
+    @Override
+    public void popContext(String logicalName) {
+
+    }
+
 }
diff --git 
a/plc4j/spi/src/test/java/org/apache/plc4x/java/spi/generation/ReadBufferTest.java
 
b/plc4j/spi/src/test/java/org/apache/plc4x/java/spi/generation/ReadBufferTest.java
index 6d75aa7..6346954 100644
--- 
a/plc4j/spi/src/test/java/org/apache/plc4x/java/spi/generation/ReadBufferTest.java
+++ 
b/plc4j/spi/src/test/java/org/apache/plc4x/java/spi/generation/ReadBufferTest.java
@@ -22,7 +22,7 @@ import org.junit.jupiter.api.Test;
 
 import java.nio.charset.StandardCharsets;
 
-import static org.junit.jupiter.api.Assertions.*;
+import static org.junit.jupiter.api.Assertions.assertEquals;
 
 class ReadBufferTest {
 
@@ -32,8 +32,8 @@ class ReadBufferTest {
     @Test
     void readString() {
         String value = new String("abcdef");
-        final ReadBuffer buffer = new 
ReadBuffer(value.getBytes(StandardCharsets.UTF_8));
-        String answer = buffer.readString(value.length() * 8, "UTF-8");
+        final ReadBuffer buffer = new 
ReadBufferByteBased(value.getBytes(StandardCharsets.UTF_8));
+        String answer = buffer.readString("", value.length() * 8, "UTF-8");
 
         assertEquals(value, answer);
     }
diff --git 
a/plc4j/utils/test-utils/src/main/java/org/apache/plc4x/test/driver/DriverTestsuiteRunner.java
 
b/plc4j/utils/test-utils/src/main/java/org/apache/plc4x/test/driver/DriverTestsuiteRunner.java
index 6701efd..95122b4 100644
--- 
a/plc4j/utils/test-utils/src/main/java/org/apache/plc4x/test/driver/DriverTestsuiteRunner.java
+++ 
b/plc4j/utils/test-utils/src/main/java/org/apache/plc4x/test/driver/DriverTestsuiteRunner.java
@@ -424,7 +424,7 @@ public class DriverTestsuiteRunner extends 
XmlTestsuiteRunner {
 
     private byte[] getBytesFromXml(Element referenceXml, boolean bigEndian) 
throws DriverTestsuiteException {
         final String className = referenceXml.attributeValue(new 
QName("className"));
-        final WriteBuffer writeBuffer = new WriteBuffer(1024, !bigEndian);
+        final WriteBufferByteBased writeBuffer = new 
WriteBufferByteBased(1024, !bigEndian);
         try {
             final MessageIO messageIO = 
getMessageIOType(className).newInstance();
             final String referenceXmlString = referenceXml.asXML();
@@ -449,7 +449,7 @@ public class DriverTestsuiteRunner extends 
XmlTestsuiteRunner {
 
     private void validateMessage(Element referenceXml, List<String> 
parserArguments, byte[] data, boolean bigEndian) throws 
DriverTestsuiteException {
         final ObjectMapper mapper = new 
XmlMapper().enableDefaultTyping().registerModule(new TestSuiteMappingModule());
-        final ReadBuffer readBuffer = new ReadBuffer(data, !bigEndian);
+        final ReadBufferByteBased readBuffer = new ReadBufferByteBased(data, 
!bigEndian);
         try {
             final String className = referenceXml.attributeValue(new 
QName("className"));
             final MessageIO<?,?> messageIO = 
getMessageIOType(className).newInstance();
diff --git 
a/plc4j/utils/test-utils/src/main/java/org/apache/plc4x/test/parserserializer/ParserSerializerTestsuiteRunner.java
 
b/plc4j/utils/test-utils/src/main/java/org/apache/plc4x/test/parserserializer/ParserSerializerTestsuiteRunner.java
index 6a6409f..811cb4f 100644
--- 
a/plc4j/utils/test-utils/src/main/java/org/apache/plc4x/test/parserserializer/ParserSerializerTestsuiteRunner.java
+++ 
b/plc4j/utils/test-utils/src/main/java/org/apache/plc4x/test/parserserializer/ParserSerializerTestsuiteRunner.java
@@ -129,7 +129,7 @@ public class ParserSerializerTestsuiteRunner extends 
XmlTestsuiteRunner {
 
     private void run(ParserSerializerTestsuite testSuite, Testcase testcase) 
throws ParserSerializerTestsuiteException {
         ObjectMapper mapper = new 
XmlMapper().enableDefaultTyping().registerModule(new TestSuiteMappingModule());
-        ReadBuffer readBuffer = new ReadBuffer(testcase.getRaw(), 
testSuite.isLittleEndian());
+        ReadBufferByteBased readBuffer = new 
ReadBufferByteBased(testcase.getRaw(), testSuite.isLittleEndian());
         String referenceXml = testcase.getXml().elements().get(0).asXML();
 
         MessageIO messageIO = getMessageIOForTestcase(testcase);
@@ -141,7 +141,7 @@ public class ParserSerializerTestsuiteRunner extends 
XmlTestsuiteRunner {
                 System.out.println(xmlString);
                 throw new ParserSerializerTestsuiteException("Differences were 
found after parsing.\n" + diff.toString());
             }
-            WriteBuffer writeBuffer = new WriteBuffer(((Message) 
msg).getLengthInBytes(), testSuite.isLittleEndian());
+            WriteBufferByteBased writeBuffer = new 
WriteBufferByteBased(((Message) msg).getLengthInBytes(), 
testSuite.isLittleEndian());
             messageIO.serialize(writeBuffer, msg);
             byte[] data = writeBuffer.getData();
             if (testcase.getRaw().length != data.length) {

Reply via email to