read method

Future<void> read(
  1. GpsPointsView<GpsPoint> view,
  2. Stream<List<int>> sourceStream,
  3. [int? streamSizeBytesHint]
)

Overwrites the contents of view with data read from sourceStream. Optionally a non-null streamSizeBytesHint may be provided to indicate how large the stream is, but see caveats in StreamReaderState.remainingStreamBytesHint on its use.

Throws ReadonlyCollectionException if view.isReadonly, as the contents of a readonly view cannot be overwritten. Throws NotEmptyCollectionException if view.isNotEmpty, as the contents of an already existing view cannot be overwritten (since there may be other views that depend on it). Throws InvalidSignatureException if the stream contains an invalid signature at either Persistence level or Persister level. Throws NewerVersionException if the stream contains a newer version at either Persistence level or Persister level.

Implementation

Future<void> read(GpsPointsView view, Stream<List<int>> sourceStream,
    [int? streamSizeBytesHint]) async {
  if (view.isReadonly) {
    throw ReadonlyCollectionException();
  }

  if (view.isNotEmpty) {
    throw NotEmptyCollectionException();
  }

  final state = StreamReaderState(sourceStream, streamSizeBytesHint);

  // Read the header signature and stop if it's unrecognized.
  await _readValidateSignature(state, _signatureAndVersion.signature);

  // Read the streaming method version and stop if it's newer than what
  // we support internally.
  await _readValidateVersion(state, _signatureAndVersion.version, 'stream');

  final persister = getPersister(view);

  // Read the persister signature and validate against the persister that's
  // supposed to read the specified view.
  await _readValidateSignature(state, persister.signature);

  // Read the persister version number and stop if it's newer than what the
  // persister writes natively.
  final loadedPersisterVersion = await _readValidateVersion(
      state, persister.version, 'persister ${persister.runtimeType}');

  // Read the metadata.
  final metadataLength = await state.readUint8();
  if (metadataLength == null || metadataLength > maxMetadataLength) {
    throw (InvalidMetadataException(
        'Expected to read metadata with max length $maxMetadataLength, '
        'but found length $metadataLength.'));
  }
  // Always read entire metadata because it's fixed-length, will trim it
  // afterwards to reflect the actual length read above.
  final metadataList = await state.readBytes(maxMetadataLength);
  if (metadataList == null) {
    throw (InvalidMetadataException(
        'Failed reading metadata, probably the stream is corrupted '
        '(too short)'));
  }
  final metadata = ByteData(metadataLength);
  metadata.buffer.asUint8List().setRange(0, metadataLength, metadataList);

  // Have the persister read and interpret the actual data.
  return persister.readViewFromStream(
      view, state, loadedPersisterVersion, metadata);
}