Rust高效数据路由库zenoh-keyexpr的使用,zenoh-keyexpr为Zenoh网络中间件提供灵活主题表达式解析与操作
Rust高效数据路由库zenoh-keyexpr的使用
警告
⚠️ 这个crate是Zenoh内部使用的。不保证API在任何版本中保持不变,包括补丁更新。强烈建议仅依赖zenoh和zenoh-ext crates,并使用它们的公共API。
安装
在项目目录中运行以下Cargo命令:
cargo add zenoh-keyexpr
或者在Cargo.toml中添加以下行:
zenoh-keyexpr = "1.5.0"
使用示例
以下是一个完整的示例,展示如何使用zenoh-keyexpr进行主题表达式解析和操作:
use zenoh_keyexpr::keyexpr;
fn main() {
// 创建keyexpr
let key = keyexpr("demo/example/test").unwrap();
// 检查keyexpr是否包含通配符
println!("Contains wildcards: {}", key.has_wildcards());
// 检查keyexpr是否包含特定前缀
println!("Starts with 'demo': {}", key.starts_with("demo").unwrap());
// 连接keyexpr
let joined = key.join("subpath").unwrap();
println!("Joined keyexpr: {}", joined);
// 检查两个keyexpr是否重叠
let other = keyexpr("demo/example/*").unwrap();
println!("Overlaps with 'demo/example/*': {}", key.overlaps(&other).unwrap());
// 检查keyexpr是否包含另一个keyexpr
println!("Includes 'demo/example': {}", key.includes(&keyexpr("demo/example").unwrap()).unwrap());
// 使用通配符匹配
let wildcard = keyexpr("demo/*/test").unwrap();
println!("Matches wildcard pattern: {}", wildcard.intersects(&key).unwrap());
}
完整示例代码
use zenoh_keyexpr::keyexpr;
fn main() {
// 示例1: 基本keyexpr创建和检查
let sensor_data = keyexpr("sensors/temperature/room1").unwrap();
println!("传感器数据路径: {}", sensor_data);
// 示例2: 通配符使用
let all_rooms = keyexpr("sensors/temperature/*").unwrap();
println!("匹配所有房间: {}", all_rooms);
println!("是否包含通配符: {}", all_rooms.has_wildcards());
// 示例3: 多级通配符
let all_sensors = keyexpr("sensors/**").unwrap();
println!("匹配所有传感器: {}", all_sensors);
// 示例4: 路径连接
let extended_path = sensor_data.join("history").unwrap();
println!("扩展后的路径: {}", extended_path);
// 示例5: 路径关系检查
println!("是否包含基础路径: {}", extended_path.includes(&sensor_data).unwrap());
// 示例6: 通配符匹配检查
let pattern = keyexpr("sensors/*/room1").unwrap();
println!("是否匹配通配符模式: {}", pattern.intersects(&sensor_data).unwrap());
// 示例7: 错误处理
match keyexpr("invalid//path") {
Ok(k) => println!("有效的keyexpr: {}", k),
Err(e) => println!("创建keyexpr失败: {}", e),
}
}
功能说明
- 主题表达式解析:zenoh-keyexpr提供了灵活的主题表达式解析能力
- 通配符支持:支持
*
和**
通配符用于模式匹配 - 关系操作:可以检查keyexpr之间的包含、重叠等关系
- 安全操作:所有操作都经过严格验证,确保表达式的有效性
注意事项
- 这个crate主要是为Zenoh内部使用设计
- 公共API可能会在没有警告的情况下更改
- 建议通过zenoh主crate来使用这些功能,而不是直接依赖这个crate
许可证
EPL-2.0 OR Apache-2.0
1 回复
Rust高效数据路由库zenoh-keyexpr
使用指南
zenoh-keyexpr
是Zenoh网络中间件中用于处理主题表达式的核心库,提供了高效灵活的主题表达式解析与操作功能。
基本概念
Zenoh使用key expression(键表达式)来标识和路由数据,类似于MQTT中的主题但功能更强大。
安装
在Cargo.toml
中添加依赖:
[dependencies]
zenoh-keyexpr = "0.7"
基本使用
创建键表达式
use zenoh_keyexpr::keyexpr;
// 创建静态键表达式(编译时检查)
let static_key = keyexpr!("demo/example");
println!("Static keyexpr: {}", static_key);
// 动态创建键表达式(运行时检查)
let dynamic_key = "demo/example".try_into().unwrap();
println!("Dynamic keyexpr: {}", dynamic_key);
键表达式操作
use zenoh_keyexpr::keyexpr;
let base = keyexpr!("demo/example");
// 连接键表达式
let joined = base.join("subtopic").unwrap();
println!("Joined: {}", joined); // 输出: demo/example/subtopic
// 检查包含关系
let parent = keyexpr!("demo/*");
println!("Does {} include {}? {}", parent, base, parent.includes(&base));
高级功能
通配符和模式匹配
use zenoh_keyexpr::keyexpr;
let pattern = keyexpr!("demo/**/sensor?");
let candidate1 = keyexpr!("demo/room1/sensor1");
let candidate2 = keyexpr!("demo/building/floor2/sensor3");
println!("Does {} match {}? {}", candidate1, pattern, pattern.matches(&candidate1));
println!("Does {} match {}? {}", candidate2, pattern, pattern.matches(&candidate2));
表达式规范化
use zenoh_keyexpr::keyexpr;
let unnormalized = keyexpr!("demo///a//b/");
let normalized = unnormalized.normalize();
println!("Normalized: {}", normalized); // 输出: demo/a/b
表达式切分
use zenoh_keyexpr::keyexpr;
let key = keyexpr!("a/b/c/d");
for chunk in key.chunks() {
println!("Chunk: {}", chunk);
}
// 输出:
// Chunk: a
// Chunk: b
// Chunk: c
// Chunk: d
与Zenoh集成
use zenoh::prelude::*;
use zenoh::config::Config;
#[async_std::main]
async fn main() {
let session = zenoh::open(Config::default()).await.unwrap();
// 发布数据
let publisher = session.publisher("demo/example").await.unwrap();
publisher.put("Hello from Rust!").await.unwrap();
// 订阅数据
let subscriber = session.subscribe("demo/*").await.unwrap();
while let Ok(sample) = subscriber.recv_async().await {
println!("Received: {} => {}", sample.key_expr, sample.value);
}
}
性能提示
- 尽可能使用
keyexpr!
宏创建静态键表达式,它在编译时完成验证 - 重用键表达式对象而不是重复创建
- 对频繁匹配的操作考虑预编译匹配模式
zenoh-keyexpr
为Zenoh提供了强大而灵活的主题表达式处理能力,是构建高效数据路由系统的关键组件。
完整示例DEMO
use zenoh::prelude::*;
use zenoh::config::Config;
use zenoh_keyexpr::keyexpr;
#[async_std::main]
async fn main() {
// 初始化Zenoh会话
let session = zenoh::open(Config::default()).await.unwrap();
// 创建静态键表达式
let pub_key = keyexpr!("demo/example");
let sub_key = keyexpr!("demo/*");
// 异步任务 - 订阅数据
let sub_task = async_std::task::spawn({
let session = session.clone();
async move {
let subscriber = session.subscribe(sub_key).await.unwrap();
println!("Subscribed to: {}", sub_key);
while let Ok(sample) = subscriber.recv_async().await {
println!("Received on {}: {}", sample.key_expr, sample.value);
}
}
});
// 发布数据
let publisher = session.publisher(pub_key).await.unwrap();
for i in 0..3 {
let msg = format!("Message {}", i);
publisher.put(msg).await.unwrap();
println!("Published to: {}", pub_key);
async_std::task::sleep(std::time::Duration::from_secs(1)).await;
}
// 等待订阅任务完成
sub_task.await;
// 关闭会话
session.close().await.unwrap();
}
这个完整示例展示了:
- 创建Zenoh会话
- 使用
keyexpr!
宏创建静态键表达式 - 异步订阅和发布消息
- 键表达式在实际通信中的应用
- 资源的正确清理
运行这个示例需要同时安装zenoh
和zenoh-keyexpr
依赖:
[dependencies]
zenoh = "0.7"
zenoh-keyexpr = "0.7"
async-std = { version = "1.9", features = ["attributes"] }