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),
    }
}

功能说明

  1. 主题表达式解析:zenoh-keyexpr提供了灵活的主题表达式解析能力
  2. 通配符支持:支持***通配符用于模式匹配
  3. 关系操作:可以检查keyexpr之间的包含、重叠等关系
  4. 安全操作:所有操作都经过严格验证,确保表达式的有效性

注意事项

  • 这个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);
    }
}

性能提示

  1. 尽可能使用keyexpr!宏创建静态键表达式,它在编译时完成验证
  2. 重用键表达式对象而不是重复创建
  3. 对频繁匹配的操作考虑预编译匹配模式

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();
}

这个完整示例展示了:

  1. 创建Zenoh会话
  2. 使用keyexpr!宏创建静态键表达式
  3. 异步订阅和发布消息
  4. 键表达式在实际通信中的应用
  5. 资源的正确清理

运行这个示例需要同时安装zenohzenoh-keyexpr依赖:

[dependencies]
zenoh = "0.7"
zenoh-keyexpr = "0.7"
async-std = { version = "1.9", features = ["attributes"] }
回到顶部