You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@plc4x.apache.org by cd...@apache.org on 2025/03/18 16:48:14 UTC
(plc4x) branch develop updated: feat: Add support for variable length unsigned integers in mspec.
This is an automated email from the ASF dual-hosted git repository.
cdutz 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 b3922460c1 feat: Add support for variable length unsigned integers in mspec.
b3922460c1 is described below
commit b3922460c194775501b004c65a78c799eef61f21
Author: Christofer Dutz <ch...@c-ware.de>
AuthorDate: Tue Mar 18 17:47:58 2025 +0100
feat: Add support for variable length unsigned integers in mspec.
---
.../language/java/JavaLanguageTemplateHelper.java | 9 ++++++++
.../templates/java/complex-type-template.java.ftlh | 4 ++++
.../java/spi/generation/ReadBufferByteBased.java | 19 ++++++++++++++++
.../plc4x/java/spi/generation/StaticHelper.java | 10 +++++++++
.../java/spi/generation/WriteBufferByteBased.java | 25 ++++++++++++++++++++++
5 files changed, 67 insertions(+)
diff --git a/code-generation/language-java/src/main/java/org/apache/plc4x/language/java/JavaLanguageTemplateHelper.java b/code-generation/language-java/src/main/java/org/apache/plc4x/language/java/JavaLanguageTemplateHelper.java
index 5e7fb08763..1168219fe2 100644
--- a/code-generation/language-java/src/main/java/org/apache/plc4x/language/java/JavaLanguageTemplateHelper.java
+++ b/code-generation/language-java/src/main/java/org/apache/plc4x/language/java/JavaLanguageTemplateHelper.java
@@ -1411,4 +1411,13 @@ public class JavaLanguageTemplateHelper extends BaseFreemarkerLanguageTemplateHe
return imports.toString();
}
+ public boolean isVarduintField(Field field) {
+ Optional<Term> encoding = field.getEncoding();
+ if (encoding.isPresent()) {
+ String encodingName = encoding.get().asLiteral().orElseThrow().asStringLiteral().orElseThrow().getValue();
+ return encodingName.equalsIgnoreCase("VARUDINT");
+ }
+ return false;
+ }
+
}
diff --git a/code-generation/language-java/src/main/resources/templates/java/complex-type-template.java.ftlh b/code-generation/language-java/src/main/resources/templates/java/complex-type-template.java.ftlh
index f242793551..b9a019cb50 100644
--- a/code-generation/language-java/src/main/resources/templates/java/complex-type-template.java.ftlh
+++ b/code-generation/language-java/src/main/resources/templates/java/complex-type-template.java.ftlh
@@ -548,7 +548,11 @@ public<#if type.isDiscriminatedParentTypeDefinition()> abstract</#if> class ${ty
<#assign vstringTypeReference = simpleTypeReference.asVstringTypeReference().orElseThrow()>
lengthInBits += ${helper.toSerializationExpression(simpleField, helper.intTypeReference, vstringTypeReference.getLengthExpression(), parserArguments)};
<#else>
+ <#if helper.isVarduintField(simpleField)>
+ lengthInBits += GET_VARUDINT_LENGTH_IN_BITS(get${simpleField.getName()?cap_first}());
+ <#else>
lengthInBits += ${simpleTypeReference.sizeInBits};
+ </#if>
</#if>
<#elseif helper.isEnumField(field)>
lengthInBits += ${helper.getEnumBaseTypeReference(simpleField.type).sizeInBits};
diff --git a/plc4j/spi/src/main/java/org/apache/plc4x/java/spi/generation/ReadBufferByteBased.java b/plc4j/spi/src/main/java/org/apache/plc4x/java/spi/generation/ReadBufferByteBased.java
index bafc651f65..0d498a955f 100644
--- a/plc4j/spi/src/main/java/org/apache/plc4x/java/spi/generation/ReadBufferByteBased.java
+++ b/plc4j/spi/src/main/java/org/apache/plc4x/java/spi/generation/ReadBufferByteBased.java
@@ -311,6 +311,25 @@ public class ReadBufferByteBased implements ReadBuffer, BufferCommons {
value += (long) (digit * Math.pow(10, i));
}
return value;
+ case "VARUDINT":
+ long result = 0;
+ int shift = 0;
+ for (int i = 0; i < 4; i++) {
+ short b = bi.readShort(true, 8);
+ // Add the lower 7 bits of b, shifted appropriately.
+ result = result << shift;
+ result |= ((long) b & 0x0000007F);
+ // If the most significant bit is 0, this is the last byte.
+ if ((b & 0x80) == 0) {
+ break;
+ }
+ shift = 7;
+ // Ensure we do not exceed the maximum allowed bit length.
+ if (shift >= bitLength) {
+ throw new ParseException("var-length-uint exceeds allowed bit length " + bitLength);
+ }
+ }
+ return result;
case "default":
if (byteOrder == ByteOrder.LITTLE_ENDIAN) {
final long longValue = bi.readLong(true, bitLength);
diff --git a/plc4j/spi/src/main/java/org/apache/plc4x/java/spi/generation/StaticHelper.java b/plc4j/spi/src/main/java/org/apache/plc4x/java/spi/generation/StaticHelper.java
index 93883498a9..643f165a2c 100644
--- a/plc4j/spi/src/main/java/org/apache/plc4x/java/spi/generation/StaticHelper.java
+++ b/plc4j/spi/src/main/java/org/apache/plc4x/java/spi/generation/StaticHelper.java
@@ -126,4 +126,14 @@ public class StaticHelper {
return hasNext ? COUNT(obj) : 0;
}
+ public static int GET_VARUDINT_LENGTH_IN_BITS(long value) {
+ int curFieldLengthInBits = 0;
+ long temp = value;
+ do {
+ curFieldLengthInBits += 8;
+ temp >>>= 7;
+ } while (temp != 0);
+ return curFieldLengthInBits;
+ }
+
}
diff --git a/plc4j/spi/src/main/java/org/apache/plc4x/java/spi/generation/WriteBufferByteBased.java b/plc4j/spi/src/main/java/org/apache/plc4x/java/spi/generation/WriteBufferByteBased.java
index 7b0bd65e2f..b0ce1dad87 100644
--- a/plc4j/spi/src/main/java/org/apache/plc4x/java/spi/generation/WriteBufferByteBased.java
+++ b/plc4j/spi/src/main/java/org/apache/plc4x/java/spi/generation/WriteBufferByteBased.java
@@ -284,6 +284,31 @@ public class WriteBufferByteBased implements WriteBuffer, BufferCommons {
}
break;
}
+ case "VARUDINT":
+ // Check that the provided value fits in the allowed bit length.
+ long maxValue = (1L << bitLength) - 1;
+ if (value > maxValue) {
+ throw new SerializationException("Provided value of " + value + " exceeds the max value of " + maxValue);
+ }
+ // Determine the number of 7-bit groups (bytes) required.
+ int numBytes = 0;
+ long temp = value;
+ do {
+ numBytes++;
+ temp >>>= 7;
+ } while (temp != 0);
+
+ // Write each 7-bit group starting from the most significant.
+ for (int i = numBytes - 1; i >= 0; i--) {
+ int shift = i * 7;
+ int b = (int) ((value >> shift) & 0x7F);
+ // Set the continuation bit for all but the last (least significant) group.
+ if (i > 0) {
+ b |= 0x80;
+ }
+ bo.writeByte(false, 8, (byte) b);
+ }
+ break;
case "default":
if (byteOrder == ByteOrder.LITTLE_ENDIAN) {
value = Long.reverseBytes(value) >> 32;