Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions build.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -683,6 +683,7 @@ tasks.register('generateRustTestCodecs', JavaExec) {
'sbe-tool/src/test/resources/issue1057.xml',
'sbe-tool/src/test/resources/issue1066.xml',
'sbe-tool/src/test/resources/issue1116.xml',
'sbe-tool/src/test/resources/issue1118.xml',
'sbe-tool/src/test/resources/optional_enum_nullify.xml',
'sbe-tool/src/test/resources/basic-variable-length-schema.xml',
'sbe-tool/src/test/resources/example-bigendian-test-schema.xml',
Expand Down
1 change: 1 addition & 0 deletions rust/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@ issue_1028 = { path = "../generated/rust/issue1028" }
issue_1057 = { path = "../generated/rust/issue1057" }
issue_1066 = { path = "../generated/rust/issue1066" }
issue_1116 = { path = "../generated/rust/issue1116" }
issue_1118 = { path = "../generated/rust/issue1118" }
baseline_bigendian = { path = "../generated/rust/baseline_bigendian" }
nested_composite_name = { path = "../generated/rust/nested_composite_name" }
sbe_tests = { path = "../generated/rust/sbe_tests" }
Expand Down
64 changes: 64 additions & 0 deletions rust/tests/issue_1118_test.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,64 @@
use issue_1118::{
flags::Flags,
issue_1118_codec::{self, Issue1118Decoder, Issue1118Encoder},
message_header_codec, ReadBuf, WriteBuf,
};

/// Choices named after a Rust keyword are reached through `get_` and `set_` prefixed accessors,
/// so the prefixed name is a plain identifier and the choice name is not escaped. This module
/// failing to compile is itself the regression this guards, since `get_r#type` does not parse.
#[test]
fn keyword_named_choices_have_usable_accessors() {
let mut flags = Flags::new(0);

flags.set_type(true);
assert!(flags.get_type());
assert!(!flags.get_match());
assert!(!flags.get_ordinary());

flags.set_match(true);
flags.set_type(false);
assert!(!flags.get_type());
assert!(flags.get_match());

flags.clear();
assert_eq!(flags.0, 0);
}

/// The choice name is written into `Debug` as a label, so it should not carry the raw identifier
/// escaping either.
#[test]
fn debug_uses_the_unescaped_choice_names() {
let mut flags = Flags::new(0);
flags.set_type(true).set_ordinary(true);

assert_eq!(
format!("{flags:?}"),
"Flags[type(0)=true,match(1)=false,ordinary(2)=true]"
);
}

#[test]
fn round_trips_a_keyword_named_choice() {
let mut buffer = vec![0u8; 256];

{
let mut encoder = Issue1118Encoder::default().wrap(
WriteBuf::new(&mut buffer),
message_header_codec::ENCODED_LENGTH,
);
let mut flags = Flags::new(0);
flags.set_match(true);
encoder.flags(flags);
}

let decoder = Issue1118Decoder::default().wrap(
ReadBuf::new(&buffer),
message_header_codec::ENCODED_LENGTH,
issue_1118_codec::SBE_BLOCK_LENGTH,
0,
);
let flags = decoder.flags();
assert!(flags.get_match());
assert!(!flags.get_type());
}
Original file line number Diff line number Diff line change
Expand Up @@ -1441,7 +1441,7 @@ private static void generateSingleBitSet(
continue;
}

final String choiceName = formatFunctionName(token.name());
final String choiceName = bitSetChoiceName(token);
final Encoding encoding = token.encoding();
final String choiceBitIndex = encoding.constValue().toString();

Expand Down Expand Up @@ -1479,7 +1479,7 @@ private static void generateSingleBitSet(
continue;
}

final String choiceName = formatFunctionName(token.name());
final String choiceName = bitSetChoiceName(token);
final String choiceBitIndex = token.encoding().constValue().toString();

if (comma)
Expand All @@ -1498,6 +1498,14 @@ private static void generateSingleBitSet(
indent(writer, 0, "}\n");
}

// A choice is only ever reached through a get_ or set_ prefixed accessor, so its name cannot
// shadow a Rust keyword on its own and must not be escaped as a raw identifier. Escaping it
// would place the r# in the middle of the accessor name, where it does not parse.
private static String bitSetChoiceName(final Token token)
{
return toLowerSnakeCase(token.name());
}

static void appendImplEncoderTrait(
final Appendable out,
final String typeName,
Expand Down
25 changes: 25 additions & 0 deletions sbe-tool/src/test/resources/issue1118.xml
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<sbe:messageSchema
xmlns:sbe="http://fixprotocol.io/2016/sbe"
package="issue1118"
id="1118"
version="0"
semanticVersion="1.0.0"
byteOrder="littleEndian">
<types>
<composite name="messageHeader">
<type name="blockLength" primitiveType="uint16"/>
<type name="templateId" primitiveType="uint16"/>
<type name="schemaId" primitiveType="uint16"/>
<type name="version" primitiveType="uint16"/>
</composite>
<set name="Flags" encodingType="uint8">
<choice name="Type">0</choice>
<choice name="Match">1</choice>
<choice name="ordinary">2</choice>
</set>
</types>
<sbe:message name="issue1118" id="1">
<field name="flags" id="1" type="Flags"/>
</sbe:message>
</sbe:messageSchema>
Loading