I'm trying to wrap my head around Rust's generics. I'm writing something to extract HTML from different web sites. What I want is something like this:
trait CanGetTitle {
fn get_title(&self) -> String;
}
struct Spider<T: CanGetTitle> {
pub parser: T
}
struct GoogleParser;
impl CanGetTitle for GoogleParser {
fn get_title(&self) -> String {
"title from H1".to_string().clone()
}
}
struct YahooParser;
impl CanGetTitle for YahooParser {
fn get_title(&self) -> String {
"title from H2".to_string().clone()
}
}
enum SiteName {
Google,
Yahoo,
}
impl SiteName {
fn from_url(url: &str) -> SiteName {
SiteName::Google
}
}
fn main() {
let url = "http://www.google.com";
let site_name = SiteName::from_url(&url);
let spider: Spider<_> = match site_name {
Google => Spider { parser: GoogleParser },
Yahoo => Spider { parser: YahooParser }
};
spider.parser.get_title(); // fails
}
I'm getting an error about the match
returning Spider
s parameterised over two different types. It expects it to return Spider<GoogleParser>
because that's the return type of the first arm of the pattern match.
How can I declare that spider
should be any Spider<T: CanGetTitle>
?
You cannot. Simply put, the compiler would have no idea how much space to allocate to store
spider
on the stack.Instead, you will want to use a trait object:
Box<CanGetTitle>
: