String generateMessageHeaderCoder( final String messageTypeName, final OutputManager outputManager, final String topType, final int headerSize) throws IOException { final String messageHeaderRepresentation = "MessageHeader"; final String headerCoderType = messageTypeName + messageHeaderRepresentation + name(); try (Writer writer = outputManager.createOutput(headerCoderType)) { appendScratchWrappingStruct(writer, headerCoderType); RustGenerator.appendImplWithLifetimeHeader(writer, headerCoderType); appendWrapMethod(writer, headerCoderType); appendDirectCodeMethods(writer, "header", messageHeaderRepresentation, topType, headerSize); writer.append("}\n"); } return headerCoderType; } }
private static void generateMessageEncoder( final OutputManager outputManager, final MessageComponents components, final List<GroupTreeNode> groupTree, final Optional<FieldsRepresentationSummary> fieldsRepresentation, final int headerSize) throws IOException { final Token msgToken = components.messageToken; final String messageTypeName = formatTypeName(msgToken.name()); final RustCodecType codecType = RustCodecType.Encoder; String topType = codecType.generateDoneCoderType(outputManager, messageTypeName); topType = generateTopVarDataCoders(messageTypeName, components.varData, outputManager, topType, codecType); topType = generateGroupsCoders(groupTree, outputManager, topType, codecType); topType = generateFixedFieldCoder(messageTypeName, outputManager, topType, fieldsRepresentation, codecType); topType = codecType.generateMessageHeaderCoder(messageTypeName, outputManager, topType, headerSize); generateEntryPoint(messageTypeName, outputManager, topType, codecType); }
private static void generateEntryPoint( final String messageTypeName, final OutputManager outputManager, final String topType, final RustCodecType codecType) throws IOException { try (Writer writer = outputManager.createOutput(messageTypeName + format(" %s entry point", codecType.name()))) { final String gerund = codecType.gerund(); writer.append(format("pub fn start_%s_%s<%s>(data: &%s%s [u8]) -> %s {\n", gerund, formatMethodName(messageTypeName), DATA_LIFETIME, DATA_LIFETIME, codecType == RustCodecType.Encoder ? " mut" : "", withLifetime(topType))); indent(writer, 1, "%s::wrap(%s { data: data, pos: 0 })\n", topType, codecType.scratchType()); writer.append("}\n"); } }
void appendScratchWrappingStruct(final Appendable appendable, final String structName) throws IOException { appendable.append(String.format("pub struct %s <%s> {\n", structName, DATA_LIFETIME)) .append(INDENT).append(String.format("%s: %s <%s>,%n", scratchProperty(), scratchType(), DATA_LIFETIME)) .append("}\n"); }
String generateDoneCoderType( final OutputManager outputManager, final String messageTypeName) throws IOException { final String doneTypeName = messageTypeName + name() + "Done"; try (Writer writer = outputManager.createOutput(doneTypeName)) { appendScratchWrappingStruct(writer, doneTypeName); RustGenerator.appendImplWithLifetimeHeader(writer, doneTypeName); indent(writer, 1, "/// Returns the number of bytes %s\n", this == Encoder ? "encoded" : "decoded"); indent(writer, 1, "pub fn unwrap(self) -> usize {\n"); indent(writer, 2, "self.%s.pos\n", scratchProperty()); indent(writer, 1, "}\n"); appendWrapMethod(writer, doneTypeName); writer.append("}\n"); } return doneTypeName; }
final String decoderType = parentContextualName + formatTypeName(name) + codecType.name(); try (Writer writer = outputManager.createOutput(name + " variable-length data")) final String contentPropertyName = groupDepth > 0 ? "parent" : codecType.scratchProperty(); indent(writer, 1, "%s: %s,\n", contentPropertyName, withLifetime(contentType)); writer.append("}\n");
void appendDirectCodeMethods( final Appendable appendable, final String methodName, final String representationType, final String nextCoderType, final int numBytes) 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); indent(appendable, 2, "Ok((v, %s::wrap(self.%s)))\n", nextCoderType, RustCodecType.Decoder.scratchProperty()); indent(appendable).append("}\n"); }
final String memberCoderType = node.contextualName + "Member" + codecType.name(); String nextCoderType = memberCoderType;
String generateDoneCoderType( final OutputManager outputManager, final String messageTypeName) throws IOException { final String doneTypeName = messageTypeName + name() + "Done"; try (Writer writer = outputManager.createOutput(doneTypeName)) { appendScratchWrappingStruct(writer, doneTypeName); RustGenerator.appendImplWithLifetimeHeader(writer, doneTypeName); indent(writer, 1, "/// Returns the number of bytes %s\n", this == Encoder ? "encoded" : "decoded"); indent(writer, 1, "pub fn unwrap(self) -> usize {\n"); indent(writer, 2, "self.%s.pos\n", scratchProperty()); indent(writer, 1, "}\n"); appendWrapMethod(writer, doneTypeName); writer.append("}\n"); } return doneTypeName; }
void appendWrapMethod(final Appendable appendable, final String structName) throws IOException { appendable.append("\n").append(INDENT).append(String.format( "fn wrap(%s: %s) -> %s {%n", scratchProperty(), RustGenerator.withLifetime(scratchType()), RustGenerator.withLifetime(structName))); indent(appendable, 2, "%s { %s: %s }\n", structName, scratchProperty(), scratchProperty()); indent(appendable).append("}\n"); }
final String decoderType = parentContextualName + formatTypeName(name) + codecType.name(); try (Writer writer = outputManager.createOutput(name + " variable-length data")) final String contentPropertyName = groupDepth > 0 ? "parent" : codecType.scratchProperty(); indent(writer, 1, "%s: %s,\n", contentPropertyName, withLifetime(contentType)); writer.append("}\n");
void appendDirectCodeMethods( final Appendable appendable, final String methodName, final String representationType, final String nextCoderType, final int numBytes) 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); indent(appendable, 2, "Ok((v, %s::wrap(self.%s)))\n", nextCoderType, RustCodecType.Encoder.scratchProperty()); indent(appendable).append("}\n\n"); indent(appendable, 1, "/// Copy the bytes of a value into the data buffer\n"); indent(appendable).append(String.format("pub fn %s_copy(mut self, t: &%s) -> CodecResult<%s> {\n", methodName, representationType, RustGenerator.withLifetime(nextCoderType))); indent(appendable, 2) .append(format("self.%s.write_type::<%s>(t, %s)?;\n", RustCodecType.Encoder.scratchProperty(), representationType, numBytes)); indent(appendable, 2).append(format("Ok(%s::wrap(self.%s))\n", nextCoderType, RustCodecType.Encoder.scratchProperty())); indent(appendable).append("}\n"); }
final String memberCoderType = node.contextualName + "Member" + codecType.name(); String nextCoderType = memberCoderType;
private static String generateFixedFieldCoder( final String messageTypeName, final OutputManager outputManager, final String topType, final Optional<FieldsRepresentationSummary> fieldsRepresentationOptional, final RustCodecType codecType) throws IOException { if (!fieldsRepresentationOptional.isPresent()) { return topType; } final FieldsRepresentationSummary fieldsRepresentation = fieldsRepresentationOptional.get(); try (Writer writer = outputManager.createOutput(messageTypeName + " Fixed fields " + codecType.name())) { final String representationStruct = fieldsRepresentation.typeName; final String decoderName = representationStruct + codecType.name(); codecType.appendScratchWrappingStruct(writer, decoderName); appendImplWithLifetimeHeader(writer, decoderName); codecType.appendWrapMethod(writer, decoderName); codecType.appendDirectCodeMethods(writer, formatMethodName(messageTypeName) + "_fields", representationStruct, topType, fieldsRepresentation.numBytes); writer.append("}\n"); // TODO - Move read position further if in-message blockLength exceeds fixed fields representation size // will require piping some data from the previously-read message header return decoderName; } }
String generateDoneCoderType( final OutputManager outputManager, final String messageTypeName) throws IOException { final String doneTypeName = messageTypeName + name() + "Done"; try (Writer writer = outputManager.createOutput(doneTypeName)) { appendScratchWrappingStruct(writer, doneTypeName); RustGenerator.appendImplWithLifetimeHeader(writer, doneTypeName); indent(writer, 1, "/// Returns the number of bytes %s\n", this == Encoder ? "encoded" : "decoded"); indent(writer, 1, "pub fn unwrap(self) -> usize {\n"); indent(writer, 2, "self.%s.pos\n", scratchProperty()); indent(writer, 1, "}\n"); appendWrapMethod(writer, doneTypeName); writer.append("}\n"); } return doneTypeName; }
private static void generateEntryPoint( final String messageTypeName, final OutputManager outputManager, final String topType, final RustCodecType codecType) throws IOException { try (Writer writer = outputManager.createOutput(messageTypeName + format(" %s entry point", codecType.name()))) { final String gerund = codecType.gerund(); writer.append(format("pub fn start_%s_%s<%s>(data: &%s%s [u8]) -> %s {\n", gerund, formatMethodName(messageTypeName), DATA_LIFETIME, DATA_LIFETIME, codecType == RustCodecType.Encoder ? " mut" : "", withLifetime(topType))); indent(writer, 1, "%s::wrap(%s { data: data, pos: 0 })\n", topType, codecType.scratchType()); writer.append("}\n"); } }
void appendScratchWrappingStruct(final Appendable appendable, final String structName) throws IOException { appendable.append(String.format("pub struct %s <%s> {\n", structName, DATA_LIFETIME)) .append(INDENT).append(String.format("%s: %s <%s>,%n", scratchProperty(), scratchType(), DATA_LIFETIME)) .append("}\n"); }
private static void generateMessageDecoder( final OutputManager outputManager, final MessageComponents components, final List<GroupTreeNode> groupTree, final Optional<FieldsRepresentationSummary> fieldsRepresentation, final int headerSize) throws IOException { final Token msgToken = components.messageToken; final String messageTypeName = formatTypeName(msgToken.name()); final RustCodecType codecType = RustCodecType.Decoder; String topType = codecType.generateDoneCoderType(outputManager, messageTypeName); topType = generateTopVarDataCoders(messageTypeName, components.varData, outputManager, topType, codecType); topType = generateGroupsCoders(groupTree, outputManager, topType, codecType); topType = generateFixedFieldCoder(messageTypeName, outputManager, topType, fieldsRepresentation, codecType); topType = codecType.generateMessageHeaderCoder(messageTypeName, outputManager, topType, headerSize); generateEntryPoint(messageTypeName, outputManager, topType, codecType); }
final String decoderType = parentContextualName + formatTypeName(name) + codecType.name(); try (Writer writer = outputManager.createOutput(name + " variable-length data")) final String contentPropertyName = groupDepth > 0 ? "parent" : codecType.scratchProperty(); indent(writer, 1, "%s: %s,\n", contentPropertyName, withLifetime(contentType)); writer.append("}\n");
void appendDirectCodeMethods( final Appendable appendable, final String methodName, final String representationType, final String nextCoderType, final int numBytes) 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); indent(appendable, 2, "Ok((v, %s::wrap(self.%s)))\n", nextCoderType, RustCodecType.Decoder.scratchProperty()); indent(appendable).append("}\n"); }