Hi,
I have the following code which I can't make compile:
struct Node {
pub channel: Channel,
pub state: NodeState,
id: Option<String>,
next_message_id: u32,
}
impl Node {
fn new() -> Self {
Node {
channel: Channel::new(),
next_message_id: 0,
id: None,
}
}
fn handle(&mut self, handler: &mut Box<dyn FnMut(String, &mut Node)>) {
self.channel.on_data(|data| handler(data, &mut self))
}
}
#[derive(Debug)]
struct Channel;
impl Channel {
fn new() -> Self {
Channel {}
}
fn on_data(&self, mut handler: impl FnMut(String)) {
for line in io::stdin().lines() {
match line {
Ok(line) => {
handler(line);
}
Err(_) => panic!("Unexpected error"),
}
}
}
}
The Node
implementation includes a handle
method that's called each time there's data coming through the channel. This is the error I get:
error[E0500]: closure requires unique access to `*self` but it is already borrowed
--> src/bin/unique-ids.rs:104:30
|
104 | self.channel.on_data(|data| handler(data, self))
| ---------------------^^^^^^---------------------
| | | | |
| | | | second borrow occurs due to use of `*self` in closure
| | | closure construction occurs here
| | first borrow later used by call
| borrow occurs here
For more information about this error, try `rustc --explain E0500`.
error: could not compile `gossip-glomers-rust` (bin "unique-ids") due to previous erro
I tried what I found suggested in other posts (or stack overflow): split the Node
into separate structs (Node
and NodeState
):
struct Node {
pub channel: Channel,
pub state: NodeState,
}
#[derive(Debug)]
struct NodeState {
pub id: Option<String>,
pub next_message_id: u32,
}
impl Node {
fn new() -> Self {
Node {
channel: Channel::new(),
state: NodeState {
next_message_id: 0,
id: None,
},
}
}
fn handle(&mut self, handler: &mut Box<dyn FnMut(String, &mut NodeState)>) {
self.channel.on_data(|data| handler(data, &mut self.state))
}
}
This works but it won't allow me do what I need next. The thing is that I need the handler
closure to invoke mutable methods (not implemented yet) in the node which executed the handler. Something like the following:
// This could be the handler passed to Node#handle
Box::new(move |line: String, node_state: &mut NodeState, node: &mut Node| {
// ...
node.send(<some data goes here>)
// ...
}
What would be the idiomatic way of doing this in Rust
? Extract the state I need for the send
method into a separate struct?
thanks