Пытаюсь написать систему сущностей-компонентов на Rust (версия rustc 1.19.0-nightly (557967766 2017-05-26)
) без использования даункастинга, а желательно еще и без макросов. Общая архитектура представляет собой свободное объединение specs
и calx-ecs
.
Я борюсь с определением рабочего метода run
, который выполняет системные действия на основе их выбранных компонентов. Требование состоит в том, чтобы системы могли заимствовать компоненты каждого соответствующего объекта изменчиво. Тем не менее, я действительно борюсь с проверкой заимствования, и я немного потерян.
Метод run
реализуется структурой Scheduler
, которая владеет структурой World
и вектором системных трейт-объектов в штучной упаковке.
pub type ComponentMask = u8;
pub trait AssemblyTrait {
fn new() -> Self;
fn match_mask(&self, entity: &Entity, mask: ComponentMask) -> bool;
fn remove(&mut self, entity: &Entity);
}
pub trait ViewTrait<'a> {
type View;
fn get_view(&'a mut self, entity: &Entity) -> Self::View;
}
pub struct World<'a, A: 'a + AssemblyTrait + ViewTrait<'a>> {
next_idx: usize,
next_uuid: UUID,
free_indices: Vec<usize>,
entities: ComponentContainer<bool>,
pub components: A,
phantom: marker::PhantomData<&'a A>,
}
pub struct Scheduler<'a, A> where A: 'a + AssemblyTrait + ViewTrait<'a> {
world: World<'a, A>,
systems: Vec<Box<'static + SystemTrait<'a, A>>>,
}
impl<'a, A> Scheduler<'a, A> where A: 'a + AssemblyTrait + ViewTrait<'a> {
// Some methods ommitted.
pub fn run(&'a mut self) {
for system in self.systems.iter() {
let mask = system.get_mask();
let mut components: Vec<A::View> = self.world.iter()
.filter(|e| self.world.match_mask(e, mask))
.map(|e| self.world.components.get_view(e))
.collect();
if components.len() > 0 {
system.run(&components);
}
}
}
}
Системный признак определяется следующим образом:
pub trait SystemTrait<'a, A> where A: AssemblyTrait + ViewTrait<'a> {
fn get_name(&self) -> &'static str;
fn get_mask(&self) -> ComponentMask;
fn run(&mut self, components: &mut [A::View]);
}
Я также опубликовал полную реализацию.
Определение ViewTrait
можно найти в этом минимальном рабочем примере, который мне удалось заставить работать благодаря параметрам времени жизни в связанном типе.
Хотя приведенный выше пример работает правильно, я продолжаю получать ошибки времени жизни для метода Scheduler::run
:
error[E0495]: cannot infer an appropriate lifetime for autoref due to conflicting requirements
--> src\lib.rs:261:48
|
261 | .map(|e| self.world.components.get_view(e))
| ^^^^^^^^
|
note: first, the lifetime cannot outlive the lifetime as defined on the body at 261:22...
--> src\lib.rs:261:22
|
261 | .map(|e| self.world.components.get_view(e))
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
note: ...so that closure can access `self`
--> src\lib.rs:261:26
|
261 | .map(|e| self.world.components.get_view(e))
| ^^^^^^^^^^^^^^^^^^^^^
note: but, the lifetime must be valid for the lifetime 'a as defined on the impl at 244:1...
--> src\lib.rs:244:1
|
244 | / impl<'a, A> Scheduler<'a, A> where A: 'a + AssemblyTrait + ViewTrait<'a> {
245 | | pub fn new(world: World<'a, A>) -> Scheduler<'a, A> {
246 | | Scheduler {
247 | | world: world,
... |
267 | | }
268 | | }
| |_^
note: ...so that types are compatible (expected &'a mut A, found &mut A)
--> src\lib.rs:261:48
|
261 | .map(|e| self.world.components.get_view(e))
| ^^^^^^^^
Scheduler
,AssemblyTrait
иViewTrait
. Эта проблема очень похожа на stackoverflow.com/q/24574741/1233251 (хотя и не с итераторами, а с вашей собственной чертой): время жизни&mut self
несовместимо со временем жизни'a
. - person E_net4 the curator   schedule 27.05.2017'a ViewTrait<'a>
, что, вероятно, завышает время жизни, как в этом вопросе: stackoverflow.com/questions/44081272. - person zstewart   schedule 27.05.2017A
, потому что структураWorld
содержит полеstd::marker::PhantomData
, которое, в свою очередь, использует ложно неиспользуемый параметр времени жизни. Я обновлю вопрос, включив в него определение структуры World. - person E Y   schedule 27.05.2017ViewTrait::View
(т.е. изменяемые ссылки в качестве возвращаемого типа), но я также многократно заимствуюWorld
несколько раз. Я думаю, что я спрашиваю; как мне все это упорядочить? - person E Y   schedule 27.05.2017'a
на уровне черты? - person Shepmaster   schedule 28.05.2017World
(и его членов). Но я до сих пор не знаю, как решить проблему взаимодействия междуSystemTrait
иViewTrait
в отношении времени жизни. В целях более подробного описания фактической проблемы, должен ли я изменить свой первоначальный вопрос или задать новый? - person E Y   schedule 31.05.2017