#Conditionally return structs with different generic types

6 messages · Page 1 of 1 (latest)

tropic tartan
#

So i'm writing an API via poem crate, tldr, the endpoint that i wrote return different vector types based on the value type.

I'm stuck at how to shorten this further considering its just the same pattern, but points have different types based on graph_type, if i make points a common var, it's gonna only pick the 'first' types i.e DataPointRF
My code that i have ```rs
#[oai(path="/stations/:station_id/graph", method="get")]
async fn get_graph(&self, ...) -> Result<GetGraphResponse>{
...
else if start.0 == end.0{
return match graph_type.0{
GraphType::Rainfall => {
Ok(GetGraphResponse::GraphRF(Json(
GraphPoints{
start: start.0,
end: end.0,
points: vec![],
left_end_of_data: None
}
)))
},
GraphType::Waterlevel => {
Ok(GetGraphResponse::GraphWL(Json(
GraphPoints{
start: start.0,
end: end.0,
points: vec![],
left_end_of_data: None
}
)))
}
}
}

For context, this is the definition for it ```rs
#[derive(Object)]
struct GraphPoints<T>{
    start: DateTime<Utc>,
    end: DateTime<Utc>,
    left_end_of_data: Option<DateTime<Utc>>,
    points: Vec<T>
}
#[derive(ApiResponse)]
enum GetGraphResponse {
    #[oai(status = 200)]
    GraphRF(Json<GraphPoints<DataPointRF>>),
    #[oai(status = 200)]
    GraphWL(Json<GraphPoints<DataPointWL>>),
}
weary dust
#

In languages with more typesystem features than Rust, this is theoretically possible (namely, you want either let-polymorphism, to type a local variable as for<T> GraphPoints<T>, or union types, to type it as GraphPoints<GraphPointsRf | GraphPointsWL>). Rust doesn't really have that, though, so you're stuck writing this twice.

You could define a helper function, I guess

#
else if start.0 == end.0 {
  //sure would be nice if we had generic closures
  fn helper<T>(start: DateTime<Utc>, end: DateTime<Utc>) -> Json<GraphPoints<T>> {  
    GraphPoints{
      start,
      end,
      points: vec![],
      left_end_of_data: None
    }
  }
  return Ok(match graph_type.0 {
    GraphType::Rainfall => GetGraphResponse::GraphRF(helper(start.0, end.0)),
    GraphType::Waterlevel => GetGraphResponse::GraphWL(helper(start.0, end.0)),
  });
}
limber nestBOT
tropic tartan
#

i see