I'm relatively certain that the answer here is "You can't do that", but on the off-chance I thought I'd ask
Is there any way that I can have a function that takes arbitrary types, and if that type implements some trait then it acts slightly differently?
Actual code. This is what I'm wanting to do:
impl<O, I, D> From<Resource<I, D>> for Respondable<O>
where
O: Serialize,
Resource<I, D>: Into<O>,
{
fn from(resource: Resource<I, D>) -> Self {
let mut result = Self::new(resource.into());
// If resource implements the ResourceCacheControl trait, then use that to add a Cache-Control header to the result.
result
}
}
I tried creating a standard implementation impl<I, D> ResourceCacheControl for Resource<I, D>
, figuring that I could then create an implementation for the more specific impl ResourceCacheControl for Resource<UserId, UserData>
, but that didn't work - instead failing with "conflicting implementations of trait". (I'm not surprised that happened, but was worth a try )
I know I can just write two versions of the method - one with a generic bound that binds to + ResourceCacheControl
and one that binds to + !ResourceCacheControl
- but that doesn't scale as I add more such traits. (I want at least to have ones for ETag and Status Code as well, so that's already 9 combinations!)
The only other way I can think of is to just give the trait a default implementation and then require an empty impl ResourceCacheControl for Resource<UserId, UserData> {}
for every resource type. Which works, but isn't really ideal.
Is there some better way that this can be achieved?
Cheers