| // Copyright (c) 2017, the Dart project authors. Please see the AUTHORS file | |
| // for details. All rights reserved. Use of this source code is governed by a | |
| // BSD-style license that can be found in the LICENSE file. | |
| /// Mixin to be used by entities that will be keys for either [EntityDataMap] | |
| /// or [EntityDataEnvMap]. | |
| mixin class EntityMapKey { | |
| int? _index; | |
| } | |
| /// Map of entities of type [K] with a corresponding data object of type [V]. | |
| class EntityDataMap<K extends EntityMapKey, V extends Object> { | |
| final List<(K, V)?> _list = []; | |
| int _length = 0; | |
| int get length => _length; | |
| /// Returns the data object stored for [entity]. | |
| V getData(K entity) { | |
| return _list[entity._index!]!.$2; | |
| } | |
| /// Registers a new [entity] with an associated [data] object. | |
| /// | |
| /// The index of [entity] is set to match its index in the entity and data | |
| /// lists in this map. | |
| K0 register<K0 extends K, V0 extends V>(K0 entity, V0 data) { | |
| entity._index = _list.length; | |
| _list.add((entity, data)); | |
| _length++; | |
| return entity; | |
| } | |
| /// Skips an index in the entity map assignments allowing for consistent | |
| /// indexing across multiple maps where some entities are filtered. | |
| void skipIndex() { | |
| _list.add(null); | |
| } | |
| void markAsCopy({required K original, required K copy}) { | |
| copy._index = original._index; | |
| } | |
| /// Calls [f] for each non-null entity with its corresponding data object. | |
| void forEach(void Function(K entity, V data) f) { | |
| // Copy the length in case the list is modified during the loop. | |
| int length = _list.length; | |
| for (int i = 0; i < length; i++) { | |
| final entry = _list[i]; | |
| if (entry != null) { | |
| f(entry.$1, entry.$2); | |
| } | |
| } | |
| } | |
| } | |
| /// Index based of entities of type [K] with a corresponding data object of | |
| /// type [V] and an environment of type [Env]. | |
| class EntityDataEnvMap< | |
| K extends EntityMapKey, | |
| V extends Object, | |
| Env extends Object | |
| > { | |
| final List<(K, V, Env)?> _list = []; | |
| int _length = 0; | |
| int get length => _length; | |
| /// Returns the environment object stored for the entity. | |
| Env getEnv(K entity) { | |
| return _list[entity._index!]!.$3; | |
| } | |
| /// Returns the data object stored for [entity]. | |
| V getData(K entity) { | |
| return _list[entity._index!]!.$2; | |
| } | |
| /// Registers a new [entity] with an associated [data] object and environment | |
| /// [env]. | |
| /// | |
| /// The index of [entity] is set to match its index in the entity, data and | |
| /// environment lists in this map. | |
| K0 register<K0 extends K, V0 extends V, Env0 extends Env>( | |
| K0 entity, | |
| V0 data, | |
| Env0 env, | |
| ) { | |
| entity._index = _list.length; | |
| _list.add((entity, data, env)); | |
| _length++; | |
| return entity; | |
| } | |
| void skipIndex() { | |
| _list.add(null); | |
| } | |
| void markAsCopy({required K original, required K copy}) { | |
| copy._index = original._index; | |
| } | |
| /// Calls [f] for each non-null entity with its corresponding data object and | |
| /// environment. | |
| void forEach(void Function(K entity, V data, Env env) f) { | |
| // Copy the length in case the list is modified during the loop. | |
| int length = _list.length; | |
| for (int i = 0; i < length; i++) { | |
| final entry = _list[i]; | |
| if (entry != null) { | |
| f(entry.$1, entry.$2, entry.$3); | |
| } | |
| } | |
| } | |
| } |