Архитектура приложения: проблема с изменяемой / неизменной ссылкой - PullRequest
0 голосов
/ 22 сентября 2018

Я пытался написать приложение, в котором пользователь может создавать объекты из шаблонов.

В моих снах код выглядит так:

struct DataTemplate {
    tmp: u32,
}

struct Data<'a> {
    name: &'a str,
    tmp: u32,
}

struct Consumer<'a> {
    items: Vec<Data<'a>>,
}

struct Library {
    items: Vec<DataTemplate>,
}

struct Application<'a> {
    library: Library,
    consumer: Consumer<'a>,
}

impl DataTemplate {
    fn new(data: u32) -> Self {
        DataTemplate { tmp: data }
    }
}

impl<'a> Data<'a> {
    fn new(name: &'a str, tmp: u32) -> Self {
        Data { name, tmp }
    }
    fn from_template(template: &DataTemplate, name: &'a str) -> Self {
        Data::new(name, template.tmp)
    }
}

impl<'a> Consumer<'a> {
    fn new() -> Self {
        Consumer { items: vec![] }
    }
    fn consume(&mut self, data: Data<'a>) {
        self.items.push(data);
    }
}

impl Library {
    fn new() -> Self {
        Library { items: vec![] }
    }
    fn add(&mut self, d: DataTemplate) {
        self.items.push(d);
    }
    fn get(&self, index: usize) -> &DataTemplate {
        &self.items[index]
    }
}

impl<'a> Application<'a> {
    fn new() -> Self {
        Application {
            library: Library::new(),
            consumer: Consumer::new(),
        }
    }
    fn get_library(&self) -> &Library {
        &self.library
    }
    fn get_library_mut(&mut self) -> &mut Library {
        &mut self.library
    }
    fn get_consumer_mut(&mut self) -> &mut Consumer<'a> {
        &mut self.consumer
    }
}

fn main() {
    let mut app = Application::new();

    use_it(&mut app);
}

fn use_it(app: &mut Application) {
    app.get_library_mut().add(DataTemplate::new(1));
    app.get_library_mut().add(DataTemplate::new(2));
    app.get_library_mut().add(DataTemplate::new(3));

    let item = app.get_library().get(1);
    app.get_consumer_mut()
        .consume(Data::from_template(item, "hi"));
}

Проблема в use_itфункция:

error[E0502]: cannot borrow `*app` as mutable because it is also borrowed as immutable
  --> src/main.rs:89:5
   |
88 |     let item = app.get_library().get(1);
   |                --- immutable borrow occurs here
89 |     app.get_consumer_mut()
   |     ^^^ mutable borrow occurs here
90 |         .consume(Data::from_template(item, "hi"));
91 | }
   | - immutable borrow ends here

Мне нужно получить неизменную ссылку на приложение (let item = app.get_library()), чтобы получить шаблон, а затем после создания элемента данных из шаблона я должен добавить его к потребителюв приложении, теперь изменяемый, конечно (app.get_consumer_mut()).

Есть ли какое-то общее решение для такой проблемы, или эта идея просто не в стиле Rust?

1 Ответ

0 голосов
/ 24 сентября 2018

Вам необходимо убедиться, что вы удалили ссылку на библиотеку, прежде чем пытаться получить доступ к потребителю.Например:

let data = Data::from_template(app.get_library().get(1), "hi");
app.get_consumer_mut().consume(data);
...