#interactive #interactive-applications #repl #eval

nightly no-std rusteval

使您的应用程序的struct和函数可交互

2个不稳定版本

0.2.0 2022年12月1日
0.1.0 2020年10月27日

#239 in 调试

Download history 579/week @ 2024-03-13 574/week @ 2024-03-20 703/week @ 2024-03-27 715/week @ 2024-04-03 593/week @ 2024-04-10 464/week @ 2024-04-17 255/week @ 2024-04-24 198/week @ 2024-05-01 428/week @ 2024-05-08 347/week @ 2024-05-15 354/week @ 2024-05-22 903/week @ 2024-05-29 356/week @ 2024-06-05 686/week @ 2024-06-12 493/week @ 2024-06-19 506/week @ 2024-06-26

每月2,141次下载

MIT/Apache

57KB
849 代码行

rusteval

此crate提供了一些特性和宏,使您的应用程序的struct和函数可交互。

使用 #[derive(Interactive)] 注释一个struct,使用 #[Methods] 注释一个struct的方法,以及使用 #[Function] 注释一个自由函数,将实现一组特性和宏,使您可以像Rust有REPL一样访问它们。

将此crate用作“打印调试”或作为人性化的测试API的替代品。

此crate与 no_std 兼容,因此您可以使用它与嵌入式设备交互,并通过USB或UART连接闪烁LED。

使用方法

  • 使用 InteractiveMethodsFunction 注释您想访问的一切
  • 定义一个新struct,它拥有或持有您想访问的对象的引用
  • 为它推导 InteractiveRoot
  • 使用特性的方法评估一个字符串(最简单的一个是 eval_to_string 但其他还允许更定制的行为)
  • 访问字段将给出它的调试表示形式
  • 调用函数或方法将解析其参数并给出其返回值的调试表示形式

由于这个crate大量使用了Debug特质,因此提供了一个辅助宏PartialDebug。它为struct实现了Debug,用占位符替换了所有未实现Debug的字段。

CLI使用方法

提供了如get_all_field_names之类的函数。这使得实现自动完成等功能成为可能。

请参考使用rustyline crate实现的自动完成示例。

示例

use rusteval::{Interactive, Methods, InteractiveRoot, Function, PartialDebug};

#[derive(Default)]
struct NoDebug;

#[derive(Interactive, PartialDebug, Default)]
struct ChildStruct {
    last_sum: f32,
    no_debug: NoDebug,
}

#[Methods]
impl ChildStruct {
    fn add(&mut self, a: f32, b: f32) -> f32 {
        self.last_sum = a + b;
        self.last_sum
    }
}

#[derive(Interactive, Debug, Default)]
struct ParentStruct {
    child: ChildStruct,
}

#[derive(InteractiveRoot, Debug, Default)]
struct Root {
    parent: ParentStruct,
}

#[Function]
fn split_str_at(s: &str, mid: usize) -> (&str, &str) {
    s.split_at(mid)
}

let mut root = Root::default();
assert_eq!(root.eval_to_string("parent.child.add(4.2, 6.9)"), "11.1");
assert_eq!(root.eval_to_string("parent.child"), "ChildStruct { last_sum: 11.1, no_debug: Unknown }");
// split_str_at("foobar", 3) => ("foo", "bar")
assert_eq!(root.eval_to_string("split_str_at(\"foobar\", 3)"), "(\"foo\", \"bar\")");

工作原理

该crate使用了不稳定的功能specialization,因此仅在nightly版本中可用。

在所有类型上实现了如try_as_interactive之类的函数。通常情况下,该方法返回一个错误,但在特殊情况下,会返回一个特质对象(在本例中为&dyn Interactive)。

然后,宏实现了一些类似这样的getter

fn get_field<'a>(&'a self, field_name: &'a str) -> Result<'_, &dyn Interactive> {
    match field_name {
        "field1" => self.field1.try_as_interactive(),
        "field2" => self.field2.try_as_interactive(),
        _ => Err(InteractiveError::FieldNotFound {
            type_name: "Struct",
            field_name,
        }),
    }
}

请参阅宏的文档以获取更多详细信息。

当前限制

  • 只有当其参数类型受支持时,才能将方法和函数设置为交互式
  • 枚举不受支持

许可证

根据您的选择,许可协议为Apache License, Version 2.0MIT许可证
除非您明确表示,否则根据Apache-2.0许可证定义的任何有意提交以包含在此crate中的贡献,都将如上所述双重许可,而不附加任何其他条款或条件。

依赖关系

~310–770KB
~18K SLoC