read method

Map<String, Object?> read(
  1. Map<String, Object?> document, {
  2. required FormatRefusal refuse,
})

document checked against this format and lifted to version.

Refuses, through refuse so the format's own exception is what a caller catches:

  • a document whose format names another format;
  • a version newer than this build reads, naming both numbers;
  • a version older than since;
  • a requires entry this build does not understands.

The result is a fresh map: document is not changed.

Implementation

Map<String, Object?> read(
  Map<String, Object?> document, {
  required FormatRefusal refuse,
}) {
  final said = document['format'];
  if (said != null && said is! String) {
    throw refuse('"format" must be a string naming the format, not $said');
  }
  if (said is String && said != id && !aliases.contains(said)) {
    throw refuse('this is a "$said" document, not "$id"');
  }
  final raw =
      document['version'] ??
      switch (legacyVersionKey) {
        final String key => document[key],
        null => null,
      };
  if (raw != null && wholeNumber(raw) == null) {
    throw refuse('"version" must be a whole number, not $raw');
  }
  final at = versionOf(document);
  if (at < 1) throw refuse('"version" counts from 1, not $at');
  if (at > version) {
    throw refuse(
      '$id version $at is newer than this build reads ($version): '
      'update flutter3d to open it',
    );
  }
  if (at < since) {
    throw refuse(
      '$id version $at is older than this build reads ($since and up): '
      'open it with an earlier flutter3d and save it again',
    );
  }
  final requires = switch (document['requires']) {
    null => const <String>[],
    final List<Object?> list when list.every((Object? e) => e is String) =>
      list.cast<String>(),
    final other => throw refuse(
      '"requires" must be a list of names, not $other',
    ),
  };
  final missing = <String>[
    for (final name in requires)
      if (!understands.contains(name)) name,
  ];
  if (missing.isNotEmpty) {
    throw refuse(
      'this $id document requires ${missing.join(', ')}, which this '
      'build does not understand: install the plugin or the flutter3d '
      'release that provides ${missing.length == 1 ? 'it' : 'them'}',
    );
  }
  return lift(<String, Object?>{...document}, from: at);
}