rwf2 / Rocket

A web framework for Rust.
https://rocket.rs
Other
24.5k stars 1.57k forks source link

Allow from form macro to work on structs with range #2736

Closed RuboGubo closed 8 months ago

RuboGubo commented 8 months ago

What's missing?

An implementation of FromFormRow for Range< T > where T: FromFormRow

Ideal Solution

Implement it, orphan types prevent it from being implemented elsewhere

Why can't this be implemented outside of Rocket?

Orphan rules

Are there workarounds usable today?

no

Alternative Solutions

n/a

Additional Context

n/a

System Checks

SergioBenitez commented 8 months ago

What is FromFormRow?

And if you mean FromForm, then what implementation semantics are you proposing for Range<T>? Please provide examples of HTML or HTTP corresponding to a form that you'd like to see parsed as a Range<T> and specify how that parse might work.

SergioBenitez commented 8 months ago

Closing due to lack of response.

RuboGubo commented 7 months ago

Hi, I'm back, I had to temporarily step away from Foss, but i'm back and happy to respond.

In terms of what you said: I ment FromFormField, which would not work anyway as Range<T> would most likely have to be implemented over two fields. In terms of what it should look like in a form, you would most likely have two fields in the form <range_var_name>.start and <range_var_name>.end. I chose those names as that is what the Range<T> type uses internally.

Example HTML Rendered: grafik

Example HTML Source:

<form class="Search" id="PrimeNumberSearch" action="{{https_url_for(request, 'SearchPrimeResult')}}" target="PrimeNumberSearchIF">
    <input type="number" name="prime_range.start" placeholder="min prime">
    <input type="number" name="prime_range.end" placeholder="max prime">
    <button class="submit" type="submit">→</button>
</form>

Example Rocket Function:

#[derive(Debug, FromForm)]
struct FormData {
    prime_range: Range<i64>,
}

#[get("/prime", data="<form>")]
async fn get_prime_form(db: &PrimeDB, form: Form<FormData>) -> Result<Json<Vec<i64>>, Status> {
    Ok(Json(get_primes(db, form.into_inner().prime_range).await?))
}

And it would of course also work outside of a struct:

#[get("/prime", data="<form>")]
async fn get_prime_form(db: &PrimeDB, form: Form<Range<i64>>) -> Result<Json<Vec<i64>>, Status> {
    Ok(Json(get_primes(db, form.into_inner()).await?))
}
<form class="Search" id="PrimeNumberSearch" action="{{https_url_for(request, 'SearchPrimeResult')}}" target="PrimeNumberSearchIF">
    <input type="number" name="start" placeholder="min prime">
    <input type="number" name="end" placeholder="max prime">
    <button class="submit" type="submit">→</button>
</form>
RuboGubo commented 7 months ago

I should point out that there are a whole family of ranges in std::ops see https://doc.rust-lang.org/std/ops/index. Unbounded ranges should work, by just parsing their corresponding start or end fields