Convert a vector of structs with type X to a vector of structs with type Y

I have two structs.

DishVariation

#[derive(Deserialize, Serialize, Clone)]
pub struct DishVariation {
    id: u64,
    variation: String,
    price: f32,
}

DishVariationJson

#[derive(Deserialize)]
pub struct DishVariationJson {
    pub variation_name: String,
    pub variation_price: f32,
}

The latter is used to easily receive input over HTTP. DishVariation is the full complicated struct with implementations.

When I receive a vector of DishVariationJson I need to convert it to a vector of DishVariation. So I can actually use the received data.

This code works:

let dish_variations: std::vec::Vec<DishVariation> = std::vec::Vec::new();
    for dish_variation_json in data.dish_variations {
        dish_variations.push(DishVariation {
            id: 0,
            variation: dish_variation_json.variation_name,
            price: dish_variation_json.variation_price,
        });
    }

(data.dish_variations has type std::vec::Vec<DishVariationJson).

But I was wondering if there is a more elegant approach. I tried to use iter and map to convert to the correct struct-type on-the-go but I am stuck.

let dish_variations : std::vec::Vec<DishVariation> = data.dish_variations.iter().map(|x| {

    })

I should be able to do something like this:

let dish_variations: std::vec::Vec<DishVariation> = data.dish_variations.iter().map(|x| {
        push(DishVariation {
            id: 0,
            variation: x.variation_name,
            price: x.variation_price,
        })
    });

Is this possible?

If you want to consume the dish_variations during conversion (as you did with for loop), this should be into_iter().

1 Like

And how do I finally push it to the vector?

You "collect" the iteration operations with .collect

Won't .collect() just give me a vector of futures which also are not executed?

I tried this:

dish.variations
                .into_iter()
                .map(|v| async { add_dish_variation(dish.id, &v, &mysql).await })
                .collect();

which yields the error

type annotations needed cannot satisfy `_: FromIterator<impl futures::Future<Output = bool>>`

I don't really know what type to give to the .collect() function. Because I just want to execute it. I tried

dish.variations
                .into_iter()
                .map(|v| async { add_dish_variation(dish.id, &v, &mysql).await })
                .collect::<std::vec::Vec<DishVariation>>();

yielding

a value of type `Vec<DishVariation>` cannot be built from an iterator over elements of type `impl futures::Future<Output = bool>` the trait `FromIterator<impl futures::Future<Output = bool>>` is not implemented for `Vec<DishVariation>`

Thanks for your help by the way.

Yes. Then you can use a cominator such as FuturesUnordered to await them.

1 Like