| // 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); |
| } |
| } |
| } |
| } |