Hello! I am trying to write library that can easely implement some design patterns.
It's shall work using iterators:
let mut cc = CommandChain::new();
cc.add_command(
UserCommand::new()
);
cc.add_command(
MailCommand::new()
);
for command in cc.iter() {
cc.on_command("one1", &["Toto", "users"]);
cc.on_command("one2", &["Toto", "users"]);
}
let t1 = thread::spawn(move||{
for command in cc.iter() {
cc.on_command("mutli1", &["Toto", "users"]);
}
});
t1.join();
I wrote prototype for this code that is not working.
https://play.rust-lang.org/?gist=4dc3ece1145105b388b7&version=stable
I am thinking that my code may be valid.
Questions:
- Is there borrow checker problem or my code just invalid?
- It is possible to fix problem?
use std::thread;
//extern crate core;
trait Command {
fn on_command(&self, name: &str, args: &[&str]);
}
struct CommandChain<'a> {
commands: Vec<Box< Command + Send + Sized + 'a>>,
}
impl<'a> CommandChain<'a> {
fn new() -> CommandChain<'a> {
CommandChain{
commands: Vec::new(),
}
}
fn add_command<T:Command + Send + Sized + 'a>(&mut self, command: T) {
self.commands.push(
Box::new(
command
)
);
}
fn run_command(&self, name: &str, args: &[&str]) {
for command in self.commands.iter() {
command.on_command(name, args);
}
}
// fn iter(&self) -> core::slice::Iter<'a, Box<Command + Send + Sized + 'a>> {
// return self.commands.iter();
// }
}
impl <'a>Iterator for CommandChain<'a> {
type Item = &'a Box<Command + Send + Sized>;
fn next(&mut self) -> Option<Self::Item> {
let value = self.commands.iter().next();
// ^ Error is here (elf.commands.iter()): error: cannot infer an appropriate lifetime for lifetime parameter in function call due to conflicting requirements [E0495]
match value {
Some(value) => {
// let value: = Box::into_raw(*value);
// let value: &Box<Command> = value;
return Some(value);
},
None => {
return None;
},
}
// return self.commands.iter().next();
}
}
struct UserCommand;
impl UserCommand {
fn new() -> UserCommand {
UserCommand
}
}
impl Command for UserCommand {
fn on_command(&self, name: &str, args: &[&str]) {
println!("UserCommand handling '{}'.", name);
}
}
struct MailCommand;
impl MailCommand {
fn new() -> MailCommand {
MailCommand
}
}
impl Command for MailCommand {
fn on_command(&self, name: &str, args: &[&str]) {
println!("MailCommand handling '{}'", name);
}
}
fn main() {
let mut cc = CommandChain::new();
cc.add_command(
UserCommand::new()
);
cc.add_command(
MailCommand::new()
);
cc.run_command("one1", &["Toto", "users"]);
cc.run_command("one2", &["Sender", "Subject"]);
let t1 = thread::spawn(move||{
// let cc = cc;
cc.run_command("mutli1", &["Toto", "users"]);
});
// let t2 = thread::spawn(move||{
// // let cc = cc;
// cc.run_command("mutli2", &["Sender", "Subject"]);
// });
let threads = vec![t1];
for thread in threads {
thread.join();
}
}
src/main.rs:35:29: 35:35 error: cannot infer an appropriate lifetime for lifetime parameter in function call due to conflicting requirements [E0495]
src/main.rs:35 let value = self.commands.iter().next();
^~~~~~
src/main.rs:34:2: 47:3 help: consider using an explicit lifetime parameter as shown: fn next(&'a mut self) -> Option<Self::Item>
src/main.rs:34 fn next(&mut self) -> Option<Self::Item> {
src/main.rs:35 let value = self.commands.iter().next();
src/main.rs:36 match value {
src/main.rs:37 Some(value) => {
src/main.rs:38 // let value: = Box::into_raw(*value);
src/main.rs:39 // let value: &Box<Command> = value;
``