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 2023/02/15 15:29:57 UTC
[plc4x] branch develop updated: feat(plc4go/spi): added DiffHex and hex highlighting
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 34ac8a1342 feat(plc4go/spi): added DiffHex and hex highlighting
34ac8a1342 is described below
commit 34ac8a13420fa2147e69726e0591714b80a3feb4
Author: Sebastian Rühl <sr...@apache.org>
AuthorDate: Wed Feb 15 16:29:47 2023 +0100
feat(plc4go/spi): added DiffHex and hex highlighting
---
plc4go/spi/utils/asciiBox.go | 5 ++++-
plc4go/spi/utils/hex.go | 36 ++++++++++++++++++++++++++++++++----
plc4go/spi/utils/hex_test.go | 43 +++++++++++++++++++++++++++++++++++++++++++
3 files changed, 79 insertions(+), 5 deletions(-)
diff --git a/plc4go/spi/utils/asciiBox.go b/plc4go/spi/utils/asciiBox.go
index d0e3e9ff30..efacc15691 100644
--- a/plc4go/spi/utils/asciiBox.go
+++ b/plc4go/spi/utils/asciiBox.go
@@ -36,6 +36,9 @@ type AsciiBox struct {
// DebugAsciiBox set to true to get debug messages
var DebugAsciiBox bool
+// ANSI_PATTERN source: https://github.com/chalk/ansi-regex/blob/main/index.js#L3
+var ANSI_PATTERN = regexp.MustCompile("[\u001b\u009b][\\[()#;?]*(?:[0-9]{1,4}(?:;[0-9]{0,4})*)?[0-9A-ORZcf-nqry=><]")
+
// AsciiBoxer is used to render something in a box
type AsciiBoxer interface {
// Box where int param is the proposed width
@@ -270,7 +273,7 @@ func (a *asciiBoxWriter) hasBorders(box AsciiBox) bool {
}
func countChars(s string) int {
- return len([]rune(s))
+ return len([]rune(ANSI_PATTERN.ReplaceAllString(s, "")))
}
//
diff --git a/plc4go/spi/utils/hex.go b/plc4go/spi/utils/hex.go
index bd493a26d6..fa98f37b99 100644
--- a/plc4go/spi/utils/hex.go
+++ b/plc4go/spi/utils/hex.go
@@ -48,12 +48,12 @@ const pipeWidth = 1
var DebugHex bool
// Dump dumps a 56 char wide hex string
-func Dump(data []byte) string {
- return DumpFixedWidth(data, DefaultWidth)
+func Dump(data []byte, highlights ...int) string {
+ return DumpFixedWidth(data, DefaultWidth, highlights...)
}
// DumpFixedWidth dumps hex as hex string. Min width of string returned is 18 up to supplied charWidth
-func DumpFixedWidth(data []byte, desiredCharWidth int) string {
+func DumpFixedWidth(data []byte, desiredCharWidth int, highlights ...int) string {
if data == nil || len(data) < 1 {
return ""
}
@@ -61,14 +61,23 @@ func DumpFixedWidth(data []byte, desiredCharWidth int) string {
data = append(data[:0:0], data...)
hexString := ""
maxBytesPerRow, indexWidth := calculateBytesPerRowAndIndexWidth(len(data), desiredCharWidth)
-
+ highlightsSet := map[int]struct{}{}
+ for _, highlight := range highlights {
+ highlightsSet[highlight] = struct{}{}
+ }
for byteIndex, rowIndex := 0, 0; byteIndex < len(data); byteIndex, rowIndex = byteIndex+maxBytesPerRow, rowIndex+1 {
indexString := fmt.Sprintf("%0*d|", indexWidth, byteIndex)
hexString += indexString
for columnIndex := 0; columnIndex < maxBytesPerRow; columnIndex++ {
absoluteIndex := byteIndex + columnIndex
if absoluteIndex < len(data) {
+ if _, ok := highlightsSet[absoluteIndex]; ok {
+ hexString += "\033[0;31m"
+ }
hexString += fmt.Sprintf("%02x ", data[absoluteIndex])
+ if _, ok := highlightsSet[absoluteIndex]; ok {
+ hexString += "\033[0m"
+ }
} else {
// align with empty byte representation
hexString += strings.Repeat(" ", byteWidth)
@@ -88,6 +97,25 @@ func DumpFixedWidth(data []byte, desiredCharWidth int) string {
return hexString[:len(hexString)-1]
}
+// DiffHex produces a hex diff AsciiBox of two byte arrays
+func DiffHex(expectedBytes, actualBytes []byte) AsciiBox {
+ numBytes := int(math.Min(float64(len(expectedBytes)), float64(len(actualBytes))))
+ brokenAt := -1
+ var diffIndexes []int
+ for i := 0; i < numBytes; i++ {
+ if expectedBytes[i] != actualBytes[i] {
+ if brokenAt < 0 {
+ brokenAt = i
+ }
+ diffIndexes = append(diffIndexes, i)
+ }
+ }
+ expectedHex := DumpFixedWidth(expectedBytes, 46, diffIndexes...)
+ actialHex := DumpFixedWidth(actualBytes, 46, diffIndexes...)
+ return AsciiBoxWriterDefault.BoxSideBySide(AsciiBoxWriterDefault.BoxString("expected", expectedHex, 0), AsciiBoxWriterDefault.BoxString("actual", actialHex, 0))
+
+}
+
func calculateBytesPerRowAndIndexWidth(numberOfBytes, desiredStringWidth int) (int, int) {
if DebugHex {
log.Debug().Msgf("Calculating max row and index for %d number of bytes and a desired string width of %d", numberOfBytes, desiredStringWidth)
diff --git a/plc4go/spi/utils/hex_test.go b/plc4go/spi/utils/hex_test.go
index 01e5035f22..8bee4efeb2 100644
--- a/plc4go/spi/utils/hex_test.go
+++ b/plc4go/spi/utils/hex_test.go
@@ -256,6 +256,49 @@ func TestDumpFixedWidth(t *testing.T) {
}
}
+func TestDiffHex(t *testing.T) {
+ type args struct {
+ expectedBytes, actualBytes []byte
+ }
+ tests := []struct {
+ name string
+ args args
+ want string
+ }{
+ {
+ name: "two identical",
+ args: args{
+ expectedBytes: []byte{1, 2, 3, 4},
+ actualBytes: []byte{1, 2, 3, 4},
+ },
+ want: `
+╔═expected═══════════════════════════════════╗╔═actual═════════════════════════════════════╗
+║0|01 02 03 04 '.... '║║0|01 02 03 04 '.... '║
+╚════════════════════════════════════════════╝╚════════════════════════════════════════════╝
+`,
+ },
+ {
+ name: "two different",
+ args: args{
+ expectedBytes: []byte{1, 2, 3, 4},
+ actualBytes: []byte{1, 2, 6, 4},
+ },
+ want: `
+╔═expected═══════════════════════════════════╗╔═actual═════════════════════════════════════╗
+║0|01 02 [0;31m03 [0m04 '.... '║║0|01 02 [0;31m06 [0m04 '.... '║
+╚════════════════════════════════════════════╝╚════════════════════════════════════════════╝
+`,
+ },
+ }
+ for _, tt := range tests {
+ t.Run(tt.name, func(t *testing.T) {
+ if got := DiffHex(tt.args.expectedBytes, tt.args.actualBytes); got.String() != strings.Trim(tt.want, "\n") {
+ t.Errorf("Dump() = \n%v\n, want \n%v\n", got, tt.want)
+ }
+ })
+ }
+}
+
func Test_maskString(t *testing.T) {
type args struct {
data []byte