rust 将可变结构传递给结构的可变属性

wbrvyc0a  于 2023-08-05  发布在  其他
关注(0)|答案(1)|浏览(100)

我正在用ratatui构建一个小的TUI工具,我想把App的可变示例传递给每个小部件,这样我就可以:

  • 处理事件并更新widget数据
  • 更新主App数据

下面是我的工具的简单结构

// app.rs
impl App {
    pub fn new() -> Self {
        Self {
            user_input: UserInput::new(),
        }
    }

    pub fn get_curr_widgets(&mut self) -> Vec<&mut dyn Component> {
        vec![
            &mut self.sidebar,
            &mut self.user_input,
        ]
    }
}

// src/components/user_input.rs
impl Component for UserInput {
    fn handle_events(&mut self, event: Event, app: &mut App) {
        match event {
            Event::Key(key_event) => match key_event.code {
                // Update App data
                // KeyCode::Enter => app.do_search(),
                // app.widget_index = -1
                KeyCode::Char(to_insert) => {
                    // Update UserInput data
                    self.enter_char(to_insert);
                }
                _ => {}
            },
            _ => {}
        }
    }
}

// event_handles.rs
pub fn handle_terminal_events(event: Event, app: &mut App) {
    let widget_index = app.widget_index;
    let widgets = app.get_widgets();
    for (index, widget) in app.get_widgets().into_iter().enumerate() {
        if widget_index == index {
            // Error: error[E0499]: cannot borrow `*app` as mutable more than once at a time
            widget.handle_events(event, app);
            break;
        }
    }
}

字符串
完整错误:

error[E0499]: cannot borrow `*app` as mutable more than once at a time
  --> src/handler.rs:51:43
   |
48 |         let widgets = app.get_widgets();
   |                     --------------- first mutable borrow occurs here
...
51 |                 widget.handle_events(event, app);
   |                      -------------        ^^^ second mutable borrow occurs here
   |                      |
   |                      first borrow later used by call


我认为行中的错误:widget.handle_events(event, app);

  • widget.App的第一个借用变量
  • 那么我们就不能将App的第二个变量传递给函数

在Rust中,我们一次只能有一个可变的ref。那么,有什么更好的方法来解决我的问题,或者我的结构是错误的?

ctehm74n

ctehm74n1#

这闻起来像是设计问题。小部件(组件)包含在应用程序中,但您试图在组件级别处理事件时改变应用程序。
理想情况下,改变App的代码应该存在于“impl App”块中。

impl App {
    pub fn new() -> Self {
        Self {
            user_input: UserInput::new(),
        }
    }

    pub fn handle_events(&mut self) {
        let mut widgets = vec![
            &mut self.sidebar,
            &mut self.user_input,
        ];
        for (index, widget) in self.get_widgets().iter_mut().enumerate() {
            if widget_index == index {
                widget.handle_events(event, self);
                break;
            }
        }
    }
}

// src/components/user_input.rs
impl Component for UserInput {
    fn handle_events(&mut self, event: Event, app: &mut App) {
        match event {
            Event::Key(key_event) => match key_event.code {
                // Update App data
                // KeyCode::Enter => app.do_search(),
                // app.widget_index = -1
                KeyCode::Char(to_insert) => {
                    // Update UserInput data
                    self.enter_char(to_insert);
                }
                _ => {}
            },
            _ => {}
        }
    }
}

// event_handles.rs
pub fn handle_terminal_events(event: Event, app: &mut App) {
    app.handle_events();
}

字符串
因此,通过此更改,您将仅在App impl的上下文(生命周期)内变更应用程序。
这应该可以解决问题。
注意:get方法通常用于读(&)而不是写(&mut)。

相关问题