import 'dart:math'; import 'package:async_tools/async_tools.dart'; import 'package:fast_immutable_collections/fast_immutable_collections.dart'; import 'package:meta/meta.dart'; import 'package:veilid_support/veilid_support.dart'; import '../../../proto/proto.dart' as proto; @immutable class InputWindow { const InputWindow({required this.elements, required this.firstPosition}) : lastPosition = firstPosition + elements.length - 1, isEmpty = elements.length == 0, length = elements.length; final IList> elements; final int firstPosition; final int lastPosition; final bool isEmpty; final int length; } class AuthorInputSource { AuthorInputSource.fromDHTLog(DHTLog dhtLog) : _dhtLog = dhtLog; //////////////////////////////////////////////////////////////////////////// Future getTailPosition() => _dhtLog.operate((reader) async => reader.length); Future> getWindow( int startPosition, int windowLength) => _dhtLog.operate((reader) async { // Don't allow negative length if (windowLength <= 0) { return const AsyncValue.data(null); } // Trim if we're beyond input source var endPosition = startPosition + windowLength - 1; startPosition = max(startPosition, 0); endPosition = max(endPosition, 0); // Get another input batch futher back try { Set? offlinePositions; if (_dhtLog.writer != null) { offlinePositions = await reader.getOfflinePositions(); } final messages = await reader.getRangeProtobuf( proto.Message.fromBuffer, startPosition, length: endPosition - startPosition + 1); if (messages == null) { return const AsyncValue.loading(); } final elements = messages.indexed .map((x) => OnlineElementState( value: x.$2, isOffline: offlinePositions?.contains(x.$1 + startPosition) ?? false)) .toIList(); final window = InputWindow(elements: elements, firstPosition: startPosition); return AsyncValue.data(window); } on Exception catch (e, st) { return AsyncValue.error(e, st); } }); //////////////////////////////////////////////////////////////////////////// final DHTLog _dhtLog; }