Skip to content

Commit abdd406

Browse files
author
Michael Ward
committed
[Rust] updated codegen to create additional function for primitive arrays that will accept an "impl Iterator". This allows an arbitrary number of items to be passed in, which will guarantee the correct number of items are encoded (defined 'nullValue' will be used where appropriate)
1 parent 8684ba4 commit abdd406

File tree

2 files changed

+89
-56
lines changed

2 files changed

+89
-56
lines changed

rust/tests/extension_test.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -187,7 +187,7 @@ fn encode_car_from_scratch() -> SbeResult<(usize, Vec<u8>)> {
187187
car.available(BooleanType::T);
188188
car.code(Model::A);
189189
car.some_numbers(&[0, 1, 2, 3]);
190-
car.vehicle_code(b"abcdef_extra_is_ignored"); // abcdef
190+
car.vehicle_code_from_iter(b"abcdef_extra_is_ignored".iter().map(|x| *x)); // abcdef
191191

192192
extras.set_cruise_control(true);
193193
extras.set_sports_pack(true);

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

Lines changed: 88 additions & 55 deletions
Original file line numberDiff line numberDiff line change
@@ -361,7 +361,23 @@ static void generateEncoderVarData(
361361
}
362362
}
363363

364-
private static void generatePrimitiveEncoder(
364+
private static void generateRustDoc(
365+
final StringBuilder sb,
366+
final int level,
367+
final Token typeToken,
368+
final Encoding encoding) throws IOException
369+
{
370+
indent(sb, level, "/// - min value: %s\n", encoding.applicableMinValue());
371+
indent(sb, level, "/// - max value: %s\n", encoding.applicableMaxValue());
372+
indent(sb, level, "/// - null value: %s\n", encoding.applicableNullValue());
373+
indent(sb, level, "/// - characterEncoding: %s\n", encoding.characterEncoding());
374+
indent(sb, level, "/// - semanticType: %s\n", encoding.semanticType());
375+
indent(sb, level, "/// - encodedOffset: %d\n", typeToken.offset());
376+
indent(sb, level, "/// - encodedLength: %d\n", typeToken.encodedLength());
377+
indent(sb, level, "/// - version: %d\n", typeToken.version());
378+
}
379+
380+
private static void generatePrimitiveArrayEncoder(
365381
final StringBuilder sb,
366382
final int level,
367383
final Token typeToken,
@@ -371,37 +387,29 @@ private static void generatePrimitiveEncoder(
371387
final PrimitiveType primitiveType = encoding.primitiveType();
372388
final String rustPrimitiveType = rustTypeName(primitiveType);
373389
final int arrayLength = typeToken.arrayLength();
374-
if (arrayLength > 1)
375-
{
376-
indent(sb, level, "/// primitive array field '%s'\n", name);
377-
indent(sb, level, "/// - min value: %s\n", encoding.applicableMinValue());
378-
indent(sb, level, "/// - max value: %s\n", encoding.applicableMaxValue());
379-
indent(sb, level, "/// - null value: %s\n", encoding.applicableNullValue());
380-
indent(sb, level, "/// - characterEncoding: %s\n", encoding.characterEncoding());
381-
indent(sb, level, "/// - semanticType: %s\n", encoding.semanticType());
382-
indent(sb, level, "/// - encodedOffset: %d\n", typeToken.offset());
383-
indent(sb, level, "/// - encodedLength: %d\n", typeToken.encodedLength());
384-
indent(sb, level, "/// - version: %d\n", typeToken.version());
385-
indent(sb, level, "#[inline]\n");
386-
indent(sb, level, "pub fn %s(&mut self, value: &[%s]) {\n",
387-
formatFunctionName(name),
388-
rustPrimitiveType);
389390

390-
// NB: must create variable 'offset' before calling mutable self.get_buf_mut()
391-
indent(sb, level + 1, "let offset = self.%s;\n", getBufOffset(typeToken));
392-
indent(sb, level + 1, "let buf = self.get_buf_mut();\n");
391+
indent(sb, level, "/// primitive array field '%s'\n", name);
392+
generateRustDoc(sb, level, typeToken, encoding);
393+
indent(sb, level, "#[inline]\n");
394+
indent(sb, level, "pub fn %s(&mut self, value: &[%s]) {\n",
395+
formatFunctionName(name), rustPrimitiveType);
393396

394-
if (rustPrimitiveType.equals("u8"))
395-
{
396-
indent(sb, level + 1, "let mid = %d.min(value.len());\n", arrayLength);
397-
indent(sb, level + 1, "buf.put_slice_at(offset, value.split_at(mid).0);\n");
398-
indent(sb, level + 1, "for i in mid..%d {\n", arrayLength);
399-
indent(sb, level + 2, "buf.put_u8_at(offset + (i * 1), %s_u8);\n", encoding.applicableNullValue());
400-
indent(sb, level + 1, "}\n");
401-
indent(sb, level, "}\n\n");
402-
return;
403-
}
397+
// NB: must create variable 'offset' before calling mutable self.get_buf_mut()
398+
indent(sb, level + 1, "debug_assert_eq!(%d, value.len());\n", arrayLength);
399+
indent(sb, level + 1, "let offset = self.%s;\n", getBufOffset(typeToken));
400+
indent(sb, level + 1, "let buf = self.get_buf_mut();\n");
404401

402+
if (rustPrimitiveType.equals("u8"))
403+
{
404+
indent(sb, level + 1, "let mid = %d.min(value.len());\n", arrayLength);
405+
indent(sb, level + 1, "buf.put_slice_at(offset, value.split_at(mid).0);\n");
406+
indent(sb, level + 1, "for i in mid..%d {\n", arrayLength);
407+
indent(sb, level + 2, "buf.put_u8_at(offset + (i * 1), %s_u8);\n", encoding.applicableNullValue());
408+
indent(sb, level + 1, "}\n");
409+
indent(sb, level, "}\n\n");
410+
}
411+
else
412+
{
405413
for (int i = 0; i < arrayLength; i++)
406414
{
407415
if (i == 0)
@@ -419,34 +427,59 @@ private static void generatePrimitiveEncoder(
419427

420428
indent(sb, level, "}\n\n");
421429
}
422-
else
430+
431+
indent(sb, level, "/// primitive array field '%s' from an Iterator\n", name);
432+
generateRustDoc(sb, level, typeToken, encoding);
433+
indent(sb, level, "#[inline]\n");
434+
indent(sb, level, "pub fn %s_from_iter(&mut self, iter: impl Iterator<Item = %s>) {\n",
435+
formatFunctionName(name), rustPrimitiveType);
436+
437+
indent(sb, level + 1, "let offset = self.%s;\n", getBufOffset(typeToken));
438+
indent(sb, level + 1, "let buf = self.get_buf_mut();\n");
439+
indent(sb, level + 1, "let iter = iter.chain(std::iter::repeat(%s_%s)).take(%d);\n",
440+
encoding.applicableNullValue(), rustPrimitiveType, arrayLength);
441+
442+
indent(sb, level + 1, "for (i, v) in iter.enumerate() {\n");
443+
indent(sb, level + 2, "buf.put_%s_at(offset + (i * %d), v);\n",
444+
rustPrimitiveType, primitiveType.size());
445+
indent(sb, level + 1, "}\n");
446+
indent(sb, level, "}\n\n");
447+
}
448+
449+
private static void generatePrimitiveEncoder(
450+
final StringBuilder sb,
451+
final int level,
452+
final Token typeToken,
453+
final String name) throws IOException
454+
{
455+
final int arrayLength = typeToken.arrayLength();
456+
if (arrayLength > 1)
423457
{
424-
if (encoding.presence() == Encoding.Presence.CONSTANT)
425-
{
426-
indent(sb, level, "// skipping CONSTANT %s\n\n", name);
427-
}
428-
else
429-
{
430-
indent(sb, level, "/// primitive field '%s'\n", name);
431-
indent(sb, level, "/// - min value: %s\n", encoding.applicableMinValue());
432-
indent(sb, level, "/// - max value: %s\n", encoding.applicableMaxValue());
433-
indent(sb, level, "/// - null value: %s\n", encoding.applicableNullValue());
434-
indent(sb, level, "/// - characterEncoding: %s\n", encoding.characterEncoding());
435-
indent(sb, level, "/// - semanticType: %s\n", encoding.semanticType());
436-
indent(sb, level, "/// - encodedOffset: %d\n", typeToken.offset());
437-
indent(sb, level, "/// - encodedLength: %d\n", typeToken.encodedLength());
438-
indent(sb, level, "/// - version: %d\n", typeToken.version());
439-
indent(sb, level, "#[inline]\n");
440-
indent(sb, level, "pub fn %s(&mut self, value: %s) {\n",
441-
formatFunctionName(name),
442-
rustPrimitiveType);
443-
444-
// NB: must create variable 'offset' before calling mutable self.get_buf_mut()
445-
indent(sb, level + 1, "let offset = self.%s;\n", getBufOffset(typeToken));
446-
indent(sb, level + 1, "self.get_buf_mut().put_%s_at(offset, value);\n", rustPrimitiveType);
447-
indent(sb, level, "}\n\n");
448-
}
458+
generatePrimitiveArrayEncoder(sb, level, typeToken, name);
459+
return;
460+
}
461+
462+
final Encoding encoding = typeToken.encoding();
463+
if (encoding.presence() == Encoding.Presence.CONSTANT)
464+
{
465+
indent(sb, level, "// skipping CONSTANT %s\n\n", name);
466+
return;
449467
}
468+
469+
final PrimitiveType primitiveType = encoding.primitiveType();
470+
final String rustPrimitiveType = rustTypeName(primitiveType);
471+
472+
indent(sb, level, "/// primitive field '%s'\n", name);
473+
generateRustDoc(sb, level, typeToken, encoding);
474+
indent(sb, level, "#[inline]\n");
475+
indent(sb, level, "pub fn %s(&mut self, value: %s) {\n",
476+
formatFunctionName(name), rustPrimitiveType);
477+
478+
// NB: must create variable 'offset' before calling mutable self.get_buf_mut()
479+
indent(sb, level + 1, "let offset = self.%s;\n", getBufOffset(typeToken));
480+
indent(sb, level + 1, "self.get_buf_mut().put_%s_at(offset, value);\n", rustPrimitiveType);
481+
indent(sb, level, "}\n\n");
482+
450483
}
451484

452485
private static void generateEnumEncoder(

0 commit comments

Comments
 (0)