# rust-generic-rpc **Repository Path**: NiceBlueChai/rust-generic-rpc ## Basic Information - **Project Name**: rust-generic-rpc - **Description**: No description available - **Primary Language**: Unknown - **License**: Not specified - **Default Branch**: master - **Homepage**: None - **GVP Project**: No ## Statistics - **Stars**: 0 - **Forks**: 0 - **Created**: 2025-10-31 - **Last Updated**: 2025-10-31 ## Categories & Tags **Categories**: Uncategorized **Tags**: None ## README # Rust RPC 框架示例 这是一个基于 Rust 实现的类型安全 RPC(远程过程调用)框架示例项目。展示了如何使用 Rust 的类型系统、泛型和宏来构建灵活且类型安全的函数调用框架。 ## 📁 项目结构 ``` hello/ ├── src/ │ ├── main.rs # 原始实验代码 - 探索生命周期和反序列化 │ ├── main2.rs # 备用测试文件 │ ├── hello.rs # Hello World 示例 │ ├── main_rpc.rs # RPC 服务演示入口 │ ├── main_macro.rs # 宏生成的 Handler 演示入口 │ ├── rpc_server.rs # 手写的 RPC 服务器实现 │ └── handler_macro.rs # 使用宏自动生成的 Handler (推荐) ├── Cargo.toml └── README.md ``` ## 🎯 核心功能 ### 1. 类型安全的函数包装 项目探索了如何将普通函数包装成可以通过 JSON 参数调用的处理器,同时保持: - ✅ **编译期类型检查** - ✅ **零运行时类型转换开销** - ✅ **自动序列化/反序列化** ### 2. 生命周期处理 在 `main.rs` 中演示了处理不同生命周期参数的挑战: ```rust // ❌ 无法直接支持 &str 参数(生命周期限制) fn test1(s: &str) -> &str { s } // ✅ 使用 Cow 作为折衷方案 fn test1(s: Cow) -> Cow { s } // ✅ 或者返回拥有所有权的类型 fn test3(s: &str) -> String { format!("processed: {}", s) } ``` ### 3. 多参数支持 支持 1-9 个参数的函数,通过以下方式实现: #### 方式一:手写实现 (`rpc_server.rs`) - `Handler1` - 单参数 - `Handler2` - 双参数 - 需要为每个参数数量手写代码 #### 方式二:宏自动生成 (`handler_macro.rs`) ⭐ 推荐 - 使用 `impl_handler!` 宏自动生成 Handler1-9 - 代码简洁,易于扩展到更多参数 ## 🚀 运行示例 ### 1. 原始实验代码 ```bash cargo run --bin main ``` 展示: - `Cow` 类型的使用 - `String` 类型的处理 - `&str` 特殊处理(通过 `AStr` 结构) - 将不同处理器存储在 `Vec>` 中 ### 2. RPC 服务演示 ```bash cargo run --bin rpc ``` 展示: - 手写的 RPC 服务器 - JSON-RPC 请求/响应 - 错误处理 输出示例: ```json Request: {"method": "add", "params": "[10, 20]"} Response: {"success":true,"result":"30","error":null} Request: {"method": "greet", "params": "[\"Alice\"]"} Response: {"success":true,"result":"\"Hello, Alice!\"","error":null} ``` ### 3. 宏生成的 Handler 演示 ⭐ 推荐 ```bash cargo run --bin macro ``` 展示: - 使用宏自动生成 Handler1-9 - 支持 2-9 个参数的函数调用 - 混合类型参数(String, i32, f64, bool) 输出示例: ``` Request: {"method": "add5", "params": "[10, 20, 30, 40, 50]"} add5(10, 20, 30, 40, 50) called Response: {"success":true,"result":"150","error":null} Request: {"method": "complex", "params": "[\"Alice\", 25, 95.5, true]"} complex("Alice", 25, 95.5, true) called Response: {"success":true,"result":"\"Alice (age: 25, score: 95.5, active: true)\"","error":null} ``` ## 🔧 技术细节 ### 1. 泛型和 PhantomData 使用 `PhantomData` 来标记类型而不实际存储: ```rust struct Handler1 { f: F, name: String, _marker: PhantomData R>, } ``` ### 2. Higher-Rank Trait Bounds (HRTB) 使用 `for<'de>` 来支持任意生命周期的反序列化: ```rust where for<'de> P: Deserialize<'de> + 'static, ``` ### 3. Trait Object 使用 trait object 实现多态存储: ```rust let mut handlers: Vec> = Vec::new(); handlers.push(Box::new(Handler2::new("add", add_fn))); ``` ### 4. 声明宏(Declarative Macros) 使用 `macro_rules!` 自动生成重复代码: ```rust macro_rules! impl_handler { ($name:ident, $($param:ident),+; $($index:tt),+) => { // 自动生成 Handler 结构体和实现 }; } impl_handler!(Handler1, P1; 0); impl_handler!(Handler2, P1, P2; 0, 1); // ... 一直到 Handler9 ``` ## 📚 核心概念解析 ### 为什么不能直接使用 `&str` 参数? ```rust fn call(&self, s: &str) { let value: serde_json::Value = serde_json::from_str(s).unwrap(); let tuple: (&str,) = serde_json::from_value(value).unwrap(); // ^^^^^ 这个 &str 需要借用某个数据 // 问题:tuple.0 借用的是 value 内部的 String // 但 value 在函数结束时会被销毁 // 导致返回的 &str 成为悬垂引用! } ``` **解决方案:** 1. 使用 `Cow` - 可借用可拥有 2. 返回 `String` - 拥有所有权 3. 使用 `serde_json::Value` 配合特殊处理 ### RPC 框架的核心组件 ``` ┌─────────────┐ │ JSON 请求 │ {"method": "add", "params": "[10, 20]"} └──────┬──────┘ │ ▼ ┌─────────────┐ │ RpcServer │ 查找方法名 └──────┬──────┘ │ ▼ ┌─────────────┐ │ Handler │ 反序列化参数 └──────┬──────┘ │ ▼ ┌─────────────┐ │ 函数调用 │ add(10, 20) └──────┬──────┘ │ ▼ ┌─────────────┐ │ JSON 响应 │ {"success": true, "result": "30"} └─────────────┘ ``` ## 🎓 学习要点 1. **Rust 生命周期系统** - 理解借用检查器的限制 2. **泛型编程** - 如何写出通用且类型安全的代码 3. **宏编程** - 减少重复代码,提高可维护性 4. **Trait Object** - 运行时多态的实现 5. **零成本抽象** - 泛型在编译期展开,无运行时开销 ## 🔮 未来扩展 可以基于此框架继续扩展: - [ ] 添加 HTTP 服务器(使用 `axum` 或 `actix-web`) - [ ] 支持异步函数(`async fn`) - [ ] WebSocket 支持 - [ ] 认证和授权中间件 - [ ] 请求日志和监控 - [ ] 批量 RPC 请求 - [ ] 双向 RPC(回调) - [ ] 自动生成客户端代码 ## 📝 依赖 ```toml [dependencies] serde = { version = "1.0.215", features = ["derive"] } serde_json = "1.0.133" ``` ## 🤝 贡献 这是一个学习项目,欢迎提出改进建议! ## 📄 许可 MIT License --- **编译环境:** - Rust 1.83.0 (2024年11月发布) - Edition 2021 **关键知识点标签:** `#rust` `#rpc` `#generics` `#macros` `#serde` `#type-safety` `#lifetimes`