Skip to content

Commit c0dae9e

Browse files
mwardadam-talosMichael Ward
authored
[Rust] update how "use declarations" are generated, now deriving Defaults for enums (#952)
* Fixed several issues: #1: LibRsDef explicitly us crate:: to disambiguate from built in mods like bool #2: Added acting_version field to Composite structs to fix compilation errors when using Composite structs. This is an incomplete implementation because the parent doesn't pass the acting_version to the composite because you need to change the signature of wrap(parent, offset) to include the acting_version, so this version just ensures that if the acting_version isn't set on the composite, it disregards the version check. #3: fixed primitiveArrayDecoder to return an empty array of the right size if less than version required. * [Rust] removed 'acting_version' field from SubGroup decoder * [Rust] updated RustGenerator::generateEnum() to support derive "Default" instead of generating impl * fixed formatting issue * [Rust] updated how 'use declarations' are generated to prevent "ambiguous glob re-exports" warnings from rust compiler --------- Co-authored-by: Adam Krieg <[email protected]> Co-authored-by: Michael Ward <[email protected]>
1 parent 060031c commit c0dae9e

File tree

12 files changed

+64
-42
lines changed

12 files changed

+64
-42
lines changed

rust/Cargo.toml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,7 @@ baseline_bigendian = { path = "../generated/rust/baseline-bigendian" }
1717
nested_composite_name = { path = "../generated/rust/nested-composite-name" }
1818

1919
[dev-dependencies]
20-
criterion = "0.3"
20+
criterion = "0.5"
2121

2222
[[bench]]
2323
name = "car_benchmark"

rust/benches/car_benchmark.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
use criterion::{black_box, criterion_group, criterion_main, Criterion};
22
use examples_uk_co_real_logic_sbe_benchmarks::*;
3+
use car_codec::encoder::*;
34

45
const MANUFACTURER: &[u8] = b"MANUFACTURER";
56
const MODEL: &[u8] = b"MODEL";

rust/benches/md_benchmark.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
use criterion::{black_box, criterion_group, criterion_main, Criterion};
22
use examples_uk_co_real_logic_sbe_benchmarks_fix::*;
3+
use market_data_incremental_refresh_trades_codec::encoder::*;
34

45
struct State {
56
buffer: Vec<u8>,

rust/tests/baseline_test.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@ use std::fs::File;
22
use std::io::prelude::*;
33

44
use examples_baseline::*;
5+
use car_codec::encoder::*;
56

67
fn read_sbe_file_generated_from_java_example() -> std::io::Result<Vec<u8>> {
78
// Generated by the generateCarExampleDataFile gradle task.

rust/tests/big_endian_test.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
use baseline_bigendian::*;
2+
use car_codec::encoder::*;
23

34
#[test]
45
fn big_endian_baseline_example() -> SbeResult<()> {

rust/tests/extension_test.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@ use std::fs::File;
22
use std::io::prelude::*;
33

44
use examples_extension::*;
5+
use car_codec::encoder::*;
56

67
fn read_sbe_file_generated_from_java_example() -> std::io::Result<Vec<u8>> {
78
// Generated by the generateCarExampleDataFile gradle task.

rust/tests/issue_895_test.rs

Lines changed: 8 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,12 @@
1-
use ::issue_895::*;
1+
use issue_895::{
2+
issue_895_codec::{decoder::Issue895Decoder, encoder::Issue895Encoder},
3+
MessageHeaderDecoder, ReadBuf, SbeResult, WriteBuf, ENCODED_LENGTH, SBE_BLOCK_LENGTH,
4+
SBE_SCHEMA_ID, SBE_SCHEMA_VERSION, SBE_TEMPLATE_ID,
5+
};
26

37
fn create_encoder(buffer: &mut Vec<u8>) -> Issue895Encoder {
4-
let issue_895 = Issue895Encoder::default().wrap(
5-
WriteBuf::new(buffer.as_mut_slice()),
6-
ENCODED_LENGTH,
7-
);
8+
let issue_895 =
9+
Issue895Encoder::default().wrap(WriteBuf::new(buffer.as_mut_slice()), ENCODED_LENGTH);
810
let mut header = issue_895.header(0);
911
header.parent().unwrap()
1012
}
@@ -72,4 +74,4 @@ fn issue_895_double_none() -> SbeResult<()> {
7274
assert_eq!(None, decoder.optional_double());
7375

7476
Ok(())
75-
}
77+
}

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

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -81,7 +81,7 @@ void generate() throws IOException
8181
// add re-export of modules
8282
for (final String module : modules)
8383
{
84-
indent(libRs, 0, "pub use %s::*;\n", toLowerSnakeCase(module));
84+
indent(libRs, 0, "pub use crate::%s::*;\n", toLowerSnakeCase(module));
8585
}
8686
indent(libRs, 0, "\n");
8787

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

Lines changed: 45 additions & 29 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,7 @@
1515
*/
1616
package uk.co.real_logic.sbe.generation.rust;
1717

18+
import org.agrona.Strings;
1819
import org.agrona.Verify;
1920
import org.agrona.generation.OutputManager;
2021
import uk.co.real_logic.sbe.PrimitiveType;
@@ -119,7 +120,7 @@ public void generate() throws IOException
119120
indent(writer, 0, "version = \"0.1.0\"\n");
120121
indent(writer, 0, "authors = [\"sbetool\"]\n");
121122
indent(writer, 0, "description = \"%s\"\n", ir.description());
122-
indent(writer, 0, "edition = \"2018\"\n\n");
123+
indent(writer, 0, "edition = \"2021\"\n\n");
123124
indent(writer, 0, "[lib]\n");
124125
indent(writer, 0, "name = \"%s\"\n", namespace);
125126
indent(writer, 0, "path = \"src/lib.rs\"\n");
@@ -151,8 +152,8 @@ public void generate() throws IOException
151152
try (Writer out = outputManager.createOutput(codecModName))
152153
{
153154
indent(out, 0, "use crate::*;\n\n");
154-
indent(out, 0, "pub use encoder::*;\n");
155-
indent(out, 0, "pub use decoder::*;\n\n");
155+
indent(out, 0, "pub use encoder::%sEncoder;\n", formatStructName(msgToken.name()));
156+
indent(out, 0, "pub use decoder::%sDecoder;\n\n", formatStructName(msgToken.name()));
156157
final String blockLengthType = blockLengthType();
157158
final String templateIdType = rustTypeName(ir.headerStructure().templateIdType());
158159
final String schemaIdType = rustTypeName(ir.headerStructure().schemaIdType());
@@ -274,7 +275,18 @@ static void generateEncoderGroups(
274275
final Token numInGroupToken = Generators.findFirst("numInGroup", tokens, index);
275276
final PrimitiveType numInGroupPrimitiveType = numInGroupToken.encoding().primitiveType();
276277

277-
indent(sb, level, "/// GROUP ENCODER\n");
278+
final String description = groupToken.description();
279+
if (!Strings.isEmpty(description))
280+
{
281+
indent(sb, level, "/// GROUP ENCODER (id=%s, description='%s')\n",
282+
groupToken.id(), description);
283+
}
284+
else
285+
{
286+
indent(sb, level, "/// GROUP ENCODER (id=%s)\n",
287+
groupToken.id());
288+
}
289+
278290
assert 4 == groupHeaderTokenCount;
279291
indent(sb, level, "#[inline]\n");
280292
indent(sb, level, "pub fn %s(self, count: %s, %1$s: %3$s<Self>) -> %3$s<Self> {\n",
@@ -553,7 +565,7 @@ private static void generateCompositeDecoder(
553565
decoderName,
554566
decoderTypeName);
555567

556-
indent(sb, level + 1, "if self.acting_version < %d {\n", fieldToken.version());
568+
indent(sb, level + 1, "if self.acting_version > 0 && self.acting_version < %d {\n", fieldToken.version());
557569
indent(sb, level + 2, "return Either::Left(self);\n");
558570
indent(sb, level + 1, "}\n\n");
559571

@@ -587,7 +599,7 @@ private static void generateBitSetDecoder(
587599

588600
if (bitsetToken.version() > 0)
589601
{
590-
indent(sb, level + 1, "if self.acting_version < %d {\n", bitsetToken.version());
602+
indent(sb, level + 1, "if self.acting_version > 0 && self.acting_version < %d {\n", bitsetToken.version());
591603
indent(sb, level + 2, "return %s::default();\n", structTypeName);
592604
indent(sb, level + 1, "}\n\n");
593605
}
@@ -647,7 +659,7 @@ private static void generatePrimitiveArrayDecoder(
647659

648660
if (fieldToken.version() > 0)
649661
{
650-
indent(sb, level + 1, "if self.acting_version < %d {\n", fieldToken.version());
662+
indent(sb, level + 1, "if self.acting_version > 0 && self.acting_version < %d {\n", fieldToken.version());
651663
indent(sb, level + 2, "return [%s; %d];\n", encoding.applicableNullValue(), arrayLength);
652664
indent(sb, level + 1, "}\n\n");
653665
}
@@ -756,7 +768,7 @@ private static void generatePrimitiveOptionalDecoder(
756768

757769
if (fieldToken.version() > 0)
758770
{
759-
indent(sb, level + 1, "if self.acting_version < %d {\n", fieldToken.version());
771+
indent(sb, level + 1, "if self.acting_version > 0 && self.acting_version < %d {\n", fieldToken.version());
760772
indent(sb, level + 2, "return None;\n");
761773
indent(sb, level + 1, "}\n\n");
762774
}
@@ -809,7 +821,7 @@ private static void generatePrimitiveRequiredDecoder(
809821

810822
if (fieldToken.version() > 0)
811823
{
812-
indent(sb, level + 1, "if self.acting_version < %d {\n", fieldToken.version());
824+
indent(sb, level + 1, "if self.acting_version > 0 && self.acting_version < %d {\n", fieldToken.version());
813825
indent(sb, level + 2, "return %s;\n",
814826
generateRustLiteral(encoding.primitiveType(), encoding.applicableNullValue().toString()));
815827
indent(sb, level + 1, "}\n\n");
@@ -897,9 +909,19 @@ static void generateDecoderGroups(
897909
i = collectVarData(tokens, i, varData);
898910

899911
final String groupName = decoderName(formatStructName(groupToken.name()));
900-
indent(sb, level, "/// GROUP DECODER\n");
901-
assert 4 == groupHeaderTokenCount;
912+
final String description = groupToken.description();
913+
if (!Strings.isEmpty(description))
914+
{
915+
indent(sb, level, "/// GROUP DECODER (id=%s, description='%s')\n",
916+
groupToken.id(), description);
917+
}
918+
else
919+
{
920+
indent(sb, level, "/// GROUP DECODER (id=%s)\n",
921+
groupToken.id());
922+
}
902923

924+
assert 4 == groupHeaderTokenCount;
903925
indent(sb, level, "#[inline]\n");
904926
if (groupToken.version() > 0)
905927
{
@@ -910,18 +932,14 @@ static void generateDecoderGroups(
910932
indent(sb, level + 2, "return None;\n");
911933
indent(sb, level + 1, "}\n\n");
912934

913-
indent(sb, level + 1, "let acting_version = self.acting_version;\n");
914-
indent(sb, level + 1, "Some(%s::default().wrap(self, acting_version as usize))\n",
915-
groupName);
935+
indent(sb, level + 1, "Some(%s::default().wrap(self))\n", groupName);
916936
}
917937
else
918938
{
919939
indent(sb, level, "pub fn %s(self) -> %2$s<Self> {\n",
920940
formatFunctionName(groupName), groupName);
921941

922-
indent(sb, level + 1, "let acting_version = self.acting_version;\n");
923-
indent(sb, level + 1, "%s::default().wrap(self, acting_version as usize)\n",
924-
groupName);
942+
indent(sb, level + 1, "%s::default().wrap(self)\n", groupName);
925943
}
926944
indent(sb, level, "}\n\n");
927945

@@ -958,7 +976,8 @@ static void generateDecoderVarData(
958976
{
959977
if (varDataToken.version() > 0)
960978
{
961-
indent(sb, level + 1, "if self.acting_version < %d {\n", varDataToken.version());
979+
indent(sb, level + 1, "if self.acting_version > 0 && self.acting_version < %d {\n",
980+
varDataToken.version());
962981
indent(sb, level + 2, "return (self.parent.as_ref().unwrap().get_limit(), 0);\n");
963982
indent(sb, level + 1, "}\n\n");
964983
}
@@ -973,7 +992,8 @@ static void generateDecoderVarData(
973992
{
974993
if (varDataToken.version() > 0)
975994
{
976-
indent(sb, level + 1, "if self.acting_version < %d {\n", varDataToken.version());
995+
indent(sb, level + 1, "if self.acting_version > 0 && self.acting_version < %d {\n",
996+
varDataToken.version());
977997
indent(sb, level + 2, "return (self.get_limit(), 0);\n");
978998
indent(sb, level + 1, "}\n\n");
979999
}
@@ -992,7 +1012,8 @@ static void generateDecoderVarData(
9921012

9931013
if (varDataToken.version() > 0)
9941014
{
995-
indent(sb, level + 1, "if self.acting_version < %d {\n", varDataToken.version());
1015+
indent(sb, level + 1, "if self.acting_version > 0 && self.acting_version < %d {\n",
1016+
varDataToken.version());
9961017
indent(sb, level + 2, "return &[] as &[u8];\n");
9971018
indent(sb, level + 1, "}\n\n");
9981019
}
@@ -1199,7 +1220,7 @@ private static void generateEnum(
11991220
throw new IllegalArgumentException("No valid values provided for enum " + originalEnumName);
12001221
}
12011222

1202-
indent(writer, 0, "#[derive(Clone, Copy, Debug, PartialEq, Eq, PartialOrd, Ord, Hash)]\n");
1223+
indent(writer, 0, "#[derive(Clone, Copy, Debug, Default, PartialEq, Eq, PartialOrd, Ord, Hash)]\n");
12031224
final String primitiveType = rustTypeName(messageBody.get(0).encoding().primitiveType());
12041225
indent(writer, 0, "#[repr(%s)]\n", primitiveType);
12051226
indent(writer, 0, "pub enum %s {\n", enumRustName);
@@ -1216,16 +1237,11 @@ private static void generateEnum(
12161237
final Encoding encoding = messageBody.get(0).encoding();
12171238
final CharSequence nullVal = generateRustLiteral(encoding.primitiveType(),
12181239
encoding.applicableNullValue().toString());
1240+
indent(writer, 1, "#[default]\n");
12191241
indent(writer, 1, "NullVal = %s, \n", nullVal);
12201242
}
12211243
indent(writer, 0, "}\n");
12221244

1223-
// Default implementation to support Default in other structs
1224-
indent(writer, 0, "impl Default for %s {\n", enumRustName);
1225-
indent(writer, 1, "#[inline]\n");
1226-
indent(writer, 1, "fn default() -> Self { %s::%s }\n", enumRustName, "NullVal");
1227-
indent(writer, 0, "}\n");
1228-
12291245
// From impl
12301246
indent(writer, 0, "impl From<%s> for %s {\n", primitiveType, enumRustName);
12311247
indent(writer, 1, "#[inline]\n");
@@ -1271,8 +1287,8 @@ private static void generateComposite(
12711287
{
12721288
indent(out, 0, "use crate::*;\n\n");
12731289

1274-
indent(out, 0, "pub use encoder::*;\n");
1275-
indent(out, 0, "pub use decoder::*;\n\n");
1290+
indent(out, 0, "pub use encoder::%sEncoder;\n", formatStructName(compositeName));
1291+
indent(out, 0, "pub use decoder::%sDecoder;\n\n", formatStructName(compositeName));
12761292

12771293
final int encodedLength = tokens.get(0).encodedLength();
12781294
if (encodedLength > 0)

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

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -260,7 +260,7 @@ private static String sanitizeMethodOrProperty(final String name)
260260
{
261261
if (shadowsKeyword(name))
262262
{
263-
return name + "_";
263+
return "r#" + name;
264264
}
265265
else
266266
{
@@ -310,7 +310,7 @@ enum ReservedKeyword
310310
{
311311
for (final ReservedKeyword value : ReservedKeyword.values())
312312
{
313-
LOWER_CASE_NAMES.add(value.name());
313+
LOWER_CASE_NAMES.add(value.name().toLowerCase());
314314
}
315315
}
316316

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

Lines changed: 0 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -157,7 +157,6 @@ void generateDecoder(
157157
indent(sb, level - 1, "pub struct %s<P> {\n", name);
158158
indent(sb, level, "parent: Option<P>,\n");
159159
indent(sb, level, "block_length: usize,\n");
160-
indent(sb, level, "acting_version: usize,\n");
161160
indent(sb, level, "count: %s,\n", rustTypeName(numInGroupPrimitiveType));
162161
indent(sb, level, "index: usize,\n");
163162
indent(sb, level, "offset: usize,\n");
@@ -174,7 +173,6 @@ void generateDecoder(
174173
indent(sb, level, "pub fn wrap(\n");
175174
indent(sb, level + 1, "mut self,\n");
176175
indent(sb, level + 1, "mut parent: P,\n");
177-
indent(sb, level + 1, "acting_version: usize,\n");
178176
indent(sb, level, ") -> Self {\n");
179177
indent(sb, level + 1, "let initial_offset = parent.get_limit();\n");
180178
indent(sb, level + 1, "let block_length = parent.get_buf().get_%s_at(initial_offset) as usize;\n",
@@ -186,7 +184,6 @@ void generateDecoder(
186184

187185
indent(sb, level + 1, "self.parent = Some(parent);\n");
188186
indent(sb, level + 1, "self.block_length = block_length;\n");
189-
indent(sb, level + 1, "self.acting_version = acting_version;\n");
190187
indent(sb, level + 1, "self.count = count;\n");
191188
indent(sb, level + 1, "self.index = usize::MAX;\n");
192189
indent(sb, level + 1, "self.offset = 0;\n");

sbe-tool/src/test/java/uk/co/real_logic/sbe/generation/rust/RustUtilTest.java

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -136,6 +136,8 @@ void functionNameCasing()
136136
assertEquals("pricenull_9", formatFunctionName("PRICENULL9"));
137137
assertEquals("price_9_book", formatFunctionName("PRICE9Book"));
138138
assertEquals("issue_435", formatFunctionName("issue435"));
139+
assertEquals("r#type", formatFunctionName("type"));
140+
139141
assertEquals("upper_case", formatFunctionName("UPPERCase"));
140142
assertEquals("no_md_entries", formatFunctionName("NoMDEntries"));
141143
assertEquals("md_entry_type_book", formatFunctionName("MD_EntryTYPEBook"));

0 commit comments

Comments
 (0)