Reputation: 1999
I have a trait called Describer
which has a function that accepts an array of bytes and returns a list of strings. For the sake of simplifying the codes, I want to accept both Fn(&[u8]) -> Vec<String>
and Fn(&[u8]) -> String
as a Describer
.
So, here is what I have done:
trait Describer {
fn get_parts(&self, data: &[u8]) -> Vec<String>;
}
impl Describer for dyn Fn(&[u8]) -> Vec<String> {
fn get_parts(&self, data: &[u8]) -> Vec<String> {
self(data)
}
}
impl Describer for dyn Fn(&[u8]) -> String {
fn get_parts(&self, data: &[u8]) -> Vec<String> {
vec![self(data)]
}
}
But if I use a closure (or a function pointer) in place of a Describer
, the compiler complains that the trait bounds are not satisfied. For example:
let x: Box<dyn Describer> = Box::new(|data: &[u8]| String::from("x"));
let y: Box<dyn Describer> = Box::new(|data: &[u8]| vec![String::from("y")]);
the trait bound `[[email protected]:223:38: 223:51]: Describer` is not satisfied
the following other types implement trait `Describer`:
(dyn for<'r> Fn(&'r [u8]) -> String + 'static)
(dyn for<'r> Fn(&'r [u8]) -> Vec<String> + 'static)
required for the cast from `[[email protected]:223:38: 223:51]` to the object type `dyn Describer
However, if I implement the trait for a generic that implements the closure type, it will work but then not possible to have both of the closure types because of the conflicting implementation error.
impl<F: Fn(&[u8]) -> Vec<String>> Describer for F {
fn get_parts(&self, data: &[u8]) -> Vec<String> {
self(data)
}
}
// Not working
impl<F: Fn(&[u8]) -> String> Describer for F {
fn get_parts(&self, data: &[u8]) -> Vec<String> {
self(data)
}
}
Upvotes: 1
Views: 78
Reputation: 70910
You can create a trait that both Vec<String>
and String
impl and convert them to Vec<String>
, then impl Describer
for functions with return type implementing this trait:
trait DescriberResult {
fn convert(self) -> Vec<String>;
}
impl DescriberResult for Vec<String> {
fn convert(self) -> Vec<String> { self }
}
impl DescriberResult for String {
fn convert(self) -> Vec<String> { vec![self] }
}
impl<R: DescriberResult, F: Fn(&[u8]) -> R> Describer for F {
fn get_parts(&self, data: &[u8]) -> Vec<String> {
self(data).convert()
}
}
Upvotes: 2