Skip to content

Commit a93149b

Browse files
committed
~ fix serialization of structs with optional fields
1 parent d4a3331 commit a93149b

File tree

1 file changed

+30
-19
lines changed

1 file changed

+30
-19
lines changed

opc-ua-sdk/sdk-core/src/main/java/org/eclipse/milo/opcua/sdk/core/types/DynamicStructCodec.java

Lines changed: 30 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
/*
2-
* Copyright (c) 2024 the Eclipse Milo Authors
2+
* Copyright (c) 2025 the Eclipse Milo Authors
33
*
44
* This program and the accompanying materials are made
55
* available under the terms of the Eclipse Public License 2.0
@@ -10,6 +10,7 @@
1010

1111
package org.eclipse.milo.opcua.sdk.core.types;
1212

13+
import static java.util.Objects.requireNonNull;
1314
import static java.util.Objects.requireNonNullElse;
1415

1516
import java.util.Arrays;
@@ -131,19 +132,26 @@ public void encodeType(EncodingContext context, UaEncoder encoder, DynamicStruct
131132
}
132133

133134
private @NonNull DynamicStruct decodeStruct(UaDecoder decoder) {
134-
StructureField[] fields = requireNonNullElse(definition.getFields(), new StructureField[0]);
135-
136135
LinkedHashMap<String, Object> members = new LinkedHashMap<>();
137136

138137
long switchField = 0xFFFFFFFFL;
139138
if (definition.getStructureType() == StructureType.StructureWithOptionalFields) {
140139
switchField = decoder.decodeUInt32("SwitchField").longValue();
141140
}
142141

143-
for (int i = 0; i < fields.length; i++) {
144-
StructureField field = fields[i];
142+
StructureField[] fields = requireNonNullElse(definition.getFields(), new StructureField[0]);
143+
144+
if (definition.getStructureType() == StructureType.StructureWithOptionalFields) {
145+
int optionalFieldIndex = 0;
146+
for (StructureField field : fields) {
147+
if (!field.getIsOptional() || (switchField >>> optionalFieldIndex++ & 1L) == 1L) {
148+
Object value = decodeFieldValue(decoder, field);
145149

146-
if (!field.getIsOptional() || ((switchField >>> i) & 1) == 1) {
150+
members.put(field.getName(), value);
151+
}
152+
}
153+
} else {
154+
for (StructureField field : fields) {
147155
Object value = decodeFieldValue(decoder, field);
148156

149157
members.put(field.getName(), value);
@@ -175,26 +183,29 @@ public void encodeType(EncodingContext context, UaEncoder encoder, DynamicStruct
175183
private void encodeStruct(UaEncoder encoder, DynamicStruct struct) {
176184
StructureField[] fields = requireNonNullElse(definition.getFields(), new StructureField[0]);
177185

178-
long switchField = 0xFFFFFFFFL;
186+
var switchField = 0L;
179187
if (definition.getStructureType() == StructureType.StructureWithOptionalFields) {
180-
switchField = 0L;
181-
for (int i = 0; i < fields.length; i++) {
182-
StructureField field = fields[i];
183-
if (!field.getIsOptional()
184-
|| (field.getIsOptional() && struct.getMembers().containsKey(field.getName()))) {
185-
186-
switchField |= (1L << i);
188+
int optionalFieldIndex = 0;
189+
for (StructureField field : fields) {
190+
if (field.getIsOptional()
191+
&& struct.getMembers().containsKey(requireNonNull(field.getName()))) {
192+
switchField = switchField | (1L << optionalFieldIndex++);
187193
}
188194
}
189195
encoder.encodeUInt32("SwitchField", UInteger.valueOf(switchField));
190196
}
191197

192-
for (int i = 0; i < fields.length; i++) {
193-
StructureField field = fields[i];
194-
195-
if (!field.getIsOptional() || ((switchField >>> i) & 1) == 1) {
198+
if (definition.getStructureType() == StructureType.StructureWithOptionalFields) {
199+
int optionalFieldIndex = 0;
200+
for (StructureField field : fields) {
201+
if (!field.getIsOptional() || ((switchField >>> optionalFieldIndex++) & 1L) == 1L) {
202+
Object value = struct.getMembers().get(field.getName());
203+
encodeFieldValue(encoder, field, value);
204+
}
205+
}
206+
} else {
207+
for (StructureField field : fields) {
196208
Object value = struct.getMembers().get(field.getName());
197-
198209
encodeFieldValue(encoder, field, value);
199210
}
200211
}

0 commit comments

Comments
 (0)