Skip to content

Commit

Permalink
feat(plc4go/spi): add footers for serializable
Browse files Browse the repository at this point in the history
  • Loading branch information
sruehl committed Oct 1, 2024
1 parent 7aea3ab commit 12ecb9e
Show file tree
Hide file tree
Showing 4 changed files with 105 additions and 32 deletions.
36 changes: 20 additions & 16 deletions plc4go/internal/s7/s7Io_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@ package s7
import (
"context"
"fmt"
"github.com/stretchr/testify/require"
"strings"
"testing"

Expand Down Expand Up @@ -155,18 +156,18 @@ func TestS7MessageBytes(t *testing.T) {
║║║║╔═errorClass╗╔═errorCode╗║║╔═parameterType╗╔═S7ParameterReadVarResponse/numItems╗║ ║║║
║║║║║ 0x00 0 ║║ 0x00 0 ║║║║ 0x04 4 ║║ 0x01 1 ║║ ║║║
║║║║╚══════20/1═╝╚═════21/1═╝║║╚═════════22/1═╝╚═══════════════════════════════23/1═╝║ ║║║
║║║╚═════════════════════════╝╚══════════════════════════════════════════════════════╝ ║║║
║║║╚═════════════════════════╝╚═════════════════════════════════════════════════22/2═╝ ║║║
║║║╔═payload/S7Payload/S7PayloadReadVarResponse/items/S7VarPayloadDataItem═════════════╗ ║║║
║║║║╔═returnCode/DataTransportErrorCode╗╔═transportSize/DataTransportSize╗╔═dataLength╗║ ║║║
║║║║║ 0xff 255 OK ║║ 0x03 3 BIT ║║ 0x0001 1 ║║ ║║║
║║║║╚═════════════════════════════24/1═╝╚═══════════════════════════25/1═╝╚══════26/2═╝║ ║║║
║║║║╔═data═══════════════════════════════════════╗ ║ ║║║
║║║║║0|01 '. '║ ║ ║║║
║║║║╚═══════════════════════════════════════28/1═╝ ║ ║║║
║║║╚═══════════════════════════════════════════════════════════════════════════════════╝ ║║║
║║╚════════════════════════════════════════════════════════════════════════════════════════╝║║
║╚══════════════════════════════════════════════════════════════════════════════════════════╝║
╚════════════════════════════════════════════════════════════════════════════════════════════╝
║║║╚══════════════════════════════════════════════════════════════════════════════24/5═╝ ║║║
║║╚══════════════════════════════════════════════════════════════════════════════════10/19═╝║║
║╚═════════════════════════════════════════════════════════════════════════════════════4/25═╝║
╚═══════════════════════════════════════════════════════════════════════════════════════0/29═╝
`,
wantStringXml: `
<TPKTPacket>
Expand Down Expand Up @@ -562,11 +563,11 @@ func TestS7MessageBytes(t *testing.T) {
║║║║║║║║║║ 0x0000 0 ║║ 0x0 0 ║ ║║║║║║║║║
║║║║║║║║║╚═════31.5/2═╝╚══33.5/0.3═╝ ║║║║║║║║║
║║║║║║║║╚═════════════════════════════════════════════════════════════════════════════════════════╝║║║║║║║║
║║║║║║║╚═══════════════════════════════════════════════════════════════════════════════════════════╝║║║║║║║
║║║║║║║╚═════════════════════════════════════════════════════════════════════════════════════24/10═╝║║║║║║║
║║║║║║╚═════════════════════════════════════════════════════════════════════════════════════════════╝║║║║║║
║║║║║╚═══════════════════════════════════════════════════════════════════════════════════════════════╝║║║║║
║║║║╚═════════════════════════════════════════════════════════════════════════════════════════════════╝║║║║
║║║╚═══════════════════════════════════════════════════════════════════════════════════════════════════╝║║║
║║║╚═════════════════════════════════════════════════════════════════════════════════════════════20/14═╝║║║
║║║╔═payload/S7Payload/S7PayloadWriteVarRequest/items/S7VarPayloadDataItem═════════════╗ ║║║
║║║║╔═returnCode/DataTransportErrorCode╗╔═transportSize/DataTransportSize╗╔═dataLength╗║ ║║║
║║║║║ 0xff 255 OK ║║ 0x04 4 BYTE_WORD_DWORD ║║0x0200 512 ║║ ║║║
Expand All @@ -580,10 +581,10 @@ func TestS7MessageBytes(t *testing.T) {
║║║║║50|af fe af fe af fe af fe af fe '..........'║ ║ ║║║
║║║║║60|af fe af fe '.... '║ ║ ║║║
║║║║╚═══════════════════════════════════════38/64═╝ ║ ║║║
║║║╚═══════════════════════════════════════════════════════════════════════════════════╝ ║║║
║║╚═════════════════════════════════════════════════════════════════════════════════════════════════════╝║║
║╚═══════════════════════════════════════════════════════════════════════════════════════════════════════╝║
╚═════════════════════════════════════════════════════════════════════════════════════════════════════════╝`,
║║║╚═════════════════════════════════════════════════════════════════════════════34/68═╝ ║║║
║║╚═══════════════════════════════════════════════════════════════════════════════════════════════10/92═╝║║
║╚══════════════════════════════════════════════════════════════════════════════════════════════════4/98═╝║
╚═══════════════════════════════════════════════════════════════════════════════════════════════════0/102═╝`,
wantStringXml: `
<TPKTPacket>
<protocolId dataType="uint" bitLength="8">3</protocolId>
Expand Down Expand Up @@ -879,12 +880,15 @@ func TestS7MessageBytes(t *testing.T) {
}
})
t.Run("Simple 2 Compact Box", func(t *testing.T) {
boxWriter := utils.NewWriteBufferBoxBased(utils.WithWriteBufferBoxBasedMergeSingleBoxes(), utils.WithWriteBufferBoxBasedOmitEmptyBoxes(), utils.WithWriteBufferBoxBasedPrintPosLengthFooter())
if err := tt.args.debuggable.SerializeWithWriteBuffer(context.Background(), boxWriter); err != nil {
t.Error(err)
}
wb := utils.NewWriteBufferBoxBased(
utils.WithWriteBufferBoxBasedMergeSingleBoxes(),
utils.WithWriteBufferBoxBasedOmitEmptyBoxes(),
utils.WithWriteBufferBoxBasedPrintPosLengthFooter(),
)
err := wb.WriteSerializable(context.Background(), tt.args.debuggable)
require.NoError(t, err)
tt.wantStringSerializedCompact = strings.Trim(tt.wantStringSerializedCompact, "\n")
if got := boxWriter.GetBox().String(); got != tt.wantStringSerializedCompact {
if got := wb.GetBox().String(); got != tt.wantStringSerializedCompact {
t.Errorf("Serialize BoxedCompact() = '\n%v\n', want '\n%v\n'", got, tt.wantStringSerializedCompact)
}
})
Expand Down
24 changes: 21 additions & 3 deletions plc4go/spi/utils/WriteBufferBoxBased.go
Original file line number Diff line number Diff line change
Expand Up @@ -311,7 +311,21 @@ func (b *boxedWriteBuffer) WriteSerializable(ctx context.Context, serializable S
if serializable == nil {
return nil
}
return serializable.SerializeWithWriteBuffer(ctx, b)
currentPos := int(b.pos) // used for footer so we remember that before we advance
if err := serializable.SerializeWithWriteBuffer(ctx, b); err != nil {
return err
}
back := b.Back()
if back == nil {
return nil
}
if ab, ok := back.Value.(AsciiBox); ok {
if la, ok := serializable.(LengthAware); ok {
bitLength := int(la.GetLengthInBits(ctx))
back.Value = ab.ChangeBoxFooter(b.getPosFooterWithCurrentPost(currentPos, bitLength))
}
}
return nil
}

func (b *boxedWriteBuffer) PopContext(logicalName string, _ ...WithWriterArgs) error {
Expand Down Expand Up @@ -366,11 +380,15 @@ func (b *boxedWriteBuffer) move(bits uint) {
}

func (b *boxedWriteBuffer) getPosFooter(bitLength int) string {
return b.getPosFooterWithCurrentPost(int(b.pos), bitLength)
}

func (b *boxedWriteBuffer) getPosFooterWithCurrentPost(currentPos, bitLength int) string {
if !b.printPosLengthFooter {
return ""
}
bytePos := int(b.pos) / 8
bitRemainder := int(b.pos) % 8
bytePos := currentPos / 8
bitRemainder := currentPos % 8
pos := strconv.Itoa(bytePos)
if bitRemainder != 0 {
pos += "." + strconv.Itoa(bitRemainder)
Expand Down
61 changes: 49 additions & 12 deletions plc4go/spi/utils/asciiBox.go
Original file line number Diff line number Diff line change
Expand Up @@ -320,24 +320,53 @@ func (a *asciiBoxWriter) getBoxFooter(box AsciiBox) string {
}

func (a *asciiBoxWriter) changeBoxName(box AsciiBox, newName string) AsciiBox {
if !a.hasBorders(box) {
return a.boxString(box.String(), WithAsciiBoxName(newName))
}
return a.changeBoxAttributes(box, &newName, nil, nil)
}

func (a *asciiBoxWriter) changeBoxHeader(box AsciiBox, newHeader string) AsciiBox {
return a.changeBoxAttributes(box, nil, &newHeader, nil)

}

func (a *asciiBoxWriter) changeBoxFooter(box AsciiBox, newFooter string) AsciiBox {
return a.changeBoxAttributes(box, nil, nil, &newFooter)
}

func (a *asciiBoxWriter) changeBoxAttributes(box AsciiBox, newName, newHeader, newFooter *string) AsciiBox {
// Current data
name := box.asciiBoxWriter.getBoxName(box)
header := box.asciiBoxWriter.getBoxHeader(box)
footer := box.asciiBoxWriter.getBoxFooter(box)
minimumWidth := countChars(a.defaultBoxSet.UpperLeftCorner + a.defaultBoxSet.HorizontalLine + newName + a.defaultBoxSet.UpperRightCorner)
if header != "" {
// set new metadata
if newName != nil {
name = *newName
}
if newHeader != nil {
header = *newHeader
}
if newFooter != nil {
footer = *newFooter
}
var newOptions = []func(options *BoxOptions){
WithAsciiBoxName(name),
WithAsciiBoxHeader(header),
WithAsciiBoxFooter(footer),
}

if !a.hasBorders(box) { // this means that this is a naked box.
return a.boxString(box.String(), newOptions...)
}
minimumWidth := countChars(a.defaultBoxSet.UpperLeftCorner + a.defaultBoxSet.HorizontalLine + name + a.defaultBoxSet.UpperRightCorner)
if header != "" { // if we have a header we need to extend that minimum width to make space for the header
minimumWidth += countChars(a.defaultBoxSet.HorizontalLine + header)
}
boxContent := a.unwrap(box)
rawWidth := boxContent.Width()
minimumWidth = max(minimumWidth, rawWidth+2)
boxContent := a.unwrap(box) // get the content itself ...
rawWidth := boxContent.Width() // ... and look at the width.
minimumWidth = max(minimumWidth, rawWidth+2) // check that we have enough space for the content.
minimumWidth = max(minimumWidth, countChars(footer)+2) // check that we have enough space for the footer.
newBox := a.BoxString(
boxContent.String(),
WithAsciiBoxName(newName),
WithAsciiBoxHeader(header),
WithAsciiBoxFooter(footer),
WithAsciiBoxCharWidth(minimumWidth),
append(newOptions, WithAsciiBoxCharWidth(minimumWidth))...,
)
newBox.compressedBoxSet = a.defaultBoxSet.contributeToCompressedBoxSet(box)
return newBox
Expand Down Expand Up @@ -452,6 +481,14 @@ func (m AsciiBox) ChangeBoxName(newName string) AsciiBox {
return m.asciiBoxWriter.changeBoxName(m, newName)
}

func (m AsciiBox) ChangeBoxHeader(newHeader string) AsciiBox {
return m.asciiBoxWriter.changeBoxHeader(m, newHeader)
}

func (m AsciiBox) ChangeBoxFooter(newFooter string) AsciiBox {
return m.asciiBoxWriter.changeBoxFooter(m, newFooter)
}

func (m AsciiBox) IsEmpty() bool {
if m.asciiBoxWriter.hasBorders(m) {
return m.asciiBoxWriter.unwrap(m).String() == ""
Expand Down
16 changes: 15 additions & 1 deletion plc4go/spi/utils/asciiBox_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -1610,7 +1610,21 @@ func Test_asciiBoxWriter_changeBoxName(t *testing.T) {
}{
{
name: "change a name",
want: AsciiBox{data: "\x00\x00"},
args: args{box: AsciiBox{asciiBoxWriter: NewAsciiBoxWriter().(*asciiBoxWriter)}},
fields: fields{
newLine: '\n',
emptyPadding: " ",
extraNameCharIndent: 1,
borderWidth: 1,
newLineCharWidth: 1,
defaultBoxSet: DefaultBoxSet(),
boxHeaderRegex: regexp.MustCompile(`^` + DefaultBoxSet().UpperLeftCorner + DefaultBoxSet().HorizontalLine + `(?P<name>[\w /]+)` + DefaultBoxSet().HorizontalLine + `*` + `(?P<header>[\w /]+)?` + DefaultBoxSet().HorizontalLine + `*` + DefaultBoxSet().UpperRightCorner),
boxFooterRegex: regexp.MustCompile(`(?m)^` + DefaultBoxSet().LowerLeftCorner + DefaultBoxSet().HorizontalLine + `*` + `(?P<footer>[\w /]+)` + DefaultBoxSet().HorizontalLine + `*` + DefaultBoxSet().LowerRightCorner),
},
want: AsciiBox{
data: "╔═╗\n║ ║\n╚═╝",
compressedBoxSet: "╔╗═║╚╝",
},
},
{
name: "full box name",
Expand Down

0 comments on commit 12ecb9e

Please sign in to comment.