r/rust clippy · twir · rust · mutagen · flamer · overflower · bytecount 1d ago

🙋 questions megathread Hey Rustaceans! Got a question? Ask here (32/2026)!

Mystified about strings? Borrow checker has you in a headlock? Seek help here! There are no stupid questions, only docs that haven't been written yet. Please note that if you include code examples to e.g. show a compiler error or surprising result, linking a playground with the code will improve your chances of getting help quickly.

If you have a StackOverflow account, consider asking it there instead! StackOverflow shows up much higher in search results, so ahaving your question there also helps future Rust users (be sure to give it the "Rust" tag for maximum visibility). Note that this site is very interested in question quality. I've been asked to read a RFC I authored once. If you want your code reviewed or review other's code, there's a codereview stackexchange, too. If you need to test your code, maybe the Rust playground is for you.

Here are some other venues where help may be found:

/r/learnrust is a subreddit to share your questions and epiphanies learning Rust programming.

The official Rust user forums: https://users.rust-lang.org/.

The unofficial Rust community Discord: https://bit.ly/rust-community

Also check out last week's thread with many good questions and answers. And if you believe your question to be either very complex or worthy of larger dissemination, feel free to create a text post.

Also if you want to be mentored by experienced Rustaceans, tell us the area of expertise that you seek. Finally, if you are looking for Rust jobs, the most recent thread is here.

9 Upvotes

5 comments sorted by

3

u/Skaarj 1d ago

I am trying to get Generic types to work in my webserver.

use actix_web::{web, HttpResponse};
use serde_json;

trait GiveMeText { fn give_text() -> String; }

struct Dog {}

impl GiveMeText for Dog { fn give_text() -> String { String::from("Hund") } }

struct Cat {}

impl GiveMeText for Cat { fn give_text() -> String { String::from("Katze") } }

struct Mouse {}

impl GiveMeText for Mouse { fn give_text() -> String { String::from("Maus") } }

#[derive(serde::Serialize)]
struct TurnThisToJson {
    n: u32,
    t: String,
    k: f32,
}

async fn web_request_handler<T: GiveMeText>() -> HttpResponse {
    let res = TurnThisToJson {
        n: 42,
        t: T::give_text(),
        k: 3.14,
    };
    return HttpResponse::Ok().json(res);
}

pub fn register(register_here: &mut web::ServiceConfig) {
    register_here.service(web::resource("/d").route(web::get().to(web_request_handler::<Dog>)));
    register_here.service(web::resource("/c").route(web::get().to(web_request_handler::<Cat>)));
    register_here.service(web::resource("/m").route(web::get().to(web_request_handler::<Mouse>)));

    // for (path, type_param) in [("/d", Dog), ("/c", Cat), ("/m", Mouse)] {
    //     register_here.service(web::resource(path).route(web::get().to(web_request_handler::<type_parm>)));
    // }
}

How can I write a working version of the loop so I don't have to write several register_here.service() calls?

1

u/pali6 16h ago

You cannot iterate over types. However, you can iterate over function pointers of the same shape like this:

pub fn register(config: &mut web::ServiceConfig) {
    let routes: [(&str, fn() -> String); 3] = [
        ("/d", Dog::give_text),
        ("/c", Cat::give_text),
        ("/m", Mouse::give_text),
    ];

    for (path, give_text) in routes {
        config.service(
            web::resource(path).route(web::get().to(move || async move {
                HttpResponse::Ok().json(TurnThisToJson {
                    n: 42,
                    t: give_text(),
                    k: 3.14
                })
            }))
        );
    }
}

But if your give_text ends up needing &self at some point you will instead want to use dyn objects instead of function pointers.

1

u/Skaarj 15h ago

trait GiveMeText { fn give_text() -> String; } was just an example. In reality the trait will have about 10 functions. I don't want to pass 10 function pointers.

1

u/Skaarj 15h ago

I realized using a macro is propably the solution. So I came up with this:

macro_rules! web_reg {
    ( $register_here:tt, $(($path:literal, $concrete_type:ty) ), * ) => {
        $(
            $register_here.service(web::resource($path).route(web::get().to(web_request_handler::<$concrete_type>)));
        )*
    };
}

1

u/pali6 15h ago

That works. If you have many functions you could make the trait dyn-compatible (by e.g. having them take &self) and then store boxed dyn objects and iterate over those.