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 0c5f2ae plc4go: first draft of WriterBufferJsonBased.go
0c5f2ae is described below
commit 0c5f2ae2f678cd12ad1dd0daf7a8b8ada22712b5
Author: Sebastian Rühl <[email protected]>
AuthorDate: Wed Apr 21 00:38:14 2021 +0200
plc4go: first draft of WriterBufferJsonBased.go
+ refactored reader and writers
---
.../resources/templates/go/model-template.go.ftlh | 12 +-
go.mod | 2 +-
go.sum | 2 +
.../plc4go/s7/readwrite/model/COTPPacket.go | 8 +-
plc4go/internal/plc4go/s7/s7Io_test.go | 217 +++++++++++++++----
plc4go/internal/plc4go/spi/utils/Buffer.go | 85 ++++++++
.../plc4go/spi/utils/ReadBufferXmlBased.go | 55 ++---
.../plc4go/spi/utils/WriteBufferBoxBased.go | 52 ++---
.../plc4go/spi/utils/WriteBufferJsonBased.go | 232 +++++++++++++++++++++
.../plc4go/spi/utils/WriteBufferXmlBased.go | 106 +++-------
plc4go/internal/plc4go/spi/utils/bufferCommons.go | 103 +++++++++
11 files changed, 689 insertions(+), 185 deletions(-)
diff --git
a/build-utils/language-go/src/main/resources/templates/go/model-template.go.ftlh
b/build-utils/language-go/src/main/resources/templates/go/model-template.go.ftlh
index 5af59d7..5d138f5 100644
---
a/build-utils/language-go/src/main/resources/templates/go/model-template.go.ftlh
+++
b/build-utils/language-go/src/main/resources/templates/go/model-template.go.ftlh
@@ -544,7 +544,7 @@ func ${type.name}Parse(io utils.ReadBuffer<#if
type.parserArguments?has_content>
<#assign arrayField = field>
// Array field (${arrayField.name})
- io.PullContext("${arrayField.name}")
+ io.PullContext("${arrayField.name}", utils.WithRenderAsList(true))
<#-- Only update curPos if the length expression uses
it -->
<#if
arrayField.loopExpression.contains("curPos")>
curPos = io.GetPos() - startPos<@emitImport import="io" />
@@ -598,7 +598,7 @@ func ${type.name}Parse(io utils.ReadBuffer<#if
type.parserArguments?has_content>
</#if>
}
</#if>
- io.CloseContext("${arrayField.name}")
+ io.CloseContext("${arrayField.name}", utils.WithRenderAsList(true))
<#break>
<#case "checksum">
<#assign checksumField = field>
@@ -691,7 +691,7 @@ func ${type.name}Parse(io utils.ReadBuffer<#if
type.parserArguments?has_content>
<#break>
<#case "manualArray">
<#assign manualArrayField = field>
- io.PullContext("${manualArrayField.name}")
+ io.PullContext("${manualArrayField.name}", utils.WithRenderAsList(true))
// Manual Array Field (${manualArrayField.name})
<#-- Only update curPos if the length expression uses
it -->
<#if
manualArrayField.loopExpression.contains("curPos")>
@@ -747,7 +747,7 @@ func ${type.name}Parse(io utils.ReadBuffer<#if
type.parserArguments?has_content>
${helper.getLanguageTypeNameForField(field)}[] ${manualArrayField.name}
= _${manualArrayField.name}List.toArray(new
${helper.getLanguageTypeNameForField(manualArrayField)}[0])
</#if>
</#if>
- io.CloseContext("${manualArrayField.name}")
+ io.CloseContext("${manualArrayField.name}",
utils.WithRenderAsList(true))
<#break>
<#case "manual">
<#assign manualField = field>
@@ -1043,11 +1043,11 @@ func (m *${type.name}) Serialize(io
utils.WriteBuffer<#if helper.getSerializerAr
// Manual Array Field (${manualArrayField.name})
if m.${manualArrayField.name?cap_first} != nil {
- io.PushContext("${manualArrayField.name}")
+ io.PushContext("${manualArrayField.name}",
utils.WithRenderAsList(true))
for(${helper.getLanguageTypeNameForField(field)} element :
m.${manualArrayField.name?cap_first}) {
${helper.toSerializationExpression(manualArrayField,
manualArrayField.serializeExpression, type.parserArguments)}
}
- io.PushContext("${manualArrayField.name}")
+ io.PopContext("${manualArrayField.name}",
utils.WithRenderAsList(true))
}
<#break>
<#case "manual">
diff --git a/go.mod b/go.mod
index eebd510..751a141 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-20210420140858-e7f2f4c6b117 //
indirect
+ github.com/apache/plc4x/plc4go v0.0.0-20210420175605-7ec5b56fe1cf //
indirect
github.com/sirupsen/logrus v1.7.0 // indirect
)
diff --git a/go.sum b/go.sum
index e36d6ad..c53de2f 100644
--- a/go.sum
+++ b/go.sum
@@ -96,6 +96,8 @@ github.com/apache/plc4x/plc4go
v0.0.0-20210419213911-a28fac5a883e h1:RH0AQ+AnzYJ
github.com/apache/plc4x/plc4go v0.0.0-20210419213911-a28fac5a883e/go.mod
h1:NqpWaMMhsu3sTm418XwsUWgmY7e2zjgpRMyddBUwmGk=
github.com/apache/plc4x/plc4go v0.0.0-20210420140858-e7f2f4c6b117
h1:aJkJp07IONjywarB9o0DlWyFRwPJIgn+Nfn1jxJz86s=
github.com/apache/plc4x/plc4go v0.0.0-20210420140858-e7f2f4c6b117/go.mod
h1:NqpWaMMhsu3sTm418XwsUWgmY7e2zjgpRMyddBUwmGk=
+github.com/apache/plc4x/plc4go v0.0.0-20210420175605-7ec5b56fe1cf
h1:HYsSjhzqXX2CWIP9iF+or7q3bLJEvB3XBx146pejQ04=
+github.com/apache/plc4x/plc4go v0.0.0-20210420175605-7ec5b56fe1cf/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/plc4go/internal/plc4go/s7/readwrite/model/COTPPacket.go
b/plc4go/internal/plc4go/s7/readwrite/model/COTPPacket.go
index a5b5c8b..fca65b6 100644
--- a/plc4go/internal/plc4go/s7/readwrite/model/COTPPacket.go
+++ b/plc4go/internal/plc4go/s7/readwrite/model/COTPPacket.go
@@ -159,7 +159,7 @@ func COTPPacketParse(io utils.ReadBuffer, cotpLen uint16)
(*COTPPacket, error) {
}
// Array field (parameters)
- io.PullContext("parameters")
+ io.PullContext("parameters", utils.WithRenderAsList(true))
curPos = io.GetPos() - startPos
// Length array
parameters := make([]*COTPParameter, 0)
@@ -173,7 +173,7 @@ func COTPPacketParse(io utils.ReadBuffer, cotpLen uint16)
(*COTPPacket, error) {
parameters = append(parameters, _item)
curPos = io.GetPos() - startPos
}
- io.CloseContext("parameters")
+ io.CloseContext("parameters", utils.WithRenderAsList(true))
// Optional Field (payload) (Can be skipped, if a given expression
evaluates to false)
curPos = io.GetPos() - startPos
@@ -223,14 +223,14 @@ func (m *COTPPacket) SerializeParent(io
utils.WriteBuffer, child ICOTPPacket, se
// Array Field (parameters)
if m.Parameters != nil {
- io.PushContext("parameters")
+ io.PushContext("parameters", utils.WithRenderAsList(true))
for _, _element := range m.Parameters {
_elementErr := _element.Serialize(io)
if _elementErr != nil {
return errors.Wrap(_elementErr, "Error
serializing 'parameters' field")
}
}
- io.PopContext("parameters")
+ io.PopContext("parameters", utils.WithRenderAsList(true))
}
// Optional Field (payload) (Can be skipped, if the value is null)
diff --git a/plc4go/internal/plc4go/s7/s7Io_test.go
b/plc4go/internal/plc4go/s7/s7Io_test.go
index 33cec3c..e803ab3 100644
--- a/plc4go/internal/plc4go/s7/s7Io_test.go
+++ b/plc4go/internal/plc4go/s7/s7Io_test.go
@@ -43,6 +43,7 @@ func TestS7MessageBytes(t *testing.T) {
wantString string
wantStringSerialized string
wantStringXml string
+ wantStringJson string
wantDump string
}{
{
@@ -220,6 +221,126 @@ func TestS7MessageBytes(t *testing.T) {
</payload>
</TPKTPacket>
`,
+ wantStringJson: `
+{
+ "TPKTPacket": {
+ "len": 29,
+ "len__plc4x_bitLength": 16,
+ "len__plc4x_dataType": "uint",
+ "payload": {
+ "COTPPacket": {
+ "COTPPacketData": {
+ "eot": false,
+ "eot__plc4x_bitLength": 1,
+ "eot__plc4x_dataType": "bit",
+ "tpduRef": 13,
+ "tpduRef__plc4x_bitLength": 7,
+ "tpduRef__plc4x_dataType": "uint"
+ },
+ "S7Message": {
+ "S7MessageResponseData": {
+ "errorClass": 0,
+ "errorClass__plc4x_bitLength": 8,
+ "errorClass__plc4x_dataType": "uint",
+ "errorCode": 0,
+ "errorCode__plc4x_bitLength": 8,
+ "errorCode__plc4x_dataType": "uint"
+ },
+ "S7Parameter": {
+ "S7ParameterReadVarResponse": {
+ "numItems": 1,
+ "numItems__plc4x_bitLength": 8,
+ "numItems__plc4x_dataType": "uint"
+ },
+ "parameterType": 4,
+ "parameterType__plc4x_bitLength": 8,
+ "parameterType__plc4x_dataType": "uint"
+ },
+ "S7Payload": {
+ "S7PayloadReadVarResponse": {
+ "items": {
+ "S7VarPayloadDataItem": {
+ "data": {
+ "value": 1,
+ "value__plc4x_bitLength": 8,
+ "value__plc4x_dataType": "int"
+ },
+ "dataLength": 1,
+ "dataLength__plc4x_bitLength": 16,
+ "dataLength__plc4x_dataType": "uint",
+ "padding": {},
+ "returnCode": {
+ "DataTransportErrorCode": 255,
+ "DataTransportErrorCode__plc4x_bitLength": 8,
+ "DataTransportErrorCode__plc4x_dataType": "uint",
+ "DataTransportErrorCode__plc4x_stringRepresentation": "OK"
+ },
+ "transportSize": {
+ "DataTransportSize": 3,
+ "DataTransportSize__plc4x_bitLength": 8,
+ "DataTransportSize__plc4x_dataType": "uint",
+ "DataTransportSize__plc4x_stringRepresentation": "BIT"
+ }
+ }
+ }
+ }
+ },
+ "messageType": 3,
+ "messageType__plc4x_bitLength": 8,
+ "messageType__plc4x_dataType": "uint",
+ "parameterLength": 2,
+ "parameterLength__plc4x_bitLength": 16,
+ "parameterLength__plc4x_dataType": "uint",
+ "payloadLength": 5,
+ "payloadLength__plc4x_bitLength": 16,
+ "payloadLength__plc4x_dataType": "uint",
+ "protocolId": 50,
+ "protocolId__plc4x_bitLength": 8,
+ "protocolId__plc4x_dataType": "uint",
+ "reserved": 0,
+ "reserved__plc4x_bitLength": 16,
+ "reserved__plc4x_dataType": "uint",
+ "tpduReference": 11,
+ "tpduReference__plc4x_bitLength": 16,
+ "tpduReference__plc4x_dataType": "uint"
+ },
+ "headerLength": 5,
+ "headerLength__plc4x_bitLength": 8,
+ "headerLength__plc4x_dataType": "uint",
+ "parameters": [
+ {
+ "COTPParameter": {
+ "COTPParameterTpduSize": {
+ "tpduSize": {
+ "COTPTpduSize": 12,
+ "COTPTpduSize__plc4x_bitLength": 8,
+ "COTPTpduSize__plc4x_dataType": "int",
+ "COTPTpduSize__plc4x_stringRepresentation": "SIZE_4096"
+ }
+ },
+ "parameterLength": 1,
+ "parameterLength__plc4x_bitLength": 8,
+ "parameterLength__plc4x_dataType": "uint",
+ "parameterType": 192,
+ "parameterType__plc4x_bitLength": 8,
+ "parameterType__plc4x_dataType": "uint"
+ }
+ }
+ ],
+ "tpduCode": 240,
+ "tpduCode__plc4x_bitLength": 8,
+ "tpduCode__plc4x_dataType": "uint"
+ }
+ },
+ "protocolId": 3,
+ "protocolId__plc4x_bitLength": 8,
+ "protocolId__plc4x_dataType": "uint",
+ "reserved": 0,
+ "reserved__plc4x_bitLength": 8,
+ "reserved__plc4x_dataType": "uint"
+ }
+}
+`,
wantDump: `
00|03 00 00 1d 05 f0 0d c0 01 0c '..........'
10|32 03 00 00 00 0b 00 02 00 05 '2.........'
@@ -229,47 +350,71 @@ func TestS7MessageBytes(t *testing.T) {
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
- // Simple 2 String
- tt.wantString = strings.Trim(tt.wantString, "\n")
- if got := tt.args.debuggable.String(); got !=
tt.wantString {
- t.Errorf("String() = '\n%v\n', want '\n%v\n'",
got, tt.wantString)
- }
- // Simple 2 Box
- boxWriter := utils.NewBoxedWriteBuffer()
- if err := tt.args.debuggable.Serialize(boxWriter); err
!= nil {
- t.Error(err)
- }
- tt.wantStringSerialized =
strings.Trim(tt.wantStringSerialized, "\n")
- if got := string(boxWriter.GetBox()); got !=
tt.wantStringSerialized {
- t.Errorf("Serialize Boxed() = '\n%v\n', want
'\n%v\n'", got, tt.wantStringSerialized)
- }
- // Simple 2 Xml
- xmlWriteBuffer := utils.NewXmlWriteBuffer()
- if err := tt.args.debuggable.Serialize(xmlWriteBuffer);
err != nil {
- t.Error(err)
+ {
+ // Simple 2 String
+ tt.wantString = strings.Trim(tt.wantString,
"\n")
+ if got := tt.args.debuggable.String(); got !=
tt.wantString {
+ t.Errorf("String() = '\n%v\n', want
'\n%v\n'", got, tt.wantString)
+ }
}
- tt.wantStringXml = strings.Trim(tt.wantStringXml, "\n")
- if got := xmlWriteBuffer.GetXmlString(); got !=
tt.wantStringXml {
- t.Errorf("Serialize Xml() = '\n%v\n', want
'\n%v\n'", got, tt.wantStringXml)
+ {
+ // Simple 2 Box
+ boxWriter := utils.NewBoxedWriteBuffer()
+ if err :=
tt.args.debuggable.Serialize(boxWriter); err != nil {
+ t.Error(err)
+ }
+ tt.wantStringSerialized =
strings.Trim(tt.wantStringSerialized, "\n")
+ if got := string(boxWriter.GetBox()); got !=
tt.wantStringSerialized {
+ t.Errorf("Serialize Boxed() = '\n%v\n',
want '\n%v\n'", got, tt.wantStringSerialized)
+ }
}
-
- // Simple Binary Serialize
- buffer := utils.NewWriteBuffer()
- if err := tt.args.debuggable.Serialize(buffer); err !=
nil {
- t.Error(err)
+ {
+ // Simple 2 Xml
+ xmlWriteBuffer := utils.NewXmlWriteBuffer()
+ if err :=
tt.args.debuggable.Serialize(xmlWriteBuffer); err != nil {
+ t.Error(err)
+ }
+ tt.wantStringXml =
strings.Trim(tt.wantStringXml, "\n")
+ if got := xmlWriteBuffer.GetXmlString(); got !=
tt.wantStringXml {
+ t.Errorf("Serialize Xml() = '\n%v\n',
want '\n%v\n'", got, tt.wantStringXml)
+ }
}
- tt.wantDump = strings.Trim(tt.wantDump, "\n")
- if got := utils.Dump(buffer.GetBytes());
!reflect.DeepEqual(got, tt.wantDump) {
- t.Errorf("Serialize() = '\n%v\n', want
'\n%v\n'", got, tt.wantDump)
+ {
+ // Simple 2 Json
+ jsonWriteBuffer := utils.NewJsonWriteBuffer()
+ if err :=
tt.args.debuggable.Serialize(jsonWriteBuffer); err != nil {
+ t.Error(err)
+ }
+ tt.wantStringJson =
strings.Trim(tt.wantStringJson, "\n")
+ if got, err := jsonWriteBuffer.GetJsonString();
err != nil || strings.Trim(got, "\n") != tt.wantStringJson {
+ if err != nil {
+ t.Error(err)
+ } else {
+ t.Errorf("Serialize Json() =
'\n%v\n', want '\n%v\n'", got, tt.wantStringJson)
+ }
+ }
}
- // and at least a roundtip
- reader := strings.NewReader(tt.wantStringXml)
- readBuffer := utils.NewXmlReadBuffer(reader)
- if got, err := model.TPKTPacketParse(readBuffer); err
!= nil || !reflect.DeepEqual(got, tt.args.debuggable) {
- if err != nil {
+ {
+ // Simple Binary Serialize
+ buffer := utils.NewWriteBuffer()
+ if err := tt.args.debuggable.Serialize(buffer);
err != nil {
t.Error(err)
- } else {
- t.Errorf("Roundtrip = '\n%v\n', want
'\n%v\n'", got, tt.wantDump)
+ }
+ tt.wantDump = strings.Trim(tt.wantDump, "\n")
+ if got := utils.Dump(buffer.GetBytes());
!reflect.DeepEqual(got, tt.wantDump) {
+ t.Errorf("Serialize() = '\n%v\n', want
'\n%v\n'", got, tt.wantDump)
+ }
+ }
+ {
+ // and at least a roundtip
+ reader := strings.NewReader(tt.wantStringXml)
+ readBuffer := utils.NewXmlReadBuffer(reader)
+ if got, err :=
model.TPKTPacketParse(readBuffer); err != nil || !reflect.DeepEqual(got,
tt.args.debuggable) {
+ if err != nil {
+ t.Error(err)
+ } else {
+ t.Errorf("Roundtrip = '\n%v\n',
want '\n%v\n'", got, tt.wantDump)
+ }
}
}
})
diff --git a/plc4go/internal/plc4go/spi/utils/Buffer.go
b/plc4go/internal/plc4go/spi/utils/Buffer.go
new file mode 100644
index 0000000..99df612
--- /dev/null
+++ b/plc4go/internal/plc4go/spi/utils/Buffer.go
@@ -0,0 +1,85 @@
+//
+// 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 utils
+
+// WithReaderWriterArgs is a marker interface for reader args supplied by the
builders
+type WithReaderWriterArgs interface {
+ WithReaderArgs
+ WithWriterArgs
+}
+
+// WithAdditionalStringRepresentation can be used by e.g. enums to supply an
additional string representation
+func WithAdditionalStringRepresentation(stringRepresentation string)
WithReaderWriterArgs {
+ return withAdditionalStringRepresentation{stringRepresentation:
stringRepresentation}
+}
+
+// WithRenderAsList indicates that an element can be rendered as list
+func WithRenderAsList(renderAsList bool) WithReaderWriterArgs {
+ return withRenderAsList{renderAsList: renderAsList}
+}
+
+///////////////////////////////////////
+///////////////////////////////////////
+//
+// Internal section
+//
+
+type readerWriterArg struct {
+}
+
+func (_ readerWriterArg) isWriterArgs() bool {
+ return true
+}
+
+func (_ readerWriterArg) isReaderArgs() bool {
+ return true
+}
+
+type withAdditionalStringRepresentation struct {
+ readerWriterArg
+ stringRepresentation string
+}
+
+type withRenderAsList struct {
+ readerWriterArg
+ renderAsList bool
+}
+
+func upcastReaderArgs(args ...WithReaderArgs) []WithReaderWriterArgs {
+ result := make([]WithReaderWriterArgs, len(args))
+ for i, arg := range args {
+ result[i] = arg.(WithReaderWriterArgs)
+ }
+ return result
+}
+
+func upcastWriterArgs(args ...WithWriterArgs) []WithReaderWriterArgs {
+ result := make([]WithReaderWriterArgs, len(args))
+ for i, arg := range args {
+ result[i] = arg.(WithReaderWriterArgs)
+ }
+ return result
+}
+
+//
+// Internal section
+//
+///////////////////////////////////////
+///////////////////////////////////////
diff --git a/plc4go/internal/plc4go/spi/utils/ReadBufferXmlBased.go
b/plc4go/internal/plc4go/spi/utils/ReadBufferXmlBased.go
index cb8434f..21e1729 100644
--- a/plc4go/internal/plc4go/spi/utils/ReadBufferXmlBased.go
+++ b/plc4go/internal/plc4go/spi/utils/ReadBufferXmlBased.go
@@ -29,8 +29,8 @@ import (
func NewXmlReadBuffer(reader io.Reader) ReadBuffer {
return &xmlReadBuffer{
- xml.NewDecoder(reader),
- 1,
+ Decoder: xml.NewDecoder(reader),
+ pos: 1,
}
}
@@ -41,6 +41,7 @@ func NewXmlReadBuffer(reader io.Reader) ReadBuffer {
//
type xmlReadBuffer struct {
+ bufferCommons
*xml.Decoder
pos uint
}
@@ -73,7 +74,7 @@ func (x *xmlReadBuffer) PullContext(logicalName string,
readerArgs ...WithReader
func (x *xmlReadBuffer) ReadBit(logicalName string, readerArgs
...WithReaderArgs) (bool, error) {
var value bool
- err := x.decode(logicalName, "bit", 1, readerArgs, &value)
+ err := x.decode(logicalName, rwBitKey, 1, readerArgs, &value)
if err != nil {
return false, err
}
@@ -83,7 +84,7 @@ func (x *xmlReadBuffer) ReadBit(logicalName string,
readerArgs ...WithReaderArgs
func (x *xmlReadBuffer) ReadUint8(logicalName string, bitLength uint8,
readerArgs ...WithReaderArgs) (uint8, error) {
var value uint8
- err := x.decode(logicalName, "uint", bitLength, readerArgs, &value)
+ err := x.decode(logicalName, rwUintKey, bitLength, readerArgs, &value)
if err != nil {
return 0, err
}
@@ -93,7 +94,7 @@ func (x *xmlReadBuffer) ReadUint8(logicalName string,
bitLength uint8, readerArg
func (x *xmlReadBuffer) ReadUint16(logicalName string, bitLength uint8,
readerArgs ...WithReaderArgs) (uint16, error) {
var value uint16
- err := x.decode(logicalName, "uint", bitLength, readerArgs, &value)
+ err := x.decode(logicalName, rwUintKey, bitLength, readerArgs, &value)
if err != nil {
return 0, err
}
@@ -103,7 +104,7 @@ func (x *xmlReadBuffer) ReadUint16(logicalName string,
bitLength uint8, readerAr
func (x *xmlReadBuffer) ReadUint32(logicalName string, bitLength uint8,
readerArgs ...WithReaderArgs) (uint32, error) {
var value uint32
- err := x.decode(logicalName, "uint", bitLength, readerArgs, &value)
+ err := x.decode(logicalName, rwUintKey, bitLength, readerArgs, &value)
if err != nil {
return 0, err
}
@@ -113,7 +114,7 @@ func (x *xmlReadBuffer) ReadUint32(logicalName string,
bitLength uint8, readerAr
func (x *xmlReadBuffer) ReadUint64(logicalName string, bitLength uint8,
readerArgs ...WithReaderArgs) (uint64, error) {
var value uint64
- err := x.decode(logicalName, "uint", bitLength, readerArgs, &value)
+ err := x.decode(logicalName, rwUintKey, bitLength, readerArgs, &value)
if err != nil {
return 0, err
}
@@ -123,7 +124,7 @@ func (x *xmlReadBuffer) ReadUint64(logicalName string,
bitLength uint8, readerAr
func (x *xmlReadBuffer) ReadInt8(logicalName string, bitLength uint8,
readerArgs ...WithReaderArgs) (int8, error) {
var value int8
- err := x.decode(logicalName, "int", bitLength, readerArgs, &value)
+ err := x.decode(logicalName, rwIntKey, bitLength, readerArgs, &value)
if err != nil {
return 0, err
}
@@ -133,7 +134,7 @@ func (x *xmlReadBuffer) ReadInt8(logicalName string,
bitLength uint8, readerArgs
func (x *xmlReadBuffer) ReadInt16(logicalName string, bitLength uint8,
readerArgs ...WithReaderArgs) (int16, error) {
var value int16
- err := x.decode(logicalName, "int", bitLength, readerArgs, &value)
+ err := x.decode(logicalName, rwIntKey, bitLength, readerArgs, &value)
if err != nil {
return 0, err
}
@@ -143,7 +144,7 @@ func (x *xmlReadBuffer) ReadInt16(logicalName string,
bitLength uint8, readerArg
func (x *xmlReadBuffer) ReadInt32(logicalName string, bitLength uint8,
readerArgs ...WithReaderArgs) (int32, error) {
var value int32
- err := x.decode(logicalName, "int", bitLength, readerArgs, &value)
+ err := x.decode(logicalName, rwIntKey, bitLength, readerArgs, &value)
if err != nil {
return 0, err
}
@@ -153,7 +154,7 @@ func (x *xmlReadBuffer) ReadInt32(logicalName string,
bitLength uint8, readerArg
func (x *xmlReadBuffer) ReadInt64(logicalName string, bitLength uint8,
readerArgs ...WithReaderArgs) (int64, error) {
var value int64
- err := x.decode(logicalName, "int", bitLength, readerArgs, &value)
+ err := x.decode(logicalName, rwIntKey, bitLength, readerArgs, &value)
if err != nil {
return 0, err
}
@@ -164,7 +165,7 @@ func (x *xmlReadBuffer) ReadInt64(logicalName string,
bitLength uint8, readerArg
func (x *xmlReadBuffer) ReadBigInt(logicalName string, bitLength uint64,
readerArgs ...WithReaderArgs) (*big.Int, error) {
var value big.Int
// TODO: bitLength is too short for a big int
- err := x.decode(logicalName, "int", uint8(bitLength), readerArgs,
&value)
+ err := x.decode(logicalName, rwIntKey, uint8(bitLength), readerArgs,
&value)
if err != nil {
return nil, err
}
@@ -178,7 +179,7 @@ func (x *xmlReadBuffer) ReadFloat32(logicalName string,
signed bool, exponentBit
bitLength += 1
}
var value float32
- err := x.decode(logicalName, "float", bitLength, readerArgs, &value)
+ err := x.decode(logicalName, rwFloatKey, bitLength, readerArgs, &value)
if err != nil {
return 0, err
}
@@ -192,7 +193,7 @@ func (x *xmlReadBuffer) ReadFloat64(logicalName string,
signed bool, exponentBit
bitLength += 1
}
var value float64
- err := x.decode(logicalName, "float", bitLength, readerArgs, &value)
+ err := x.decode(logicalName, rwFloatKey, bitLength, readerArgs, &value)
if err != nil {
return 0, err
}
@@ -206,7 +207,7 @@ func (x *xmlReadBuffer) ReadBigFloat(logicalName string,
signed bool, exponentBi
bitLength += 1
}
var value big.Float
- err := x.decode(logicalName, "float", bitLength, readerArgs, &value)
+ err := x.decode(logicalName, rwFloatKey, bitLength, readerArgs, &value)
if err != nil {
return nil, err
}
@@ -217,7 +218,7 @@ func (x *xmlReadBuffer) ReadBigFloat(logicalName string,
signed bool, exponentBi
func (x *xmlReadBuffer) ReadString(logicalName string, bitLength uint32,
readerArgs ...WithReaderArgs) (string, error) {
var value string
// TODO: bitlength too short
- err := x.decode(logicalName, "string", uint8(bitLength), readerArgs,
&value)
+ err := x.decode(logicalName, rwStringKey, uint8(bitLength), readerArgs,
&value)
if err != nil {
return "", err
}
@@ -279,7 +280,7 @@ func (x *xmlReadBuffer) decode(logicalName string, dataType
string, bitLength ui
if err != nil {
return err
}
- err = validateStartElement(startElement, logicalName, dataType,
bitLength, readerArgs...)
+ err = x.validateStartElement(startElement, logicalName, dataType,
bitLength, readerArgs...)
if err != nil {
return err
}
@@ -290,38 +291,38 @@ func (x *xmlReadBuffer) decode(logicalName string,
dataType string, bitLength ui
return nil
}
-func validateStartElement(startElement xml.StartElement, logicalName string,
dataType string, bitLength uint8, readerArgs ...WithReaderArgs) error {
- logicalName = sanitizeLogicalName(logicalName)
+func (x *xmlReadBuffer) validateStartElement(startElement xml.StartElement,
logicalName string, dataType string, bitLength uint8, readerArgs
...WithReaderArgs) error {
+ logicalName = x.sanitizeLogicalName(logicalName)
if startElement.Name.Local != logicalName {
return errors.Errorf("unexpected element '%s'. Expected '%s'",
startElement.Name.Local, logicalName)
- } else if err := validateAttr(startElement.Attr, dataType, bitLength,
readerArgs...); err != nil {
+ } else if err := x.validateAttr(startElement.Attr, dataType, bitLength,
readerArgs...); err != nil {
return errors.Wrap(err, "Error validating Attributes")
}
return nil
}
-func validateAttr(attr []xml.Attr, dataType string, bitLength uint8,
readerArgs ...WithReaderArgs) error {
+func (x *xmlReadBuffer) validateAttr(attr []xml.Attr, dataType string,
bitLength uint8, readerArgs ...WithReaderArgs) error {
dataTypeValidated := false
bitLengthValidate := false
for _, attribute := range attr {
switch attribute.Name.Local {
- case "dataType":
+ case rwDataTypeKey:
if attribute.Value != dataType {
- return errors.Errorf("Unexpected dataType :%s.
Want %s", attribute.Value, dataType)
+ return errors.Errorf("Unexpected %s :%s. Want
%s", rwDataTypeKey, attribute.Value, dataType)
}
dataTypeValidated = true
- case "bitLength":
+ case rwBitLengthKey:
if attribute.Value != fmt.Sprintf("%d", bitLength) {
- return errors.Errorf("Unexpected bitLength
'%s'. Want '%d'", attribute.Value, bitLength)
+ return errors.Errorf("Unexpected %s '%s'. Want
'%d'", rwBitLengthKey, attribute.Value, bitLength)
}
bitLengthValidate = true
}
}
if !dataTypeValidated {
- return errors.New("required attribute dataType missing")
+ return errors.Errorf("required attribute %s missing",
rwDataTypeKey)
}
if !bitLengthValidate {
- return errors.New("required attribute bitLength missing")
+ return errors.Errorf("required attribute %s missing",
rwBitLengthKey)
}
return nil
}
diff --git a/plc4go/internal/plc4go/spi/utils/WriteBufferBoxBased.go
b/plc4go/internal/plc4go/spi/utils/WriteBufferBoxBased.go
index 34acf88..24b5e68 100644
--- a/plc4go/internal/plc4go/spi/utils/WriteBufferBoxBased.go
+++ b/plc4go/internal/plc4go/spi/utils/WriteBufferBoxBased.go
@@ -38,23 +38,14 @@ func NewBoxedWriteBuffer() WriteBufferBoxBased {
}
}
-// WithAdditionalStringRepresentation can be used by e.g. enums to supply an
additional string representation
-func WithAdditionalStringRepresentation(stringRepresentation string)
WithWriterArgs {
- return withAdditionalStringRepresentation{stringRepresentation:
stringRepresentation}
-}
-
///////////////////////////////////////
///////////////////////////////////////
//
// Internal section
//
-type withAdditionalStringRepresentation struct {
- writerArg
- stringRepresentation string
-}
-
type boxedWriteBuffer struct {
+ bufferCommons
*list.List
desiredWidth int
currentWidth int
@@ -78,7 +69,7 @@ func (b *boxedWriteBuffer) PushContext(_ string, _
...WithWriterArgs) error {
}
func (b *boxedWriteBuffer) WriteBit(logicalName string, value bool, writerArgs
...WithWriterArgs) error {
- additionalStringRepresentation :=
extractAdditionalStringRepresentation(writerArgs...)
+ additionalStringRepresentation :=
b.extractAdditionalStringRepresentation(upcastWriterArgs(writerArgs...)...)
asInt := 0
if value {
asInt = 1
@@ -88,79 +79,79 @@ func (b *boxedWriteBuffer) WriteBit(logicalName string,
value bool, writerArgs .
}
func (b *boxedWriteBuffer) WriteUint8(logicalName string, bitLength uint8,
value uint8, writerArgs ...WithWriterArgs) error {
- additionalStringRepresentation :=
extractAdditionalStringRepresentation(writerArgs...)
+ additionalStringRepresentation :=
b.extractAdditionalStringRepresentation(upcastWriterArgs(writerArgs...)...)
b.PushBack(BoxString(logicalName, fmt.Sprintf("%#0*x %d%s",
bitLength/4, value, value, additionalStringRepresentation), 0))
return nil
}
func (b *boxedWriteBuffer) WriteUint16(logicalName string, bitLength uint8,
value uint16, writerArgs ...WithWriterArgs) error {
- additionalStringRepresentation :=
extractAdditionalStringRepresentation(writerArgs...)
+ additionalStringRepresentation :=
b.extractAdditionalStringRepresentation(upcastWriterArgs(writerArgs...)...)
b.PushBack(BoxString(logicalName, fmt.Sprintf("%#0*x %d%s",
bitLength/4, value, value, additionalStringRepresentation), 0))
return nil
}
func (b *boxedWriteBuffer) WriteUint32(logicalName string, bitLength uint8,
value uint32, writerArgs ...WithWriterArgs) error {
- additionalStringRepresentation :=
extractAdditionalStringRepresentation(writerArgs...)
+ additionalStringRepresentation :=
b.extractAdditionalStringRepresentation(upcastWriterArgs(writerArgs...)...)
b.PushBack(BoxString(logicalName, fmt.Sprintf("%#0*x %d%s",
bitLength/4, value, value, additionalStringRepresentation), 0))
return nil
}
func (b *boxedWriteBuffer) WriteUint64(logicalName string, bitLength uint8,
value uint64, writerArgs ...WithWriterArgs) error {
- additionalStringRepresentation :=
extractAdditionalStringRepresentation(writerArgs...)
+ additionalStringRepresentation :=
b.extractAdditionalStringRepresentation(upcastWriterArgs(writerArgs...)...)
b.PushBack(BoxString(logicalName, fmt.Sprintf("%#0*x %d%s",
bitLength/4, value, value, additionalStringRepresentation), 0))
return nil
}
func (b *boxedWriteBuffer) WriteInt8(logicalName string, bitLength uint8,
value int8, writerArgs ...WithWriterArgs) error {
- additionalStringRepresentation :=
extractAdditionalStringRepresentation(writerArgs...)
+ additionalStringRepresentation :=
b.extractAdditionalStringRepresentation(upcastWriterArgs(writerArgs...)...)
b.PushBack(BoxString(logicalName, fmt.Sprintf("%#0*x %d%s",
bitLength/4, value, value, additionalStringRepresentation), 0))
return nil
}
func (b *boxedWriteBuffer) WriteInt16(logicalName string, bitLength uint8,
value int16, writerArgs ...WithWriterArgs) error {
- additionalStringRepresentation :=
extractAdditionalStringRepresentation(writerArgs...)
+ additionalStringRepresentation :=
b.extractAdditionalStringRepresentation(upcastWriterArgs(writerArgs...)...)
b.PushBack(BoxString(logicalName, fmt.Sprintf("%#0*x %d%s",
bitLength/4, value, value, additionalStringRepresentation), 0))
return nil
}
func (b *boxedWriteBuffer) WriteInt32(logicalName string, bitLength uint8,
value int32, writerArgs ...WithWriterArgs) error {
- additionalStringRepresentation :=
extractAdditionalStringRepresentation(writerArgs...)
+ additionalStringRepresentation :=
b.extractAdditionalStringRepresentation(upcastWriterArgs(writerArgs...)...)
b.PushBack(BoxString(logicalName, fmt.Sprintf("%#0*x %d%s",
bitLength/4, value, value, additionalStringRepresentation), 0))
return nil
}
func (b *boxedWriteBuffer) WriteInt64(logicalName string, bitLength uint8,
value int64, writerArgs ...WithWriterArgs) error {
- additionalStringRepresentation :=
extractAdditionalStringRepresentation(writerArgs...)
+ additionalStringRepresentation :=
b.extractAdditionalStringRepresentation(upcastWriterArgs(writerArgs...)...)
b.PushBack(BoxString(logicalName, fmt.Sprintf("%#0*x %d%s",
bitLength/4, value, value, additionalStringRepresentation), 0))
return nil
}
func (b *boxedWriteBuffer) WriteBigInt(logicalName string, bitLength uint8,
value *big.Int, writerArgs ...WithWriterArgs) error {
- additionalStringRepresentation :=
extractAdditionalStringRepresentation(writerArgs...)
+ additionalStringRepresentation :=
b.extractAdditionalStringRepresentation(upcastWriterArgs(writerArgs...)...)
b.PushBack(BoxString(logicalName, fmt.Sprintf("%#0*x %d%s",
bitLength/4, value, value, additionalStringRepresentation), 0))
return nil
}
func (b *boxedWriteBuffer) WriteFloat32(logicalName string, bitLength uint8,
value float32, writerArgs ...WithWriterArgs) error {
- additionalStringRepresentation :=
extractAdditionalStringRepresentation(writerArgs...)
+ additionalStringRepresentation :=
b.extractAdditionalStringRepresentation(upcastWriterArgs(writerArgs...)...)
b.PushBack(BoxString(logicalName, fmt.Sprintf("%#0*x %f%s",
bitLength/4, value, value, additionalStringRepresentation), 0))
return nil
}
func (b *boxedWriteBuffer) WriteFloat64(logicalName string, bitLength uint8,
value float64, writerArgs ...WithWriterArgs) error {
- additionalStringRepresentation :=
extractAdditionalStringRepresentation(writerArgs...)
+ additionalStringRepresentation :=
b.extractAdditionalStringRepresentation(upcastWriterArgs(writerArgs...)...)
b.PushBack(BoxString(logicalName, fmt.Sprintf("%#0*x %f%s",
bitLength/4, value, value, additionalStringRepresentation), 0))
return nil
}
func (b *boxedWriteBuffer) WriteBigFloat(logicalName string, bitLength uint8,
value *big.Float, writerArgs ...WithWriterArgs) error {
- additionalStringRepresentation :=
extractAdditionalStringRepresentation(writerArgs...)
+ additionalStringRepresentation :=
b.extractAdditionalStringRepresentation(upcastWriterArgs(writerArgs...)...)
b.PushBack(BoxString(logicalName, fmt.Sprintf("%#0*x %f%s",
bitLength/4, value, value, additionalStringRepresentation), 0))
return nil
}
func (b *boxedWriteBuffer) WriteString(logicalName string, bitLength uint8, _
string, value string, writerArgs ...WithWriterArgs) error {
- additionalStringRepresentation :=
extractAdditionalStringRepresentation(writerArgs...)
+ additionalStringRepresentation :=
b.extractAdditionalStringRepresentation(upcastWriterArgs(writerArgs...)...)
b.PushBack(BoxString(logicalName, fmt.Sprintf("%#0*x %s%s",
bitLength/4, value, value, additionalStringRepresentation), 0))
return nil
}
@@ -187,16 +178,3 @@ findTheBox:
b.PushBack(asciiBox)
return nil
}
-
-func extractAdditionalStringRepresentation(writerArgs ...WithWriterArgs)
string {
- for _, arg := range writerArgs {
- if !arg.isWriterArgs() {
- panic("not a writer arg")
- }
- switch arg.(type) {
- case withAdditionalStringRepresentation:
- return " " +
arg.(withAdditionalStringRepresentation).stringRepresentation
- }
- }
- return ""
-}
diff --git a/plc4go/internal/plc4go/spi/utils/WriteBufferJsonBased.go
b/plc4go/internal/plc4go/spi/utils/WriteBufferJsonBased.go
new file mode 100644
index 0000000..237b12c
--- /dev/null
+++ b/plc4go/internal/plc4go/spi/utils/WriteBufferJsonBased.go
@@ -0,0 +1,232 @@
+//
+// 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 utils
+
+import (
+ "encoding/json"
+ "fmt"
+ "github.com/pkg/errors"
+ "math/big"
+ "strings"
+)
+
+type WriteBufferJsonBased interface {
+ WriteBuffer
+ GetJsonString() (string, error)
+}
+
+func NewJsonWriteBuffer() WriteBufferJsonBased {
+ var jsonString strings.Builder
+ encoder := json.NewEncoder(&jsonString)
+ encoder.SetIndent("", " ")
+ return &jsonWriteBuffer{
+ jsonString: &jsonString,
+ Encoder: encoder,
+ }
+}
+
+///////////////////////////////////////
+///////////////////////////////////////
+//
+// Internal section
+//
+
+type jsonWriteBuffer struct {
+ bufferCommons
+ stack
+ *json.Encoder
+ jsonString *strings.Builder
+ rootNode interface{}
+}
+
+type elementContext struct {
+ logicalName string
+ properties map[string]interface{}
+}
+
+type listContext struct {
+ logicalName string
+ list []interface{}
+}
+
+//
+// Internal section
+//
+///////////////////////////////////////
+///////////////////////////////////////
+
+func (j *jsonWriteBuffer) PushContext(logicalName string, writerArgs
...WithWriterArgs) error {
+ renderedAsList :=
j.isToBeRenderedAsList(upcastWriterArgs(writerArgs...)...)
+ if renderedAsList {
+ j.Push(&listContext{logicalName, make([]interface{}, 0)})
+ } else {
+ j.Push(&elementContext{logicalName,
make(map[string]interface{})})
+ }
+ return nil
+}
+
+func (j *jsonWriteBuffer) WriteBit(logicalName string, value bool, writerArgs
...WithWriterArgs) error {
+ return j.encodeNode(logicalName, value, j.generateAttr(logicalName,
rwBitKey, 1, writerArgs...))
+}
+
+func (j *jsonWriteBuffer) WriteUint8(logicalName string, bitLength uint8,
value uint8, writerArgs ...WithWriterArgs) error {
+ return j.encodeNode(logicalName, value, j.generateAttr(logicalName,
rwUintKey, bitLength, writerArgs...))
+}
+
+func (j *jsonWriteBuffer) WriteUint16(logicalName string, bitLength uint8,
value uint16, writerArgs ...WithWriterArgs) error {
+ return j.encodeNode(logicalName, value, j.generateAttr(logicalName,
rwUintKey, bitLength, writerArgs...))
+}
+
+func (j *jsonWriteBuffer) WriteUint32(logicalName string, bitLength uint8,
value uint32, writerArgs ...WithWriterArgs) error {
+ return j.encodeNode(logicalName, value, j.generateAttr(logicalName,
rwUintKey, bitLength, writerArgs...))
+}
+
+func (j *jsonWriteBuffer) WriteUint64(logicalName string, bitLength uint8,
value uint64, writerArgs ...WithWriterArgs) error {
+ return j.encodeNode(logicalName, value, j.generateAttr(logicalName,
rwUintKey, bitLength, writerArgs...))
+}
+
+func (j *jsonWriteBuffer) WriteInt8(logicalName string, bitLength uint8, value
int8, writerArgs ...WithWriterArgs) error {
+ return j.encodeNode(logicalName, value, j.generateAttr(logicalName,
rwIntKey, bitLength, writerArgs...))
+}
+
+func (j *jsonWriteBuffer) WriteInt16(logicalName string, bitLength uint8,
value int16, writerArgs ...WithWriterArgs) error {
+ return j.encodeNode(logicalName, value, j.generateAttr(logicalName,
rwIntKey, bitLength, writerArgs...))
+}
+
+func (j *jsonWriteBuffer) WriteInt32(logicalName string, bitLength uint8,
value int32, writerArgs ...WithWriterArgs) error {
+ return j.encodeNode(logicalName, value, j.generateAttr(logicalName,
rwIntKey, bitLength, writerArgs...))
+}
+
+func (j *jsonWriteBuffer) WriteInt64(logicalName string, bitLength uint8,
value int64, writerArgs ...WithWriterArgs) error {
+ return j.encodeNode(logicalName, value, j.generateAttr(logicalName,
rwIntKey, bitLength, writerArgs...))
+}
+
+func (j *jsonWriteBuffer) WriteBigInt(logicalName string, bitLength uint8,
value *big.Int, writerArgs ...WithWriterArgs) error {
+ return j.encodeNode(logicalName, value, j.generateAttr(logicalName,
rwIntKey, bitLength, writerArgs...))
+}
+
+func (j *jsonWriteBuffer) WriteFloat32(logicalName string, bitLength uint8,
value float32, writerArgs ...WithWriterArgs) error {
+ return j.encodeNode(logicalName, value, j.generateAttr(logicalName,
rwFloatKey, bitLength, writerArgs...))
+}
+
+func (j *jsonWriteBuffer) WriteFloat64(logicalName string, bitLength uint8,
value float64, writerArgs ...WithWriterArgs) error {
+ return j.encodeNode(logicalName, value, j.generateAttr(logicalName,
rwFloatKey, bitLength, writerArgs...))
+}
+
+func (j *jsonWriteBuffer) WriteBigFloat(logicalName string, bitLength uint8,
value *big.Float, writerArgs ...WithWriterArgs) error {
+ return j.encodeNode(logicalName, value, j.generateAttr(logicalName,
rwFloatKey, bitLength, writerArgs...))
+}
+
+func (j *jsonWriteBuffer) WriteString(logicalName string, bitLength uint8,
encoding string, value string, writerArgs ...WithWriterArgs) error {
+ attr := j.generateAttr(logicalName, rwStringKey, bitLength,
writerArgs...)
+ attr[fmt.Sprintf("__plc4x_%s", rwEncodingKey)] = encoding
+ return j.encodeNode(logicalName, value, attr)
+}
+
+func (j *jsonWriteBuffer) PopContext(logicalName string, _ ...WithWriterArgs)
error {
+ pop := j.Pop()
+ var poppedName string
+ var unwrapped interface{}
+ switch pop.(type) {
+ case *elementContext:
+ context := pop.(*elementContext)
+ poppedName = context.logicalName
+ unwrapped = context.properties
+ case *listContext:
+ context := pop.(*listContext)
+ poppedName = context.logicalName
+ unwrapped = context.list
+ default:
+ panic("broken context")
+ }
+ if poppedName != logicalName {
+ return errors.Errorf("unexpected closing context %s, expected
%s", poppedName, logicalName)
+ }
+ if j.Empty() {
+ lastElement := make(map[string]interface{})
+ lastElement[logicalName] = unwrapped
+ j.rootNode = lastElement
+ return nil
+ }
+ j.rootNode = j.Peek()
+ switch j.rootNode.(type) {
+ case *elementContext:
+ context := j.rootNode.(*elementContext)
+ context.properties[logicalName] = unwrapped
+ case *listContext:
+ context := j.rootNode.(*listContext)
+ wrappedWrap := make(map[string]interface{})
+ wrappedWrap[logicalName] = unwrapped
+ context.list = append(context.list, wrappedWrap)
+ default:
+ panic("broken context")
+ }
+ return nil
+}
+
+func (j *jsonWriteBuffer) GetJsonString() (string, error) {
+ if j.rootNode == nil {
+ return "", errors.New("No content available")
+ }
+ err := j.Encode(j.rootNode)
+ if err != nil {
+ return "", err
+ }
+ return j.jsonString.String(), nil
+}
+
+func (j *jsonWriteBuffer) encodeNode(logicalName string, value interface{},
attr map[string]interface{}, _ ...WithWriterArgs) error {
+ logicalName = j.sanitizeLogicalName(logicalName)
+ peek := j.Peek()
+ switch peek.(type) {
+ case *elementContext:
+ context := peek.(*elementContext)
+ context.properties[logicalName] = value
+ for key, attrValue := range attr {
+ context.properties[key] = attrValue
+ }
+ return nil
+ case *listContext:
+ context := peek.(*listContext)
+ m := make(map[string]interface{})
+ m[logicalName] = value
+ context.list = append(context.list, m)
+ return nil
+ default:
+ panic("broken context")
+ }
+}
+
+func (j *jsonWriteBuffer) generateAttr(logicalName string, dataType string,
bitLength uint8, writerArgs ...WithWriterArgs) map[string]interface{} {
+ logicalName = j.sanitizeLogicalName(logicalName)
+ attr := make(map[string]interface{})
+ attr[fmt.Sprintf("%s__plc4x_%s", logicalName, rwDataTypeKey)] = dataType
+ attr[fmt.Sprintf("%s__plc4x_%s", logicalName, rwBitLengthKey)] =
bitLength
+ for _, arg := range writerArgs {
+ if !arg.isWriterArgs() {
+ panic("not a writer arg")
+ }
+ switch arg.(type) {
+ case withAdditionalStringRepresentation:
+ attr[fmt.Sprintf("%s__plc4x_%s", logicalName,
rwStringRepresentationKey)] =
arg.(withAdditionalStringRepresentation).stringRepresentation
+ }
+ }
+ return attr
+}
diff --git a/plc4go/internal/plc4go/spi/utils/WriteBufferXmlBased.go
b/plc4go/internal/plc4go/spi/utils/WriteBufferXmlBased.go
index 7193c0f..8a0bbbd 100644
--- a/plc4go/internal/plc4go/spi/utils/WriteBufferXmlBased.go
+++ b/plc4go/internal/plc4go/spi/utils/WriteBufferXmlBased.go
@@ -20,7 +20,6 @@
package utils
import (
- "bufio"
"encoding/xml"
"fmt"
"math/big"
@@ -34,7 +33,7 @@ type WriteBufferXmlBased interface {
func NewXmlWriteBuffer() WriteBufferXmlBased {
var xmlString strings.Builder
- encoder := xml.NewEncoder(bufio.NewWriterSize(&xmlString, 1024*16))
+ encoder := xml.NewEncoder(&xmlString)
encoder.Indent("", " ")
return &xmlWriteBuffer{
xmlString: &xmlString,
@@ -49,6 +48,7 @@ func NewXmlWriteBuffer() WriteBufferXmlBased {
//
type xmlWriteBuffer struct {
+ bufferCommons
xmlString *strings.Builder
*xml.Encoder
}
@@ -61,114 +61,72 @@ type xmlWriteBuffer struct {
func (x *xmlWriteBuffer) PushContext(logicalName string, _ ...WithWriterArgs)
error {
// Pre-emptive flush to avoid overflow when for a long time no context
gets popped
- if err := x.Encoder.Flush(); err != nil {
+ if err := x.Flush(); err != nil {
return err
}
- return x.Encoder.EncodeToken(xml.StartElement{Name: xml.Name{Local:
sanitizeLogicalName(logicalName)}})
+ return x.EncodeToken(xml.StartElement{Name: xml.Name{Local:
x.sanitizeLogicalName(logicalName)}})
}
func (x *xmlWriteBuffer) WriteBit(logicalName string, value bool, writerArgs
...WithWriterArgs) error {
- return x.EncodeElement(value, xml.StartElement{
- Name: xml.Name{Local: sanitizeLogicalName(logicalName)},
- Attr: generateAttr("bit", 1, writerArgs...),
- })
+ return x.encodeElement(logicalName, value, x.generateAttr(rwBitKey, 1,
writerArgs...), writerArgs...)
}
func (x *xmlWriteBuffer) WriteUint8(logicalName string, bitLength uint8, value
uint8, writerArgs ...WithWriterArgs) error {
- return x.EncodeElement(value, xml.StartElement{
- Name: xml.Name{Local: sanitizeLogicalName(logicalName)},
- Attr: generateAttr("uint", bitLength, writerArgs...),
- })
+ return x.encodeElement(logicalName, value, x.generateAttr(rwUintKey,
bitLength, writerArgs...), writerArgs...)
}
func (x *xmlWriteBuffer) WriteUint16(logicalName string, bitLength uint8,
value uint16, writerArgs ...WithWriterArgs) error {
- return x.EncodeElement(value, xml.StartElement{
- Name: xml.Name{Local: sanitizeLogicalName(logicalName)},
- Attr: generateAttr("uint", bitLength, writerArgs...),
- })
+ return x.encodeElement(logicalName, value, x.generateAttr(rwUintKey,
bitLength, writerArgs...), writerArgs...)
}
func (x *xmlWriteBuffer) WriteUint32(logicalName string, bitLength uint8,
value uint32, writerArgs ...WithWriterArgs) error {
- return x.EncodeElement(value, xml.StartElement{
- Name: xml.Name{Local: sanitizeLogicalName(logicalName)},
- Attr: generateAttr("uint", bitLength, writerArgs...),
- })
+ return x.encodeElement(logicalName, value, x.generateAttr(rwUintKey,
bitLength, writerArgs...), writerArgs...)
}
func (x *xmlWriteBuffer) WriteUint64(logicalName string, bitLength uint8,
value uint64, writerArgs ...WithWriterArgs) error {
- return x.EncodeElement(value, xml.StartElement{
- Name: xml.Name{Local: sanitizeLogicalName(logicalName)},
- Attr: generateAttr("uint", bitLength, writerArgs...),
- })
+ return x.encodeElement(logicalName, value, x.generateAttr(rwUintKey,
bitLength, writerArgs...), writerArgs...)
}
func (x *xmlWriteBuffer) WriteInt8(logicalName string, bitLength uint8, value
int8, writerArgs ...WithWriterArgs) error {
- return x.EncodeElement(value, xml.StartElement{
- Name: xml.Name{Local: sanitizeLogicalName(logicalName)},
- Attr: generateAttr("int", bitLength, writerArgs...),
- })
+ return x.encodeElement(logicalName, value, x.generateAttr(rwIntKey,
bitLength, writerArgs...), writerArgs...)
}
func (x *xmlWriteBuffer) WriteInt16(logicalName string, bitLength uint8, value
int16, writerArgs ...WithWriterArgs) error {
- return x.EncodeElement(value, xml.StartElement{
- Name: xml.Name{Local: sanitizeLogicalName(logicalName)},
- Attr: generateAttr("int", bitLength, writerArgs...),
- })
+ return x.encodeElement(logicalName, value, x.generateAttr(rwIntKey,
bitLength, writerArgs...), writerArgs...)
}
func (x *xmlWriteBuffer) WriteInt32(logicalName string, bitLength uint8, value
int32, writerArgs ...WithWriterArgs) error {
- return x.EncodeElement(value, xml.StartElement{
- Name: xml.Name{Local: sanitizeLogicalName(logicalName)},
- Attr: generateAttr("int", bitLength, writerArgs...),
- })
+ return x.encodeElement(logicalName, value, x.generateAttr(rwIntKey,
bitLength, writerArgs...), writerArgs...)
}
func (x *xmlWriteBuffer) WriteInt64(logicalName string, bitLength uint8, value
int64, writerArgs ...WithWriterArgs) error {
- return x.EncodeElement(value, xml.StartElement{
- Name: xml.Name{Local: sanitizeLogicalName(logicalName)},
- Attr: generateAttr("int", bitLength, writerArgs...),
- })
+ return x.encodeElement(logicalName, value, x.generateAttr(rwIntKey,
bitLength, writerArgs...), writerArgs...)
}
func (x *xmlWriteBuffer) WriteBigInt(logicalName string, bitLength uint8,
value *big.Int, writerArgs ...WithWriterArgs) error {
- return x.EncodeElement(value, xml.StartElement{
- Name: xml.Name{Local: sanitizeLogicalName(logicalName)},
- Attr: generateAttr("int", bitLength, writerArgs...),
- })
+ return x.encodeElement(logicalName, value, x.generateAttr(rwIntKey,
bitLength, writerArgs...), writerArgs...)
}
func (x *xmlWriteBuffer) WriteFloat32(logicalName string, bitLength uint8,
value float32, writerArgs ...WithWriterArgs) error {
- return x.EncodeElement(value, xml.StartElement{
- Name: xml.Name{Local: sanitizeLogicalName(logicalName)},
- Attr: generateAttr("float", bitLength, writerArgs...),
- })
+ return x.encodeElement(logicalName, value, x.generateAttr(rwFloatKey,
bitLength, writerArgs...), writerArgs...)
}
func (x *xmlWriteBuffer) WriteFloat64(logicalName string, bitLength uint8,
value float64, writerArgs ...WithWriterArgs) error {
- return x.EncodeElement(value, xml.StartElement{
- Name: xml.Name{Local: sanitizeLogicalName(logicalName)},
- Attr: generateAttr("float", bitLength, writerArgs...),
- })
+ return x.encodeElement(logicalName, value, x.generateAttr(rwFloatKey,
bitLength, writerArgs...), writerArgs...)
}
func (x *xmlWriteBuffer) WriteBigFloat(logicalName string, bitLength uint8,
value *big.Float, writerArgs ...WithWriterArgs) error {
- return x.EncodeElement(value, xml.StartElement{
- Name: xml.Name{Local: sanitizeLogicalName(logicalName)},
- Attr: generateAttr("float", bitLength, writerArgs...),
- })
+ return x.encodeElement(logicalName, value, x.generateAttr(rwFloatKey,
bitLength, writerArgs...), writerArgs...)
}
func (x *xmlWriteBuffer) WriteString(logicalName string, bitLength uint8,
encoding string, value string, writerArgs ...WithWriterArgs) error {
- attr := generateAttr("string", bitLength, writerArgs...)
- attr = append(attr, xml.Attr{Name: xml.Name{Local: "encoding"}, Value:
encoding})
- return x.EncodeElement(value, xml.StartElement{
- Name: xml.Name{Local: sanitizeLogicalName(logicalName)},
- Attr: attr,
- })
+ attr := x.generateAttr(rwStringKey, bitLength, writerArgs...)
+ attr = append(attr, xml.Attr{Name: xml.Name{Local: rwEncodingKey},
Value: encoding})
+ return x.encodeElement(logicalName, value, attr, writerArgs...)
}
func (x *xmlWriteBuffer) PopContext(logicalName string, _ ...WithWriterArgs)
error {
- if err := x.Encoder.EncodeToken(xml.EndElement{Name: xml.Name{Local:
sanitizeLogicalName(logicalName)}}); err != nil {
+ if err := x.Encoder.EncodeToken(xml.EndElement{Name: xml.Name{Local:
x.sanitizeLogicalName(logicalName)}}); err != nil {
return err
}
return x.Encoder.Flush()
@@ -178,14 +136,21 @@ func (x *xmlWriteBuffer) GetXmlString() string {
return x.xmlString.String()
}
-func generateAttr(dataType string, bitLength uint8, writerArgs
...WithWriterArgs) []xml.Attr {
+func (x *xmlWriteBuffer) encodeElement(logicalName string, value interface{},
attr []xml.Attr, _ ...WithWriterArgs) error {
+ return x.EncodeElement(value, xml.StartElement{
+ Name: xml.Name{Local: x.sanitizeLogicalName(logicalName)},
+ Attr: attr,
+ })
+}
+
+func (x *xmlWriteBuffer) generateAttr(dataType string, bitLength uint8,
writerArgs ...WithWriterArgs) []xml.Attr {
attrs := make([]xml.Attr, 2)
attrs[0] = xml.Attr{
- Name: xml.Name{Local: "dataType"},
+ Name: xml.Name{Local: rwDataTypeKey},
Value: dataType,
}
attrs[1] = xml.Attr{
- Name: xml.Name{Local: "bitLength"},
+ Name: xml.Name{Local: rwBitLengthKey},
Value: fmt.Sprintf("%d", bitLength),
}
for _, arg := range writerArgs {
@@ -195,17 +160,10 @@ func generateAttr(dataType string, bitLength uint8,
writerArgs ...WithWriterArgs
switch arg.(type) {
case withAdditionalStringRepresentation:
attrs = append(attrs, xml.Attr{
- Name: xml.Name{Local: "stringRepresentation"},
+ Name: xml.Name{Local:
rwStringRepresentationKey},
Value:
arg.(withAdditionalStringRepresentation).stringRepresentation,
})
}
}
return attrs
}
-
-func sanitizeLogicalName(logicalName string) string {
- if logicalName == "" {
- return "value"
- }
- return logicalName
-}
diff --git a/plc4go/internal/plc4go/spi/utils/bufferCommons.go
b/plc4go/internal/plc4go/spi/utils/bufferCommons.go
new file mode 100644
index 0000000..fcec099
--- /dev/null
+++ b/plc4go/internal/plc4go/spi/utils/bufferCommons.go
@@ -0,0 +1,103 @@
+//
+// 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 utils
+
+import "container/list"
+
+const (
+ rwDataTypeKey = "dataType"
+ rwBitLengthKey = "bitLength"
+ rwStringRepresentationKey = "stringRepresentation"
+ rwBitKey = "bit"
+ rwUintKey = "uint"
+ rwIntKey = "int"
+ rwFloatKey = "float"
+ rwStringKey = "string"
+ rwEncodingKey = "encoding"
+)
+
+type bufferCommons struct {
+}
+
+func (b bufferCommons) sanitizeLogicalName(logicalName string) string {
+ if logicalName == "" {
+ return "value"
+ }
+ return logicalName
+}
+
+func (b bufferCommons) isToBeRenderedAsList(readerWriterArgs
...WithReaderWriterArgs) bool {
+ for _, arg := range readerWriterArgs {
+ if !arg.isWriterArgs() && !arg.isReaderArgs() {
+ panic("not a reader or writer arg")
+ }
+ switch arg.(type) {
+ case withRenderAsList:
+ return arg.(withRenderAsList).renderAsList
+ }
+ }
+ return false
+}
+
+func (b bufferCommons) extractAdditionalStringRepresentation(readerWriterArgs
...WithReaderWriterArgs) string {
+ for _, arg := range readerWriterArgs {
+ if !arg.isWriterArgs() && !arg.isReaderArgs() {
+ panic("not a reader or writer arg")
+ }
+ switch arg.(type) {
+ case withAdditionalStringRepresentation:
+ return " " +
arg.(withAdditionalStringRepresentation).stringRepresentation
+ }
+ }
+ return ""
+}
+
+type stack struct {
+ list.List
+}
+
+func (s *stack) Push(value interface{}) interface{} {
+ s.PushBack(value)
+ return value
+}
+
+func (s *stack) Pop() interface{} {
+ if s.Len() <= 0 {
+ return nil
+ }
+ element := s.Back()
+ if element == nil {
+ return nil
+ }
+ s.Remove(element)
+ return element.Value
+}
+
+func (s *stack) Peek() interface{} {
+ back := s.Back()
+ if back == nil {
+ return nil
+ }
+ return back.Value
+}
+
+func (s stack) Empty() bool {
+ return s.Len() == 0
+}