You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@plc4x.apache.org by sr...@apache.org on 2021/11/29 14:26:26 UTC

[plc4x] branch develop updated: feat(plc4go/try-assert): try/assert is now working in golang

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


The following commit(s) were added to refs/heads/develop by this push:
     new c076381  feat(plc4go/try-assert): try/assert is now working in golang
c076381 is described below

commit c0763817575aeb27189149828d0d94d139f2cbd0
Author: Sebastian Rühl <sr...@apache.org>
AuthorDate: Mon Nov 29 15:21:08 2021 +0100

    feat(plc4go/try-assert): try/assert is now working in golang
---
 .../resources/templates/go/model-template.go.ftlh  | 18 ++++--
 .../drivers/tests/manual_bacnet_PcapTest_test.go   |  2 +-
 .../bacnetip/readwrite/model/BACnetComplexTag.go   |  6 ++
 .../BACnetConfirmedServiceRequestWriteProperty.go  | 16 ++++--
 .../model/BACnetUnconfirmedServiceRequestWhoHas.go | 64 +++++++++++++++-------
 .../plc4go/bacnetip/readwrite/model/NPDU.go        | 32 +++++++----
 .../knxnetip/readwrite/model/ConnectionResponse.go | 32 +++++++----
 .../plc4go/s7/readwrite/model/COTPPacket.go        | 16 ++++--
 .../plc4go/s7/readwrite/model/S7Message.go         | 32 +++++++----
 plc4go/internal/plc4go/spi/utils/ReadBuffer.go     |  2 +
 .../plc4go/spi/utils/ReadBufferByteBased.go        | 10 ++++
 .../plc4go/spi/utils/ReadBufferJsonBased.go        |  4 ++
 .../plc4go/spi/utils/ReadBufferXmlBased.go         |  4 ++
 plc4go/internal/plc4go/spi/utils/Utils.go          |  4 ++
 14 files changed, 176 insertions(+), 66 deletions(-)

diff --git a/code-generation/language-go/src/main/resources/templates/go/model-template.go.ftlh b/code-generation/language-go/src/main/resources/templates/go/model-template.go.ftlh
index b3b0078..a5981b2 100644
--- a/code-generation/language-go/src/main/resources/templates/go/model-template.go.ftlh
+++ b/code-generation/language-go/src/main/resources/templates/go/model-template.go.ftlh
@@ -851,6 +851,7 @@ func ${type.name}Parse(readBuffer utils.ReadBuffer<#if hasParserArguments>, ${pa
 			return nil, closeErr
 		}
 			<#else>
+		currentPos := readBuffer.GetPos()
 		if pullErr := readBuffer.PullContext("${optionalField.name}"); pullErr != nil {
 			return nil, pullErr
 		}
@@ -876,12 +877,16 @@ func ${type.name}Parse(readBuffer utils.ReadBuffer<#if hasParserArguments>, ${pa
 		_val, _err := ${typeName}Parse(readBuffer${refParams})
                 </...@compress>
 
-		if _err != nil {
+		switch {
+		case _err != nil && _err != utils.ParseAssertError:
 			return nil, errors.Wrap(_err, "Error parsing '${optionalField.name}' field")<@emitImport import="github.com/pkg/errors" />
-		}
-		${optionalField.name} = Cast${helper.getLanguageTypeNameForField(field)}(_val)
-		if closeErr := readBuffer.CloseContext("${optionalField.name}"); closeErr != nil {
-			return nil, closeErr
+		case _err == utils.ParseAssertError:
+			readBuffer.SetPos(currentPos)
+		default:
+			${optionalField.name} = Cast${helper.getLanguageTypeNameForField(field)}(_val)
+			if closeErr := readBuffer.CloseContext("${optionalField.name}"); closeErr != nil {
+				return nil, closeErr
+			}
 		}
 			</#if>
 	}
@@ -922,6 +927,9 @@ func ${type.name}Parse(readBuffer utils.ReadBuffer<#if hasParserArguments>, ${pa
 	}
 	${assertField.name} = Cast${helper.getLanguageTypeNameForField(field)}(_val)
 			</#if>
+	if ${assertField.name} != ${helper.toParseExpression(assertField, assertField.type, assertField.conditionExpression, parserArguments)} {
+		return nil, utils.ParseAssertError
+	}
 				<#break>
 			<#case "padding">
 				<#assign paddingField = field.asPaddingField().orElseThrow()>
diff --git a/plc4go/cmd/main/drivers/tests/manual_bacnet_PcapTest_test.go b/plc4go/cmd/main/drivers/tests/manual_bacnet_PcapTest_test.go
index 137b70f..7427ec2 100644
--- a/plc4go/cmd/main/drivers/tests/manual_bacnet_PcapTest_test.go
+++ b/plc4go/cmd/main/drivers/tests/manual_bacnet_PcapTest_test.go
@@ -54,7 +54,7 @@ func Test(t *testing.T) {
 	driverManager := plc4go.NewPlcDriverManager()
 	driverManager.RegisterDriver(bacnetip.NewDriver())
 	driverManager.(spi.TransportAware).RegisterTransport(pcap.NewTransport())
-	result := <-driverManager.GetConnection("bacnet-ip:pcap://" + file + "?transport-type=udp&speed-factor=1")
+	result := <-driverManager.GetConnection("bacnet-ip:pcap://" + file + "?transport-type=udp&speed-factor=4")
 	if result.GetErr() != nil {
 		panic(result.GetErr())
 	}
diff --git a/plc4go/internal/plc4go/bacnetip/readwrite/model/BACnetComplexTag.go b/plc4go/internal/plc4go/bacnetip/readwrite/model/BACnetComplexTag.go
index 09d6b8a..41884d5 100644
--- a/plc4go/internal/plc4go/bacnetip/readwrite/model/BACnetComplexTag.go
+++ b/plc4go/internal/plc4go/bacnetip/readwrite/model/BACnetComplexTag.go
@@ -139,12 +139,18 @@ func BACnetComplexTagParse(readBuffer utils.ReadBuffer, tagNumberArgument uint8,
 	if _err != nil {
 		return nil, errors.Wrap(_err, "Error parsing 'tagNumber' field")
 	}
+	if tagNumber != tagNumberArgument {
+		return nil, utils.ParseAssertError
+	}
 
 	// Assert Field (tagClass) (Can be skipped, if a given expression evaluates to false)
 	tagClass, _err := TagClassParse(readBuffer)
 	if _err != nil {
 		return nil, errors.Wrap(_err, "Error parsing 'tagClass' field")
 	}
+	if tagClass != TagClass_CONTEXT_SPECIFIC_TAGS {
+		return nil, utils.ParseAssertError
+	}
 
 	// Simple Field (lengthValueType)
 	lengthValueType, _lengthValueTypeErr := readBuffer.ReadUint8("lengthValueType", 3)
diff --git a/plc4go/internal/plc4go/bacnetip/readwrite/model/BACnetConfirmedServiceRequestWriteProperty.go b/plc4go/internal/plc4go/bacnetip/readwrite/model/BACnetConfirmedServiceRequestWriteProperty.go
index 5b7eb41..87f48d7 100644
--- a/plc4go/internal/plc4go/bacnetip/readwrite/model/BACnetConfirmedServiceRequestWriteProperty.go
+++ b/plc4go/internal/plc4go/bacnetip/readwrite/model/BACnetConfirmedServiceRequestWriteProperty.go
@@ -240,16 +240,22 @@ func BACnetConfirmedServiceRequestWritePropertyParse(readBuffer utils.ReadBuffer
 	curPos = readBuffer.GetPos() - startPos
 	var priority *BACnetTag = nil
 	if bool((curPos) < ((len) - (1))) {
+		currentPos := readBuffer.GetPos()
 		if pullErr := readBuffer.PullContext("priority"); pullErr != nil {
 			return nil, pullErr
 		}
 		_val, _err := BACnetTagParse(readBuffer)
-		if _err != nil {
+
+		switch {
+		case _err != nil && _err != utils.ParseAssertError:
 			return nil, errors.Wrap(_err, "Error parsing 'priority' field")
-		}
-		priority = CastBACnetTag(_val)
-		if closeErr := readBuffer.CloseContext("priority"); closeErr != nil {
-			return nil, closeErr
+		case _err == utils.ParseAssertError:
+			readBuffer.SetPos(currentPos)
+		default:
+			priority = CastBACnetTag(_val)
+			if closeErr := readBuffer.CloseContext("priority"); closeErr != nil {
+				return nil, closeErr
+			}
 		}
 	}
 
diff --git a/plc4go/internal/plc4go/bacnetip/readwrite/model/BACnetUnconfirmedServiceRequestWhoHas.go b/plc4go/internal/plc4go/bacnetip/readwrite/model/BACnetUnconfirmedServiceRequestWhoHas.go
index c133bf3..03d8d58 100644
--- a/plc4go/internal/plc4go/bacnetip/readwrite/model/BACnetUnconfirmedServiceRequestWhoHas.go
+++ b/plc4go/internal/plc4go/bacnetip/readwrite/model/BACnetUnconfirmedServiceRequestWhoHas.go
@@ -129,64 +129,88 @@ func BACnetUnconfirmedServiceRequestWhoHasParse(readBuffer utils.ReadBuffer, len
 	// Optional Field (deviceInstanceRangeLowLimit) (Can be skipped, if a given expression evaluates to false)
 	var deviceInstanceRangeLowLimit *BACnetComplexTagUnsignedInteger = nil
 	{
+		currentPos := readBuffer.GetPos()
 		if pullErr := readBuffer.PullContext("deviceInstanceRangeLowLimit"); pullErr != nil {
 			return nil, pullErr
 		}
 		_val, _err := BACnetComplexTagParse(readBuffer, uint8(0), BACnetDataType_UNSIGNED_INTEGER)
-		if _err != nil {
+
+		switch {
+		case _err != nil && _err != utils.ParseAssertError:
 			return nil, errors.Wrap(_err, "Error parsing 'deviceInstanceRangeLowLimit' field")
-		}
-		deviceInstanceRangeLowLimit = CastBACnetComplexTagUnsignedInteger(_val)
-		if closeErr := readBuffer.CloseContext("deviceInstanceRangeLowLimit"); closeErr != nil {
-			return nil, closeErr
+		case _err == utils.ParseAssertError:
+			readBuffer.SetPos(currentPos)
+		default:
+			deviceInstanceRangeLowLimit = CastBACnetComplexTagUnsignedInteger(_val)
+			if closeErr := readBuffer.CloseContext("deviceInstanceRangeLowLimit"); closeErr != nil {
+				return nil, closeErr
+			}
 		}
 	}
 
 	// Optional Field (deviceInstanceRangeHighLimit) (Can be skipped, if a given expression evaluates to false)
 	var deviceInstanceRangeHighLimit *BACnetComplexTagUnsignedInteger = nil
 	if bool((deviceInstanceRangeLowLimit) != (nil)) {
+		currentPos := readBuffer.GetPos()
 		if pullErr := readBuffer.PullContext("deviceInstanceRangeHighLimit"); pullErr != nil {
 			return nil, pullErr
 		}
 		_val, _err := BACnetComplexTagParse(readBuffer, uint8(1), BACnetDataType_UNSIGNED_INTEGER)
-		if _err != nil {
+
+		switch {
+		case _err != nil && _err != utils.ParseAssertError:
 			return nil, errors.Wrap(_err, "Error parsing 'deviceInstanceRangeHighLimit' field")
-		}
-		deviceInstanceRangeHighLimit = CastBACnetComplexTagUnsignedInteger(_val)
-		if closeErr := readBuffer.CloseContext("deviceInstanceRangeHighLimit"); closeErr != nil {
-			return nil, closeErr
+		case _err == utils.ParseAssertError:
+			readBuffer.SetPos(currentPos)
+		default:
+			deviceInstanceRangeHighLimit = CastBACnetComplexTagUnsignedInteger(_val)
+			if closeErr := readBuffer.CloseContext("deviceInstanceRangeHighLimit"); closeErr != nil {
+				return nil, closeErr
+			}
 		}
 	}
 
 	// Optional Field (objectIdentifier) (Can be skipped, if a given expression evaluates to false)
 	var objectIdentifier *BACnetComplexTagOctetString = nil
 	{
+		currentPos := readBuffer.GetPos()
 		if pullErr := readBuffer.PullContext("objectIdentifier"); pullErr != nil {
 			return nil, pullErr
 		}
 		_val, _err := BACnetComplexTagParse(readBuffer, uint8(2), BACnetDataType_OCTET_STRING)
-		if _err != nil {
+
+		switch {
+		case _err != nil && _err != utils.ParseAssertError:
 			return nil, errors.Wrap(_err, "Error parsing 'objectIdentifier' field")
-		}
-		objectIdentifier = CastBACnetComplexTagOctetString(_val)
-		if closeErr := readBuffer.CloseContext("objectIdentifier"); closeErr != nil {
-			return nil, closeErr
+		case _err == utils.ParseAssertError:
+			readBuffer.SetPos(currentPos)
+		default:
+			objectIdentifier = CastBACnetComplexTagOctetString(_val)
+			if closeErr := readBuffer.CloseContext("objectIdentifier"); closeErr != nil {
+				return nil, closeErr
+			}
 		}
 	}
 
 	// Optional Field (objectName) (Can be skipped, if a given expression evaluates to false)
 	var objectName *BACnetComplexTagOctetString = nil
 	if bool((objectIdentifier) == (nil)) {
+		currentPos := readBuffer.GetPos()
 		if pullErr := readBuffer.PullContext("objectName"); pullErr != nil {
 			return nil, pullErr
 		}
 		_val, _err := BACnetComplexTagParse(readBuffer, uint8(3), BACnetDataType_OCTET_STRING)
-		if _err != nil {
+
+		switch {
+		case _err != nil && _err != utils.ParseAssertError:
 			return nil, errors.Wrap(_err, "Error parsing 'objectName' field")
-		}
-		objectName = CastBACnetComplexTagOctetString(_val)
-		if closeErr := readBuffer.CloseContext("objectName"); closeErr != nil {
-			return nil, closeErr
+		case _err == utils.ParseAssertError:
+			readBuffer.SetPos(currentPos)
+		default:
+			objectName = CastBACnetComplexTagOctetString(_val)
+			if closeErr := readBuffer.CloseContext("objectName"); closeErr != nil {
+				return nil, closeErr
+			}
 		}
 	}
 
diff --git a/plc4go/internal/plc4go/bacnetip/readwrite/model/NPDU.go b/plc4go/internal/plc4go/bacnetip/readwrite/model/NPDU.go
index 226f115..600e74a 100644
--- a/plc4go/internal/plc4go/bacnetip/readwrite/model/NPDU.go
+++ b/plc4go/internal/plc4go/bacnetip/readwrite/model/NPDU.go
@@ -313,32 +313,44 @@ func NPDUParse(readBuffer utils.ReadBuffer, npduLength uint16) (*NPDU, error) {
 	// Optional Field (nlm) (Can be skipped, if a given expression evaluates to false)
 	var nlm *NLM = nil
 	if messageTypeFieldPresent {
+		currentPos := readBuffer.GetPos()
 		if pullErr := readBuffer.PullContext("nlm"); pullErr != nil {
 			return nil, pullErr
 		}
 		_val, _err := NLMParse(readBuffer, uint16(npduLength)-uint16(uint16(uint16(uint16(uint16(uint16(2))+uint16(uint16(utils.InlineIf(sourceSpecified, func() interface{} { return uint16(uint16(uint16(3)) + uint16((*sourceLength))) }, func() interface{} { return uint16(uint16(0)) }).(uint16))))+uint16(uint16(utils.InlineIf(destinationSpecified, func() interface{} { return uint16(uint16(uint16(3)) + uint16((*destinationLength))) }, func() interface{} { return uint16(uint16(0)) }).(uint16))))+ [...]
-		if _err != nil {
+
+		switch {
+		case _err != nil && _err != utils.ParseAssertError:
 			return nil, errors.Wrap(_err, "Error parsing 'nlm' field")
-		}
-		nlm = CastNLM(_val)
-		if closeErr := readBuffer.CloseContext("nlm"); closeErr != nil {
-			return nil, closeErr
+		case _err == utils.ParseAssertError:
+			readBuffer.SetPos(currentPos)
+		default:
+			nlm = CastNLM(_val)
+			if closeErr := readBuffer.CloseContext("nlm"); closeErr != nil {
+				return nil, closeErr
+			}
 		}
 	}
 
 	// Optional Field (apdu) (Can be skipped, if a given expression evaluates to false)
 	var apdu *APDU = nil
 	if !(messageTypeFieldPresent) {
+		currentPos := readBuffer.GetPos()
 		if pullErr := readBuffer.PullContext("apdu"); pullErr != nil {
 			return nil, pullErr
 		}
 		_val, _err := APDUParse(readBuffer, uint16(npduLength)-uint16(uint16(uint16(uint16(uint16(uint16(2))+uint16(uint16(utils.InlineIf(sourceSpecified, func() interface{} { return uint16(uint16(uint16(3)) + uint16((*sourceLength))) }, func() interface{} { return uint16(uint16(0)) }).(uint16))))+uint16(uint16(utils.InlineIf(destinationSpecified, func() interface{} { return uint16(uint16(uint16(3)) + uint16((*destinationLength))) }, func() interface{} { return uint16(uint16(0)) }).(uint16)))) [...]
-		if _err != nil {
+
+		switch {
+		case _err != nil && _err != utils.ParseAssertError:
 			return nil, errors.Wrap(_err, "Error parsing 'apdu' field")
-		}
-		apdu = CastAPDU(_val)
-		if closeErr := readBuffer.CloseContext("apdu"); closeErr != nil {
-			return nil, closeErr
+		case _err == utils.ParseAssertError:
+			readBuffer.SetPos(currentPos)
+		default:
+			apdu = CastAPDU(_val)
+			if closeErr := readBuffer.CloseContext("apdu"); closeErr != nil {
+				return nil, closeErr
+			}
 		}
 	}
 
diff --git a/plc4go/internal/plc4go/knxnetip/readwrite/model/ConnectionResponse.go b/plc4go/internal/plc4go/knxnetip/readwrite/model/ConnectionResponse.go
index f1269b5..24fa745 100644
--- a/plc4go/internal/plc4go/knxnetip/readwrite/model/ConnectionResponse.go
+++ b/plc4go/internal/plc4go/knxnetip/readwrite/model/ConnectionResponse.go
@@ -143,32 +143,44 @@ func ConnectionResponseParse(readBuffer utils.ReadBuffer) (*KnxNetIpMessage, err
 	// Optional Field (hpaiDataEndpoint) (Can be skipped, if a given expression evaluates to false)
 	var hpaiDataEndpoint *HPAIDataEndpoint = nil
 	if bool((status) == (Status_NO_ERROR)) {
+		currentPos := readBuffer.GetPos()
 		if pullErr := readBuffer.PullContext("hpaiDataEndpoint"); pullErr != nil {
 			return nil, pullErr
 		}
 		_val, _err := HPAIDataEndpointParse(readBuffer)
-		if _err != nil {
+
+		switch {
+		case _err != nil && _err != utils.ParseAssertError:
 			return nil, errors.Wrap(_err, "Error parsing 'hpaiDataEndpoint' field")
-		}
-		hpaiDataEndpoint = CastHPAIDataEndpoint(_val)
-		if closeErr := readBuffer.CloseContext("hpaiDataEndpoint"); closeErr != nil {
-			return nil, closeErr
+		case _err == utils.ParseAssertError:
+			readBuffer.SetPos(currentPos)
+		default:
+			hpaiDataEndpoint = CastHPAIDataEndpoint(_val)
+			if closeErr := readBuffer.CloseContext("hpaiDataEndpoint"); closeErr != nil {
+				return nil, closeErr
+			}
 		}
 	}
 
 	// Optional Field (connectionResponseDataBlock) (Can be skipped, if a given expression evaluates to false)
 	var connectionResponseDataBlock *ConnectionResponseDataBlock = nil
 	if bool((status) == (Status_NO_ERROR)) {
+		currentPos := readBuffer.GetPos()
 		if pullErr := readBuffer.PullContext("connectionResponseDataBlock"); pullErr != nil {
 			return nil, pullErr
 		}
 		_val, _err := ConnectionResponseDataBlockParse(readBuffer)
-		if _err != nil {
+
+		switch {
+		case _err != nil && _err != utils.ParseAssertError:
 			return nil, errors.Wrap(_err, "Error parsing 'connectionResponseDataBlock' field")
-		}
-		connectionResponseDataBlock = CastConnectionResponseDataBlock(_val)
-		if closeErr := readBuffer.CloseContext("connectionResponseDataBlock"); closeErr != nil {
-			return nil, closeErr
+		case _err == utils.ParseAssertError:
+			readBuffer.SetPos(currentPos)
+		default:
+			connectionResponseDataBlock = CastConnectionResponseDataBlock(_val)
+			if closeErr := readBuffer.CloseContext("connectionResponseDataBlock"); closeErr != nil {
+				return nil, closeErr
+			}
 		}
 	}
 
diff --git a/plc4go/internal/plc4go/s7/readwrite/model/COTPPacket.go b/plc4go/internal/plc4go/s7/readwrite/model/COTPPacket.go
index 6406e9d..fc83413 100644
--- a/plc4go/internal/plc4go/s7/readwrite/model/COTPPacket.go
+++ b/plc4go/internal/plc4go/s7/readwrite/model/COTPPacket.go
@@ -178,16 +178,22 @@ func COTPPacketParse(readBuffer utils.ReadBuffer, cotpLen uint16) (*COTPPacket,
 	curPos = readBuffer.GetPos() - startPos
 	var payload *S7Message = nil
 	if bool((curPos) < (cotpLen)) {
+		currentPos := readBuffer.GetPos()
 		if pullErr := readBuffer.PullContext("payload"); pullErr != nil {
 			return nil, pullErr
 		}
 		_val, _err := S7MessageParse(readBuffer)
-		if _err != nil {
+
+		switch {
+		case _err != nil && _err != utils.ParseAssertError:
 			return nil, errors.Wrap(_err, "Error parsing 'payload' field")
-		}
-		payload = CastS7Message(_val)
-		if closeErr := readBuffer.CloseContext("payload"); closeErr != nil {
-			return nil, closeErr
+		case _err == utils.ParseAssertError:
+			readBuffer.SetPos(currentPos)
+		default:
+			payload = CastS7Message(_val)
+			if closeErr := readBuffer.CloseContext("payload"); closeErr != nil {
+				return nil, closeErr
+			}
 		}
 	}
 
diff --git a/plc4go/internal/plc4go/s7/readwrite/model/S7Message.go b/plc4go/internal/plc4go/s7/readwrite/model/S7Message.go
index e0b7bdf..00b0eeb 100644
--- a/plc4go/internal/plc4go/s7/readwrite/model/S7Message.go
+++ b/plc4go/internal/plc4go/s7/readwrite/model/S7Message.go
@@ -202,32 +202,44 @@ func S7MessageParse(readBuffer utils.ReadBuffer) (*S7Message, error) {
 	// Optional Field (parameter) (Can be skipped, if a given expression evaluates to false)
 	var parameter *S7Parameter = nil
 	if bool((parameterLength) > (0)) {
+		currentPos := readBuffer.GetPos()
 		if pullErr := readBuffer.PullContext("parameter"); pullErr != nil {
 			return nil, pullErr
 		}
 		_val, _err := S7ParameterParse(readBuffer, messageType)
-		if _err != nil {
+
+		switch {
+		case _err != nil && _err != utils.ParseAssertError:
 			return nil, errors.Wrap(_err, "Error parsing 'parameter' field")
-		}
-		parameter = CastS7Parameter(_val)
-		if closeErr := readBuffer.CloseContext("parameter"); closeErr != nil {
-			return nil, closeErr
+		case _err == utils.ParseAssertError:
+			readBuffer.SetPos(currentPos)
+		default:
+			parameter = CastS7Parameter(_val)
+			if closeErr := readBuffer.CloseContext("parameter"); closeErr != nil {
+				return nil, closeErr
+			}
 		}
 	}
 
 	// Optional Field (payload) (Can be skipped, if a given expression evaluates to false)
 	var payload *S7Payload = nil
 	if bool((payloadLength) > (0)) {
+		currentPos := readBuffer.GetPos()
 		if pullErr := readBuffer.PullContext("payload"); pullErr != nil {
 			return nil, pullErr
 		}
 		_val, _err := S7PayloadParse(readBuffer, messageType, (parameter))
-		if _err != nil {
+
+		switch {
+		case _err != nil && _err != utils.ParseAssertError:
 			return nil, errors.Wrap(_err, "Error parsing 'payload' field")
-		}
-		payload = CastS7Payload(_val)
-		if closeErr := readBuffer.CloseContext("payload"); closeErr != nil {
-			return nil, closeErr
+		case _err == utils.ParseAssertError:
+			readBuffer.SetPos(currentPos)
+		default:
+			payload = CastS7Payload(_val)
+			if closeErr := readBuffer.CloseContext("payload"); closeErr != nil {
+				return nil, closeErr
+			}
 		}
 	}
 
diff --git a/plc4go/internal/plc4go/spi/utils/ReadBuffer.go b/plc4go/internal/plc4go/spi/utils/ReadBuffer.go
index da39edb..10a2ef2 100644
--- a/plc4go/internal/plc4go/spi/utils/ReadBuffer.go
+++ b/plc4go/internal/plc4go/spi/utils/ReadBuffer.go
@@ -26,6 +26,8 @@ import (
 type ReadBuffer interface {
 	// GetPos return the current byte position
 	GetPos() uint16
+	// SetPos sets the position to the supplied byte position
+	SetPos(pos uint16)
 	// HasMore returns true if there are bitLength bits available
 	HasMore(bitLength uint8) bool
 	// PullContext signals that we expect now a context with the supplied logical name
diff --git a/plc4go/internal/plc4go/spi/utils/ReadBufferByteBased.go b/plc4go/internal/plc4go/spi/utils/ReadBufferByteBased.go
index 59d15cd..14972fe 100644
--- a/plc4go/internal/plc4go/spi/utils/ReadBufferByteBased.go
+++ b/plc4go/internal/plc4go/spi/utils/ReadBufferByteBased.go
@@ -94,6 +94,16 @@ func (rb *byteReadBuffer) GetPos() uint16 {
 	return uint16(rb.pos / 8)
 }
 
+func (rb *byteReadBuffer) SetPos(pos uint16) {
+	rb.Reset()
+	bytesToSkip := make([]byte, pos)
+	_, err := rb.reader.Read(bytesToSkip)
+	if err != nil {
+		panic(err)
+	}
+	rb.pos = uint64(pos * 8)
+}
+
 func (rb *byteReadBuffer) GetBytes() []byte {
 	return rb.data
 }
diff --git a/plc4go/internal/plc4go/spi/utils/ReadBufferJsonBased.go b/plc4go/internal/plc4go/spi/utils/ReadBufferJsonBased.go
index e7b371b..af1f390 100644
--- a/plc4go/internal/plc4go/spi/utils/ReadBufferJsonBased.go
+++ b/plc4go/internal/plc4go/spi/utils/ReadBufferJsonBased.go
@@ -80,6 +80,10 @@ func (j *jsonReadBuffer) GetPos() uint16 {
 	return uint16(j.pos / 8)
 }
 
+func (j *jsonReadBuffer) SetPos(pos uint16) {
+	j.pos = uint(pos * 8)
+}
+
 func (j *jsonReadBuffer) HasMore(bitLength uint8) bool {
 	// TODO: work with x.InputOffset() and check if we are at EOF
 	return true
diff --git a/plc4go/internal/plc4go/spi/utils/ReadBufferXmlBased.go b/plc4go/internal/plc4go/spi/utils/ReadBufferXmlBased.go
index ac4ece5..823e3ba 100644
--- a/plc4go/internal/plc4go/spi/utils/ReadBufferXmlBased.go
+++ b/plc4go/internal/plc4go/spi/utils/ReadBufferXmlBased.go
@@ -73,6 +73,10 @@ func (x *xmlReadBuffer) GetPos() uint16 {
 	return uint16(x.pos / 8)
 }
 
+func (x *xmlReadBuffer) SetPos(pos uint16) {
+	x.pos = uint(pos * 8)
+}
+
 func (x *xmlReadBuffer) HasMore(bitLength uint8) bool {
 	// TODO: work with x.InputOffset() and check if we are at EOF
 	return true
diff --git a/plc4go/internal/plc4go/spi/utils/Utils.go b/plc4go/internal/plc4go/spi/utils/Utils.go
index 4f11f40..c9c16dd 100644
--- a/plc4go/internal/plc4go/spi/utils/Utils.go
+++ b/plc4go/internal/plc4go/spi/utils/Utils.go
@@ -19,6 +19,8 @@
 
 package utils
 
+import "github.com/pkg/errors"
+
 // InlineIf is basically a inline if like construct for golang
 func InlineIf(test bool, a func() interface{}, b func() interface{}) interface{} {
 	if test {
@@ -27,3 +29,5 @@ func InlineIf(test bool, a func() interface{}, b func() interface{}) interface{}
 		return b()
 	}
 }
+
+var ParseAssertError = errors.New("Wrong assertion")