I have some hierarchy of traits and i need to adapt both structs and flatbuffers table to be used via the trait as follows:
// trait
pub trait TFilter : Clone {
fn get_text(&self) -> &str;
}
// structure
#[derive(Clone)]
pub struct FilterStruct {
pub text: String
}
impl TFilter for FilterStruct {
fn get_text(&self) -> &str {
&self.text
}
}
impl TFilter for FilterTable<'_> {
fn get_text(&self) -> &str {
self.text()
}
}
flatbuffers schema (IDL):
table FilterTable {
text: string (required);
}
It works fine with the following usage:
pub fn accept_filter(filter: &dyn TFilter) {
println!("{}", filter.get_text());
}
accept_filter(&FilterStruct {
text: "hello".to_owned()
});
The problem happens when i inheritance is introduced: a new trait that extends the base trait:
pub trait TActiveFilter {
fn get_filter(&self) -> Cow<dyn TFilter>;
fn get_title(&self) -> &str;
}
a new structure that extends the base struct ("extend by containing"):
#[derive(Clone)]
pub struct ActiveFilterStruct {
pub filter: FilterStruct,
pub title: String
}
impl TActiveFilter for ActiveFilterStruct {
fn get_filter(&self) -> Cow<dyn TFilter> {
Cow::Borrowed(&self.filter)
}
fn get_title(&self) -> &str {
&self.title
}
}
and a new flatbuffers table that extends the base table:
table ActiveFilterTable {
filter: FilterTable (required);
title: string (required);
}
impl TActiveFilter for ActiveFilterTable<'_> {
fn get_filter(&self) -> Cow<dyn TFilter> {
Cow::Owned(self.filter())
}
fn get_title(&self) -> &str {
self.title()
}
}
The actual problem is that flatbuffer's generated Rust file returns instances (not references) and one has to own it, so using the Cow (struct already own and returns the reference but flatbuffer's impl has to own the result).
However with Cow i get the following:
error[E0038]: the trait `TFilter` cannot be made into an object
--> src/wrapper.rs:76:30
|
76 | pub fn accept_filter(filter: Cow<dyn TFilter>) {
| ^^^^^^^^^^^^^^^^ `TFilter` cannot be made into an object
|
note: for a trait to be "object safe" it needs to allow building a vtable to allow the call to be resolvable dynamically; for more information visit <https://doc.rust-lang.org/reference/items/traits.html#object-safety>
--> src/wrapper.rs:5:21
|
5 | pub trait TFilter : Clone {
| ------- ^^^^^ ...because it requires `Self: Sized`
| |
| this trait cannot be made into an object...
What exactly must be made?