1

我正在寻找一种在我的项目中使用功能性事件类型机制的方法。还没有任何东西在生产中,所以甚至可以从头开始重写:

我想找两件事:

  • 存在价值 ( 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
    }

然后,我将火箭用于一个简单的端点。这是出现问题的地方:

#[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<>字段。

4

2 回答 2

3

这里真正的问题是:你真正想要做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")
}
于 2021-09-29T07:40:46.910 回答
2

您可以模式匹配嵌套结构:

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

操场

于 2021-09-29T07:34:39.940 回答