如何从Payload枚举中移除无用的单元类型变体?
解决方案
针对你的场景,有几种无需将Q和B统一为单个trait的技术可以移除负载中的单元类型:
1. 手动提取辅助函数
编写专用的辅助函数,利用单元类型的特性在编译时保证提取的安全性:
enum Payload<Q, B> { Query(Q), Body(B), } // 提取GET请求的Query负载 fn extract_query<Q>(payload: Payload<Q, ()>) -> Q { match payload { Payload::Query(query) => query, // 业务逻辑中GET请求不会走到Body分支,此处unreachable!()编译时不会触发运行时错误 Payload::Body(()) => unreachable!("GET请求的Payload不应包含Body变体"), } } // 提取POST请求的Body负载 fn extract_body<B>(payload: Payload<(), B>) -> B { match payload { Payload::Body(body) => body, Payload::Query(()) => unreachable!("POST请求的Payload不应包含Query变体"), } }
业务处理器可以直接接收目标类型:
// GET请求处理器 fn get_handler(query: Query) { // 处理逻辑 } // POST请求处理器 fn post_handler(body: Body) { // 处理逻辑 } // 调用示例 let get_payload: Payload<Query, ()> = f(...); get_handler(extract_query(get_payload)); let post_payload: Payload<(), Body> = f(...); post_handler(extract_body(post_payload));
2. 利用标准库From/Into trait实现自动转换
虽然用到了trait,但这是Rust标准库内置的,无需自定义新trait,实现成本极低:
impl<Q> From<Payload<Q, ()>> for Q { fn from(payload: Payload<Q, ()>) -> Self { match payload { Payload::Query(query) => query, Payload::Body(()) => unreachable!(), } } } impl<B> From<Payload<(), B>> for B { fn from(payload: Payload<(), B>) -> Self { match payload { Payload::Body(body) => body, Payload::Query(()) => unreachable!(), } } }
调用时可以直接用into()方法完成转换:
get_handler(get_payload.into()); post_handler(post_payload.into());
3. 宏简化提取逻辑
如果想进一步简化代码,可以编写一个宏自动处理匹配逻辑:
macro_rules! extract_payload { ($payload:expr) => { match $payload { Payload::Query(val) => val, Payload::Body(val) => val, } }; }
使用宏直接提取目标值:
get_handler(extract_payload!(get_payload)); post_handler(extract_payload!(post_payload));
以上三种方案都不需要将Q和B统一为单个trait,且能安全地移除Payload中的无用单元类型,让业务处理器的签名更简洁。
内容的提问来源于stack exchange,提问作者Incömplete
相关产品推荐
相关产品推荐

