Skip to content

Commit ebb9ad2

Browse files
authored
Merge pull request #519 from ZackPierce/generated_rust_docs
[Rust] Improve the self-documentation of generated rust code
2 parents c856547 + 327e666 commit ebb9ad2

File tree

3 files changed

+83
-47
lines changed

3 files changed

+83
-47
lines changed

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

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -66,14 +66,18 @@ void appendDirectCodeMethods(
6666
final String nextCoderType,
6767
final int numBytes) throws IOException
6868
{
69+
indent(appendable, 1, "\n/// Create a mutable struct reference overlaid atop the data buffer\n");
70+
indent(appendable, 1, "/// such that changes to the struct directly edit the buffer. \n");
71+
indent(appendable, 1, "/// Note that the initial content of the struct's fields may be garbage.\n");
6972
indent(appendable, 1, "pub fn %s(mut self) -> CodecResult<(&%s mut %s, %s)> {\n",
7073
methodName, DATA_LIFETIME, representationType, RustGenerator.withLifetime(nextCoderType));
7174
indent(appendable, 2, "let v = self.%s.writable_overlay::<%s>(%s)?;\n",
7275
RustCodecType.Encoder.scratchProperty(), representationType, numBytes);
7376
indent(appendable, 2, "Ok((v, %s::wrap(self.%s)))\n",
7477
nextCoderType, RustCodecType.Encoder.scratchProperty());
75-
indent(appendable).append("}\n");
78+
indent(appendable).append("}\n\n");
7679

80+
indent(appendable, 1, "/// Copy the bytes of a value into the data buffer\n");
7781
indent(appendable).append(String.format("pub fn %s_copy(mut self, t: &%s) -> CodecResult<%s> {\n",
7882
methodName, representationType, RustGenerator.withLifetime(nextCoderType)));
7983
indent(appendable, 2)

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

Lines changed: 77 additions & 45 deletions
Original file line numberDiff line numberDiff line change
@@ -127,7 +127,7 @@ private static Optional<FieldsRepresentationSummary> generateFieldsRepresentatio
127127
}
128128

129129
final String representationStruct = messageTypeName + "Fields";
130-
try (Writer writer = outputManager.createOutput(messageTypeName + "Fixed Fields"))
130+
try (Writer writer = outputManager.createOutput(messageTypeName + " Fixed-size Fields"))
131131
{
132132
appendStructHeader(writer, representationStruct, true);
133133
appendStructFields(writer, namedFieldTokens);
@@ -1077,19 +1077,24 @@ private static void generateEnums(final Ir ir, final OutputManager outputManager
10771077

10781078
static void generateSharedImports(final Ir ir, final OutputManager outputManager) throws IOException
10791079
{
1080-
try (Writer writer = outputManager.createOutput("Shared Imports"))
1080+
try (Writer writer = outputManager.createOutput("Imports core rather than std to broaden usable environments."))
10811081
{
10821082
writer.append("extern crate core;\n");
10831083
}
10841084
}
10851085

10861086
static void generateResultEnums(final OutputManager outputManager) throws IOException
10871087
{
1088-
try (Writer writer = outputManager.createOutput("Result types"))
1088+
try (Writer writer = outputManager.createOutput("Result types for error handling"))
10891089
{
1090+
writer.append("\n/// Errors that may occur during the course of encoding or decoding.\n");
10901091
writer.append("#[derive(Debug)]\n");
10911092
writer.append("pub enum CodecErr {\n");
1092-
indent(writer, 1, "NotEnoughBytes,\n");
1093+
indent(writer, 1, "/// Too few bytes in the byte-slice to read or write the data structure relevant\n");
1094+
indent(writer, 1, "/// to the current state of the codec\n");
1095+
indent(writer, 1, "NotEnoughBytes,\n\n");
1096+
indent(writer, 1, "/// Groups and vardata are constrained by the numeric type chosen to represent their\n");
1097+
indent(writer, 1, "/// length as well as optional maxima imposed by the schema\n");
10931098
indent(writer, 1, "SliceIsLongerThanAllowedBySchema,\n");
10941099
writer.append("}\n\n");
10951100
writer.append("pub type CodecResult<T> = core::result::Result<T, CodecErr>;\n");
@@ -1098,7 +1103,7 @@ static void generateResultEnums(final OutputManager outputManager) throws IOExce
10981103

10991104
static void generateEncoderScratchStruct(final Ir ir, final OutputManager outputManager) throws IOException
11001105
{
1101-
try (Writer writer = outputManager.createOutput("Scratch Encoder Data Wrapper"))
1106+
try (Writer writer = outputManager.createOutput("Scratch Encoder Data Wrapper - codec internal use only"))
11021107
{
11031108
writer.append("#[derive(Debug)]\n");
11041109
writer.append(format("struct %s<%s> {\n", SCRATCH_ENCODER_TYPE, DATA_LIFETIME));
@@ -1108,6 +1113,8 @@ static void generateEncoderScratchStruct(final Ir ir, final OutputManager output
11081113

11091114
writer.append(format("%nimpl<%s> %s<%s> {\n", DATA_LIFETIME, SCRATCH_ENCODER_TYPE, DATA_LIFETIME));
11101115

1116+
indent(writer, 1, "/// Copy the bytes of a value into the data buffer\n");
1117+
indent(writer, 1, "/// Advances the `pos` index to after the newly-written bytes.\n");
11111118
indent(writer).append("#[inline]\n");
11121119
indent(writer).append("fn write_type<T>(&mut self, t: & T, num_bytes: usize) -> " +
11131120
"CodecResult<()> {\n");
@@ -1122,8 +1129,12 @@ static void generateEncoderScratchStruct(final Ir ir, final OutputManager output
11221129
indent(writer, 2).append("} else {\n");
11231130
indent(writer, 3).append("Err(CodecErr::NotEnoughBytes)\n");
11241131
indent(writer, 2).append("}\n");
1125-
indent(writer).append("}\n");
1132+
indent(writer).append("}\n\n");
11261133

1134+
indent(writer, 1, "/// Create a struct reference overlaid atop the data buffer\n");
1135+
indent(writer, 1, "/// such that changes to the struct directly edit the buffer. \n");
1136+
indent(writer, 1, "/// Note that the initial content of the struct's fields may be garbage.\n");
1137+
indent(writer, 1, "/// Advances the `pos` index to after the newly-written bytes.\n");
11271138
indent(writer).append("#[inline]\n");
11281139
indent(writer, 1, "fn writable_overlay<T>(&mut self, num_bytes: usize) " +
11291140
"-> CodecResult<&%s mut T> {\n", DATA_LIFETIME);
@@ -1138,41 +1149,10 @@ static void generateEncoderScratchStruct(final Ir ir, final OutputManager output
11381149
indent(writer, 2).append("} else {\n");
11391150
indent(writer, 3).append("Err(CodecErr::NotEnoughBytes)\n");
11401151
indent(writer, 2).append("}\n");
1141-
indent(writer).append("}\n");
1142-
1143-
indent(writer).append("#[inline]\n");
1144-
indent(writer, 1, "fn writable_slice<T>(&mut self, count: usize, bytes_per_item: usize) " +
1145-
"-> CodecResult<&%s mut [T]> {\n", DATA_LIFETIME);
1146-
indent(writer, 2).append("let end = self.pos + (count * bytes_per_item);\n");
1147-
indent(writer, 2).append("if end <= self.data.len() {\n");
1148-
indent(writer, 3, "let v: &%s mut [T] = unsafe {\n", DATA_LIFETIME);
1149-
indent(writer, 4).append("core::slice::from_raw_parts_mut(" +
1150-
"self.data[self.pos..end].as_mut_ptr() as *mut T, count)\n");
1151-
indent(writer, 3).append("};\n");
1152-
indent(writer, 3).append("self.pos = end;\n");
1153-
indent(writer, 3).append("Ok(v)\n");
1154-
indent(writer, 2).append("} else {\n");
1155-
indent(writer, 3).append("Err(CodecErr::NotEnoughBytes)\n");
1156-
indent(writer, 2).append("}\n");
1157-
indent(writer).append("}\n");
1158-
1159-
indent(writer).append("#[inline]\n");
1160-
indent(writer).append("fn write_slice_without_count<T>(&mut self, t: &[T], bytes_per_item: usize) -> " +
1161-
"CodecResult<()> {\n");
1162-
indent(writer, 2).append("let content_bytes_size = bytes_per_item * t.len();\n");
1163-
indent(writer, 2).append("let end = self.pos + content_bytes_size;\n");
1164-
indent(writer, 2).append("if end <= self.data.len() {\n");
1165-
indent(writer, 3).append("let source_bytes: &[u8] = unsafe {\n");
1166-
indent(writer, 4).append("core::slice::from_raw_parts(t.as_ptr() as *const u8, content_bytes_size)\n");
1167-
indent(writer, 3).append("};\n");
1168-
indent(writer, 3).append("(&mut self.data[self.pos..end]).copy_from_slice(source_bytes);\n");
1169-
indent(writer, 3).append("self.pos = end;\n");
1170-
indent(writer, 3).append("Ok(())\n");
1171-
indent(writer, 2).append("} else {\n");
1172-
indent(writer, 3).append("Err(CodecErr::NotEnoughBytes)\n");
1173-
indent(writer, 2).append("}\n");
1174-
indent(writer).append("}\n");
1152+
indent(writer).append("}\n\n");
11751153

1154+
indent(writer, 1, "/// Copy the bytes of a value into the data buffer at a specific position\n");
1155+
indent(writer, 1, "/// Does **not** alter the `pos` index.\n");
11761156
indent(writer).append("#[inline]\n");
11771157
indent(writer).append("fn write_at_position<T>(&mut self, position: usize, t: & T, num_bytes: usize) -> " +
11781158
"CodecResult<()> {\n");
@@ -1188,14 +1168,59 @@ static void generateEncoderScratchStruct(final Ir ir, final OutputManager output
11881168
indent(writer, 2).append("}\n");
11891169
indent(writer).append("}\n");
11901170

1171+
generateEncoderScratchSliceMethods(writer);
1172+
11911173
writer.append("}\n");
11921174

11931175
}
11941176
}
11951177

1178+
static void generateEncoderScratchSliceMethods(final Appendable writer) throws IOException
1179+
{
1180+
indent(writer, 1, "/// Create a mutable slice overlaid atop the data buffer directly\n");
1181+
indent(writer, 1, "/// such that changes to the slice contents directly edit the buffer\n");
1182+
indent(writer, 1, "/// Note that the initial content of the slice's members' fields may be garbage.\n");
1183+
indent(writer, 1, "/// Advances the `pos` index to after the region representing the slice.\n");
1184+
indent(writer).append("#[inline]\n");
1185+
indent(writer, 1, "fn writable_slice<T>(&mut self, count: usize, bytes_per_item: usize) " +
1186+
"-> CodecResult<&%s mut [T]> {\n", DATA_LIFETIME);
1187+
indent(writer, 2).append("let end = self.pos + (count * bytes_per_item);\n");
1188+
indent(writer, 2).append("if end <= self.data.len() {\n");
1189+
indent(writer, 3, "let v: &%s mut [T] = unsafe {\n", DATA_LIFETIME);
1190+
indent(writer, 4).append("core::slice::from_raw_parts_mut(" +
1191+
"self.data[self.pos..end].as_mut_ptr() as *mut T, count)\n");
1192+
indent(writer, 3).append("};\n");
1193+
indent(writer, 3).append("self.pos = end;\n");
1194+
indent(writer, 3).append("Ok(v)\n");
1195+
indent(writer, 2).append("} else {\n");
1196+
indent(writer, 3).append("Err(CodecErr::NotEnoughBytes)\n");
1197+
indent(writer, 2).append("}\n");
1198+
indent(writer).append("}\n\n");
1199+
1200+
indent(writer, 1, "/// Copy the raw bytes of a slice's contents into the data buffer\n");
1201+
indent(writer, 1, "/// Does **not** encode the length of the slice explicitly into the buffer.\n");
1202+
indent(writer, 1, "/// Advances the `pos` index to after the newly-written slice bytes.\n");
1203+
indent(writer).append("#[inline]\n");
1204+
indent(writer).append("fn write_slice_without_count<T>(&mut self, t: &[T], bytes_per_item: usize) -> " +
1205+
"CodecResult<()> {\n");
1206+
indent(writer, 2).append("let content_bytes_size = bytes_per_item * t.len();\n");
1207+
indent(writer, 2).append("let end = self.pos + content_bytes_size;\n");
1208+
indent(writer, 2).append("if end <= self.data.len() {\n");
1209+
indent(writer, 3).append("let source_bytes: &[u8] = unsafe {\n");
1210+
indent(writer, 4).append("core::slice::from_raw_parts(t.as_ptr() as *const u8, content_bytes_size)\n");
1211+
indent(writer, 3).append("};\n");
1212+
indent(writer, 3).append("(&mut self.data[self.pos..end]).copy_from_slice(source_bytes);\n");
1213+
indent(writer, 3).append("self.pos = end;\n");
1214+
indent(writer, 3).append("Ok(())\n");
1215+
indent(writer, 2).append("} else {\n");
1216+
indent(writer, 3).append("Err(CodecErr::NotEnoughBytes)\n");
1217+
indent(writer, 2).append("}\n");
1218+
indent(writer).append("}\n");
1219+
}
1220+
11961221
static void generateDecoderScratchStruct(final OutputManager outputManager) throws IOException
11971222
{
1198-
try (Writer writer = outputManager.createOutput("Scratch Decoder Data Wrapper"))
1223+
try (Writer writer = outputManager.createOutput("Scratch Decoder Data Wrapper - codec internal use only"))
11991224
{
12001225
writer.append("#[derive(Debug)]\n");
12011226
writer.append(format("struct %s<%s> {\n", SCRATCH_DECODER_TYPE, DATA_LIFETIME));
@@ -1205,6 +1230,9 @@ static void generateDecoderScratchStruct(final OutputManager outputManager) thro
12051230

12061231
writer.append(format("%nimpl<%s> %s<%s> {\n", DATA_LIFETIME, SCRATCH_DECODER_TYPE, DATA_LIFETIME));
12071232

1233+
indent(writer, 1, "/// Create a struct reference overlaid atop the data buffer\n");
1234+
indent(writer, 1, "/// such that the struct's contents directly reflect the buffer. \n");
1235+
indent(writer, 1, "/// Advances the `pos` index by the size of the struct in bytes.\n");
12081236
indent(writer).append("#[inline]\n");
12091237
indent(writer, 1, "fn read_type<T>(&mut self, num_bytes: usize) -> CodecResult<&%s T> {\n", DATA_LIFETIME);
12101238
indent(writer, 2).append("let end = self.pos + num_bytes;\n");
@@ -1216,8 +1244,9 @@ static void generateDecoderScratchStruct(final OutputManager outputManager) thro
12161244
indent(writer, 2).append("} else {\n");
12171245
indent(writer, 3).append("Err(CodecErr::NotEnoughBytes)\n");
12181246
indent(writer, 2).append("}\n");
1219-
indent(writer).append("}\n");
1247+
indent(writer).append("}\n\n");
12201248

1249+
indent(writer, 1, "/// Advances the `pos` index by a set number of bytes.\n");
12211250
indent(writer).append("#[inline]\n");
12221251
indent(writer).append("fn skip_bytes(&mut self, num_bytes: usize) -> CodecResult<()> {\n");
12231252
indent(writer, 2).append("let end = self.pos + num_bytes;\n");
@@ -1227,8 +1256,11 @@ static void generateDecoderScratchStruct(final OutputManager outputManager) thro
12271256
indent(writer, 2).append("} else {\n");
12281257
indent(writer, 3).append("Err(CodecErr::NotEnoughBytes)\n");
12291258
indent(writer, 2).append("}\n");
1230-
indent(writer).append("}\n");
1259+
indent(writer).append("}\n\n");
12311260

1261+
indent(writer, 1, "/// Create a slice reference overlaid atop the data buffer\n");
1262+
indent(writer, 1, "/// such that the slice's members' contents directly reflect the buffer.\n");
1263+
indent(writer, 1, "/// Advances the `pos` index by the size of the slice contents in bytes.\n");
12321264
indent(writer).append("#[inline]\n");
12331265
indent(writer, 1, "fn read_slice<T>(&mut self, count: usize, bytes_per_item: usize) " +
12341266
"-> CodecResult<&%s [T]> {\n", DATA_LIFETIME);
@@ -1370,13 +1402,13 @@ private void generateMessageHeaderDefault(
13701402
final HeaderStructure header = ir.headerStructure();
13711403
final String messageTypeName = formatTypeName(messageToken.name());
13721404
final String wrapperName = messageTypeName + "MessageHeader";
1373-
try (Writer writer = outputManager.createOutput(messageTypeName + " Message Header default"))
1405+
try (Writer writer = outputManager.createOutput(messageTypeName + " specific Message Header "))
13741406
{
13751407
appendStructHeader(writer, wrapperName, true);
13761408
indent(writer, 1, "pub message_header: MessageHeader\n");
13771409
writer.append("}\n");
13781410

1379-
writer.append(format("impl Default for %s {\n", wrapperName));
1411+
indent(writer, 1, "impl Default for %s {\n", wrapperName);
13801412
indent(writer, 1, "fn default() -> %s {\n", wrapperName);
13811413
indent(writer, 2, "%s {\n", wrapperName);
13821414

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

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -78,7 +78,7 @@ public void generateSharedImports() throws IOException
7878

7979
private static void assertContainsSharedImports(final String generatedRust)
8080
{
81-
assertTrue(generatedRust.contains("Shared Imports"));
81+
assertTrue(generatedRust.contains("Imports core rather than std"));
8282
assertTrue(generatedRust.contains("extern crate core;"));
8383
}
8484

0 commit comments

Comments
 (0)