Hello there! I've got a quandary that I find a bit hard to wrap my head around.
Basically, I'm trying to build a collection of transformer functions that inherit a Transform trait, e.g
enum TargetContent {
None,
BinArray(Vec<u8>),
String(String),
}
struct TargetDescriptor<Content> {
pub content: Content,
}
type CompositeTargetDescriptor = TargetDescriptor<TargetContent>;
trait Transformer {
fn transform(&self, transform_target: CompositeTargetDescriptor) -> Result<CompositeTargetDescriptor, Error>;
}
struct TransformerContainer {
pub transformers: Vec<Box<dyn Transformer>>,
}
impl TransformerContainer {
pub fn transform(&self, mut transform_target: CompositeTargetDescriptor) -> Result<CompositeTargetDescriptor, Error> {
for transformer in &self.transformers {
transform_target = transformer.transform(transform_target)?;
}
}
}
This works as intended but I can't drop the feeling that there's a better way of doing this. Currently all the transformers that inherit the Transformer trait need to convert the CompositeTargetDescriptor
into the generic TargetDescriptor<Content>
which I do by using a series of From
implementations e.g
impl Transformer for SomeTransformer {
fn transform(&self, transform_target: CompositeTargetDescriptor) -> Result<CompositeTargetDescriptor, Error> {
// Transform into the generic type here
let mut target_descriptor: TargetDescriptor<String> = transform_target.into();
// Do some transformations of the content here
target_descriptor.content = "Scrappy".into_string();
// Transform back into a composite descriptor
Ok(target_descriptor.into())
}
}
I'd much rather be able to implement a transformer struct that can specify a generic type so I don't have to do all the manual into's, something like:
impl Transformer for SomeTransformer {
// TargetDescriptor implements the From<CompositeTargetDescriptor>
fn transform(&self, target_descriptor: TargetDescriptor<String>) -> Result<Into<CompositeTargetDescriptor>, Error> {
target_descriptor.content = "Scrappy".into_string();
Ok(target_descriptor)
}
}
This doesn't work well with having a transformer container as it requires the size to be known at compile-time, and this does not seem to work:
trait Transformer {
fn transform(&self, transform_target: From<CompositeTargetDescriptor>) -> Into<CompositeTargetDescriptor, Error>;
}
struct TransformerContainer {
pub transformers: Vec<Box<dyn Transformer>>,
}
as I get the error
the trait `std::convert::From` cannot be made into an object
`std::convert::From` cannot be made into an object
note: the trait cannot be made into an object because it requires `Self: Sized`
So yeah, I'm not sure if there's any better way of implementing this, I'm happy with the current implementation as it seems to work fine, but would be glad to know of any other way of implementing this in a nicer way as I feel like I've exhausted my (very limited) knowledge in Rust, and probably programming in general.
Thanks in advance!