static void generateDecoderVarData(
        final StringBuilder sb,
        final List<Token> tokens,
        final int level,
        final boolean isSubGroup) throws IOException
    {
        for (int i = 0, size = tokens.size(); i < size; )
        {
            final Token varDataToken = tokens.get(i);
            if (varDataToken.signal() != Signal.BEGIN_VAR_DATA)
            {
                throw new IllegalStateException("tokens must begin with BEGIN_VAR_DATA: token=" + varDataToken);
            }

            final String characterEncoding = characterEncoding(tokens.get(i + 3).encoding());
            final String propertyName = toLowerSnakeCase(varDataToken.name());
            final Token lengthToken = tokens.get(i + 2);
            final Encoding lengthEncoding = lengthToken.encoding();
            final PrimitiveType lengthType = lengthEncoding.primitiveType();

            indent(sb, level, "/// VAR_DATA DECODER - character encoding: '%s'\n", characterEncoding);
            indent(sb, level, "#[inline]\n");
            indent(sb, level, "pub fn %s_decoder(&mut self) -> (usize, usize) {\n", propertyName);

            if (isSubGroup)
            {
                if (varDataToken.version() > 0)
                {
                    indent(sb, level + 1, "if self.acting_version() < %d {\n",
                        varDataToken.version());
                    indent(sb, level + 2, "return (self.parent.as_ref().unwrap().get_limit(), 0);\n");
                    indent(sb, level + 1, "}\n\n");
                }

                indent(sb, level + 1, "let offset = self.parent.as_ref().expect(\"parent missing\").get_limit();\n");
                indent(sb, level + 1, "let data_length = self.get_buf().get_%s_at(offset) as usize;\n",
                    rustTypeName(lengthType));
                indent(sb, level + 1, "self.parent.as_mut().unwrap().set_limit(offset + %d + data_length);\n",
                    lengthType.size());
            }
            else
            {
                if (varDataToken.version() > 0)
                {
                    indent(sb, level + 1, "if self.acting_version() < %d {\n",
                        varDataToken.version());
                    indent(sb, level + 2, "return (self.get_limit(), 0);\n");
                    indent(sb, level + 1, "}\n\n");
                }

                indent(sb, level + 1, "let offset = self.get_limit();\n");
                indent(sb, level + 1, "let data_length = self.get_buf().get_%s_at(offset) as usize;\n",
                    rustTypeName(lengthType));
                indent(sb, level + 1, "self.set_limit(offset + %d + data_length);\n", lengthType.size());
            }
            indent(sb, level + 1, "(offset + %d, data_length)\n", lengthType.size());
            indent(sb, level, "}\n\n");

            // function to return slice form given coord
            indent(sb, level, "#[inline]\n");
            indent(sb, level, "pub fn %s_slice(&'a self, coordinates: (usize, usize)) -> &'a [u8] {\n", propertyName);

            if (varDataToken.version() > 0)
            {
                indent(sb, level + 1, "if self.acting_version() < %d {\n",
                    varDataToken.version());
                indent(sb, level + 2, "return &[] as &[u8];\n");
                indent(sb, level + 1, "}\n\n");
            }

            indent(sb, level + 1, "debug_assert!(self.get_limit() >= coordinates.0 + coordinates.1);\n");
            indent(sb, level + 1, "self.get_buf().get_slice_at(coordinates.0, coordinates.1)\n");
            indent(sb, level, "}\n\n");

            i += varDataToken.componentTokenCount();
        }
    }
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