Skip to content

Commit c67e20a

Browse files
committed
[Java] Generate check that encoding is complete.
Previously, we checked the order of encoding was correct but not that the encoding reached a terminal state. In this commit, I've added code to generate a new method `checkEncodingIsComplete` on Java encoders. It verifies that a terminal state has been reached; otherwise, it throws an exception with information about the current state and transitions.
1 parent c0b8cdb commit c67e20a

File tree

5 files changed

+293
-2
lines changed

5 files changed

+293
-2
lines changed

sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/java/AccessOrderModel.java

Lines changed: 10 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -48,6 +48,7 @@ final class AccessOrderModel
4848
private final Int2ObjectHashMap<State> versionWrappedStates = new Int2ObjectHashMap<>();
4949
private final State notWrappedState = allocateState("NOT_WRAPPED");
5050
private State encoderWrappedState;
51+
private Set<State> terminalEncoderStates;
5152

5253
static boolean generateAccessOrderChecks()
5354
{
@@ -86,6 +87,11 @@ void forEachDecoderWrappedState(final IntObjConsumer<State> consumer)
8687
}
8788
}
8889

90+
void forEachTerminalEncoderState(final Consumer<State> consumer)
91+
{
92+
terminalEncoderStates.forEach(consumer);
93+
}
94+
8995
void forEachStateOrderedByStateNumber(final Consumer<State> consumer)
9096
{
9197
transitionsByState.keySet().stream()
@@ -165,8 +171,6 @@ private void findTransitions(
165171

166172
versionWrappedStates.put(version, versionWrappedState);
167173

168-
encoderWrappedState = versionWrappedState;
169-
170174
final CodecInteraction wrapInteraction = interactionFactory.wrap(version);
171175

172176
allocateTransitions(
@@ -183,6 +187,10 @@ private void findTransitions(
183187
);
184188

185189
walkSchemaLevel(transitionCollector, fields, groups, varData);
190+
191+
// Last writer (highest version) wins when there are multiple versions
192+
encoderWrappedState = versionWrappedState;
193+
terminalEncoderStates = transitionCollector.exitStates();
186194
});
187195
}
188196

sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/java/JavaGenerator.java

Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -273,6 +273,7 @@ private void generateEncoder(
273273
generateEncoderVarData(sb, className, accessOrderModel, varData, BASE_INDENT);
274274

275275
generateEncoderDisplay(sb, decoderName(msgToken.name()));
276+
generateFullyEncodedCheck(sb, accessOrderModel);
276277

277278
out.append(sb);
278279
out.append("}\n");
@@ -395,6 +396,36 @@ private static CharSequence generateFieldOrderStates(final AccessOrderModel acce
395396
return sb;
396397
}
397398

399+
private static void generateFullyEncodedCheck(
400+
final StringBuilder sb,
401+
final AccessOrderModel accessOrderModel)
402+
{
403+
if (null == accessOrderModel)
404+
{
405+
return;
406+
}
407+
408+
sb.append("\n");
409+
410+
sb.append(" public void checkEncodingIsComplete()\n")
411+
.append(" {\n")
412+
.append(" switch (codecState)\n")
413+
.append(" {\n");
414+
415+
accessOrderModel.forEachTerminalEncoderState(state ->
416+
{
417+
sb.append(" case ").append(stateCaseForSwitchCase(state)).append(":\n")
418+
.append(" return;\n");
419+
});
420+
421+
sb.append(" default:\n")
422+
.append(" throw new IllegalStateException(\"Not fully encoded, current state: \" +\n")
423+
.append(" CodecStates.name(codecState) + \", allowed transitions: \" +\n")
424+
.append(" CodecStates.transitions(codecState));\n")
425+
.append(" }\n")
426+
.append(" }\n\n");
427+
}
428+
398429
private static String accessOrderListenerMethodName(final Token token)
399430
{
400431
return "on" + Generators.toUpperFirstChar(token.name()) + "Accessed";

sbe-tool/src/main/java/uk/co/real_logic/sbe/ir/generated/FrameCodecEncoder.java

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -728,4 +728,18 @@ public StringBuilder appendTo(final StringBuilder builder)
728728

729729
return decoder.appendTo(builder);
730730
}
731+
732+
public void checkEncodingIsComplete()
733+
{
734+
switch (codecState)
735+
{
736+
case CodecStates.V0_SEMANTICVERSION_DONE:
737+
return;
738+
default:
739+
throw new IllegalStateException("Not fully encoded, current state: " +
740+
CodecStates.name(codecState) + ", allowed transitions: " +
741+
CodecStates.transitions(codecState));
742+
}
743+
}
744+
731745
}

sbe-tool/src/main/java/uk/co/real_logic/sbe/ir/generated/TokenCodecEncoder.java

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2027,4 +2027,18 @@ public StringBuilder appendTo(final StringBuilder builder)
20272027

20282028
return decoder.appendTo(builder);
20292029
}
2030+
2031+
public void checkEncodingIsComplete()
2032+
{
2033+
switch (codecState)
2034+
{
2035+
case CodecStates.V0_REFERENCEDNAME_DONE:
2036+
return;
2037+
default:
2038+
throw new IllegalStateException("Not fully encoded, current state: " +
2039+
CodecStates.name(codecState) + ", allowed transitions: " +
2040+
CodecStates.transitions(codecState));
2041+
}
2042+
}
2043+
20302044
}

0 commit comments

Comments
 (0)