一次检查多个嵌套枚举中的 Some, None
Check Some, None in multiple nested enums at once
我正在寻找一种在我的项目中使用功能性事件类型机制的方法。尚未投入生产,因此甚至可以从头开始重写:
我想找两件事:
- 存在价值 (
Option<T>
)
- 不同类型的函数处理,确定性
我已经完成了后者,但我对第一个有一些问题:
对于看起来像这样的请求:
POST http://127.0.0.1:8000/publish_event HTTP/1.1
content-type: application/json
{
"source_id": "user:asdf",
"key": "temperature",
"value": 25
}
我设置了以下结构和枚举:
use std::option::{Option};
use serde::{Deserialize};
#[derive(Deserialize, Debug)]
pub struct EventPayload<T>{
pub key: String,
pub tag: Option<String>,
pub value: Option<T>
}
#[derive(Deserialize, Debug)]
#[serde(untagged)]
pub enum EventValue {
String(EventPayload<String>),
Float(EventPayload<f32>),
Int(EventPayload<i32>),
Bool(EventPayload<bool>)
}
#[derive(Deserialize, Debug)]
pub struct PublishSingleValueEventRequest {
pub source_id: String,
#[serde(flatten)]
pub manifest: EventValue
}
然后,我将 rocket 用于一个简单的端点。这是出现问题的地方:
#[macro_use] extern crate rocket;
use rocket::serde::json::Json;
use rocket::http::Status;
#[post("/publish_event", format="application/json", data="<request>")]
pub fn publish_event(request: Json<PublishSingleValueEventRequest>) -> Status {
let event = request.0;
/* This region does not compile
let evt_val: Option = match event.manifest {
EventValue::String(x) => x.value,
EventValue::Float(x) => x.value,
EventValue::Int(x) => x.value,
EventValue::Bool(x) => x.value
};
match evt_val {
Some(x) => println!("Event value: {:?}", x),
None => println!("No event value provided")
}
*/
println!("{:?}", event.manifest);
match event.manifest {
EventValue::String(x) => {
println!("String payload: {:?}", x.value);
}
EventValue::Float(x) => {
println!("Float payload: {:?}", x.value);
}
EventValue::Int(x) => {
println!("Int payload: {:?}", x.value);
}
EventValue::Bool(x) => {
println!("Bool payload: {:?}", x.value);
}
}
Status::Accepted
}
#[launch]
fn rocket() -> _ {
rocket::build().mount("/", routes![publish_event])
}
我也希望这样更像
match event.manifest.value {
Some(x) => ...,
None => ...
}
...而不是手动展开 .value
Option<>
字段。
您可以模式匹配嵌套结构:
fn main() {
let payload: EventPayload<i32> = EventPayload {
key: "foo".to_string(),
tag: None,
value: Some(10),
};
let value = EventValue::Int(payload);
match value {
EventValue::Int(EventPayload {value: Some(x), ..}) => {
println!("Some value: {}", x);
}
EventValue::String(EventPayload {value: Some(message), ..}) => {
println!("Some message: {}", message);
}
_ => {
println!("whatever");
}
}
}
这里真正的问题是:您真正想用 evt_val
做什么?如果你只想显示它,那么你可以映射到 Option<&dyn Debug>
:
let evt_val: Option::<&dyn Debug> = match event.manifest {
EventValue::String(x) => x.value.as_ref().map (|v| v as &dyn Debug),
EventValue::Float(x) => x.value.as_ref().map (|v| v as &dyn Debug),
EventValue::Int(x) => x.value.as_ref().map (|v| v as &dyn Debug),
EventValue::Bool(x) => x.value.as_ref().map (|v| v as &dyn Debug),
};
match evt_val {
Some(x) => println!("Event value: {:?}", x),
None => println!("No event value provided")
}
我正在寻找一种在我的项目中使用功能性事件类型机制的方法。尚未投入生产,因此甚至可以从头开始重写:
我想找两件事:
- 存在价值 (
Option<T>
) - 不同类型的函数处理,确定性
我已经完成了后者,但我对第一个有一些问题: 对于看起来像这样的请求:
POST http://127.0.0.1:8000/publish_event HTTP/1.1
content-type: application/json
{
"source_id": "user:asdf",
"key": "temperature",
"value": 25
}
我设置了以下结构和枚举:
use std::option::{Option};
use serde::{Deserialize};
#[derive(Deserialize, Debug)]
pub struct EventPayload<T>{
pub key: String,
pub tag: Option<String>,
pub value: Option<T>
}
#[derive(Deserialize, Debug)]
#[serde(untagged)]
pub enum EventValue {
String(EventPayload<String>),
Float(EventPayload<f32>),
Int(EventPayload<i32>),
Bool(EventPayload<bool>)
}
#[derive(Deserialize, Debug)]
pub struct PublishSingleValueEventRequest {
pub source_id: String,
#[serde(flatten)]
pub manifest: EventValue
}
然后,我将 rocket 用于一个简单的端点。这是出现问题的地方:
#[macro_use] extern crate rocket;
use rocket::serde::json::Json;
use rocket::http::Status;
#[post("/publish_event", format="application/json", data="<request>")]
pub fn publish_event(request: Json<PublishSingleValueEventRequest>) -> Status {
let event = request.0;
/* This region does not compile
let evt_val: Option = match event.manifest {
EventValue::String(x) => x.value,
EventValue::Float(x) => x.value,
EventValue::Int(x) => x.value,
EventValue::Bool(x) => x.value
};
match evt_val {
Some(x) => println!("Event value: {:?}", x),
None => println!("No event value provided")
}
*/
println!("{:?}", event.manifest);
match event.manifest {
EventValue::String(x) => {
println!("String payload: {:?}", x.value);
}
EventValue::Float(x) => {
println!("Float payload: {:?}", x.value);
}
EventValue::Int(x) => {
println!("Int payload: {:?}", x.value);
}
EventValue::Bool(x) => {
println!("Bool payload: {:?}", x.value);
}
}
Status::Accepted
}
#[launch]
fn rocket() -> _ {
rocket::build().mount("/", routes![publish_event])
}
我也希望这样更像
match event.manifest.value {
Some(x) => ...,
None => ...
}
...而不是手动展开 .value
Option<>
字段。
您可以模式匹配嵌套结构:
fn main() {
let payload: EventPayload<i32> = EventPayload {
key: "foo".to_string(),
tag: None,
value: Some(10),
};
let value = EventValue::Int(payload);
match value {
EventValue::Int(EventPayload {value: Some(x), ..}) => {
println!("Some value: {}", x);
}
EventValue::String(EventPayload {value: Some(message), ..}) => {
println!("Some message: {}", message);
}
_ => {
println!("whatever");
}
}
}
这里真正的问题是:您真正想用 evt_val
做什么?如果你只想显示它,那么你可以映射到 Option<&dyn Debug>
:
let evt_val: Option::<&dyn Debug> = match event.manifest {
EventValue::String(x) => x.value.as_ref().map (|v| v as &dyn Debug),
EventValue::Float(x) => x.value.as_ref().map (|v| v as &dyn Debug),
EventValue::Int(x) => x.value.as_ref().map (|v| v as &dyn Debug),
EventValue::Bool(x) => x.value.as_ref().map (|v| v as &dyn Debug),
};
match evt_val {
Some(x) => println!("Event value: {:?}", x),
None => println!("No event value provided")
}