4 个版本
使用旧的Rust 2015
| 0.2.3 | 2023年10月15日 | 
|---|---|
| 0.2.2 | 2022年12月16日 | 
| 0.2.1 | 2022年11月14日 | 
| 0.2.0 | 2022年10月29日 | 
#1859 in 进程宏
在 2 个库中使用 (通过 rat-in-a-tube)
37KB
123 行
Rat In a Tube
RIAT是Halo:Combat Evolved脚本的免费脚本编译器。
要编译,您需要Rust编译器和Cargo。
示例用法
Rat in a Tube 可以在Rust、C和C++中使用。
Rust
RIAT是一个Rust库,因此您可以直接在您的Rust库中使用它。
extern crate rat_in_a_tube;
use rat_in_a_tube::Compiler;
/** Return true if successful. Return false on failure. */
fn compile_scripts_rust(script_file_name: &str, script_data: &[u8]) -> bool {
    // Instantiate our instance
    let mut compiler = Compiler::new(CompileTarget::HaloCEA);
    // Try to compile
    match compiler.read_script_data(script_file_name, script_data) {
        Ok(_) => (),
        Err(e) => {
            let file = e.get_file();
            let message = e.get_message();
            let (line,column) = e.get_position();
            eprintln!("Failed to read script data: {file}:{line}:{column}: {message}");
            return false;
        }
    }
    let script_data = match compiler.digest_tokens() {
        Ok(n) => n,
        Err(e) => {
            let file = e.get_file();
            let message = e.get_message();
            let (line,column) = e.get_position();
            eprintln!("Failed to compile script data: {file}:{line}:{column}: {message}");
            return false;
        }
    };
    // Print information
    println!("Script count: {}", script_data.get_scripts().len());
    println!("Global count: {}", script_data.get_globals().len());
    println!("Node count: {}", script_data.get_nodes().len());
    return true;
}
C
RIAT通过riatc包提供了C绑定。您需要使用您选择的工具链链接riatc库,并将riatc的include目录添加到您的include列表中。
#include <riat/riat.h>
#include <stdlib.h>
#include <stdio.h>
#include <stdint.h>
#include <string.h>
/* Return 0 if successful. Return a nonzero value if failed. */
int compile_scripts_c(const char *script_file_name, const uint8_t *script_data, size_t script_data_length) {
    /* Put variables here */
    int result = 0;
    RIATCompiledScriptData *compiled_script_data = NULL;
    RIATScriptC *scripts = NULL;
    RIATGlobalC *globals = NULL;
    RIATScriptNodeC *nodes = NULL;
    size_t script_count, global_count, node_count;
    /* Zero-out error struct. Not required, but calling riat_error_free() on a zeroed out struct is always OK. */
    RIATCompileErrorC error;
    memset(&error, 0, sizeof(error));
    /* Instantiate our instance */
    RIATCompiler *compiler = riat_compiler_new(RIAT_HaloCEA);
    /* Try to compile */
    if(riat_compiler_read_script_data(compiler, script_file_name, script_data, script_data_length, &error) != 0) {
        fprintf(stderr, "Failed to read script data: %s:%zu:%zu: %s\n", error.file, error.line, error.column, error.message);
        result = 1;
        goto CLEANUP;
    }
    if((compiled_script_data = riat_compiler_compile_script_data(compiler, &error)) == NULL) {
        fprintf(stderr, "Failed to compile script data: %s:%zu:%zu: %s\n", error.file, error.line, error.column, error.message);
        result = 1;
        goto CLEANUP;
    }
    /* Get the sizes */
    script_count = riat_script_data_get_scripts(compiled_script_data, NULL);
    global_count = riat_script_data_get_globals(compiled_script_data, NULL);
    node_count = riat_script_data_get_nodes(compiled_script_data, NULL);
    /* Allocate */
    scripts = malloc(sizeof(*scripts) * script_count);
    globals = malloc(sizeof(*globals) * global_count);
    nodes = malloc(sizeof(*nodes) * node_count);
    /* If any of those returned false, we failed */
    if(scripts == NULL || globals == NULL || nodes == NULL) {
        fprintf(stderr, "Allocation error!\n");
        result = 2;
        goto CLEANUP;
    }
    /* Read everything */
    riat_script_data_get_scripts(compiled_script_data, scripts);
    riat_script_data_get_globals(compiled_script_data, globals);
    riat_script_data_get_nodes(compiled_script_data, nodes);
    /* Print information */
    printf("Script count: %zu\n", script_count);
    printf("Global count: %zu\n", global_count);
    printf("Node count %zu\n", node_count);
    /* Cleanup */
    CLEANUP:
    riat_error_free(&error);
    riat_compiler_free(compiler);
    riat_script_data_free(compiled_script_data);
    free(scripts);
    free(globals);
    free(nodes);
    /* Done! */
    return result;
}
C++
rustc包还包含一个C++头文件。您需要使用您选择的工具链编译riatc库,并将riatc的include目录添加到您的include列表中。
虽然您可以使用C头文件与您的C++库一起使用,但C++头文件通过std::vector等容器提供异常、类型安全和自动内存管理。
#include <riat/riat.hpp>
#include <iostream>
#include <cstdint>
#include <vector>
// Return true if successful. Return false on failure.
bool compile_scripts_cpp(const char *script_file_name, const std::vector<std::uint8_t> &script_data) {
    // Instantiate our instance
    RIAT::Compiler instance(RIATCompileTarget::RIAT_HaloCEA);
    RIAT::CompilerScriptResult result;
    // Try to compile
    try {
        instance.read_script_data(script_data.data(), script_data.size(), script_file_name);
        result = instance.compile_scripts();
    }
    catch(std::exception &e) {
        std::cerr << "Error when compiling: " << e.what() << "\n";
        return false;
    }
    // Print information
    auto scripts = result.get_scripts();
    auto globals = result.get_globals();
    auto nodes = result.get_nodes();
    std::cout << "Script count:" << scripts.size() << std::endl;
    std::cout << "Global count:" << globals.size() << std::endl;
    std::cout << "Node count:" << nodes.size() << std::endl;
    // Done!
    return true;
}
依赖项
~0.6–1.4MB
~32K SLoC