I'm confused about how to use Rust's trait objects. I have a lot of vague partial-understandings but in the end I don't understand the error I'm getting.
I am trying to implement the Command Pattern in rust in order to move a cursor around a terminal. I have it set up to send trait objects that implement a Command trait, and have the Command trait generically typed. Can I not make this trait generic?
Here's an example-ified version of my code:
pub trait Command<T> {
fn execute(&self, target_instance: &mut T);
}
pub trait Commandable<T> {
fn send(&mut self, cmd: Box<impl Command<T>>);
}
//-------------------------------------------------------
struct Cursor {
pos: (isize, isize),
}
impl Cursor {
fn move_me(&mut self, direction: (isize, isize)) {
self.pos.0 += direction.0;
self.pos.1 += direction.1;
}
}
impl Commandable<Cursor> for Cursor {
fn send(&mut self, cmd: Box<impl Command<Cursor>>) {
cmd.execute(self);
}
}
struct MoveCommand {
move_direction: (isize, isize),
}
impl MoveCommand {
pub fn new(move_direction: (isize, isize)) -> Self {
MoveCommand { move_direction }
}
}
impl Command<Cursor> for MoveCommand {
fn execute(&self, cursor: &mut Cursor) {
cursor.move_me(self.move_direction);
}
}
//------------------------------------------------------
fn handle_input(input: Option<&str>, target: &mut impl Commandable<Cursor>) {
let mut cmd: Option<Box<dyn Command<Cursor>>> = None;
if let Some(key) = input {
match key {
"K" => cmd = Some(Box::new(MoveCommand::new( (0, -1) ))),
"J" => cmd = Some(Box::new(MoveCommand::new( (0, 1) ))),
"H" => cmd = Some(Box::new(MoveCommand::new( (-1, 0) ))),
"L" => cmd = Some(Box::new(MoveCommand::new( (1, 0) ))),
_ => {}
}
}
if let Some(boxed_cmd) = cmd {
target.send(boxed_cmd); // <-----------------ERROR IS HERE
}
}
fn main() {
let mut cursor = Cursor { pos: (0, 0) };
handle_input(Some("K"), &mut cursor);
}
Here's the error:
error[E0277]: the size for values of type `dyn Command<Cursor>` cannot be known at compilation time
--> src/main.rs:54:21
|
54 | target.send(boxed_cmd);
| ^^^^^^^^^ doesn't have a size known at compile-time
|
= help: the trait `Sized` is not implemented for `dyn Command<Cursor>`