selectMany<SubState, Result> method
Select many sub states and combine them by projector
.
The returned Stream is a single-subscription Stream.
Implementation
StateStream<Result> selectMany<SubState, Result>(
List<Selector<State, SubState>> selectors,
List<Equality<SubState>?> subStateEquals,
Result Function(List<SubState> subStates) projector, {
Equality<Result>? equals,
}) {
final length = selectors.length;
if (length != subStateEquals.length) {
throw ArgumentError(
'selectors and subStateEquals should have same length');
}
if (length == 0) {
throw ArgumentError('selectors and subStateEquals must be not empty');
}
if (length == 1) {
throw ArgumentError(
'selectors contains single element. Use select(selector) instead.');
}
selectors = selectors.toList(growable: false);
subStateEquals = subStateEquals.toList(growable: false);
if (length == 2) {
return _select2Internal<State, SubState, SubState, Result>(
this,
selectors[0],
selectors[1],
(subState1, subState2) => projector([subState1, subState2]),
subStateEquals[0],
subStateEquals[1],
equals,
);
}
if (length == 3) {
return _select3Internal<State, SubState, SubState, SubState, Result>(
this,
selectors[0],
selectors[1],
selectors[2],
(subState1, subState2, subState3) =>
projector([subState1, subState2, subState3]),
subStateEquals[0],
subStateEquals[1],
subStateEquals[2],
equals,
);
}
if (length == 4) {
return _select4Internal<State, SubState, SubState, SubState, SubState,
Result>(
this,
selectors[0],
selectors[1],
selectors[2],
selectors[3],
(subState1, subState2, subState3, subState4) =>
projector([subState1, subState2, subState3, subState4]),
subStateEquals[0],
subStateEquals[1],
subStateEquals[2],
subStateEquals[3],
equals,
);
}
List<SubState> selectSubStates(State state) =>
selectors.map((s) => s(state)).toList(growable: false);
final eqs = subStateEquals
.map((e) => e ?? StateStream.defaultEquality)
.toList(growable: false);
late final indices = Iterable<int>.generate(length);
bool subStatesEquals(List<SubState> previous, List<SubState> next) =>
indices.every((i) => eqs[i](previous[i], next[i]));
final currentSubStates = selectSubStates(value);
return map(selectSubStates)
.toStateStream(currentSubStates, equals: subStatesEquals)
.map(projector)
.toStateStream(projector(currentSubStates), equals: equals);
}