tynavi
tynavi(全称 Type Navigator)是一个面向深层数据导航场景的 Rust Selector 模式库。
它从 onebot-api 的 selector 设计中演化而来,但在这里被拆成了更通用的独立实现:支持不可变链式调用、父节点回溯、标准库容器扩展,以及可选的 derive / attribute 宏自动生成能力。
当前状态
- 当前 crate 版本:
0.1.2 - Rust edition:
2024 - 最低工具链要求:
>= 1.85 - 主 crate 默认启用
fullfeature default-features = false时可退回仅标准库核心能力
需要特别注意的是:
- 核心 Selector API 本身不依赖第三方运行时库
- 但仓库当前已经包含可选生态扩展依赖与
tynavi-macros过程宏子 crate - 因为默认 feature 是
full,直接引入tynavi时并不是“默认零依赖扩展面”
如果你想只使用最小核心能力,建议这样声明:
[]
= { = "0.1.2", = false }
核心设计
核心类型:
Current:当前游标指向的类型Parent:父节点快照类型cursor: Option<&'a Current>:当前是否匹配
与 onebot-api 早期可变 Selector 不同,tynavi 采用不可变快照语义:
- 过滤方法返回新的
Self - 路由方法返回
Selector<'a, Child, Self> - 父节点快照可通过
backtrack()/up()安全返回
这使它很适合表达一类固定问题:
- 从嵌套结构中持续下钻
- 在链路中逐步过滤
- 某一步失败后自动进入未匹配态
- 需要在深入检查后回到上层上下文继续处理
快速开始
use ;
let user = User ;
let city = user
.as_selector
.route_to
.route_to
.starts_with
.extract;
assert_eq!;
let adult = user
.as_selector
.route_to
.route_to
.ge
.is_matched;
assert!;
父节点回溯
let profile = user.as_selector.route_to;
let city = profile
.route_to
.contains;
assert!;
assert!;
assert!;
backtrack():直接返回父节点快照up():返回父节点,并在当前未匹配时把未匹配状态向上传递
已实现的核心 API
通用构造 / 路由 / 处理
newwithsame_parentroute_toreplacemapselectextract/cond_extractextract_async/cond_extract_asyncinspect/inspect_cursorfilter/cond_filterfilter_async/cond_filter_asyncrequire_matchedparentbacktrackupor_a_parent_a/or_a_parent_b/or_b_parent_a/or_b_parent_b
标准库类型扩展
当前已内置以下常见类型支持:
- 数值类型:
i8i16i32i64i128isizeu8u16u32u64u128usizef32f64 - 字符串类型:
&str、str、String - 容器与指针:
Option<T>、Result<T, E>、HashMap<K, V>、&[T]、Box<T>、Rc<T>、Arc<T>
其中已实现的典型能力包括:
- 数值比较:
eq、not_eq、gt、lt、ge、le及其cond_* - 字符串过滤:
starts_with、ends_with、contains、contains_char、empty - 切片导航:
first、last、indexof、find、any、all、none HashMap导航:keyof、find_key、find、contains_key、contains_valueOption路由:flattenResult路由:ok、err- 智能指针解引用:
as_ref
生态扩展
当前通过 feature 提供以下扩展:
httpaxumtungsteniteserde_jsonreqwestderive
full 会一次性启用:
[ "serde_json", "tungstenite", "http", "axum", "reqwest"]
如果只想启用某一类扩展,可以关闭默认 feature 再手动选择:
[]
= { = "0.1.2", = false, = ["reqwest"] }
reqwest 示例
use Response as HttpResponse;
use ;
use AsSelector;
let mut req = new;
req.headers_mut.insert;
*req.body_mut = Some;
assert!;
assert!;
let res = from;
assert!;
assert!;
serde_json 示例
use json;
use AsSelector;
let value = json!;
assert!;
宏支持
仓库当前已经提供 tynavi-macros 子 crate,并通过主 crate 的 derive feature 暴露两类宏:
#[derive(Selector)]#[selector]
它们适合把结构体 / 枚举上的手写导航方法批量生成出来,尤其适用于事件模型或较大的领域对象。
[]
= { = "0.1.2", = false, = ["derive"] }
使用示例:
use ;
use AsSelector;
let event = Message;
assert!;
更完整的宏说明见 macros/docs/selector.md。
与 onebot-api Selector 的差异
| 特性 | onebot-api 旧版 selector | tynavi |
|---|---|---|
| 类型签名 | Selector<'a, T> |
Selector<'a, Current, Parent> |
| 可变性 | &mut self 风格 |
不可变快照,过滤返回 Self |
| 父节点追踪 | 无 | 有,支持 backtrack() / up() |
| 生成方式 | 主要依赖宏生成 | 可手写扩展,也支持 derive / selector 宏 |
| 适用范围 | onebot-api 事件模型 | 任意 Rust 类型与若干生态对象 |
构建与测试
项目使用 .rustfmt.toml,采用硬制表符格式。