Skip to content

Rust codec improvements - handle offsets, custom group size encoding #679

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 12 commits into from
May 7, 2019
3 changes: 2 additions & 1 deletion build.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -533,9 +533,10 @@ task generateRustCarExample(type: JavaExec) {
classpath = project(':sbe-all').sourceSets.main.runtimeClasspath
systemProperties(
'sbe.output.dir': 'rust/car_example/src',
'sbe.xinclude.aware': 'true',
'sbe.target.language': 'uk.co.real_logic.sbe.generation.rust.Rust',
'sbe.target.namespace': 'car_example_generated_codec')
args = ['sbe-tool/src/test/resources/example-schema.xml']
args = ['sbe-samples/src/main/resources/example-schema.xml']
}

task generateCarExampleDataFile(type: JavaExec) {
Expand Down
36 changes: 18 additions & 18 deletions rust/car_example/src/main.rs
Original file line number Diff line number Diff line change
Expand Up @@ -45,11 +45,11 @@ impl std::convert::From<CodecErr> for IoError {

fn decode_car_and_assert_expected_content(buffer: &[u8]) -> CodecResult<()> {
let (h, dec_fields) = start_decoding_car(&buffer).header()?;
assert_eq!(49u16, h.block_length);
assert_eq!(45u16, {h.block_length});
assert_eq!(h.block_length as usize, ::std::mem::size_of::<CarFields>());
assert_eq!(1u16, h.template_id);
assert_eq!(1u16, h.schema_id);
assert_eq!(0u16, h.version);
assert_eq!(1u16, {h.template_id});
assert_eq!(1u16, {h.schema_id});
assert_eq!(0u16, {h.version});
println!("Header read");

assert_eq!(Model::C, CarFields::discounted_model());
Expand All @@ -59,16 +59,16 @@ fn decode_car_and_assert_expected_content(buffer: &[u8]) -> CodecResult<()> {
let mut found_fuel_figures = Vec::<FuelFigure>::with_capacity(EXPECTED_FUEL_FIGURES.len());

let (fields, dec_fuel_figures_header) = dec_fields.car_fields()?;
assert_eq!(1234, fields.serial_number);
assert_eq!(2013, fields.model_year);
assert_eq!(BooleanType::T, fields.available);
assert_eq!([97_i8, 98, 99, 100, 101, 102], fields.vehicle_code); // abcdef
assert_eq!([0_u32, 1, 2, 3, 4], fields.some_numbers);
assert_eq!(1234, {fields.serial_number});
assert_eq!(2013, {fields.model_year});
assert_eq!(BooleanType::T, {fields.available});
assert_eq!([97_i8, 98, 99, 100, 101, 102], {fields.vehicle_code}); // abcdef
assert_eq!([1, 2, 3, 4], {fields.some_numbers});
assert_eq!(6, fields.extras.0);
assert!(fields.extras.get_cruise_control());
assert!(fields.extras.get_sports_pack());
assert!(!fields.extras.get_sun_roof());
assert_eq!(2000, fields.engine.capacity);
assert_eq!(2000, {fields.engine.capacity});
assert_eq!(4, fields.engine.num_cylinders);
assert_eq!(BoostType::NITROUS, fields.engine.booster.boost_type);
assert_eq!(200, fields.engine.booster.horse_power);
Expand All @@ -82,12 +82,12 @@ fn decode_car_and_assert_expected_content(buffer: &[u8]) -> CodecResult<()> {
let (usage_description, next_step) = dec_usage_description.usage_description()?;
let usage_str = std::str::from_utf8(usage_description).unwrap();
println!("Fuel Figure: Speed: {0}, MPG: {1}, Usage: {2}",
ff_fields.speed,
ff_fields.mpg,
{ff_fields.speed},
{ff_fields.mpg},
usage_str);
found_fuel_figures.push(FuelFigure {
speed: ff_fields.speed,
mpg: ff_fields.mpg,
speed: {ff_fields.speed},
mpg: {ff_fields.mpg},
usage_description: usage_str,
});
match next_step {
Expand Down Expand Up @@ -117,8 +117,8 @@ fn decode_car_and_assert_expected_content(buffer: &[u8]) -> CodecResult<()> {
let (accel_slice, next_step) = dec_acceleration_header.acceleration_as_slice()?;
for accel_fields in accel_slice {
println!("Acceleration: MPH: {0}, Seconds: {1}",
accel_fields.mph,
accel_fields.seconds);
{accel_fields.mph},
{accel_fields.seconds});
}
match next_step {
Either::Left(more_members) => dec_pf_members = more_members,
Expand Down Expand Up @@ -165,7 +165,7 @@ fn encode_car_from_scratch() -> CodecResult<Vec<u8>> {
fields.available = BooleanType::T;
fields.code = Model::A;
fields.vehicle_code = [97_i8, 98, 99, 100, 101, 102]; // abcdef
fields.some_numbers = [0_u32, 1, 2, 3, 4];
fields.some_numbers = [1, 2, 3, 4];
fields.extras = OptionalExtras::new();
fields.extras.set_cruise_control(true)
.set_sports_pack(true)
Expand Down Expand Up @@ -274,4 +274,4 @@ const EXPECTED_PERF_FIXTURES: &'static [PerfFigure] = &[PerfFigure {
mph: 100,
seconds: 11.8,
}],
}];
}];
Original file line number Diff line number Diff line change
Expand Up @@ -44,12 +44,18 @@ void appendDirectCodeMethods(
final String methodName,
final String representationType,
final String nextCoderType,
final int numBytes) throws IOException
final int numBytes,
final int trailingBytes) throws IOException
{
indent(appendable, 1, "pub fn %s(mut self) -> CodecResult<(&%s %s, %s)> {\n",
methodName, DATA_LIFETIME, representationType, RustGenerator.withLifetime(nextCoderType));
indent(appendable, 2, "let v = self.%s.read_type::<%s>(%s)?;\n",
RustCodecType.Decoder.scratchProperty(), representationType, numBytes);
if (trailingBytes > 0)
{
indent(appendable, 2, "self.%s.skip_bytes(%s)?;\n",
RustCodecType.Decoder.scratchProperty(), trailingBytes);
}
indent(appendable, 2, "Ok((v, %s::wrap(self.%s)))\n",
nextCoderType, RustCodecType.Decoder.scratchProperty());
indent(appendable).append("}\n");
Expand Down Expand Up @@ -78,15 +84,20 @@ void appendDirectCodeMethods(
final String methodName,
final String representationType,
final String nextCoderType,
final int numBytes) throws IOException
final int numBytes,
final int trailingBytes) throws IOException
{
indent(appendable, 1, "\n/// Create a mutable struct reference overlaid atop the data buffer\n");
indent(appendable, 1, "/// such that changes to the struct directly edit the buffer. \n");
indent(appendable, 1, "/// Note that the initial content of the struct's fields may be garbage.\n");
indent(appendable, 1, "pub fn %s(mut self) -> CodecResult<(&%s mut %s, %s)> {\n",
methodName, DATA_LIFETIME, representationType, RustGenerator.withLifetime(nextCoderType));
indent(appendable, 2, "let v = self.%s.writable_overlay::<%s>(%s)?;\n",
RustCodecType.Encoder.scratchProperty(), representationType, numBytes);
if (trailingBytes > 0)
{
indent(appendable, 2, "// add trailing bytes to extend the end position of the scratch buffer\n");
}
indent(appendable, 2, "let v = self.%s.writable_overlay::<%s>(%s+%s)?;\n",
RustCodecType.Encoder.scratchProperty(), representationType, numBytes, trailingBytes);
indent(appendable, 2, "Ok((v, %s::wrap(self.%s)))\n",
nextCoderType, RustCodecType.Encoder.scratchProperty());
indent(appendable).append("}\n\n");
Expand All @@ -97,6 +108,12 @@ void appendDirectCodeMethods(
indent(appendable, 2)
.append(format("self.%s.write_type::<%s>(t, %s)?;\n",
RustCodecType.Encoder.scratchProperty(), representationType, numBytes));
if (trailingBytes > 0)
{
indent(appendable, 2, "// fixed message length > sum of field lengths\n");
indent(appendable, 2, "self.%s.skip_bytes(%s)?;\n",
RustCodecType.Decoder.scratchProperty(), trailingBytes);
}
indent(appendable, 2).append(format("Ok(%s::wrap(self.%s))\n",
nextCoderType, RustCodecType.Encoder.scratchProperty()));
indent(appendable).append("}\n");
Expand Down Expand Up @@ -125,7 +142,8 @@ abstract void appendDirectCodeMethods(
String methodName,
String representationType,
String nextCoderType,
int numBytes) throws IOException;
int numBytes,
int trailingBytes) throws IOException;

abstract String gerund();

Expand Down Expand Up @@ -175,7 +193,7 @@ String generateMessageHeaderCoder(
appendScratchWrappingStruct(writer, headerCoderType);
RustGenerator.appendImplWithLifetimeHeader(writer, headerCoderType);
appendWrapMethod(writer, headerCoderType);
appendDirectCodeMethods(writer, "header", messageHeaderRepresentation, topType, headerSize);
appendDirectCodeMethods(writer, "header", messageHeaderRepresentation, topType, headerSize, 0);
writer.append("}\n");
}

Expand Down
Loading