Ogeon / rustful

[OUTDATED] A light HTTP framework for Rust
https://docs.rs/rustful
Apache License 2.0
862 stars 51 forks source link

Add parsing shortcuts for things like path variables #55

Closed Ogeon closed 9 years ago

Ogeon commented 9 years ago

@tmmcguire mentioned on reddit that it would be nice to have a quick way to parse values from query and path parameters. I think it sounds like a good idea, since it's not too uncommon to expect these values to be, for example, numbers or other non-text data. The question is how this should be implemented. As a wrapper around HashMap? As a trait? What should be returned?

The good thing with wrappers is that they would not need to be imported, but the annoying part is that they has to be "unwrapped" if we want to get the internals. I'm not sure that this is that big of a problem in this case. A trait, on the other hand, would only add methods and not affect the API in any other way, but it would have to be imported to be used.

The get method in HashMap returns Option<&Value> and the parse method returns Result<T, T::Err>, which means that we have to combine these in a good way. Turning the Result<T, T::Err> into an Option<T> forces us to throw away the error, which may or may not be ok. Returning Option<Result<T, T::Err>> or Result<Option<T>, T::Err> would somewhat defeat the purpose of all this. I'm therefore leaning towards returning Result<T, Option<T::Err>>, which allows quick unwrapping and still provides an error. An alternative would be to create a custom error type, but I feel like Option may be clear enough in this case.

I'm imagining something like this:

//The name was pulled out of thin air
//Implements Deref, DerefMut and Into<HashMap<String, String>>
struct Parameters(HashMap<String, String>);

impl Parameters {
    fn parse<K: ..., V: FromStr>(key: K) -> Result<V, Option<V::Err>> {
        ...
    }

    //These may be added for convenience:
    fn parse_or<K: ..., V: FromStr>(key: K, or: V) -> V {
        ...
    }

    fn parse_or_else<K: ..., V: FromStr, F: Fn(Option<V::Err>) -> V>(key: K, or_else: F) -> V {
        ...
    }
}

parse_or and parse_or_else would be the same as calling unwrap_or and unwrap_or_else on the result from parse, but may still be added while we are at it.

Ogeon commented 9 years ago

I decided to prototype this idea in #56.