Skip to content

Commit

Permalink
[C++] check for not wrapped state in decodeLength() when precedence c…
Browse files Browse the repository at this point in the history
…hecks are enabled
  • Loading branch information
nbradac committed Jan 8, 2025
1 parent a209a2f commit 5151bd8
Show file tree
Hide file tree
Showing 2 changed files with 80 additions and 1 deletion.
Original file line number Diff line number Diff line change
Expand Up @@ -536,6 +536,18 @@ private static void generateAccessOrderException(
.append(fieldPrecedenceModel.generatedRepresentationClassName()).append(".\");\n");
}

private static void generateAccessOrderException(
final StringBuilder sb,
final String indent,
final String action)
{
sb.append(indent).append("throw AccessOrderError(")
.append("std::string(\"Illegal access. \") + \n")
.append(indent).append(INDENT)
.append("\"Cannot call \\\"").append(action)
.append("()\\\" in state: \" + codecStateName(codecState()));\n");
}

private static void generateAccessOrderListenerMethodForNextGroupElement(
final StringBuilder sb,
final FieldPrecedenceModel fieldPrecedenceModel,
Expand Down Expand Up @@ -3027,6 +3039,7 @@ private CharSequence generateMessageFlyweightCode(

" SBE_NODISCARD std::uint64_t decodeLength() const\n" +
" {\n" +
"%22$s" +
" %10$s skipper(m_buffer, m_offset, m_bufferLength, m_actingBlockLength, m_actingVersion);\n" +
" skipper.skip();\n" +
" return skipper.encodedLength();\n" +
Expand Down Expand Up @@ -3071,7 +3084,8 @@ private CharSequence generateMessageFlyweightCode(
generateCodecStateTransitionForWrappingLatestVersion(fieldPrecedenceModel),
generateOnWrappedListener(fieldPrecedenceModel),
generateCodecStateTransitionForWrapping(fieldPrecedenceModel),
generateHiddenCopyConstructor(" ", className));
generateHiddenCopyConstructor(" ", className),
generateCheckForNotWrappedState("decodeLength", fieldPrecedenceModel));
}

private CharSequence generateAccessOrderErrorType(final FieldPrecedenceModel fieldPrecedenceModel)
Expand Down Expand Up @@ -3311,6 +3325,31 @@ private CharSequence generateCodecStateTransitionForWrapping(final FieldPreceden
return generateAccessOrderListenerCall(fieldPrecedenceModel, TWO_INDENT, "onWrapped", "actingVersion");
}

private CharSequence generateCheckForNotWrappedState(
final String action,
final FieldPrecedenceModel fieldPrecedenceModel)
{
if (null == fieldPrecedenceModel)
{
return "";
}

final StringBuilder sb = new StringBuilder();
sb.append("#if defined(").append(precedenceChecksFlagName).append(")\n")
.append(TWO_INDENT)
.append("if (codecState() == ")
.append(qualifiedStateCase(fieldPrecedenceModel.notWrappedState()))
.append(")\n")
.append(TWO_INDENT).append("{\n");

generateAccessOrderException(sb, THREE_INDENT, action);

sb.append(TWO_INDENT).append("}\n")
.append("#endif\n");

return sb;
}

private CharSequence generateCodecStateTransitionForWrappingLatestVersion(
final FieldPrecedenceModel fieldPrecedenceModel
)
Expand Down
40 changes: 40 additions & 0 deletions sbe-tool/src/test/cpp/FieldAccessOrderCheckTest.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -5048,3 +5048,43 @@ TEST_F(FieldAccessOrderCheckTest, worksWithInsertionOperator)
EXPECT_EQ(decoder.getBAsString(), "abc");
EXPECT_EQ(decoder.getCAsString(), "def");
}

TEST_F(FieldAccessOrderCheckTest, shouldThrowExceptionWhenNotWrapped)
{
MultipleVarLength encoder;
encoder.wrapForEncode(m_buffer, OFFSET, BUFFER_LEN);
encoder.a(42);
encoder.putB("abc");
encoder.putC("def");
encoder.checkEncodingIsComplete();

MultipleVarLength decoder;

EXPECT_THROW(
{
try
{
decoder.decodeLength();
}
catch (const std::exception &e)
{
EXPECT_THAT(
e.what(),
HasSubstr("Illegal access. Cannot call \"decodeLength()\" in state: NOT_WRAPPED")
);
throw;
}
},
std::logic_error
);

decoder.wrapForDecode(
m_buffer,
OFFSET,
MultipleVarLength::sbeBlockLength(),
MultipleVarLength::sbeSchemaVersion(),
BUFFER_LEN
);

decoder.decodeLength();
}

0 comments on commit 5151bd8

Please sign in to comment.