#Rust Generic

7 messages · Page 1 of 1 (latest)

misty lintel
#

I have the following code

pub enum Endpoint<T> {
    CreateRoom(T),
}

async fn request_impl<T, R>(end_point: Endpoint<T>) -> Result<R, ()>
where
    R: DeserializeOwned,
{
    let resp = http::Request::get("/path").send().await.unwrap();

    resp.status() == 200;

    resp.json().await.map_err(|_| ())
}

This code works, but we can see that when calling request_impl, we need to specify the returned type at the call site in order for it work. like let resp: usize = request_impl(Endpoint::CreateRoom(request)).await.unwrap()

Is there any trick i can do to the Endpoint enum (or some generic trick) so that the response typed is tied to the request typed during function definition? so that calling the function with a CreateRoomRequest will make sure that the function return a CreateRoomResponse

exotic flame
#

It feels like it can be done with associated types, but you don't use end_point in the function so it is not clear how they are connected

#
pub enum Endpoint<T> {
    CreateRoom(T),
}

trait Connected {
    type R;
}

You could go from Endpoint<T> to R by implementing the trait above, but you want R to implement a certain trait, otherwise it just says that for any given Endpoint<T> it can return any R, and the caller wouldn't really be able to do anything with that R as it will be just a generic type with no guarantees about what it can do (if it also calls with a generic T).

#

and if it's just pure type R = T; then it's pointless as you can just return Result<T, ()> in the function instead of Result<R, ()> then

final badger
#

in context of http most likely they are different)

misty lintel
#

Thank you guys, yup, i think i probbaly need to define a wrapper function that returns the specific response for each enum (request) created

velvet breach
#

I guess the problem is that with an enum it can't tell at compile time what the response type should be, because it doesn't know what variant (request type) is going to be passed

If you want to lift it to the type level you could have the various request types be structs that you implement a trait on, that maps the request type to the appropriate response type which could then be checked at compile time

So if Endpoint were a trait instead then perhaps you'd have your function take T: Endpoint and the return type can be set to T::R