Skip to content
Merged
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 @@ -682,6 +682,7 @@ tasks.register('generateRustTestCodecs', JavaExec) {
'sbe-tool/src/test/resources/issue1028.xml',
'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/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 @@ -19,6 +19,7 @@ issue_987 = { path = "../generated/rust/issue987" }
issue_1028 = { path = "../generated/rust/issue1028" }
issue_1057 = { path = "../generated/rust/issue1057" }
issue_1066 = { path = "../generated/rust/issue1066" }
issue_1116 = { path = "../generated/rust/issue1116" }
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
44 changes: 44 additions & 0 deletions rust/tests/issue_1116_test.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,44 @@
use issue_1116::{
foo_bar::FooBar,
issue_1116_codec::{self, Issue1116Decoder, Issue1116Encoder},
message_header_codec, ReadBuf, WriteBuf,
};

/// The schema declares `nullValue="254"` on the type `FooBar` encodes to, so the generated null
/// value has to be 254 rather than the uint8 default of 255. The Java, C++ and Go generators all
/// emit 254 for this schema.
#[test]
fn enum_null_value_comes_from_the_schema() {
// The discriminant, which is what the encoder writes.
assert_eq!(FooBar::NullVal as u8, 254);

// The `From` conversion, which is generated separately from the discriminant.
assert_eq!(u8::from(FooBar::NullVal), 254);

assert_eq!(FooBar::from(254), FooBar::NullVal);
}

/// A peer decoding this message in another language reads the schema's null value off the wire, so
/// that is the byte the Rust encoder has to write.
#[test]
fn encodes_and_decodes_the_schema_null_value() {
let mut buffer = vec![0u8; 256];

{
let mut encoder = Issue1116Encoder::default().wrap(
WriteBuf::new(&mut buffer),
message_header_codec::ENCODED_LENGTH,
);
encoder.foo_bar(FooBar::NullVal);
}

assert_eq!(buffer[message_header_codec::ENCODED_LENGTH], 254);

let decoder = Issue1116Decoder::default().wrap(
ReadBuf::new(&buffer),
message_header_codec::ENCODED_LENGTH,
issue_1116_codec::SBE_BLOCK_LENGTH,
0,
);
assert_eq!(decoder.foo_bar(), FooBar::NullVal);
}
Original file line number Diff line number Diff line change
Expand Up @@ -1615,10 +1615,13 @@ private static void generateEnum(
indent(writer, 1, "%s = %s, \n", token.name(), literal);
}

// The null value is declared on the enum itself, or on the type it encodes to, so it
// has to be read from the enum token. A valid value token never carries one, which makes
// applicableNullValue() fall back to the primitive type default instead of the schema one.
final CharSequence nullVal = rustNullLiteral(enumTokens.get(0).encoding());

// null value
{
final Encoding encoding = messageBody.get(0).encoding();
final CharSequence nullVal = rustNullLiteral(encoding);
indent(writer, 1, "#[default]\n");
indent(writer, 1, "NullVal = %s, \n", nullVal);
}
Expand All @@ -1628,7 +1631,7 @@ private static void generateEnum(
generateFromPrimitiveForEnum(enumRustName, primitiveType, messageBody, writer);

// Into impl
generateFromEnumForPrimitive(enumRustName, primitiveType, messageBody, writer);
generateFromEnumForPrimitive(enumRustName, primitiveType, messageBody, nullVal, writer);

// FromStr impl
generateFromStrImplForEnum(enumRustName, messageBody, writer);
Expand Down Expand Up @@ -1666,6 +1669,7 @@ private static void generateFromEnumForPrimitive(
final String enumRustName,
final String primitiveType,
final List<Token> messageBody,
final CharSequence nullVal,
final Appendable writer) throws IOException
{
indent(writer, 0, "impl From<%s> for %s {\n", enumRustName, primitiveType);
Expand All @@ -1680,11 +1684,7 @@ private static void generateFromEnumForPrimitive(
indent(writer, 3, "%s::%s => %s, \n", enumRustName, token.name(), literal);
}

{
final Encoding encoding = messageBody.get(0).encoding();
final CharSequence nullVal = rustNullLiteral(encoding);
indent(writer, 3, "%s::NullVal => %s,\n", enumRustName, nullVal);
}
indent(writer, 3, "%s::NullVal => %s,\n", enumRustName, nullVal);
indent(writer, 2, "}\n");
indent(writer, 1, "}\n");
indent(writer, 0, "}\n");
Expand Down
25 changes: 25 additions & 0 deletions sbe-tool/src/test/resources/issue1116.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="issue1116"
id="1116"
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>
<type name="FooBarEncoding" primitiveType="uint8" presence="optional" nullValue="254"/>
<enum name="FooBar" encodingType="FooBarEncoding">
<validValue name="Foo">0</validValue>
<validValue name="Bar">1</validValue>
</enum>
</types>
<sbe:message name="issue1116" id="1">
<field name="fooBar" id="1" type="FooBar"/>
</sbe:message>
</sbe:messageSchema>
Loading