3 个版本

0.1.2 2023 年 7 月 16 日
0.1.1 2023 年 7 月 10 日
0.1.0 2023 年 7 月 10 日

#711 in 开发工具

MIT 许可证

9KB
127

hot_potato:热重载你的 Rust 代码

Github crates.io License Stars GitHub repo size Lines of code

此包允许你在开发过程中动态重载函数体和修改魔法值,从而实现快速更改而无需整个重启和导航到当前可交互项。

请注意,这仅在您的开发环境中有效 - 而不是在已发布的构建中!

强烈建议将所有土豆代码从发布构建中删除!此包旨在方便设计和开发,不适合在已部署的构建中使用。

目录

快速入门

(请参阅test_project以获取基本实现)

  1. hot_potato 添加到您的项目中
cargo add hot_potato
  1. 创建您想要热重载的函数,并使用 potato 进行注释
use hot_potato::potato;

/// t: time [0.0;1.0]
#[potato]
fn interpolate(t: f32) -> f32 {
    // linear interpolation for now
    t
}
  1. 在启动时加载函数
use hot_potato::build_and_reload_potatoes;

fn main() {
    build_and_reload_potatoes().expect("error loading potatoes");
    ...
}
  1. 创建一个重载触发器(热键、UI 小部件或输入等)
fn main() {
    // some quick and dirty loop
    loop {
        // make sure this is called at least once before any potato func is called!
        build_and_reload_potatoes().expect("error loading potatoes");

        for i in 0..=5 {
            let t = i as f32 / 5.0;
            println!("{t} -> {}", interpolate(t));
        }

        println!("Press enter to hot-reload");
        // just waits for input and then starts the loop anew...
        std::io::stdin().read_line(&mut String::new()).unwrap();
    }
}
  1. 在您的 Cargo.toml 中配置 lib 目标
[lib]
path = "src/main.rs"
crate-type = ["cdylib"]

[[bin]]
name = "test_project"
path = "src/main.rs"

lib 目标用于热重载,而 bin 目标是您的默认运行编译目标。

  1. 使用 cargo run 运行

尝试编辑插值函数并触发重载

/// t: time [0.0;1.0]
#[potato]
fn interpolate(t: f32) -> f32 {
    // quadratic
    t * t
}
/// t: time [0.0;1.0]
#[potato]
fn interpolate(t: f32) -> f32 {
    // ease in-out
    x * x * (3.0 - 2.0 * x)
}

魔法值调整

在这种情况下,我们想要显示一个具有特定颜色的窗口小部件,但我们并不完全满意。

请注意,您仍然需要一个初始的 build_and_reload_potatoes,但在值调整后不需要这样的重载。

伪代码,请参阅test_project以获取一些真实代码

// We are not quite happy with our color... 
// Instead of starting the whole app anew every time we change it slightly,
// or having to change our code in a way that we pass around those values
// and having to change that back later, we can just glue those magic parameters to 
// that function and change them from anywhere
#[potato(r: u8 = 0xFF, g: u8 = 0x00, b: u8 = 0xFF)]
fn show_colored_thing(text: &str, ui: &mut UIContext) -> f32 {
    let mut widget = Widget::new();
    widget.title = Some(text);
    widget.bg_color = Color::from_rgba(r, g, b, 0xFF);
    ui.popup(widget);
}

// Somewhere in an debug ui handler that has an "apply&test" button.
// Also lets just pretend we have 3 debug ui sliders for rgb.
fn on_click_apply(red: Slider, green: Slider, blue: Slider, ui: &mut UIContext) {
    show_colored_thing.set::<u8>("r", (red.get_slider_value() * 255.0) as u8);
    show_colored_thing.set::<u8>("g", (green.get_slider_value() * 255.0) as u8);
    show_colored_thing.set::<u8>("b", (blue.get_slider_value() * 255.0) as u8);
}

// Somewhere we also have an "open popup" button
fn on_click_open(ui: &mut UIContext) {
    show_colored_thing("Test RGB popup", ui);
}

功能

它能做什么

  • 几乎可以热重载任何函数体
  • 快速调整魔法值

它不能做什么

  • 热重载函数签名更改或任意代码
  • 热重载特质方法或泛型
  • 给你做三明治

警告:函数签名更改和类似的随意操作将导致未定义的行为,很可能是 STATUS_ACCESS_VIOLATION 或类似的崩溃。

依赖项

~1–6.5MB
~34K SLoC