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 2026/08/19 18:04:22 UTC

(plc4x) 03/12: fix(codegen/go): pass the field encoding through the deprecated data-io path

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

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

commit b40e3ac731ca36a5e451d62666496b5d6306c389
Author: Sebastian Rühl <sr...@apache.org>
AuthorDate: Wed Aug 19 18:05:16 2026 +0200

    fix(codegen/go): pass the field encoding through the deprecated data-io path
    
    The migrated read and write templates forward an mspec `encoding` to the
    buffers, but the deprecated data-io path dropped it silently. Now that the Go
    buffers act on BCD that asymmetry has teeth: the S7 DATE_AND_TIME data item
    would serialize its manual `year` field as BCD, because serializeSiemensYear
    passes the option itself, while month, day, hour and the rest went out as raw
    binary - half a frame in each encoding.
    
    This only takes effect once the Go models are regenerated; the checked-in
    generated code still carries the old call shape. The read half of that
    particular data item is dead either way - it assigns every field to `_` and
    falls through to "unsupported type" - so nothing regresses in the meantime.
---
 .../language/go/GoLanguageTemplateHelper.java      | 69 +++++++++++++++-------
 1 file changed, 49 insertions(+), 20 deletions(-)

diff --git a/code-generation/language/go/src/main/java/org/apache/plc4x/language/go/GoLanguageTemplateHelper.java b/code-generation/language/go/src/main/java/org/apache/plc4x/language/go/GoLanguageTemplateHelper.java
index b4e8ad2075..b05e25e3b1 100644
--- a/code-generation/language/go/src/main/java/org/apache/plc4x/language/go/GoLanguageTemplateHelper.java
+++ b/code-generation/language/go/src/main/java/org/apache/plc4x/language/go/GoLanguageTemplateHelper.java
@@ -381,6 +381,35 @@ public class GoLanguageTemplateHelper extends BaseFreemarkerLanguageTemplateHelp
         return isNotAnComplexTypeReference && arrayTypeIsNotAnComplexTypeReference;
     }
 
+    /**
+     * Renders the trailing {@code , utils.WithEncoding("...")} argument for a numeric field that
+     * declares an {@code encoding} in the mspec, or the empty string when it declares none.
+     * <p>
+     * The migrated (non deprecated) read/write templates pass the encoding through as
+     * {@code codegen.WithEncoding(...)}, but the deprecated data-io path below used to drop it
+     * silently. That made the S7 {@code DATE_AND_TIME} data item emit a half BCD, half raw binary
+     * frame once the Go byte buffers started honouring {@code encoding='"BCD"'}: the manual
+     * {@code year} field went through {@code serializeSiemensYear} (which passes the option
+     * explicitly) while {@code month}/{@code day}/... did not.
+     *
+     * @param field the field being rendered, may be {@code null}
+     * @return the writer/reader argument to append, or {@code ""}
+     */
+    private String getEncodingOption(TypedField field) {
+        if (field == null) {
+            return "";
+        }
+        final Optional<Term> encodingTerm = field.getEncoding();
+        if (encodingTerm.isEmpty()) {
+            return "";
+        }
+        String encoding = encodingTerm.get().asLiteral()
+            .orElseThrow(() -> new FreemarkerException("Encoding must be a literal"))
+            .asStringLiteral()
+            .orElseThrow(() -> new FreemarkerException("Encoding must be a quoted string value")).getValue();
+        return ", utils.WithEncoding(\"" + encoding + "\")";
+    }
+
     @Deprecated
     public String getSpecialReadBufferReadMethodCall(String logicalName, SimpleTypeReference simpleTypeReference, TypedField field) {
         return "/*TODO: migrate me*/" + getReadBufferReadMethodCall(logicalName, simpleTypeReference, null, field);
@@ -407,33 +436,33 @@ public class GoLanguageTemplateHelper extends BaseFreemarkerLanguageTemplateHelp
             case UINT:
                 IntegerTypeReference unsignedIntegerTypeReference = (IntegerTypeReference) simpleTypeReference;
                 if (unsignedIntegerTypeReference.getSizeInBits() <= 8) {
-                    return "/*TODO: migrate me*/" + "readBuffer.ReadUint8(\"" + logicalName + "\", " + unsignedIntegerTypeReference.getSizeInBits() + ")";
+                    return "/*TODO: migrate me*/" + "readBuffer.ReadUint8(\"" + logicalName + "\", " + unsignedIntegerTypeReference.getSizeInBits() + getEncodingOption(field) + ")";
                 }
                 if (unsignedIntegerTypeReference.getSizeInBits() <= 16) {
-                    return "/*TODO: migrate me*/" + "readBuffer.ReadUint16(\"" + logicalName + "\", " + unsignedIntegerTypeReference.getSizeInBits() + ")";
+                    return "/*TODO: migrate me*/" + "readBuffer.ReadUint16(\"" + logicalName + "\", " + unsignedIntegerTypeReference.getSizeInBits() + getEncodingOption(field) + ")";
                 }
                 if (unsignedIntegerTypeReference.getSizeInBits() <= 32) {
-                    return "/*TODO: migrate me*/" + "readBuffer.ReadUint32(\"" + logicalName + "\", " + unsignedIntegerTypeReference.getSizeInBits() + ")";
+                    return "/*TODO: migrate me*/" + "readBuffer.ReadUint32(\"" + logicalName + "\", " + unsignedIntegerTypeReference.getSizeInBits() + getEncodingOption(field) + ")";
                 }
                 if (unsignedIntegerTypeReference.getSizeInBits() <= 64) {
-                    return "/*TODO: migrate me*/" + "readBuffer.ReadUint64(\"" + logicalName + "\", " + unsignedIntegerTypeReference.getSizeInBits() + ")";
+                    return "/*TODO: migrate me*/" + "readBuffer.ReadUint64(\"" + logicalName + "\", " + unsignedIntegerTypeReference.getSizeInBits() + getEncodingOption(field) + ")";
                 }
-                return "/*TODO: migrate me*/" + "readBuffer.ReadBigInt(\"" + logicalName + "\", " + unsignedIntegerTypeReference.getSizeInBits() + ")";
+                return "/*TODO: migrate me*/" + "readBuffer.ReadBigInt(\"" + logicalName + "\", " + unsignedIntegerTypeReference.getSizeInBits() + getEncodingOption(field) + ")";
             case INT:
                 IntegerTypeReference integerTypeReference = (IntegerTypeReference) simpleTypeReference;
                 if (integerTypeReference.getSizeInBits() <= 8) {
-                    return "/*TODO: migrate me*/" + "readBuffer.ReadInt8(\"" + logicalName + "\", " + integerTypeReference.getSizeInBits() + ")";
+                    return "/*TODO: migrate me*/" + "readBuffer.ReadInt8(\"" + logicalName + "\", " + integerTypeReference.getSizeInBits() + getEncodingOption(field) + ")";
                 }
                 if (integerTypeReference.getSizeInBits() <= 16) {
-                    return "/*TODO: migrate me*/" + "readBuffer.ReadInt16(\"" + logicalName + "\", " + integerTypeReference.getSizeInBits() + ")";
+                    return "/*TODO: migrate me*/" + "readBuffer.ReadInt16(\"" + logicalName + "\", " + integerTypeReference.getSizeInBits() + getEncodingOption(field) + ")";
                 }
                 if (integerTypeReference.getSizeInBits() <= 32) {
-                    return "/*TODO: migrate me*/" + "readBuffer.ReadInt32(\"" + logicalName + "\", " + integerTypeReference.getSizeInBits() + ")";
+                    return "/*TODO: migrate me*/" + "readBuffer.ReadInt32(\"" + logicalName + "\", " + integerTypeReference.getSizeInBits() + getEncodingOption(field) + ")";
                 }
                 if (integerTypeReference.getSizeInBits() <= 64) {
-                    return "/*TODO: migrate me*/" + "readBuffer.ReadInt64(\"" + logicalName + "\", " + integerTypeReference.getSizeInBits() + ")";
+                    return "/*TODO: migrate me*/" + "readBuffer.ReadInt64(\"" + logicalName + "\", " + integerTypeReference.getSizeInBits() + getEncodingOption(field) + ")";
                 }
-                return "/*TODO: migrate me*/" + "readBuffer.ReadBigInt(\"" + logicalName + "\", " + integerTypeReference.getSizeInBits() + ")";
+                return "/*TODO: migrate me*/" + "readBuffer.ReadBigInt(\"" + logicalName + "\", " + integerTypeReference.getSizeInBits() + getEncodingOption(field) + ")";
             case FLOAT:
                 FloatTypeReference floatTypeReference = (FloatTypeReference) simpleTypeReference;
                 if (floatTypeReference.getSizeInBits() <= 32) {
@@ -689,33 +718,33 @@ public class GoLanguageTemplateHelper extends BaseFreemarkerLanguageTemplateHelp
             case UINT:
                 IntegerTypeReference unsignedIntegerTypeReference = (IntegerTypeReference) simpleTypeReference;
                 if (unsignedIntegerTypeReference.getSizeInBits() <= 8) {
-                    return "/*TODO: migrate me*/" + "writeBuffer.WriteUint8(\"" + logicalName + "\", " + unsignedIntegerTypeReference.getSizeInBits() + ", uint8(" + fieldName + ")" + writerArgsString + ")";
+                    return "/*TODO: migrate me*/" + "writeBuffer.WriteUint8(\"" + logicalName + "\", " + unsignedIntegerTypeReference.getSizeInBits() + ", uint8(" + fieldName + ")" + writerArgsString + getEncodingOption(field) + ")";
                 }
                 if (unsignedIntegerTypeReference.getSizeInBits() <= 16) {
-                    return "/*TODO: migrate me*/" + "writeBuffer.WriteUint16(\"" + logicalName + "\", " + unsignedIntegerTypeReference.getSizeInBits() + ", uint16(" + fieldName + ")" + writerArgsString + ")";
+                    return "/*TODO: migrate me*/" + "writeBuffer.WriteUint16(\"" + logicalName + "\", " + unsignedIntegerTypeReference.getSizeInBits() + ", uint16(" + fieldName + ")" + writerArgsString + getEncodingOption(field) + ")";
                 }
                 if (unsignedIntegerTypeReference.getSizeInBits() <= 32) {
-                    return "/*TODO: migrate me*/" + "writeBuffer.WriteUint32(\"" + logicalName + "\", " + unsignedIntegerTypeReference.getSizeInBits() + ", uint32(" + fieldName + ")" + writerArgsString + ")";
+                    return "/*TODO: migrate me*/" + "writeBuffer.WriteUint32(\"" + logicalName + "\", " + unsignedIntegerTypeReference.getSizeInBits() + ", uint32(" + fieldName + ")" + writerArgsString + getEncodingOption(field) + ")";
                 }
                 if (unsignedIntegerTypeReference.getSizeInBits() <= 64) {
-                    return "/*TODO: migrate me*/" + "writeBuffer.WriteUint64(\"" + logicalName + "\", " + unsignedIntegerTypeReference.getSizeInBits() + ", uint64(" + fieldName + ")" + writerArgsString + ")";
+                    return "/*TODO: migrate me*/" + "writeBuffer.WriteUint64(\"" + logicalName + "\", " + unsignedIntegerTypeReference.getSizeInBits() + ", uint64(" + fieldName + ")" + writerArgsString + getEncodingOption(field) + ")";
                 }
-                return "/*TODO: migrate me*/" + "writeBuffer.WriteBigInt(\"" + logicalName + "\", " + unsignedIntegerTypeReference.getSizeInBits() + ", " + fieldName + writerArgsString + ")";
+                return "/*TODO: migrate me*/" + "writeBuffer.WriteBigInt(\"" + logicalName + "\", " + unsignedIntegerTypeReference.getSizeInBits() + ", " + fieldName + writerArgsString + getEncodingOption(field) + ")";
             case INT:
                 IntegerTypeReference integerTypeReference = (IntegerTypeReference) simpleTypeReference;
                 if (integerTypeReference.getSizeInBits() <= 8) {
-                    return "/*TODO: migrate me*/" + "writeBuffer.WriteInt8(\"" + logicalName + "\", " + integerTypeReference.getSizeInBits() + ", int8(" + fieldName + ")" + writerArgsString + ")";
+                    return "/*TODO: migrate me*/" + "writeBuffer.WriteInt8(\"" + logicalName + "\", " + integerTypeReference.getSizeInBits() + ", int8(" + fieldName + ")" + writerArgsString + getEncodingOption(field) + ")";
                 }
                 if (integerTypeReference.getSizeInBits() <= 16) {
-                    return "/*TODO: migrate me*/" + "writeBuffer.WriteInt16(\"" + logicalName + "\", " + integerTypeReference.getSizeInBits() + ", int16(" + fieldName + ")" + writerArgsString + ")";
+                    return "/*TODO: migrate me*/" + "writeBuffer.WriteInt16(\"" + logicalName + "\", " + integerTypeReference.getSizeInBits() + ", int16(" + fieldName + ")" + writerArgsString + getEncodingOption(field) + ")";
                 }
                 if (integerTypeReference.getSizeInBits() <= 32) {
-                    return "/*TODO: migrate me*/" + "writeBuffer.WriteInt32(\"" + logicalName + "\", " + integerTypeReference.getSizeInBits() + ", int32(" + fieldName + ")" + writerArgsString + ")";
+                    return "/*TODO: migrate me*/" + "writeBuffer.WriteInt32(\"" + logicalName + "\", " + integerTypeReference.getSizeInBits() + ", int32(" + fieldName + ")" + writerArgsString + getEncodingOption(field) + ")";
                 }
                 if (integerTypeReference.getSizeInBits() <= 64) {
-                    return "/*TODO: migrate me*/" + "writeBuffer.WriteInt64(\"" + logicalName + "\", " + integerTypeReference.getSizeInBits() + ", int64(" + fieldName + ")" + writerArgsString + ")";
+                    return "/*TODO: migrate me*/" + "writeBuffer.WriteInt64(\"" + logicalName + "\", " + integerTypeReference.getSizeInBits() + ", int64(" + fieldName + ")" + writerArgsString + getEncodingOption(field) + ")";
                 }
-                return "/*TODO: migrate me*/" + "writeBuffer.WriteBigInt(\"" + logicalName + "\", " + integerTypeReference.getSizeInBits() + ", " + fieldName + writerArgsString + ")";
+                return "/*TODO: migrate me*/" + "writeBuffer.WriteBigInt(\"" + logicalName + "\", " + integerTypeReference.getSizeInBits() + ", " + fieldName + writerArgsString + getEncodingOption(field) + ")";
             case FLOAT:
             case UFLOAT:
                 FloatTypeReference floatTypeReference = (FloatTypeReference) simpleTypeReference;