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 2021/12/23 15:17:11 UTC
[plc4x] 01/02: fix: Made it possible to use enum types in arrays, made at least simple fields also support encoding feature: added support for variable length uint 32 encoding (varLenUint32)
This is an automated email from the ASF dual-hosted git repository.
cdutz pushed a commit to branch feature/mqtt5_support
in repository https://gitbox.apache.org/repos/asf/plc4x.git
commit c21998dde654673aec113e6a6a002d8fbf0c5334
Author: cdutz <ch...@c-ware.de>
AuthorDate: Thu Dec 23 16:14:46 2021 +0100
fix: Made it possible to use enum types in arrays, made at least simple fields also support encoding
feature: added support for variable length uint 32 encoding (varLenUint32)
---
.../language/java/JavaLanguageTemplateHelper.java | 25 ++++++++++++++++++++++
.../templates/java/model-template.java.ftlh | 16 ++++++++++++--
.../plc4x/java/spi/codegen/FieldCommons.java | 17 +++++++++++++++
.../java/spi/codegen/fields/FieldWriterArray.java | 12 +++++++++++
.../spi/codegen/fields/FieldWriterFactory.java | 4 ++++
.../codegen/io/DataReaderSimpleUnsignedLong.java | 10 +++++++--
.../codegen/io/DataWriterSimpleUnsignedLong.java | 10 +++++++--
.../plc4x/java/spi/generation/ReadBuffer.java | 17 +++++++++++++++
.../plc4x/java/spi/generation/WriteBuffer.java | 15 +++++++++++++
9 files changed, 120 insertions(+), 6 deletions(-)
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 a0a6a72..db1a478 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
@@ -1135,6 +1135,31 @@ public class JavaLanguageTemplateHelper extends BaseFreemarkerLanguageTemplateHe
variableLiteral.getChild().map(child -> "." + toVariableExpressionRest(field, resultType, child)).orElse(""));
}
+ public String getSizeInBits(TypedField field, List<Argument> parserArguments) {
+ String encoding = null;
+ final Optional<Term> encodingOptional = field.getEncoding();
+ if (encodingOptional.isPresent()) {
+ encoding = toParseExpression(field, field.getType(), encodingOptional.get(), parserArguments);
+ }
+ if(field.getType().isSimpleTypeReference()) {
+ final SimpleTypeReference simpleTypeReference = field.getType().asSimpleTypeReference().orElseThrow();
+ if(encoding != null) {
+ if("\"varLenUint32\"".equals(encoding)) {
+ if((simpleTypeReference.getSizeInBits() != 32) && (simpleTypeReference.getBaseType() == SimpleTypeReference.SimpleBaseType.UINT)) {
+ throw new RuntimeException("varLenUint32 currently only supported for 'unit 32' typed fields");
+ }
+ String fieldName = field.asNamedField().orElseThrow().getName();
+ return "(" + fieldName + " <= 0x7F) ? 8 : (" + fieldName + " <= 0xFF7F) ? 16 : (" + fieldName + " <= 0xFFFF7F) ? 24 : (" + fieldName + " <= 0xFFFFFF7FL) ? 32 : -1";
+ } else {
+ throw new RuntimeException("Unsupported encoding '" + encoding + "'");
+ }
+ } else {
+ return "" + simpleTypeReference.getSizeInBits();
+ }
+ }
+ throw new RuntimeException("getSizeInBits only supported for simple types.");
+ }
+
public String getSizeInBits(ComplexTypeDefinition complexTypeDefinition, List<Argument> parserArguments) {
int sizeInBits = 0;
StringBuilder sb = new StringBuilder();
diff --git a/code-generation/language-java/src/main/resources/templates/java/model-template.java.ftlh b/code-generation/language-java/src/main/resources/templates/java/model-template.java.ftlh
index 07dc000..c2f3364 100644
--- a/code-generation/language-java/src/main/resources/templates/java/model-template.java.ftlh
+++ b/code-generation/language-java/src/main/resources/templates/java/model-template.java.ftlh
@@ -54,6 +54,8 @@ import static org.apache.plc4x.java.spi.codegen.fields.FieldWriterFactory.*;
import org.apache.plc4x.java.api.value.*;
import org.apache.plc4x.java.spi.codegen.io.DataWriterComplexDefault;
import org.apache.plc4x.java.spi.codegen.io.DataWriterEnumDefault;
+import org.apache.plc4x.java.spi.codegen.WithOption;
+import org.apache.plc4x.java.spi.generation.ByteOrder;
import org.apache.plc4x.java.spi.generation.Message;
import org.apache.plc4x.java.spi.generation.MessageIO;
import org.apache.plc4x.java.spi.generation.SerializationException;
@@ -191,6 +193,8 @@ public<#if type.isDiscriminatedParentTypeDefinition()> abstract</#if> class ${ty
writeByteArrayField("${namedField.name}", ${namedField.name}, writeByteArray(writeBuffer, 8));
<#elseif arrayField.type.isSimpleTypeReference()>
writeSimpleTypeArrayField("${namedField.name}", ${namedField.name}, ${helper.getDataWriterCall(typedField.type, namedField.name)});
+ <#elseif helper.isEnumTypeReference(arrayField.type)>
+ writeEnumTypeArrayField("${namedField.name}", ${namedField.name}, ${helper.getEnumDataWriterCall(typedField.type, namedField.name, "value")});
<#else>
writeComplexTypeArrayField("${namedField.name}", ${namedField.name}, writeBuffer);
</#if>
@@ -281,7 +285,7 @@ public<#if type.isDiscriminatedParentTypeDefinition()> abstract</#if> class ${ty
<#assign namedField = field.asNamedField().orElseThrow()>
// Simple Field (${namedField.name})
- <#if helper.isEnumTypeReference(typedField.type)>writeSimpleEnumField("${namedField.name}", "${helper.getLanguageTypeNameForField(field)}", ${namedField.name}, ${helper.getEnumDataWriterCall(typedField.type, namedField.name, "value")});<#else>writeSimpleField("${namedField.name}", ${simpleField.name}, ${helper.getDataWriterCall(typedField.type, namedField.name)});</#if>
+ <#if helper.isEnumTypeReference(typedField.type)>writeSimpleEnumField("${namedField.name}", "${helper.getLanguageTypeNameForField(field)}", ${namedField.name}, ${helper.getEnumDataWriterCall(typedField.type, namedField.name, "value")});<#else>writeSimpleField("${namedField.name}", ${simpleField.name}, ${helper.getDataWriterCall(typedField.type, namedField.name)}${helper.getFieldOptions(typedField, parserArguments)});</#if>
<#break>
<#case "switch">
<#assign switchField = field.asSwitchField().orElseThrow()>
@@ -330,11 +334,19 @@ public<#if type.isDiscriminatedParentTypeDefinition()> abstract</#if> class ${ty
<#assign complexTypeReference = arrayField.type.asComplexTypeReference().orElseThrow()>
for(${complexTypeReference.name} element : ${arrayField.name}) {
boolean last = ++i >= ${arrayField.name}.size();
+ <#if helper.isEnumField(field)>
+ lengthInBits += ${helper.getEnumBaseTypeReference(arrayField.type).sizeInBits};
+ <#else>
lengthInBits += element.getLengthInBits();
+ </#if>
}
<#else>
for(Message element : ${arrayField.name}) {
+ <#if helper.isEnumField(field)>
+ lengthInBits += ${helper.getEnumBaseTypeReference(arrayField.type).sizeInBits};
+ <#else>
lengthInBits += element.getLengthInBits();
+ </#if>
}
</#if>
}
@@ -450,7 +462,7 @@ public<#if type.isDiscriminatedParentTypeDefinition()> abstract</#if> class ${ty
<#assign vstringTypeReference = simpleTypeReference.asVstringTypeReference().orElseThrow()>
lengthInBits += ${helper.toSerializationExpression(simpleField, helper.intTypeReference, vstringTypeReference.getLengthExpression(), parserArguments)};
<#else>
- lengthInBits += ${simpleTypeReference.sizeInBits};
+ lengthInBits += ${helper.getSizeInBits(simpleField, parserArguments)};
</#if>
<#elseif helper.isEnumField(field)>
lengthInBits += ${helper.getEnumBaseTypeReference(simpleField.type).sizeInBits};
diff --git a/plc4j/spi/src/main/java/org/apache/plc4x/java/spi/codegen/FieldCommons.java b/plc4j/spi/src/main/java/org/apache/plc4x/java/spi/codegen/FieldCommons.java
index 5225f60..66d4ab3 100644
--- a/plc4j/spi/src/main/java/org/apache/plc4x/java/spi/codegen/FieldCommons.java
+++ b/plc4j/spi/src/main/java/org/apache/plc4x/java/spi/codegen/FieldCommons.java
@@ -75,6 +75,23 @@ public interface FieldCommons {
}
}
+ default Optional<String> extractEncoding(WithReaderArgs... readerArgs) {
+ return extractEncoding(Stream.of(readerArgs).map(WithReaderWriterArgs.class::cast).toArray(WithReaderWriterArgs[]::new));
+ }
+
+ default Optional<String> extractEncoding(WithWriterArgs... writerArgs) {
+ return extractEncoding(Stream.of(writerArgs).map(WithReaderWriterArgs.class::cast).toArray(WithReaderWriterArgs[]::new));
+ }
+
+ default Optional<String> extractEncoding(WithReaderWriterArgs... readerWriterArgs) {
+ for (WithReaderWriterArgs arg : readerWriterArgs) {
+ if (arg instanceof withOptionEncoding) {
+ return Optional.of(((withOptionEncoding) arg).encoding());
+ }
+ }
+ return Optional.empty();
+ }
+
@FunctionalInterface
interface RunParseWrapped<T> {
T run() throws ParseException;
diff --git a/plc4j/spi/src/main/java/org/apache/plc4x/java/spi/codegen/fields/FieldWriterArray.java b/plc4j/spi/src/main/java/org/apache/plc4x/java/spi/codegen/fields/FieldWriterArray.java
index d1fdce0..474bcd2 100644
--- a/plc4j/spi/src/main/java/org/apache/plc4x/java/spi/codegen/fields/FieldWriterArray.java
+++ b/plc4j/spi/src/main/java/org/apache/plc4x/java/spi/codegen/fields/FieldWriterArray.java
@@ -56,4 +56,16 @@ public class FieldWriterArray<T> implements FieldCommons {
}, writeBuffer, extractByteOder(writerArgs).orElse(null));
}
+ public void writeEnumTypeArrayField(String logicalName, List<T> values, DataWriter<T> dataWriter, WithWriterArgs... writerArgs) throws SerializationException {
+ switchSerializeByteOrderIfNecessary(() -> {
+ if (values != null) {
+ dataWriter.pushContext(logicalName, WithReaderWriterArgs.WithRenderAsList(true));
+ for (T value : values) {
+ dataWriter.write("value", value, writerArgs);
+ }
+ dataWriter.popContext(logicalName, WithReaderWriterArgs.WithRenderAsList(true));
+ }
+ }, dataWriter, extractByteOder(writerArgs).orElse(null));
+ }
+
}
diff --git a/plc4j/spi/src/main/java/org/apache/plc4x/java/spi/codegen/fields/FieldWriterFactory.java b/plc4j/spi/src/main/java/org/apache/plc4x/java/spi/codegen/fields/FieldWriterFactory.java
index 2fd10c2..8ca7a67 100644
--- a/plc4j/spi/src/main/java/org/apache/plc4x/java/spi/codegen/fields/FieldWriterFactory.java
+++ b/plc4j/spi/src/main/java/org/apache/plc4x/java/spi/codegen/fields/FieldWriterFactory.java
@@ -39,6 +39,10 @@ public class FieldWriterFactory {
new FieldWriterArray<Message>().writeComplexTypeArrayField(logicalName, value, writeBuffer, writerArgs);
}
+ public static <T> void writeEnumTypeArrayField(String logicalName, List<T> value, DataWriter<T> dataWriter, WithWriterArgs... writerArgs) throws SerializationException {
+ new FieldWriterArray<T>().writeEnumTypeArrayField(logicalName, value, dataWriter, writerArgs);
+ }
+
public static <T> void writeByteArrayField(String logicalName, byte[] value, DataWriter<byte[]> dataWriter, WithWriterArgs... writerArgs) throws SerializationException {
new FieldWriterArray<T>().writeByteArrayField(logicalName, value, dataWriter, writerArgs);
}
diff --git a/plc4j/spi/src/main/java/org/apache/plc4x/java/spi/codegen/io/DataReaderSimpleUnsignedLong.java b/plc4j/spi/src/main/java/org/apache/plc4x/java/spi/codegen/io/DataReaderSimpleUnsignedLong.java
index d36ba98..5d42da7 100644
--- a/plc4j/spi/src/main/java/org/apache/plc4x/java/spi/codegen/io/DataReaderSimpleUnsignedLong.java
+++ b/plc4j/spi/src/main/java/org/apache/plc4x/java/spi/codegen/io/DataReaderSimpleUnsignedLong.java
@@ -18,11 +18,12 @@
*/
package org.apache.plc4x.java.spi.codegen.io;
+import org.apache.plc4x.java.spi.codegen.FieldCommons;
import org.apache.plc4x.java.spi.generation.ParseException;
import org.apache.plc4x.java.spi.generation.ReadBuffer;
import org.apache.plc4x.java.spi.generation.WithReaderArgs;
-public class DataReaderSimpleUnsignedLong extends DataReaderSimpleBase<Long> {
+public class DataReaderSimpleUnsignedLong extends DataReaderSimpleBase<Long> implements FieldCommons {
public DataReaderSimpleUnsignedLong(ReadBuffer readBuffer, int bitLength) {
super(readBuffer, bitLength);
@@ -30,7 +31,12 @@ public class DataReaderSimpleUnsignedLong extends DataReaderSimpleBase<Long> {
@Override
public Long read(String logicalName, WithReaderArgs... readerArgs) throws ParseException {
- return readBuffer.readUnsignedLong(logicalName, bitLength, readerArgs);
+ String encoding = extractEncoding(readerArgs).orElse(null);
+ if("varLenUint32".equals(encoding)) {
+ return readBuffer.readVariableLengthUnsignedInteger(logicalName, bitLength, readerArgs);
+ } else {
+ return readBuffer.readUnsignedLong(logicalName, bitLength, readerArgs);
+ }
}
}
diff --git a/plc4j/spi/src/main/java/org/apache/plc4x/java/spi/codegen/io/DataWriterSimpleUnsignedLong.java b/plc4j/spi/src/main/java/org/apache/plc4x/java/spi/codegen/io/DataWriterSimpleUnsignedLong.java
index 7d3e1e6..cbc917c 100644
--- a/plc4j/spi/src/main/java/org/apache/plc4x/java/spi/codegen/io/DataWriterSimpleUnsignedLong.java
+++ b/plc4j/spi/src/main/java/org/apache/plc4x/java/spi/codegen/io/DataWriterSimpleUnsignedLong.java
@@ -18,11 +18,12 @@
*/
package org.apache.plc4x.java.spi.codegen.io;
+import org.apache.plc4x.java.spi.codegen.FieldCommons;
import org.apache.plc4x.java.spi.generation.SerializationException;
import org.apache.plc4x.java.spi.generation.WithWriterArgs;
import org.apache.plc4x.java.spi.generation.WriteBuffer;
-public class DataWriterSimpleUnsignedLong extends DataWriterSimpleBase<Long> {
+public class DataWriterSimpleUnsignedLong extends DataWriterSimpleBase<Long> implements FieldCommons {
public DataWriterSimpleUnsignedLong(WriteBuffer writeBuffer, int bitLength) {
super(writeBuffer, bitLength);
@@ -30,7 +31,12 @@ public class DataWriterSimpleUnsignedLong extends DataWriterSimpleBase<Long> {
@Override
public void write(String logicalName, Long value, WithWriterArgs... writerArgs) throws SerializationException {
- writeBuffer.writeUnsignedLong(logicalName, bitLength, value, writerArgs);
+ String encoding = extractEncoding(writerArgs).orElse(null);
+ if("varLenUint32".equals(encoding)) {
+ writeBuffer.writeVariableLengthUnsignedInteger(logicalName, bitLength, value, writerArgs);
+ } else {
+ writeBuffer.writeUnsignedLong(logicalName, bitLength, value, writerArgs);
+ }
}
}
diff --git a/plc4j/spi/src/main/java/org/apache/plc4x/java/spi/generation/ReadBuffer.java b/plc4j/spi/src/main/java/org/apache/plc4x/java/spi/generation/ReadBuffer.java
index 5bc4246..2c635ff 100644
--- a/plc4j/spi/src/main/java/org/apache/plc4x/java/spi/generation/ReadBuffer.java
+++ b/plc4j/spi/src/main/java/org/apache/plc4x/java/spi/generation/ReadBuffer.java
@@ -80,6 +80,23 @@ public interface ReadBuffer extends ByteOrderAware {
return readUnsignedBigInteger("", bitLength);
}
+ default long readVariableLengthUnsignedInteger(String logicalName, int bitLength, WithReaderArgs... readerArgs) throws ParseException {
+ long value = readUnsignedShort(8);
+ if(value >= 0x7F) {
+ value = (value << 8) | (readUnsignedShort(8));
+ if(value >= 0xFF7F) {
+ value = (value << 8) | (readUnsignedShort(8));
+ if(value >= 0xFFFF7F) {
+ value = (value << 8) | (readUnsignedShort(8));
+ if(value >= 0xFFFFFF7F) {
+ throw new ParseException("Value too big for variable length 32 bit unsigned integer");
+ }
+ }
+ }
+ }
+ return value;
+ }
+
byte readSignedByte(String logicalName, int bitLength, WithReaderArgs... readerArgs) throws ParseException;
default byte readSignedByte(int bitLength) throws ParseException {
diff --git a/plc4j/spi/src/main/java/org/apache/plc4x/java/spi/generation/WriteBuffer.java b/plc4j/spi/src/main/java/org/apache/plc4x/java/spi/generation/WriteBuffer.java
index 7cf9eca..e953311 100644
--- a/plc4j/spi/src/main/java/org/apache/plc4x/java/spi/generation/WriteBuffer.java
+++ b/plc4j/spi/src/main/java/org/apache/plc4x/java/spi/generation/WriteBuffer.java
@@ -78,6 +78,21 @@ public interface WriteBuffer extends ByteOrderAware {
writeUnsignedBigInteger("", bitLength, value);
}
+ default void writeVariableLengthUnsignedInteger(String logicalName, int maxBitLength, Long value, WithWriterArgs... writerArgs) throws SerializationException {
+ if((value <= 0x7F) && (maxBitLength >= 8)) {
+ writeUnsignedShort(8, value.byteValue());
+ } else if((value <= 0xFF7F) && (maxBitLength >= 16)) {
+ writeUnsignedInt(16, value.shortValue());
+ } else if((value <= 0xFFFF7F) && (maxBitLength >= 24)) {
+ writeUnsignedLong(24, value.intValue());
+ } else if((value <= 0xFFFFFF7FL) && (maxBitLength >= 32)) {
+ // TODO: This sucks, I know ...
+ writeUnsignedBigInteger(32, new BigInteger(value.toString()));
+ } else {
+ throw new SerializationException("Error serializing variable length unsigned int with value " + value);
+ }
+ }
+
void writeSignedByte(String logicalName, int bitLength, byte value, WithWriterArgs... writerArgs) throws SerializationException;
default void writeSignedByte(int bitLength, byte value) throws SerializationException {