Постоянное состояние железа со ссылкой на структуру

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

Пример:

use iron::prelude::*;
use iron::typemap::Key;
use persistent::Read;
use router::Router;

pub struct Controller;

pub struct Rest {
    controller: Controller,
}

impl Key for &Controller {
    type Value = Self;
}

impl Rest {
    pub fn run(&self) {
        let router = Router::new();
        let mut chain = Chain::new(router);
        chain.link(Read::<&Controller>::both(&self.controller));
        Iron::new(chain).http(format!("0.0.0.0:1234")).ok();
    }
}

fn main() {
    Rest {
        controller: Controller,
    }
    .run();
}
[dependencies]
iron = "0.6.*"
router = "0.6.*"
persistent = "0.4.0"

Суть примера

error[E0478]: lifetime bound not satisfied
  --> src/main.rs:12:6
   |
12 | impl Key for &Controller {
   |      ^^^
   |
note: lifetime parameter instantiated with the lifetime '_ as defined on the impl at 12:14
  --> src/main.rs:12:14
   |
12 | impl Key for &Controller {
   |              ^
   = note: but lifetime parameter must outlive the static lifetime

error[E0495]: cannot infer an appropriate lifetime for lifetime parameter `'_` due to conflicting requirements
  --> src/main.rs:12:6
   |
12 | impl Key for &Controller {
   |      ^^^
   |
note: first, the lifetime cannot outlive the lifetime '_ as defined on the impl at 12:14...
  --> src/main.rs:12:14
   |
12 | impl Key for &Controller {
   |              ^
   = note: ...so that the types are compatible:
           expected typemap::Key
              found typemap::Key
   = note: but, the lifetime must be valid for the static lifetime...
note: ...so that the type `&Controller` will meet its required lifetime bounds
  --> src/main.rs:12:6
   |
12 | impl Key for &Controller {
   |      ^^^

person Brice Lechatellier    schedule 06.05.2019    source источник
comment
Я хочу иметь возможность повторно использовать контроллер на разных маршрутах — и вы хотите, чтобы постоянные данные были глобально общими для всех этих маршрутов, или у каждого маршрута есть свои уникальные постоянные данные?   -  person Shepmaster    schedule 07.05.2019
comment
Я хочу, чтобы постоянные данные были глобально доступны для всех этих маршрутов.   -  person Brice Lechatellier    schedule 07.05.2019


Ответы (2)


Как говорится в сообщении об ошибке:

но параметр времени жизни должен пережить статическое время жизни

Это связано с тем, что Key использует Any в качестве суперчерты, для которой требуется 'static:

pub trait Any: 'static {
    fn type_id(&self) -> TypeId;
}

Самое простое решение — реализовать Key для значения, а затем передать значение Read::both:

impl Key for Controller {
    type Value = Self;
}

impl Rest {
    pub fn run(self) {
        let router = Router::new();
        let mut chain = Chain::new(router);
        chain.link(Read::<Controller>::both(self.controller));
        Iron::new(chain).http(format!("0.0.0.0:1234")).ok();
    }
}

Я хочу, чтобы постоянные данные были глобально доступны для всех этих маршрутов.

В этом случае я бы полностью отказался от использования постоянного ящика и просто создал бы синглтон:

person Shepmaster    schedule 07.05.2019
comment
как бы выглядело более сложное решение, если бы я хотел иметь ссылку на контроллер? - person Brice Lechatellier; 07.05.2019
comment
@BriceLechatellier извините за двусмысленную формулировку — нет способа реализовать Key для ссылки, если только ссылка не является 'static (также известной как глобальная), поэтому сложного решения нет. Я имею в виду, что предоставленное решение является самым простым рабочим решением, начиная с предложенной вами структуры. Я связался с альтернативными вопросами и ответами, которые показывают, как иметь такой глобальный. - person Shepmaster; 07.05.2019

Вам нужно добавить явное время жизни, привязанное к вашему блоку impl. В противном случае компилятор не имеет ни малейшего представления о достоверности ссылки на контроллер.

Это должно работать, хотя я не проверял это

pub struct Rest {
    controller: controller::Controller,
}

impl<'a> Key for &'a controller::Controller {
    type Value = Self;
}

impl Rest {
    pub fn run(&self) {
        let mut router = Router::new();
        let mut chain = Chain::new(router);
        chain.link(Read::<&controller::Controller>::both(&self.controller));
        Iron::new(chain).http(format!("0.0.0.0:1234"))
    }
}

Кстати, я не думаю, что вам нужно указывать тип при вызове Read, компилятор должен иметь возможность определить его из контекста.

person AdminXVII    schedule 06.05.2019
comment
Спасибо, отредактировал основной вопрос с предложением, все еще выдавая ошибки относительно срока службы. - person Brice Lechatellier; 06.05.2019