From 50bb679017606796f131328b4f7bd6597b2dc15e Mon Sep 17 00:00:00 2001 From: Adam Krieg Date: Sat, 17 Dec 2022 22:04:22 -0500 Subject: [PATCH 1/5] 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. --- .../sbe/generation/rust/LibRsDef.java | 2 +- .../sbe/generation/rust/RustGenerator.java | 20 ++++++++++--------- .../sbe/generation/rust/RustUtil.java | 4 ++-- .../sbe/generation/rust/RustUtilTest.java | 2 ++ 4 files changed, 16 insertions(+), 12 deletions(-) diff --git a/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/rust/LibRsDef.java b/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/rust/LibRsDef.java index 4913e30b9d..7fbecbb514 100644 --- a/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/rust/LibRsDef.java +++ b/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/rust/LibRsDef.java @@ -81,7 +81,7 @@ void generate() throws IOException // add re-export of modules for (final String module : modules) { - indent(libRs, 0, "pub use %s::*;\n", toLowerSnakeCase(module)); + indent(libRs, 0, "pub use crate::%s::*;\n", toLowerSnakeCase(module)); } indent(libRs, 0, "\n"); diff --git a/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/rust/RustGenerator.java b/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/rust/RustGenerator.java index e7e26bcc31..189473779b 100644 --- a/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/rust/RustGenerator.java +++ b/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/rust/RustGenerator.java @@ -542,7 +542,7 @@ private static void generateCompositeDecoder( decoderName, decoderTypeName); - indent(sb, level + 1, "if self.acting_version < %d {\n", fieldToken.version()); + indent(sb, level + 1, "if self.acting_version > 0 && self.acting_version < %d {\n", fieldToken.version()); indent(sb, level + 2, "return Either::Left(self);\n"); indent(sb, level + 1, "}\n\n"); @@ -576,7 +576,7 @@ private static void generateBitSetDecoder( if (bitsetToken.version() > 0) { - indent(sb, level + 1, "if self.acting_version < %d {\n", bitsetToken.version()); + indent(sb, level + 1, "if self.acting_version > 0 && self.acting_version < %d {\n", bitsetToken.version()); indent(sb, level + 2, "return %s::default();\n", structTypeName); indent(sb, level + 1, "}\n\n"); } @@ -636,8 +636,8 @@ private static void generatePrimitiveArrayDecoder( if (fieldToken.version() > 0) { - indent(sb, level + 1, "if self.acting_version < %d {\n", fieldToken.version()); - indent(sb, level + 2, "return [%s, %d];\n", encoding.applicableNullValue(), arrayLength); + indent(sb, level + 1, "if self.acting_version > 0 && self.acting_version < %d {\n", fieldToken.version()); + indent(sb, level + 2, "return [%s; %d];\n", encoding.applicableNullValue(), arrayLength); indent(sb, level + 1, "}\n\n"); } @@ -737,7 +737,7 @@ private static void generatePrimitiveOptionalDecoder( if (fieldToken.version() > 0) { - indent(sb, level + 1, "if self.acting_version < %d {\n", fieldToken.version()); + indent(sb, level + 1, "if self.acting_version > 0 && self.acting_version < %d {\n", fieldToken.version()); indent(sb, level + 2, "return None;\n"); indent(sb, level + 1, "}\n\n"); } @@ -790,7 +790,7 @@ private static void generatePrimitiveRequiredDecoder( if (fieldToken.version() > 0) { - indent(sb, level + 1, "if self.acting_version < %d {\n", fieldToken.version()); + indent(sb, level + 1, "if self.acting_version > 0 && self.acting_version < %d {\n", fieldToken.version()); indent(sb, level + 2, "return %s;\n", generateRustLiteral(encoding.primitiveType(), encoding.applicableNullValue().toString())); indent(sb, level + 1, "}\n\n"); @@ -939,7 +939,7 @@ static void generateDecoderVarData( { if (varDataToken.version() > 0) { - indent(sb, level + 1, "if self.acting_version < %d {\n", varDataToken.version()); + indent(sb, level + 1, "if self.acting_version > 0 && self.acting_version < %d {\n", varDataToken.version()); indent(sb, level + 2, "return (self.parent.as_ref().unwrap().get_limit(), 0);\n"); indent(sb, level + 1, "}\n\n"); } @@ -954,7 +954,7 @@ static void generateDecoderVarData( { if (varDataToken.version() > 0) { - indent(sb, level + 1, "if self.acting_version < %d {\n", varDataToken.version()); + indent(sb, level + 1, "if self.acting_version > 0 && self.acting_version < %d {\n", varDataToken.version()); indent(sb, level + 2, "return (self.get_limit(), 0);\n"); indent(sb, level + 1, "}\n\n"); } @@ -973,7 +973,7 @@ static void generateDecoderVarData( if (varDataToken.version() > 0) { - indent(sb, level + 1, "if self.acting_version < %d {\n", varDataToken.version()); + indent(sb, level + 1, "if self.acting_version > 0 && self.acting_version < %d {\n", varDataToken.version()); indent(sb, level + 2, "return &[] as &[u8];\n"); indent(sb, level + 1, "}\n\n"); } @@ -1354,6 +1354,7 @@ private static void generateCompositeEncoder( indent(out, 1, "pub struct %s

{\n", encoderName); indent(out, 2, "parent: Option

,\n"); indent(out, 2, "offset: usize,\n"); + indent(out, 2, "acting_version: usize,\n"); indent(out, 1, "}\n\n"); appendImplWriterForComposite(out, 1, encoderName); @@ -1413,6 +1414,7 @@ private static void generateCompositeDecoder( indent(out, 1, "pub struct %s

{\n", decoderName); indent(out, 2, "parent: Option

,\n"); indent(out, 2, "offset: usize,\n"); + indent(out, 2, "acting_version: usize,\n"); indent(out, 1, "}\n\n"); appendImplReaderForComposite(out, 1, decoderName); diff --git a/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/rust/RustUtil.java b/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/rust/RustUtil.java index 731f57199d..3cc69fda4e 100644 --- a/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/rust/RustUtil.java +++ b/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/rust/RustUtil.java @@ -260,7 +260,7 @@ private static String sanitizeMethodOrProperty(final String name) { if (shadowsKeyword(name)) { - return name + "_"; + return "r#" + name; } else { @@ -310,7 +310,7 @@ enum ReservedKeyword { for (final ReservedKeyword value : ReservedKeyword.values()) { - LOWER_CASE_NAMES.add(value.name()); + LOWER_CASE_NAMES.add(value.name().toLowerCase()); } } diff --git a/sbe-tool/src/test/java/uk/co/real_logic/sbe/generation/rust/RustUtilTest.java b/sbe-tool/src/test/java/uk/co/real_logic/sbe/generation/rust/RustUtilTest.java index cab7fc9f10..2132b75ba2 100644 --- a/sbe-tool/src/test/java/uk/co/real_logic/sbe/generation/rust/RustUtilTest.java +++ b/sbe-tool/src/test/java/uk/co/real_logic/sbe/generation/rust/RustUtilTest.java @@ -136,6 +136,8 @@ void functionNameCasing() assertEquals("pricenull_9", formatFunctionName("PRICENULL9")); assertEquals("price_9_book", formatFunctionName("PRICE9Book")); assertEquals("issue_435", formatFunctionName("issue435")); + assertEquals("r#type", formatFunctionName("type")); + assertEquals("upper_case", formatFunctionName("UPPERCase")); assertEquals("no_md_entries", formatFunctionName("NoMDEntries")); assertEquals("md_entry_type_book", formatFunctionName("MD_EntryTYPEBook")); From 6b993b8604032a01771459d922f0f9ad3fa93f5d Mon Sep 17 00:00:00 2001 From: Michael Ward Date: Thu, 13 Apr 2023 15:53:33 -0500 Subject: [PATCH 2/5] [Rust] removed 'acting_version' field from SubGroup decoder --- .../real_logic/sbe/generation/rust/RustGenerator.java | 10 +++------- .../uk/co/real_logic/sbe/generation/rust/SubGroup.java | 3 --- 2 files changed, 3 insertions(+), 10 deletions(-) diff --git a/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/rust/RustGenerator.java b/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/rust/RustGenerator.java index 25e200a268..c582f9025f 100644 --- a/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/rust/RustGenerator.java +++ b/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/rust/RustGenerator.java @@ -119,7 +119,7 @@ public void generate() throws IOException indent(writer, 0, "version = \"0.1.0\"\n"); indent(writer, 0, "authors = [\"sbetool\"]\n"); indent(writer, 0, "description = \"%s\"\n", ir.description()); - indent(writer, 0, "edition = \"2018\"\n\n"); + indent(writer, 0, "edition = \"2021\"\n\n"); indent(writer, 0, "[lib]\n"); indent(writer, 0, "name = \"%s\"\n", namespace); indent(writer, 0, "path = \"src/lib.rs\"\n"); @@ -910,18 +910,14 @@ static void generateDecoderGroups( indent(sb, level + 2, "return None;\n"); indent(sb, level + 1, "}\n\n"); - indent(sb, level + 1, "let acting_version = self.acting_version;\n"); - indent(sb, level + 1, "Some(%s::default().wrap(self, acting_version as usize))\n", - groupName); + indent(sb, level + 1, "Some(%s::default().wrap(self))\n", groupName); } else { indent(sb, level, "pub fn %s(self) -> %2$s {\n", formatFunctionName(groupName), groupName); - indent(sb, level + 1, "let acting_version = self.acting_version;\n"); - indent(sb, level + 1, "%s::default().wrap(self, acting_version as usize)\n", - groupName); + indent(sb, level + 1, "%s::default().wrap(self)\n", groupName); } indent(sb, level, "}\n\n"); diff --git a/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/rust/SubGroup.java b/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/rust/SubGroup.java index 756e019fdf..d7fd2cc55d 100644 --- a/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/rust/SubGroup.java +++ b/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/rust/SubGroup.java @@ -157,7 +157,6 @@ void generateDecoder( indent(sb, level - 1, "pub struct %s

{\n", name); indent(sb, level, "parent: Option

,\n"); indent(sb, level, "block_length: usize,\n"); - indent(sb, level, "acting_version: usize,\n"); indent(sb, level, "count: %s,\n", rustTypeName(numInGroupPrimitiveType)); indent(sb, level, "index: usize,\n"); indent(sb, level, "offset: usize,\n"); @@ -174,7 +173,6 @@ void generateDecoder( indent(sb, level, "pub fn wrap(\n"); indent(sb, level + 1, "mut self,\n"); indent(sb, level + 1, "mut parent: P,\n"); - indent(sb, level + 1, "acting_version: usize,\n"); indent(sb, level, ") -> Self {\n"); indent(sb, level + 1, "let initial_offset = parent.get_limit();\n"); indent(sb, level + 1, "let block_length = parent.get_buf().get_%s_at(initial_offset) as usize;\n", @@ -186,7 +184,6 @@ void generateDecoder( indent(sb, level + 1, "self.parent = Some(parent);\n"); indent(sb, level + 1, "self.block_length = block_length;\n"); - indent(sb, level + 1, "self.acting_version = acting_version;\n"); indent(sb, level + 1, "self.count = count;\n"); indent(sb, level + 1, "self.index = usize::MAX;\n"); indent(sb, level + 1, "self.offset = 0;\n"); From 08ce8c25606f4eca0ca4a7a2d12c1382b2563c1c Mon Sep 17 00:00:00 2001 From: Michael Ward Date: Thu, 13 Apr 2023 16:07:03 -0500 Subject: [PATCH 3/5] [Rust] updated RustGenerator::generateEnum() to support derive "Default" instead of generating impl --- .../co/real_logic/sbe/generation/rust/RustGenerator.java | 9 ++------- 1 file changed, 2 insertions(+), 7 deletions(-) diff --git a/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/rust/RustGenerator.java b/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/rust/RustGenerator.java index c582f9025f..51e38a4241 100644 --- a/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/rust/RustGenerator.java +++ b/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/rust/RustGenerator.java @@ -1195,7 +1195,7 @@ private static void generateEnum( throw new IllegalArgumentException("No valid values provided for enum " + originalEnumName); } - indent(writer, 0, "#[derive(Clone, Copy, Debug, PartialEq, Eq, PartialOrd, Ord, Hash)]\n"); + indent(writer, 0, "#[derive(Clone, Copy, Debug, Default, PartialEq, Eq, PartialOrd, Ord, Hash)]\n"); final String primitiveType = rustTypeName(messageBody.get(0).encoding().primitiveType()); indent(writer, 0, "#[repr(%s)]\n", primitiveType); indent(writer, 0, "pub enum %s {\n", enumRustName); @@ -1212,16 +1212,11 @@ private static void generateEnum( final Encoding encoding = messageBody.get(0).encoding(); final CharSequence nullVal = generateRustLiteral(encoding.primitiveType(), encoding.applicableNullValue().toString()); + indent(writer, 1, "#[default]\n"); indent(writer, 1, "NullVal = %s, \n", nullVal); } indent(writer, 0, "}\n"); - // Default implementation to support Default in other structs - indent(writer, 0, "impl Default for %s {\n", enumRustName); - indent(writer, 1, "#[inline]\n"); - indent(writer, 1, "fn default() -> Self { %s::%s }\n", enumRustName, "NullVal"); - indent(writer, 0, "}\n"); - // From impl indent(writer, 0, "impl From<%s> for %s {\n", primitiveType, enumRustName); indent(writer, 1, "#[inline]\n"); From ff78633febb58861d78886c384f8f17d27bcab14 Mon Sep 17 00:00:00 2001 From: Michael Ward Date: Fri, 4 Aug 2023 18:12:56 -0500 Subject: [PATCH 4/5] fixed formatting issue --- .../co/real_logic/sbe/generation/rust/RustGenerator.java | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/rust/RustGenerator.java b/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/rust/RustGenerator.java index 58a71aac2d..be0f94c155 100644 --- a/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/rust/RustGenerator.java +++ b/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/rust/RustGenerator.java @@ -954,7 +954,8 @@ static void generateDecoderVarData( { if (varDataToken.version() > 0) { - indent(sb, level + 1, "if self.acting_version > 0 && self.acting_version < %d {\n", varDataToken.version()); + indent(sb, level + 1, "if self.acting_version > 0 && self.acting_version < %d {\n", + varDataToken.version()); indent(sb, level + 2, "return (self.parent.as_ref().unwrap().get_limit(), 0);\n"); indent(sb, level + 1, "}\n\n"); } @@ -969,7 +970,8 @@ static void generateDecoderVarData( { if (varDataToken.version() > 0) { - indent(sb, level + 1, "if self.acting_version > 0 && self.acting_version < %d {\n", varDataToken.version()); + indent(sb, level + 1, "if self.acting_version > 0 && self.acting_version < %d {\n", + varDataToken.version()); indent(sb, level + 2, "return (self.get_limit(), 0);\n"); indent(sb, level + 1, "}\n\n"); } @@ -988,7 +990,8 @@ static void generateDecoderVarData( if (varDataToken.version() > 0) { - indent(sb, level + 1, "if self.acting_version > 0 && self.acting_version < %d {\n", varDataToken.version()); + indent(sb, level + 1, "if self.acting_version > 0 && self.acting_version < %d {\n", + varDataToken.version()); indent(sb, level + 2, "return &[] as &[u8];\n"); indent(sb, level + 1, "}\n\n"); } From 5220cc05710e93bd7f6cc59e34339b5efae36fee Mon Sep 17 00:00:00 2001 From: Michael Ward Date: Tue, 8 Aug 2023 08:08:03 -0500 Subject: [PATCH 5/5] [Rust] updated how 'use declarations' are generated to prevent "ambiguous glob re-exports" warnings from rust compiler --- rust/Cargo.toml | 2 +- rust/benches/car_benchmark.rs | 1 + rust/benches/md_benchmark.rs | 1 + rust/tests/baseline_test.rs | 1 + rust/tests/big_endian_test.rs | 1 + rust/tests/extension_test.rs | 1 + rust/tests/issue_895_test.rs | 14 ++++---- .../sbe/generation/rust/RustGenerator.java | 36 +++++++++++++++---- 8 files changed, 43 insertions(+), 14 deletions(-) diff --git a/rust/Cargo.toml b/rust/Cargo.toml index 8b7c1e774d..020747c06d 100644 --- a/rust/Cargo.toml +++ b/rust/Cargo.toml @@ -17,7 +17,7 @@ baseline_bigendian = { path = "../generated/rust/baseline-bigendian" } nested_composite_name = { path = "../generated/rust/nested-composite-name" } [dev-dependencies] -criterion = "0.3" +criterion = "0.5" [[bench]] name = "car_benchmark" diff --git a/rust/benches/car_benchmark.rs b/rust/benches/car_benchmark.rs index 7ca9c2e5c8..92b964147a 100644 --- a/rust/benches/car_benchmark.rs +++ b/rust/benches/car_benchmark.rs @@ -1,5 +1,6 @@ use criterion::{black_box, criterion_group, criterion_main, Criterion}; use examples_uk_co_real_logic_sbe_benchmarks::*; +use car_codec::encoder::*; const MANUFACTURER: &[u8] = b"MANUFACTURER"; const MODEL: &[u8] = b"MODEL"; diff --git a/rust/benches/md_benchmark.rs b/rust/benches/md_benchmark.rs index b429622f92..ab7f4bf367 100644 --- a/rust/benches/md_benchmark.rs +++ b/rust/benches/md_benchmark.rs @@ -1,5 +1,6 @@ use criterion::{black_box, criterion_group, criterion_main, Criterion}; use examples_uk_co_real_logic_sbe_benchmarks_fix::*; +use market_data_incremental_refresh_trades_codec::encoder::*; struct State { buffer: Vec, diff --git a/rust/tests/baseline_test.rs b/rust/tests/baseline_test.rs index ca45f14b43..c223c83989 100644 --- a/rust/tests/baseline_test.rs +++ b/rust/tests/baseline_test.rs @@ -2,6 +2,7 @@ use std::fs::File; use std::io::prelude::*; use examples_baseline::*; +use car_codec::encoder::*; fn read_sbe_file_generated_from_java_example() -> std::io::Result> { // Generated by the generateCarExampleDataFile gradle task. diff --git a/rust/tests/big_endian_test.rs b/rust/tests/big_endian_test.rs index d3a6952dec..a1e107bc8d 100644 --- a/rust/tests/big_endian_test.rs +++ b/rust/tests/big_endian_test.rs @@ -1,4 +1,5 @@ use baseline_bigendian::*; +use car_codec::encoder::*; #[test] fn big_endian_baseline_example() -> SbeResult<()> { diff --git a/rust/tests/extension_test.rs b/rust/tests/extension_test.rs index c189763c6f..ad813c056f 100644 --- a/rust/tests/extension_test.rs +++ b/rust/tests/extension_test.rs @@ -2,6 +2,7 @@ use std::fs::File; use std::io::prelude::*; use examples_extension::*; +use car_codec::encoder::*; fn read_sbe_file_generated_from_java_example() -> std::io::Result> { // Generated by the generateCarExampleDataFile gradle task. diff --git a/rust/tests/issue_895_test.rs b/rust/tests/issue_895_test.rs index 6c7090d2da..dd9b19fa04 100644 --- a/rust/tests/issue_895_test.rs +++ b/rust/tests/issue_895_test.rs @@ -1,10 +1,12 @@ -use ::issue_895::*; +use issue_895::{ + issue_895_codec::{decoder::Issue895Decoder, encoder::Issue895Encoder}, + MessageHeaderDecoder, ReadBuf, SbeResult, WriteBuf, ENCODED_LENGTH, SBE_BLOCK_LENGTH, + SBE_SCHEMA_ID, SBE_SCHEMA_VERSION, SBE_TEMPLATE_ID, +}; fn create_encoder(buffer: &mut Vec) -> Issue895Encoder { - let issue_895 = Issue895Encoder::default().wrap( - WriteBuf::new(buffer.as_mut_slice()), - ENCODED_LENGTH, - ); + let issue_895 = + Issue895Encoder::default().wrap(WriteBuf::new(buffer.as_mut_slice()), ENCODED_LENGTH); let mut header = issue_895.header(0); header.parent().unwrap() } @@ -72,4 +74,4 @@ fn issue_895_double_none() -> SbeResult<()> { assert_eq!(None, decoder.optional_double()); Ok(()) -} \ No newline at end of file +} diff --git a/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/rust/RustGenerator.java b/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/rust/RustGenerator.java index be0f94c155..cb06bbc96a 100644 --- a/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/rust/RustGenerator.java +++ b/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/rust/RustGenerator.java @@ -15,6 +15,7 @@ */ package uk.co.real_logic.sbe.generation.rust; +import org.agrona.Strings; import org.agrona.Verify; import org.agrona.generation.OutputManager; import uk.co.real_logic.sbe.PrimitiveType; @@ -151,8 +152,8 @@ public void generate() throws IOException try (Writer out = outputManager.createOutput(codecModName)) { indent(out, 0, "use crate::*;\n\n"); - indent(out, 0, "pub use encoder::*;\n"); - indent(out, 0, "pub use decoder::*;\n\n"); + indent(out, 0, "pub use encoder::%sEncoder;\n", formatStructName(msgToken.name())); + indent(out, 0, "pub use decoder::%sDecoder;\n\n", formatStructName(msgToken.name())); final String blockLengthType = blockLengthType(); final String templateIdType = rustTypeName(ir.headerStructure().templateIdType()); final String schemaIdType = rustTypeName(ir.headerStructure().schemaIdType()); @@ -274,7 +275,18 @@ static void generateEncoderGroups( final Token numInGroupToken = Generators.findFirst("numInGroup", tokens, index); final PrimitiveType numInGroupPrimitiveType = numInGroupToken.encoding().primitiveType(); - indent(sb, level, "/// GROUP ENCODER\n"); + final String description = groupToken.description(); + if (!Strings.isEmpty(description)) + { + indent(sb, level, "/// GROUP ENCODER (id=%s, description='%s')\n", + groupToken.id(), description); + } + else + { + indent(sb, level, "/// GROUP ENCODER (id=%s)\n", + groupToken.id()); + } + assert 4 == groupHeaderTokenCount; indent(sb, level, "#[inline]\n"); indent(sb, level, "pub fn %s(self, count: %s, %1$s: %3$s) -> %3$s {\n", @@ -897,9 +909,19 @@ static void generateDecoderGroups( i = collectVarData(tokens, i, varData); final String groupName = decoderName(formatStructName(groupToken.name())); - indent(sb, level, "/// GROUP DECODER\n"); - assert 4 == groupHeaderTokenCount; + final String description = groupToken.description(); + if (!Strings.isEmpty(description)) + { + indent(sb, level, "/// GROUP DECODER (id=%s, description='%s')\n", + groupToken.id(), description); + } + else + { + indent(sb, level, "/// GROUP DECODER (id=%s)\n", + groupToken.id()); + } + assert 4 == groupHeaderTokenCount; indent(sb, level, "#[inline]\n"); if (groupToken.version() > 0) { @@ -1265,8 +1287,8 @@ private static void generateComposite( { indent(out, 0, "use crate::*;\n\n"); - indent(out, 0, "pub use encoder::*;\n"); - indent(out, 0, "pub use decoder::*;\n\n"); + indent(out, 0, "pub use encoder::%sEncoder;\n", formatStructName(compositeName)); + indent(out, 0, "pub use decoder::%sDecoder;\n\n", formatStructName(compositeName)); final int encodedLength = tokens.get(0).encodedLength(); if (encodedLength > 0)