Hi everyone,
Recently I started planning to write a program that can drive a SSD1306 (a simple I2C OLED display) to display my single board computer's stats. I searched GitHub and found embedded-graphics (available on crates). It worked really well by itself, but when I'm trying to make some more abstractions based on it, I met a problem.
Because I'm using a SBC instead of a microcontroller, resource is not that limited and re-allocation is possible and acceptable. My goal is to create something like a "rendering query" so that I can separate the the part that draws the widgets from the part that do the rendering and actual displaying. In order to do that, I tried to create a vector of trait objects of the Drawable
trait by doing something like this:
struct WidgetsBundle<C> {
widget: Vec<Box<dyn Drawable<C>>>,
}
It failed with E0038 and Ferris says it is because the trait Drawable
itself has a type parameter.
pub trait Drawable<C>
where
C: PixelColor,
{
fn draw<D: DrawTarget<C>>(self, display: &mut D) -> Result<(), D::Error>;
}
(The original declaration of the Drawable
trait)
I tried to workaround that by implementing another trait that does not have the type parameter because in my use case there is only one certain type of display
.
pub type Display = GraphicsMode<I2cInterface<I2cdev>>; // From some other libraries
pub trait Widget {
fn draw(self, display: &mut Display);
}
But when I failed at trying to implementing Widget
to Drawable
, and I did not find many information about how to solve this.
I wrote a mock code for the situation I'm facing on Rust Playground:
// For my usage, I want to store data that has implemented the ForeignTrait.
// So at the beginning, I used Box<dyn ForeignTrait<Y>> and got E0038,
// because ForeignTrait<Y> has a type parameter Y.
//
// In order to solve that, I wrote my own trait(MyTrait, l. 37),
// because I'm only going to use MyType(l.22) and it had already implemented
// ForeignTrait(l. 29 and all the other required traits).
//
// Problem (either one of them):
// 1. Is it possible to create a trait object for ForeignTrait.
// 2. If 1 cannot be accomplished, is there anyway to implement MyTrait for
// ForeignTrait.
trait WhateverTrait<Y> {
// Just a dummy trait
}
trait YetAnotherTrait {
// This trait does not matter
}
struct MyType;
// My type already implemented both traits
impl<Y> WhateverTrait<Y> for MyType {}
impl YetAnotherTrait for MyType {}
// This trait is from a library that I cannot alter
trait ForeignTrait<Y>
where
Y: YetAnotherTrait,
{
fn foreign_function<W: WhateverTrait<Y>>(self, whatever: &mut W);
}
// Replaced WhateverTrait<W> with MyType since I'll only be using MyType.
trait MyTrait {
fn foreign_function(self, whatever: &mut MyType);
}
// Trying to make ForeignTrait a trait object (E0038).
// use std::vec::Vec;
// struct MyGoal<Y>
// where
// Y: YetAnotherTrait,
// {
// inner: Vec<Box<dyn ForeignTrait<Y>>>,
// }
// My attemps to impl MyTrait for ForeignTrait
// 1st attemp (E0109, E0107).
// impl<Y, F> MyTrait for F<Y>
// where
// Y: YetAnotherTrait,
// F: ForeignTrait,
// {
// fn foreign_function(self, whatever: &mut MyType) {
// ()
// }
// }
// 2nd attemp (E0207).
// impl<Y, F> MyTrait for F
// where
// Y: YetAnotherTrait,
// F: ForeignTrait<Y>,
// {
// fn foreign_function(self, whatever: &mut MyType) {
// ()
// }
// }
// 3rd attemp (E0038).
// impl<Y> MyTrait for dyn ForeignTrait<Y>
// where
// Y: YetAnotherTrait,
// {
// fn foreign_function(self, whatever: &mut MyType) {
// ()
// }
// }
fn main() {
println!("Hello, world!");
}
Is there anyway to accomplish the "render query"-like abstraction I would like to make? I'm worrying about am I thinking it wrong.
Thanks everyone for reading this.