static void generateDecoderGroups(
        final String schemaVersionType,
        final StringBuilder sb,
        final List<Token> tokens,
        final int level,
        final ParentDef parentDef) throws IOException
    {
        for (int i = 0, size = tokens.size(); i < size; i++)
        {
            final Token groupToken = tokens.get(i);
            if (groupToken.signal() != Signal.BEGIN_GROUP)
            {
                throw new IllegalStateException("tokens must begin with BEGIN_GROUP: token=" + groupToken);
            }

            ++i;
            final int index = i;
            final int groupHeaderTokenCount = tokens.get(i).componentTokenCount();
            i += groupHeaderTokenCount;

            final List<Token> fields = new ArrayList<>();
            i = collectFields(tokens, i, fields);

            final List<Token> groups = new ArrayList<>();
            i = collectGroups(tokens, i, groups);

            final List<Token> varData = new ArrayList<>();
            i = collectVarData(tokens, i, varData);

            final String groupName = decoderName(formatStructName(groupToken.name()));
            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)
            {
                indent(sb, level, "pub fn %s(self) -> Option<%2$s<Self>> {\n",
                    formatFunctionName(groupName), groupName);

                indent(sb, level + 1, "if self.acting_version() < %d {\n", groupToken.version());
                indent(sb, level + 2, "return None;\n");
                indent(sb, level + 1, "}\n\n");

                indent(sb, level + 1, "Some(%s::default().wrap(self))\n", groupName);
            }
            else
            {
                indent(sb, level, "pub fn %s(self) -> %2$s<Self> {\n",
                    formatFunctionName(groupName), groupName);

                indent(sb, level + 1, "%s::default().wrap(self)\n", groupName);
            }
            indent(sb, level, "}\n\n");

            final SubGroup subGroup = parentDef.addSubGroup(groupName, level, groupToken);
            subGroup.generateDecoder(schemaVersionType, tokens, fields, groups, varData, index);
        }
    }
Create a new Rust language {@link CodeGenerator}.

@param ir            for the messages and types.
@param crateVersion  for the generated crate.
@param outputManager for generating the codecs to.
sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/rust/RustGenerator.java