implement Into for builder-wrapped types?
Hi again,
Caveat: this ticket might just be down to me not understanding the vagaries of the From/Into
mechanics, but I think the API would be much easier to use if Into<T>
was implemented in the crate from String/str for the various builder-wrapped types.
For example, take FeatureVisibilityLevel
in the below snippet
#[derive(Debug, Clone, Builder, Serialize, Default)]
#[builder(default)]
#[builder(field(private))]
#[builder(setter(into, strip_option))]
pub struct CreateProjectParams {
/// The name of the project
#[builder(setter(skip))]
pub(crate) name: Option<String>,
/// The path of the project
#[builder(setter(skip))]
pub(crate) path: Option<String>,
/// Namespace for the new projects (defaults to current user namespaces)
namespace_id: Option<u64>,
/// `master` by default
default_branch: Option<String>,
/// Short project description
description: Option<String>,
/// One of `disabled`, `private`, `enabled`
issues_access_level: Option<FeatureVisibilityLevel>,
/// One of `disabled`, `private`, `enabled`
repository_access_level: Option<FeatureVisibilityLevel>,
/// One of `disabled`, `private`, `enabled`
merge_requests_access_level: Option<FeatureVisibilityLevel>,
/// One of `disabled`, `private`, `enabled`
builds_access_level: Option<FeatureVisibilityLevel>,
/// One of `disabled`, `private`, `enabled`
wiki_access_level: Option<FeatureVisibilityLevel>,
/// One of `disabled`, `private`, `enabled`
snippets_access_level: Option<FeatureVisibilityLevel>,
/// One of `disabled`, `private`, `enabled`, `public`
pages_access_level: Option<FeatureVisibilityLevel>,
the #[builder(setter(into, strip_option))]
makes the setter methods generic over Into<T>
. As I get it, this means that if Into<FeatureVisibilityLevel>
is implemented for strings or slices, that I can simply pass a string into the setter, rather than a variant of FeatureVisibilityLevel.
Initially, not knowing better I initially just knocked up some conversion functions like this (this for the regular VisibilityLevel
, rather than FeatureVisibilityLevel
, but the point still holds):
pub fn visibility_level_from_str(s: &str) -> Result<VisibilityLevel> {
match s {
"public" => Ok(VisibilityLevel::Public),
"internal" => Ok(VisibilityLevel::Internal),
"private" => Ok(VisibilityLevel::Private),
_ => Err(anyhow!("Incorrect visibility level"))
}
}
which then means when I call the setter function, I do this:
if args.occurrences_of("visibility") > 0 {
p.visibility(visibility_level_from_str(args.value_of("visibility").unwrap()).unwrap());
}
Having had a think about this, it would probably cleaner and more idiomatic if I had an implementation of Into<VisibilityLevel>
for Strings and slices, but, alas, I've run into the limitation of not being permitted to implement an external trait for an external type. @ben.boeckel what are your thoughts about adding this to the crate? I can attempt a PR, but I'm reticent to do anything with all the refactoring going on...
Also perhaps the enum_serialise!()
macro could be generalised to add these implementations.