acquire method
Future<ChatImageDecodeReservation>
acquire({
- required int decodedBytes,
- required ChatImageDecodeCancellation cancellation,
Implementation
Future<ChatImageDecodeReservation> acquire({
required int decodedBytes,
required ChatImageDecodeCancellation cancellation,
}) {
final bool isCancelled;
try {
isCancelled = cancellation.isCancelled;
} catch (error, stackTrace) {
return Future<ChatImageDecodeReservation>.error(error, stackTrace);
}
if (isCancelled) {
return Future<ChatImageDecodeReservation>.error(
const ChatImageDecodeCancelled(),
);
}
if (decodedBytes < 0) {
return Future<ChatImageDecodeReservation>.error(
RangeError.range(
decodedBytes,
0,
_budget.maxEmbeddedMediaBytes,
'decodedBytes',
),
);
}
if (decodedBytes > _budget.maxEmbeddedMediaBytes) {
return Future<ChatImageDecodeReservation>.error(
ChatInputLimitExceeded(
resource: 'ACP image decoded bytes',
limit: _budget.maxEmbeddedMediaBytes,
observedAtLeast: _budget.maxEmbeddedMediaBytes + 1,
),
);
}
final previewPixels = _budget.maxImagePreviewPixels;
final reservedBytes = decodedBytes + previewPixels * 4;
if (previewPixels >
_budget.maxImagePreviewPixelsGlobal - _reservedPreviewPixels) {
return Future<ChatImageDecodeReservation>.error(
ChatInputLimitExceeded(
resource: 'ACP image preview pixels',
limit: _budget.maxImagePreviewPixelsGlobal,
observedAtLeast: _budget.maxImagePreviewPixelsGlobal + 1,
),
);
}
if (reservedBytes > _budget.maxImageDecodeBytesGlobal - _reservedBytes) {
return Future<ChatImageDecodeReservation>.error(
ChatInputLimitExceeded(
resource: 'ACP image decode bytes',
limit: _budget.maxImageDecodeBytesGlobal,
observedAtLeast: _budget.maxImageDecodeBytesGlobal + 1,
),
);
}
_reservedPreviewPixels += previewPixels;
_reservedBytes += reservedBytes;
if (_activeDecodes < _budget.maxConcurrentImageDecodes) {
_activeDecodes += 1;
return Future<ChatImageDecodeReservation>.value(
_ChatImageDecodeReservation(
this,
decodedBytes,
previewPixels,
reservedBytes,
),
);
}
final waiter = _ChatImageDecodeWaiter(
decodedBytes: decodedBytes,
previewPixels: previewPixels,
reservedBytes: reservedBytes,
cancellation: cancellation,
);
_waiters.add(waiter);
late void Function() cancelListener;
cancelListener = () => _cancelWaiter(waiter);
waiter.cancelListener = cancelListener;
try {
cancellation.addListener(cancelListener);
} catch (error, stackTrace) {
waiter.registrationInProgress = false;
if (waiter.waiting) {
waiter.waiting = false;
waiter.unlink();
_releaseInstalledCapacity(
previewPixels: waiter.previewPixels,
reservedBytes: waiter.reservedBytes,
);
}
final removeError = _removeWaiterListener(waiter);
_grantWaiters();
if (removeError != null) {
_reportChatImageDecodeCallbackError(
removeError.error,
removeError.stackTrace,
);
}
return Future<ChatImageDecodeReservation>.error(error, stackTrace);
}
waiter.registrationInProgress = false;
final completer = Completer<ChatImageDecodeReservation>();
waiter.completer = completer;
if (waiter.cancelledDuringRegistration) {
completer.completeError(const ChatImageDecodeCancelled());
} else {
_grantWaiters();
}
return completer.future;
}