blob: 5ac86693338b1acacb4f300dfefb78f9d9df017c [file] [log] [blame]
// Copyright (c) 2021, 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.
import 'dart:async';
class MoreTypedStreamController<T, ListenData, PauseData> {
final StreamController<T> controller;
/// A wrapper around [StreamController] that statically guarantees its
/// clients that [onPause] and [onCancel] can only be invoked after
/// [onListen], and [onResume] can only be invoked after [onPause].
///
/// There is no static guarantee that [onPause] will not be invoked twice.
///
/// Internally the wrapper is not safe, and uses explicit null checks.
factory MoreTypedStreamController({
required ListenData Function(StreamController<T>) onListen,
PauseData Function(ListenData)? onPause,
void Function(ListenData, PauseData)? onResume,
FutureOr<void> Function(ListenData)? onCancel,
bool sync = false,
}) {
ListenData? listenData;
PauseData? pauseData;
var controller = StreamController<T>(
onPause: () {
if (pauseData != null) {
throw StateError('Already paused');
}
var local_onPause = onPause;
if (local_onPause != null) {
pauseData = local_onPause(listenData!);
}
},
onResume: () {
var local_onResume = onResume;
if (local_onResume != null) {
var local_pauseData = pauseData!;
pauseData = null;
local_onResume(listenData!, local_pauseData);
}
},
onCancel: () {
var local_onCancel = onCancel;
if (local_onCancel != null) {
var local_listenData = listenData!;
listenData = null;
local_onCancel(local_listenData);
}
},
sync: sync,
);
controller.onListen = () {
listenData = onListen(controller);
};
return MoreTypedStreamController._(controller);
}
MoreTypedStreamController._(this.controller);
}