blob: f37e8ddd8342c87ae00ef048c50c5e5970f8e3fc [file] [log] [blame] [edit]
// 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);
}
}
}
}