@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.
@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 inHashMap
returnsOption<&Value>
and theparse
method returnsResult<T, T::Err>
, which means that we have to combine these in a good way. Turning theResult<T, T::Err>
into anOption<T>
forces us to throw away the error, which may or may not be ok. ReturningOption<Result<T, T::Err>>
orResult<Option<T>, T::Err>
would somewhat defeat the purpose of all this. I'm therefore leaning towards returningResult<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 likeOption
may be clear enough in this case.I'm imagining something like this:
parse_or
andparse_or_else
would be the same as callingunwrap_or
andunwrap_or_else
on the result fromparse
, but may still be added while we are at it.